summaryrefslogtreecommitdiff
path: root/MdeModulePkg
diff options
context:
space:
mode:
authorRyan Harkin <ryan.harkin@linaro.org>2013-09-19 13:01:48 +0100
committerRyan Harkin <ryan.harkin@linaro.org>2013-09-19 13:01:48 +0100
commitcad230532f8dd53d993c9631dc574f4b196e8e99 (patch)
tree74084743cc55c30fe59f85b0f4e9e89d6ec8e6f5 /MdeModulePkg
parentfe29a8a877edb5f8495c1da34f98c023e0e9be45 (diff)
parent2e4c39a43c92d4e99140c3735a4091029797780e (diff)
Merging uefi-next/linaro-release into masterlinaro-uefi-2013.09
Signed-off-by: Ryan Harkin <ryan.harkin@linaro.org>
Diffstat (limited to 'MdeModulePkg')
-rw-r--r--MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AhciMode.c30
-rw-r--r--MdeModulePkg/Bus/Ata/AtaAtapiPassThru/IdeMode.c29
-rw-r--r--MdeModulePkg/Bus/Ata/AtaBusDxe/AtaPassThruExecute.c10
-rw-r--r--MdeModulePkg/Bus/I2c/I2cDxe/I2cBus.c1468
-rw-r--r--MdeModulePkg/Bus/I2c/I2cDxe/I2cBusDxe.inf54
-rw-r--r--MdeModulePkg/Bus/I2c/I2cDxe/I2cDxe.c75
-rw-r--r--MdeModulePkg/Bus/I2c/I2cDxe/I2cDxe.h1097
-rw-r--r--MdeModulePkg/Bus/I2c/I2cDxe/I2cDxe.inf56
-rw-r--r--MdeModulePkg/Bus/I2c/I2cDxe/I2cHost.c1169
-rw-r--r--MdeModulePkg/Bus/I2c/I2cDxe/I2cHostDxe.inf53
-rw-r--r--MdeModulePkg/Bus/Pci/EhciDxe/EhciDebug.c148
-rw-r--r--MdeModulePkg/Bus/Pci/EhciDxe/EhciSched.c10
-rw-r--r--MdeModulePkg/Bus/Pci/EhciDxe/UsbHcMem.c4
-rw-r--r--MdeModulePkg/Bus/Pci/EhciPei/EhcPeim.c6
-rw-r--r--MdeModulePkg/Bus/Pci/EhciPei/EhciSched.c20
-rw-r--r--MdeModulePkg/Bus/Pci/NvmExpressDxe/ComponentName.c233
-rw-r--r--MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpress.c1057
-rw-r--r--MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpress.h614
-rw-r--r--MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressBlockIo.c559
-rw-r--r--MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressBlockIo.h111
-rw-r--r--MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressDiskInfo.c162
-rw-r--r--MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressDiskInfo.h129
-rw-r--r--MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressDxe.inf68
-rw-r--r--MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressHci.c926
-rw-r--r--MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressHci.h790
-rw-r--r--MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressPassthru.c884
-rw-r--r--MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressPassthru.h299
-rw-r--r--MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h3
-rw-r--r--MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf3
-rw-r--r--MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.c16
-rw-r--r--MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.c47
-rw-r--r--MdeModulePkg/Bus/Pci/UhciDxe/UhciSched.c6
-rw-r--r--MdeModulePkg/Bus/Pci/UhciPei/UhcPeim.c37
-rw-r--r--MdeModulePkg/Bus/Pci/UhciPei/UhcPeim.h3
-rw-r--r--MdeModulePkg/Bus/Pci/XhciDxe/UsbHcMem.c758
-rw-r--r--MdeModulePkg/Bus/Pci/XhciDxe/UsbHcMem.h213
-rw-r--r--MdeModulePkg/Bus/Pci/XhciDxe/Xhci.c33
-rw-r--r--MdeModulePkg/Bus/Pci/XhciDxe/Xhci.h12
-rw-r--r--MdeModulePkg/Bus/Pci/XhciDxe/XhciDxe.inf4
-rw-r--r--MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c564
-rw-r--r--MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.h17
-rw-r--r--MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBus.c4
-rw-r--r--MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBus.h7
-rw-r--r--MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.c28
-rw-r--r--MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.h6
-rw-r--r--MdeModulePkg/Bus/Usb/UsbBusPei/UsbIoPeim.c10
-rw-r--r--MdeModulePkg/Bus/Usb/UsbBusPei/UsbPeim.h10
-rw-r--r--MdeModulePkg/Core/Dxe/DxeMain.h8
-rw-r--r--MdeModulePkg/Core/Dxe/Hand/Handle.c8
-rw-r--r--MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf4
-rw-r--r--MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c6
-rw-r--r--MdeModulePkg/Include/Guid/FaultTolerantWrite.h54
-rw-r--r--MdeModulePkg/Include/Guid/SystemNvDataGuid.h73
-rw-r--r--MdeModulePkg/Include/Library/CustomizedDisplayLib.h356
-rw-r--r--MdeModulePkg/Include/Ppi/Usb2HostController.h8
-rw-r--r--MdeModulePkg/Include/Ppi/UsbHostController.h10
-rw-r--r--MdeModulePkg/Include/Ppi/UsbIo.h14
-rw-r--r--MdeModulePkg/Include/Protocol/DisplayProtocol.h350
-rw-r--r--MdeModulePkg/Include/Protocol/FormBrowserEx2.h90
-rw-r--r--MdeModulePkg/Library/CustomizedDisplayLib/Colors.h (renamed from MdeModulePkg/Universal/SetupBrowserDxe/Colors.h)0
-rw-r--r--MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.c921
-rw-r--r--MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.inf74
-rw-r--r--MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.unibin0 -> 7256 bytes
-rw-r--r--MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLibInternal.c914
-rw-r--r--MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLibInternal.h295
-rw-r--r--MdeModulePkg/Library/UefiHiiLib/HiiLib.c1090
-rw-r--r--MdeModulePkg/MdeModulePkg.dec44
-rw-r--r--MdeModulePkg/MdeModulePkg.dsc9
-rw-r--r--MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf2
-rw-r--r--MdeModulePkg/Universal/Console/TerminalDxe/TerminalConIn.c6
-rw-r--r--MdeModulePkg/Universal/DevicePathDxe/DevicePath.c44
-rw-r--r--MdeModulePkg/Universal/DevicePathDxe/DevicePath.h433
-rw-r--r--MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf23
-rw-r--r--MdeModulePkg/Universal/DevicePathDxe/DevicePathFromText.c3210
-rw-r--r--MdeModulePkg/Universal/DevicePathDxe/DevicePathToText.c2071
-rw-r--r--MdeModulePkg/Universal/DevicePathDxe/DevicePathUtilities.c234
-rw-r--r--MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIo.c1275
-rw-r--r--MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIo.h171
-rw-r--r--MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIoDxe.inf4
-rw-r--r--MdeModulePkg/Universal/Disk/PartitionDxe/ElTorito.c5
-rw-r--r--MdeModulePkg/Universal/Disk/PartitionDxe/Gpt.c18
-rw-r--r--MdeModulePkg/Universal/Disk/PartitionDxe/Mbr.c6
-rw-r--r--MdeModulePkg/Universal/Disk/PartitionDxe/Partition.c230
-rw-r--r--MdeModulePkg/Universal/Disk/PartitionDxe/Partition.h16
-rw-r--r--MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf4
-rw-r--r--MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf66
-rw-r--r--MdeModulePkg/Universal/DisplayEngineDxe/FormDisplay.c3255
-rw-r--r--MdeModulePkg/Universal/DisplayEngineDxe/FormDisplay.h589
-rw-r--r--MdeModulePkg/Universal/DisplayEngineDxe/FormDisplayStr.uni (renamed from MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserStr.uni)bin14784 -> 8660 bytes
-rw-r--r--MdeModulePkg/Universal/DisplayEngineDxe/InputHandler.c (renamed from MdeModulePkg/Universal/SetupBrowserDxe/InputHandler.c)621
-rw-r--r--MdeModulePkg/Universal/DisplayEngineDxe/ProcessOptions.c1431
-rw-r--r--MdeModulePkg/Universal/DriverSampleDxe/DriverSample.c21
-rw-r--r--MdeModulePkg/Universal/DriverSampleDxe/DriverSample.h1
-rw-r--r--MdeModulePkg/Universal/DriverSampleDxe/DriverSampleDxe.inf2
-rw-r--r--MdeModulePkg/Universal/DriverSampleDxe/Vfr.vfr62
-rw-r--r--MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWrite.c26
-rw-r--r--MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWrite.h45
-rw-r--r--MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf5
-rw-r--r--MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmm.inf3
-rw-r--r--MdeModulePkg/Universal/FaultTolerantWriteDxe/FtwMisc.c41
-rw-r--r--MdeModulePkg/Universal/FaultTolerantWriteDxe/UpdateWorkingBlock.c12
-rw-r--r--MdeModulePkg/Universal/FaultTolerantWritePei/FaultTolerantWritePei.c321
-rw-r--r--MdeModulePkg/Universal/FaultTolerantWritePei/FaultTolerantWritePei.inf61
-rw-r--r--MdeModulePkg/Universal/HiiDatabaseDxe/ConfigRouting.c2285
-rw-r--r--MdeModulePkg/Universal/HiiDatabaseDxe/Database.c19
-rw-r--r--MdeModulePkg/Universal/HiiDatabaseDxe/Font.c17
-rw-r--r--MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabase.h83
-rw-r--r--MdeModulePkg/Universal/HiiDatabaseDxe/String.c22
-rw-r--r--MdeModulePkg/Universal/Network/IScsiDxe/IScsiProto.c2
-rw-r--r--MdeModulePkg/Universal/Network/SnpDxe/Snp.c7
-rw-r--r--MdeModulePkg/Universal/PlatformDriOverrideDxe/InternalPlatDriOverrideDxe.h3
-rw-r--r--MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatDriOverrideDxe.c44
-rw-r--r--MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatformDriOverrideDxe.inf3
-rw-r--r--MdeModulePkg/Universal/SetupBrowserDxe/Expression.c8
-rw-r--r--MdeModulePkg/Universal/SetupBrowserDxe/Expression.h265
-rw-r--r--MdeModulePkg/Universal/SetupBrowserDxe/IfrParse.c103
-rw-r--r--MdeModulePkg/Universal/SetupBrowserDxe/Presentation.c2464
-rw-r--r--MdeModulePkg/Universal/SetupBrowserDxe/Print.c272
-rw-r--r--MdeModulePkg/Universal/SetupBrowserDxe/ProcessOptions.c1075
-rw-r--r--MdeModulePkg/Universal/SetupBrowserDxe/Setup.c2316
-rw-r--r--MdeModulePkg/Universal/SetupBrowserDxe/Setup.h829
-rw-r--r--MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf26
-rw-r--r--MdeModulePkg/Universal/SetupBrowserDxe/Ui.c4027
-rw-r--r--MdeModulePkg/Universal/SetupBrowserDxe/Ui.h1067
-rw-r--r--MdeModulePkg/Universal/Variable/Pei/Variable.c449
-rw-r--r--MdeModulePkg/Universal/Variable/Pei/Variable.h14
-rw-r--r--MdeModulePkg/Universal/Variable/Pei/VariablePei.inf12
-rw-r--r--MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c376
-rw-r--r--MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.h10
-rw-r--r--MdeModulePkg/Universal/Variable/RuntimeDxe/VariableDxe.c31
-rw-r--r--MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf1
-rw-r--r--MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.c6
-rw-r--r--MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf1
133 files changed, 28954 insertions, 17367 deletions
diff --git a/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AhciMode.c b/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AhciMode.c
index 2001175fe..950b5da03 100644
--- a/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AhciMode.c
+++ b/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AhciMode.c
@@ -1,7 +1,7 @@
/** @file
The file for AHCI mode of ATA host controller.
- Copyright (c) 2010 - 2012, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2010 - 2013, Intel Corporation. All rights reserved.<BR>
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
@@ -1487,9 +1487,18 @@ AhciAtaSmartReturnStatusCheck (
);
if (EFI_ERROR (Status)) {
+ REPORT_STATUS_CODE (
+ EFI_ERROR_CODE | EFI_ERROR_MINOR,
+ (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_DISABLED)
+ );
return EFI_DEVICE_ERROR;
}
+ REPORT_STATUS_CODE (
+ EFI_PROGRESS_CODE,
+ (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_ENABLE)
+ );
+
FisBaseAddr = (UINTN)AhciRegisters->AhciRFis + Port * sizeof (EFI_AHCI_RECEIVED_FIS);
Value = *(UINT32 *) (FisBaseAddr + EFI_AHCI_D2H_FIS_OFFSET);
@@ -1503,12 +1512,19 @@ AhciAtaSmartReturnStatusCheck (
// The threshold exceeded condition is not detected by the device
//
DEBUG ((EFI_D_INFO, "The S.M.A.R.T threshold exceeded condition is not detected\n"));
-
+ REPORT_STATUS_CODE (
+ EFI_PROGRESS_CODE,
+ (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_UNDERTHRESHOLD)
+ );
} else if ((LBAMid == 0xf4) && (LBAHigh == 0x2c)) {
//
// The threshold exceeded condition is detected by the device
//
DEBUG ((EFI_D_INFO, "The S.M.A.R.T threshold exceeded condition is detected\n"));
+ REPORT_STATUS_CODE (
+ EFI_PROGRESS_CODE,
+ (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_OVERTHRESHOLD)
+ );
}
}
@@ -1549,11 +1565,21 @@ AhciAtaSmartSupport (
//
DEBUG ((EFI_D_INFO, "S.M.A.R.T feature is not supported at port [%d] PortMultiplier [%d]!\n",
Port, PortMultiplier));
+ REPORT_STATUS_CODE (
+ EFI_ERROR_CODE | EFI_ERROR_MINOR,
+ (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_NOTSUPPORTED)
+ );
} else {
//
// Check if the feature is enabled. If not, then enable S.M.A.R.T.
//
if ((IdentifyData->AtaData.command_set_feature_enb_85 & 0x0001) != 0x0001) {
+
+ REPORT_STATUS_CODE (
+ EFI_PROGRESS_CODE,
+ (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_DISABLE)
+ );
+
ZeroMem (&AtaCommandBlock, sizeof (EFI_ATA_COMMAND_BLOCK));
AtaCommandBlock.AtaCommand = ATA_CMD_SMART;
diff --git a/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/IdeMode.c b/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/IdeMode.c
index caffc1cde..b9d16140b 100644
--- a/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/IdeMode.c
+++ b/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/IdeMode.c
@@ -1,7 +1,7 @@
/** @file
Header file for AHCI mode of ATA host controller.
- Copyright (c) 2010 - 2012, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2010 - 2013, Intel Corporation. All rights reserved.<BR>
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
@@ -2296,9 +2296,18 @@ IdeAtaSmartReturnStatusCheck (
);
if (EFI_ERROR (Status)) {
+ REPORT_STATUS_CODE (
+ EFI_ERROR_CODE | EFI_ERROR_MINOR,
+ (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_DISABLED)
+ );
return EFI_DEVICE_ERROR;
}
+ REPORT_STATUS_CODE (
+ EFI_PROGRESS_CODE,
+ (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_ENABLE)
+ );
+
LBAMid = IdeReadPortB (Instance->PciIo, Instance->IdeRegisters[Channel].CylinderLsb);
LBAHigh = IdeReadPortB (Instance->PciIo, Instance->IdeRegisters[Channel].CylinderMsb);
@@ -2307,12 +2316,19 @@ IdeAtaSmartReturnStatusCheck (
// The threshold exceeded condition is not detected by the device
//
DEBUG ((EFI_D_INFO, "The S.M.A.R.T threshold exceeded condition is not detected\n"));
-
+ REPORT_STATUS_CODE (
+ EFI_PROGRESS_CODE,
+ (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_UNDERTHRESHOLD)
+ );
} else if ((LBAMid == 0xf4) && (LBAHigh == 0x2c)) {
//
// The threshold exceeded condition is detected by the device
//
DEBUG ((EFI_D_INFO, "The S.M.A.R.T threshold exceeded condition is detected\n"));
+ REPORT_STATUS_CODE (
+ EFI_PROGRESS_CODE,
+ (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_OVERTHRESHOLD)
+ );
}
return EFI_SUCCESS;
@@ -2350,12 +2366,21 @@ IdeAtaSmartSupport (
//
DEBUG ((EFI_D_INFO, "S.M.A.R.T feature is not supported at [%a] channel [%a] device!\n",
(Channel == 1) ? "secondary" : "primary", (Device == 1) ? "slave" : "master"));
+ REPORT_STATUS_CODE (
+ EFI_ERROR_CODE | EFI_ERROR_MINOR,
+ (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_NOTSUPPORTED)
+ );
} else {
//
// Check if the feature is enabled. If not, then enable S.M.A.R.T.
//
if ((IdentifyData->AtaData.command_set_feature_enb_85 & 0x0001) != 0x0001) {
+ REPORT_STATUS_CODE (
+ EFI_PROGRESS_CODE,
+ (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_DISABLE)
+ );
+
ZeroMem (&AtaCommandBlock, sizeof (EFI_ATA_COMMAND_BLOCK));
AtaCommandBlock.AtaCommand = ATA_CMD_SMART;
diff --git a/MdeModulePkg/Bus/Ata/AtaBusDxe/AtaPassThruExecute.c b/MdeModulePkg/Bus/Ata/AtaBusDxe/AtaPassThruExecute.c
index 2c79f46ed..b1bedd80e 100644
--- a/MdeModulePkg/Bus/Ata/AtaBusDxe/AtaPassThruExecute.c
+++ b/MdeModulePkg/Bus/Ata/AtaBusDxe/AtaPassThruExecute.c
@@ -10,7 +10,7 @@
for Security Protocol Specific layout. This implementation uses big endian for
Cylinder register.
- Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2009 - 2013, Intel Corporation. All rights reserved.<BR>
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
@@ -541,19 +541,21 @@ TransferAtaDevice (
//
// As AtaBus is used to manage ATA devices, we have to use the lowest transfer rate to
// calculate the possible maximum timeout value for each read/write operation.
+ // The timout value is rounded up to nearest integar and here an additional 30s is added
+ // to follow ATA spec in which it mentioned that the device may take up to 30s to respond
+ // commands in the Standby/Idle mode.
//
if (AtaDevice->UdmaValid) {
//
// Calculate the maximum timeout value for DMA read/write operation.
//
- Packet->Timeout = EFI_TIMER_PERIOD_SECONDS ((TransferLength * AtaDevice->BlockMedia.BlockSize) / 2100000 + 1);
+ Packet->Timeout = EFI_TIMER_PERIOD_SECONDS (DivU64x32 (MultU64x32 (TransferLength, AtaDevice->BlockMedia.BlockSize), 2100000) + 31);
} else {
//
// Calculate the maximum timeout value for PIO read/write operation
//
- Packet->Timeout = EFI_TIMER_PERIOD_SECONDS ((TransferLength * AtaDevice->BlockMedia.BlockSize) / 3300000 + 1);
+ Packet->Timeout = EFI_TIMER_PERIOD_SECONDS (DivU64x32 (MultU64x32 (TransferLength, AtaDevice->BlockMedia.BlockSize), 3300000) + 31);
}
-
return AtaDevicePassThru (AtaDevice, TaskPacket, Event);
}
diff --git a/MdeModulePkg/Bus/I2c/I2cDxe/I2cBus.c b/MdeModulePkg/Bus/I2c/I2cDxe/I2cBus.c
new file mode 100644
index 000000000..3da1474ed
--- /dev/null
+++ b/MdeModulePkg/Bus/I2c/I2cDxe/I2cBus.c
@@ -0,0 +1,1468 @@
+/** @file
+ This file implements I2C IO Protocol which enables the user to manipulate a single
+ I2C device independent of the host controller and I2C design.
+
+ Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>
+ 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 "I2cDxe.h"
+
+//
+// EFI_DRIVER_BINDING_PROTOCOL instance
+//
+EFI_DRIVER_BINDING_PROTOCOL gI2cBusDriverBinding = {
+ I2cBusDriverSupported,
+ I2cBusDriverStart,
+ I2cBusDriverStop,
+ 0x10,
+ NULL,
+ NULL
+};
+
+//
+// Template for I2C Bus Child Device.
+//
+I2C_DEVICE_CONTEXT gI2cDeviceContextTemplate = {
+ I2C_DEVICE_SIGNATURE,
+ NULL,
+ { // I2cIo Protocol
+ I2cBusQueueRequest, // QueueRequest
+ NULL, // DeviceGuid
+ 0, // DeviceIndex
+ 0, // HardwareRevision
+ NULL // I2cControllerCapabilities
+ },
+ NULL, // DevicePath
+ NULL, // I2cDevice
+ NULL, // I2cBusContext
+};
+
+//
+// Template for controller device path node.
+//
+CONTROLLER_DEVICE_PATH gControllerDevicePathTemplate = {
+ {
+ HARDWARE_DEVICE_PATH,
+ HW_CONTROLLER_DP,
+ {
+ (UINT8) (sizeof (CONTROLLER_DEVICE_PATH)),
+ (UINT8) ((sizeof (CONTROLLER_DEVICE_PATH)) >> 8)
+ }
+ },
+ 0
+};
+
+//
+// Template for vendor device path node.
+//
+VENDOR_DEVICE_PATH gVendorDevicePathTemplate = {
+ {
+ HARDWARE_DEVICE_PATH,
+ HW_VENDOR_DP,
+ {
+ (UINT8) (sizeof (VENDOR_DEVICE_PATH)),
+ (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)
+ }
+ },
+ { 0x0, 0x0, 0x0, { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }}
+};
+
+//
+// Driver name table
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mI2cBusDriverNameTable[] = {
+ { "eng;en", (CHAR16 *) L"I2C Bus Driver" },
+ { NULL , NULL }
+};
+
+//
+// EFI Component Name Protocol
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gI2cBusComponentName = {
+ (EFI_COMPONENT_NAME_GET_DRIVER_NAME) I2cBusComponentNameGetDriverName,
+ (EFI_COMPONENT_NAME_GET_CONTROLLER_NAME) I2cBusComponentNameGetControllerName,
+ "eng"
+};
+
+//
+// EFI Component Name 2 Protocol
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gI2cBusComponentName2 = {
+ I2cBusComponentNameGetDriverName,
+ I2cBusComponentNameGetControllerName,
+ "en"
+};
+
+/**
+ Retrieves a Unicode string that is the user readable name of the driver.
+
+ This function retrieves the user readable name of a driver in the form of a
+ Unicode string. If the driver specified by This has a user readable name in
+ the language specified by Language, then a pointer to the driver name is
+ returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
+ by This does not support the language specified by Language,
+ then EFI_UNSUPPORTED is returned.
+
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param Language[in] A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified
+ in RFC 4646 or ISO 639-2 language code format.
+
+ @param DriverName[out] A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ driver specified by This in the language
+ specified by Language.
+
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by
+ This and the language specified by Language was
+ returned in DriverName.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER DriverName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+I2cBusComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME2_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ )
+{
+ return LookupUnicodeString2 (
+ Language,
+ This->SupportedLanguages,
+ mI2cBusDriverNameTable,
+ DriverName,
+ (BOOLEAN)(This != &gI2cBusComponentName2)
+ );
+}
+
+/**
+ Retrieves a Unicode string that is the user readable name of the controller
+ that is being managed by a driver.
+
+ This function retrieves the user readable name of the controller specified by
+ ControllerHandle and ChildHandle in the form of a Unicode string. If the
+ driver specified by This has a user readable name in the language specified by
+ Language, then a pointer to the controller name is returned in ControllerName,
+ and EFI_SUCCESS is returned. If the driver specified by This is not currently
+ managing the controller specified by ControllerHandle and ChildHandle,
+ then EFI_UNSUPPORTED is returned. If the driver specified by This does not
+ support the language specified by Language, then EFI_UNSUPPORTED is returned.
+
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param ControllerHandle[in] The handle of a controller that the driver
+ specified by This is managing. This handle
+ specifies the controller whose name is to be
+ returned.
+
+ @param ChildHandle[in] The handle of the child controller to retrieve
+ the name of. This is an optional parameter that
+ may be NULL. It will be NULL for device
+ drivers. It will also be NULL for a bus drivers
+ that wish to retrieve the name of the bus
+ controller. It will not be NULL for a bus
+ driver that wishes to retrieve the name of a
+ child controller.
+
+ @param Language[in] A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified in
+ RFC 4646 or ISO 639-2 language code format.
+
+ @param ControllerName[out] A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ controller specified by ControllerHandle and
+ ChildHandle in the language specified by
+ Language from the point of view of the driver
+ specified by This.
+
+ @retval EFI_SUCCESS The Unicode string for the user readable name in
+ the language specified by Language for the
+ driver specified by This was returned in
+ DriverName.
+
+ @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
+
+ @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
+ EFI_HANDLE.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This is not currently
+ managing the controller specified by
+ ControllerHandle and ChildHandle.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+I2cBusComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME2_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ Check if the child of I2C controller has been created.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] Controller I2C controller handle.
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path.
+ @param[in] RemainingHasControllerNode Indicate if RemainingDevicePath contains CONTROLLER_DEVICE_PATH.
+ @param[in] RemainingControllerNumber Controller number in CONTROLLER_DEVICE_PATH.
+
+ @retval EFI_SUCCESS The child of I2C controller is not created.
+ @retval Others The child of I2C controller has been created or other errors happen.
+
+**/
+EFI_STATUS
+CheckRemainingDevicePath (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath,
+ IN BOOLEAN RemainingHasControllerNode,
+ IN UINT32 RemainingControllerNumber
+ )
+{
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_PROTOCOL *SystemDevicePath;
+ EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer;
+ UINTN EntryCount;
+ UINTN Index;
+ BOOLEAN SystemHasControllerNode;
+ UINT32 SystemControllerNumber;
+
+ SystemHasControllerNode = FALSE;
+ SystemControllerNumber = 0;
+
+ Status = gBS->OpenProtocolInformation (
+ Controller,
+ &gEfiI2cHostProtocolGuid,
+ &OpenInfoBuffer,
+ &EntryCount
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ for (Index = 0; Index < EntryCount; Index++) {
+ if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {
+ Status = gBS->OpenProtocol (
+ OpenInfoBuffer[Index].ControllerHandle,
+ &gEfiDevicePathProtocolGuid,
+ (VOID **) &SystemDevicePath,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (!EFI_ERROR (Status)) {
+ //
+ // Find vendor device path node and compare
+ //
+ while (!IsDevicePathEnd (SystemDevicePath)) {
+ if ((DevicePathType (SystemDevicePath) == HARDWARE_DEVICE_PATH) &&
+ (DevicePathSubType (SystemDevicePath) == HW_VENDOR_DP)) {
+ //
+ // Check if vendor device path is same between system device path and remaining device path
+ //
+ if (CompareMem (SystemDevicePath, RemainingDevicePath, sizeof (VENDOR_DEVICE_PATH)) == 0) {
+ //
+ // Get controller node appended after vendor node
+ //
+ SystemDevicePath = NextDevicePathNode (SystemDevicePath);
+ if ((DevicePathType (SystemDevicePath) == HARDWARE_DEVICE_PATH) &&
+ (DevicePathSubType (SystemDevicePath) == HW_CONTROLLER_DP)) {
+ SystemHasControllerNode = TRUE;
+ SystemControllerNumber = ((CONTROLLER_DEVICE_PATH *) SystemDevicePath)->ControllerNumber;
+ } else {
+ SystemHasControllerNode = FALSE;
+ SystemControllerNumber = 0;
+ }
+ if (((SystemHasControllerNode) && (!RemainingHasControllerNode) && (SystemControllerNumber == 0)) ||
+ ((!SystemHasControllerNode) && (RemainingHasControllerNode) && (RemainingControllerNumber == 0)) ||
+ ((SystemHasControllerNode) && (RemainingHasControllerNode) && (SystemControllerNumber == RemainingControllerNumber)) ||
+ ((!SystemHasControllerNode) && (!RemainingHasControllerNode))) {
+ DEBUG ((EFI_D_ERROR, "This I2C device has been already started.\n"));
+ Status = EFI_UNSUPPORTED;
+ break;
+ }
+ }
+ }
+ SystemDevicePath = NextDevicePathNode (SystemDevicePath);
+ }
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+ }
+ }
+ }
+ FreePool (OpenInfoBuffer);
+ return Status;
+}
+
+/**
+ Tests to see if this driver supports a given controller. If a child device is provided,
+ it further tests to see if this driver supports creating a handle for the specified child device.
+
+ This function checks to see if the driver specified by This supports the device specified by
+ ControllerHandle. Drivers will typically use the device path attached to
+ ControllerHandle and/or the services from the bus I/O abstraction attached to
+ ControllerHandle to determine if the driver supports ControllerHandle. This function
+ may be called many times during platform initialization. In order to reduce boot times, the tests
+ performed by this function must be very small, and take as little time as possible to execute. This
+ function must not change the state of any hardware devices, and this function must be aware that the
+ device specified by ControllerHandle may already be managed by the same driver or a
+ different driver. This function must match its calls to AllocatePages() with FreePages(),
+ AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
+ Since ControllerHandle may have been previously started by the same driver, if a protocol is
+ already in the opened state, then it must not be closed with CloseProtocol(). This is required
+ to guarantee the state of ControllerHandle is not modified by this function.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of the controller to test. This handle
+ must support a protocol interface that supplies
+ an I/O abstraction to the driver.
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
+ parameter is ignored by device drivers, and is optional for bus
+ drivers. For bus drivers, if this parameter is not NULL, then
+ the bus driver must determine if the bus controller specified
+ by ControllerHandle and the child controller specified
+ by RemainingDevicePath are both supported by this
+ bus driver.
+
+ @retval EFI_SUCCESS The device specified by ControllerHandle and
+ RemainingDevicePath is supported by the driver specified by This.
+ @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
+ RemainingDevicePath is already being managed by the driver
+ specified by This.
+ @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
+ RemainingDevicePath is already being managed by a different
+ driver or an application that requires exclusive access.
+ Currently not implemented.
+ @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
+ RemainingDevicePath is not supported by the driver specified by This.
+**/
+EFI_STATUS
+EFIAPI
+I2cBusDriverSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+{
+ EFI_STATUS Status;
+ EFI_I2C_ENUMERATE_PROTOCOL *I2cEnumerate;
+ EFI_I2C_HOST_PROTOCOL *I2cHost;
+ EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *DevPathNode;
+ BOOLEAN RemainingHasControllerNode;
+ UINT32 RemainingControllerNumber;
+
+ RemainingHasControllerNode = FALSE;
+ RemainingControllerNumber = 0;
+
+ //
+ // Determine if the I2c Enumerate Protocol is available
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiI2cEnumerateProtocolGuid,
+ (VOID **) &I2cEnumerate,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if ((EFI_ERROR (Status)) && (Status != EFI_ALREADY_STARTED)) {
+ return Status;
+ }
+
+ if (!EFI_ERROR (Status)) {
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiI2cEnumerateProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ }
+
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ (VOID **) &ParentDevicePath,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+
+ if ((EFI_ERROR (Status)) && (Status != EFI_ALREADY_STARTED)) {
+ return Status;
+ }
+
+ if (!EFI_ERROR (Status)) {
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ }
+
+ if ((RemainingDevicePath != NULL) && !IsDevicePathEnd (RemainingDevicePath)) {
+ //
+ // Check if the first node of RemainingDevicePath is a hardware vendor device path
+ //
+ if ((DevicePathType (RemainingDevicePath) != HARDWARE_DEVICE_PATH) ||
+ (DevicePathSubType (RemainingDevicePath) != HW_VENDOR_DP)) {
+ return EFI_UNSUPPORTED;
+ }
+ //
+ // Check if the second node of RemainingDevicePath is a controller node
+ //
+ DevPathNode = NextDevicePathNode (RemainingDevicePath);
+ if (!IsDevicePathEnd (DevPathNode)) {
+ if ((DevicePathType (DevPathNode) != HARDWARE_DEVICE_PATH) ||
+ (DevicePathSubType (DevPathNode) != HW_CONTROLLER_DP)) {
+ return EFI_UNSUPPORTED;
+ } else {
+ RemainingHasControllerNode = TRUE;
+ RemainingControllerNumber = ((CONTROLLER_DEVICE_PATH *) DevPathNode)->ControllerNumber;
+ }
+ }
+ }
+
+ //
+ // Determine if the I2C Host Protocol is available
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiI2cHostProtocolGuid,
+ (VOID **) &I2cHost,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+
+ if (!EFI_ERROR (Status)) {
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiI2cHostProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ }
+
+
+ if (Status == EFI_ALREADY_STARTED) {
+ if ((RemainingDevicePath == NULL) ||
+ ((RemainingDevicePath != NULL) && IsDevicePathEnd (RemainingDevicePath))) {
+ //
+ // If RemainingDevicePath is NULL or is the End of Device Path Node, return EFI_SUCCESS.
+ //
+ Status = EFI_SUCCESS;
+ } else {
+ //
+ // Test if the child with the RemainingDevicePath has already been created.
+ //
+ Status = CheckRemainingDevicePath (
+ This,
+ Controller,
+ RemainingDevicePath,
+ RemainingHasControllerNode,
+ RemainingControllerNumber
+ );
+ }
+ }
+
+ return Status;
+}
+
+/**
+ Starts a device controller or a bus controller.
+
+ The Start() function is designed to be invoked from the EFI boot service ConnectController().
+ As a result, much of the error checking on the parameters to Start() has been moved into this
+ common boot service. It is legal to call Start() from other locations,
+ but the following calling restrictions must be followed or the system behavior will not be deterministic.
+ 1. ControllerHandle must be a valid EFI_HANDLE.
+ 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
+ EFI_DEVICE_PATH_PROTOCOL.
+ 3. Prior to calling Start(), the Supported() function for the driver specified by This must
+ have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of the controller to start. This handle
+ must support a protocol interface that supplies
+ an I/O abstraction to the driver.
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
+ parameter is ignored by device drivers, and is optional for bus
+ drivers. For a bus driver, if this parameter is NULL, then handles
+ for all the children of Controller are created by this driver.
+ If this parameter is not NULL and the first Device Path Node is
+ not the End of Device Path Node, then only the handle for the
+ child device specified by the first Device Path Node of
+ RemainingDevicePath is created by this driver.
+ If the first Device Path Node of RemainingDevicePath is
+ the End of Device Path Node, no child handle is created by this
+ driver.
+
+ @retval EFI_SUCCESS The device was started.
+ @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ @retval Others The driver failded to start the device.
+
+**/
+EFI_STATUS
+EFIAPI
+I2cBusDriverStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+{
+ EFI_I2C_ENUMERATE_PROTOCOL *I2cEnumerate;
+ EFI_I2C_HOST_PROTOCOL *I2cHost;
+ I2C_BUS_CONTEXT *I2cBusContext;
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
+
+ I2cBusContext = NULL;
+ ParentDevicePath = NULL;
+ I2cEnumerate = NULL;
+ I2cHost = NULL;
+
+ //
+ // Determine if the I2C controller is available
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiI2cHostProtocolGuid,
+ (VOID**)&I2cHost,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {
+ DEBUG ((EFI_D_ERROR, "I2cBus: open I2C host error, Status = %r\n", Status));
+ return Status;
+ }
+
+ if (Status == EFI_ALREADY_STARTED) {
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiCallerIdGuid,
+ (VOID **) &I2cBusContext,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "I2cBus: open private protocol error, Status = %r.\n", Status));
+ return Status;
+ }
+ }
+
+ //
+ // Get the I2C bus enumeration API
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiI2cEnumerateProtocolGuid,
+ (VOID**)&I2cEnumerate,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {
+ DEBUG ((EFI_D_ERROR, "I2cBus: open I2C enumerate error, Status = %r\n", Status));
+ goto Error;
+ }
+
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ (VOID **) &ParentDevicePath,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {
+ DEBUG ((EFI_D_ERROR, "I2cBus: open device path error, Status = %r\n", Status));
+ goto Error;
+ }
+
+ if ((RemainingDevicePath != NULL) && IsDevicePathEnd (RemainingDevicePath)) {
+ //
+ // If RemainingDevicePath is the End of Device Path Node,
+ // don't create any child device and return EFI_SUCESS
+ //
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Allocate the buffer for I2C_BUS_CONTEXT if it is not allocated before.
+ //
+ if (I2cBusContext == NULL) {
+ //
+ // Allocate the I2C context structure for the current I2C controller
+ //
+ I2cBusContext = AllocateZeroPool (sizeof (I2C_BUS_CONTEXT));
+ if (I2cBusContext == NULL) {
+ DEBUG ((EFI_D_ERROR, "I2cBus: there is no enough memory to allocate.\n"));
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Error;
+ }
+
+ /*
+ +----------------+
+ .->| I2C_BUS_CONTEXT|<----- This file Protocol (gEfiCallerIdGuid) installed on I2C Controller handle
+ | +----------------+
+ |
+ | +----------------------------+
+ | | I2C_DEVICE_CONTEXT |
+ `--| |
+ | |
+ | I2C IO Protocol Structure | <----- I2C IO Protocol
+ | |
+ +----------------------------+
+
+ */
+ I2cBusContext->I2cHost = I2cHost;
+ I2cBusContext->I2cEnumerate = I2cEnumerate;
+ //
+ // Parent controller used to create children
+ //
+ I2cBusContext->Controller = Controller;
+ //
+ // Parent controller device path used to create children device path
+ //
+ I2cBusContext->ParentDevicePath = ParentDevicePath;
+
+ I2cBusContext->DriverBindingHandle = This->DriverBindingHandle;
+
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &Controller,
+ &gEfiCallerIdGuid,
+ I2cBusContext,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "I2cBus: install private protocol error, Status = %r.\n", Status));
+ goto Error;
+ }
+ }
+
+ //
+ // Start the driver
+ //
+ Status = RegisterI2cDevice (I2cBusContext, Controller, RemainingDevicePath);
+
+ return Status;
+
+Error:
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "I2cBus: Start() function failed, Status = %r\n", Status));
+ if (ParentDevicePath != NULL) {
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ }
+
+ if (I2cHost != NULL) {
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiI2cHostProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ }
+
+ if (I2cEnumerate != NULL) {
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiI2cEnumerateProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ }
+
+ if (I2cBusContext != NULL) {
+ Status = gBS->UninstallMultipleProtocolInterfaces (
+ &Controller,
+ gEfiCallerIdGuid,
+ I2cBusContext,
+ NULL
+ );
+ FreePool (I2cBusContext);
+ }
+ }
+
+ //
+ // Return the operation status.
+ //
+ return Status;
+}
+
+
+/**
+ Stops a device controller or a bus controller.
+
+ The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
+ As a result, much of the error checking on the parameters to Stop() has been moved
+ into this common boot service. It is legal to call Stop() from other locations,
+ but the following calling restrictions must be followed or the system behavior will not be deterministic.
+ 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
+ same driver's Start() function.
+ 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
+ EFI_HANDLE. In addition, all of these handles must have been created in this driver's
+ Start() function, and the Start() function must have called OpenProtocol() on
+ ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle A handle to the device being stopped. The handle must
+ support a bus specific I/O protocol for the driver
+ to use to stop the device.
+ @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
+ @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
+ if NumberOfChildren is 0.
+
+ @retval EFI_SUCCESS The device was stopped.
+ @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
+
+**/
+EFI_STATUS
+EFIAPI
+I2cBusDriverStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ )
+{
+ I2C_BUS_CONTEXT *I2cBusContext;
+ EFI_STATUS Status;
+ BOOLEAN AllChildrenStopped;
+ UINTN Index;
+
+ if (NumberOfChildren == 0) {
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiI2cHostProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiI2cEnumerateProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiCallerIdGuid,
+ (VOID **) &I2cBusContext,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (!EFI_ERROR (Status)) {
+ gBS->UninstallMultipleProtocolInterfaces (
+ Controller,
+ &gEfiCallerIdGuid,
+ I2cBusContext,
+ NULL
+ );
+ //
+ // No more child now, free bus context data.
+ //
+ FreePool (I2cBusContext);
+ }
+ return Status;
+ }
+
+ AllChildrenStopped = TRUE;
+
+ for (Index = 0; Index < NumberOfChildren; Index++) {
+
+ Status = UnRegisterI2cDevice (This, Controller, ChildHandleBuffer[Index]);
+ if (EFI_ERROR (Status)) {
+ AllChildrenStopped = FALSE;
+ }
+ }
+
+ if (!AllChildrenStopped) {
+ return EFI_DEVICE_ERROR;
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ Enumerate the I2C bus
+
+ This routine walks the platform specific data describing the
+ I2C bus to create the I2C devices where driver GUIDs were
+ specified.
+
+ @param[in] I2cBusContext Address of an I2C_BUS_CONTEXT structure
+ @param[in] Controller Handle to the controller
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path.
+
+ @retval EFI_SUCCESS The bus is successfully configured
+
+**/
+EFI_STATUS
+RegisterI2cDevice (
+ IN I2C_BUS_CONTEXT *I2cBusContext,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+{
+ I2C_DEVICE_CONTEXT *I2cDeviceContext;
+ EFI_STATUS Status;
+ CONST EFI_I2C_DEVICE *Device;
+ CONST EFI_I2C_DEVICE *TempDevice;
+ UINT32 RemainingPathDeviceIndex;
+ EFI_DEVICE_PATH_PROTOCOL *DevPathNode;
+ BOOLEAN BuildControllerNode;
+ UINTN Count;
+
+ Status = EFI_SUCCESS;
+ BuildControllerNode = TRUE;
+
+ //
+ // Default DeviceIndex
+ //
+ RemainingPathDeviceIndex = 0;
+
+ //
+ // Determine the controller number in Controller Node Device Path when RemainingDevicePath is not NULL.
+ //
+ if (RemainingDevicePath != NULL) {
+ //
+ // Check if there is a controller node appended after vendor node
+ //
+ DevPathNode = NextDevicePathNode (RemainingDevicePath);
+ if ((DevicePathType (DevPathNode) == HARDWARE_DEVICE_PATH) &&
+ (DevicePathSubType(DevPathNode) == HW_CONTROLLER_DP)) {
+ //
+ // RemainingDevicePath != NULL and RemainingDevicePath contains Controller Node,
+ // add Controller Node to Device Path on child handle.
+ //
+ RemainingPathDeviceIndex = ((CONTROLLER_DEVICE_PATH *) DevPathNode)->ControllerNumber;
+ } else {
+ //
+ // RemainingDevicePath != NULL and RemainingDevicePath does not contain Controller Node,
+ // do not add controller node to Device Path on child handle.
+ //
+ BuildControllerNode = FALSE;
+ }
+ }
+
+ //
+ // Walk the list of I2C devices on this bus
+ //
+ Device = NULL;
+ while (TRUE) {
+ //
+ // Get the next I2C device
+ //
+ Status = I2cBusContext->I2cEnumerate->Enumerate (I2cBusContext->I2cEnumerate, &Device);
+ if (EFI_ERROR (Status) || Device == NULL) {
+ if (RemainingDevicePath != NULL) {
+ Status = EFI_NOT_FOUND;
+ } else {
+ Status = EFI_SUCCESS;
+ }
+ break;
+ }
+
+ //
+ // Determine if the device info is valid
+ //
+ if ((Device->DeviceGuid == NULL) || (Device->SlaveAddressCount == 0) || (Device->SlaveAddressArray == NULL)) {
+ DEBUG ((EFI_D_ERROR, "Invalid EFI_I2C_DEVICE reported by I2c Enumerate protocol.\n"));
+ continue;
+ }
+
+ if (RemainingDevicePath == NULL) {
+ if (Device->DeviceIndex == 0) {
+ //
+ // Determine if the controller node is necessary when controller number is zero in I2C device
+ //
+ TempDevice = NULL;
+ Count = 0;
+ while (TRUE) {
+ //
+ // Get the next I2C device
+ //
+ Status = I2cBusContext->I2cEnumerate->Enumerate (I2cBusContext->I2cEnumerate, &TempDevice);
+ if (EFI_ERROR (Status) || TempDevice == NULL) {
+ Status = EFI_SUCCESS;
+ break;
+ }
+ if (CompareGuid (Device->DeviceGuid, TempDevice->DeviceGuid)) {
+ Count++;
+ }
+ }
+ if (Count == 1) {
+ //
+ // RemainingDevicePath == NULL and only DeviceIndex 0 is present on the I2C bus,
+ // do not add Controller Node to Device Path on child handle.
+ //
+ BuildControllerNode = FALSE;
+ }
+ }
+ } else {
+ //
+ // Find I2C device reported in Remaining Device Path
+ //
+ if ((!CompareGuid (&((VENDOR_DEVICE_PATH *)RemainingDevicePath)->Guid, Device->DeviceGuid)) ||
+ (RemainingPathDeviceIndex != Device->DeviceIndex)) {
+ continue;
+ }
+ }
+
+ //
+ // Build the device context for current I2C device.
+ //
+ I2cDeviceContext = NULL;
+ I2cDeviceContext = AllocateCopyPool (sizeof (I2C_DEVICE_CONTEXT), &gI2cDeviceContextTemplate);
+ ASSERT (I2cDeviceContext != NULL);
+ if (I2cDeviceContext == NULL) {
+ continue;
+ }
+
+ //
+ // Initialize the specific device context
+ //
+ I2cDeviceContext->I2cBusContext = I2cBusContext;
+ I2cDeviceContext->I2cDevice = Device;
+ I2cDeviceContext->I2cIo.DeviceGuid = Device->DeviceGuid;
+ I2cDeviceContext->I2cIo.DeviceIndex = Device->DeviceIndex;
+ I2cDeviceContext->I2cIo.HardwareRevision = Device->HardwareRevision;
+ I2cDeviceContext->I2cIo.I2cControllerCapabilities = I2cBusContext->I2cHost->I2cControllerCapabilities;
+
+ //
+ // Build the device path
+ //
+ Status = I2cBusDevicePathAppend (I2cDeviceContext, BuildControllerNode);
+ ASSERT_EFI_ERROR (Status);
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ //
+ // Install the protocol
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &I2cDeviceContext->Handle,
+ &gEfiI2cIoProtocolGuid,
+ &I2cDeviceContext->I2cIo,
+ &gEfiDevicePathProtocolGuid,
+ I2cDeviceContext->DevicePath,
+ NULL );
+ if (EFI_ERROR (Status)) {
+ //
+ // Free resources for this I2C device
+ //
+ ReleaseI2cDeviceContext (I2cDeviceContext);
+ continue;
+ }
+
+ //
+ // Create the child handle
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiI2cHostProtocolGuid,
+ (VOID **) &I2cBusContext->I2cHost,
+ I2cBusContext->DriverBindingHandle,
+ I2cDeviceContext->Handle,
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
+ );
+ if (EFI_ERROR (Status)) {
+ Status = gBS->UninstallMultipleProtocolInterfaces (
+ I2cDeviceContext->Handle,
+ &gEfiDevicePathProtocolGuid,
+ I2cDeviceContext->DevicePath,
+ &gEfiI2cIoProtocolGuid,
+ &I2cDeviceContext->I2cIo,
+ NULL
+ );
+ //
+ // Free resources for this I2C device
+ //
+ ReleaseI2cDeviceContext (I2cDeviceContext);
+ continue;
+ }
+
+ if (RemainingDevicePath != NULL) {
+ //
+ // Child has been created successfully
+ //
+ break;
+ }
+ }
+
+ return Status;
+}
+
+
+/**
+ Queue an I2C transaction for execution on the I2C device.
+
+ This routine must be called at or below TPL_NOTIFY. For synchronous
+ requests this routine must be called at or below TPL_CALLBACK.
+
+ This routine queues an I2C transaction to the I2C controller for
+ execution on the I2C bus.
+
+ When Event is NULL, QueueRequest() operates synchronously and returns
+ the I2C completion status as its return value.
+
+ When Event is not NULL, QueueRequest() synchronously returns EFI_SUCCESS
+ indicating that the asynchronous I2C transaction was queued. The values
+ above are returned in the buffer pointed to by I2cStatus upon the
+ completion of the I2C transaction when I2cStatus is not NULL.
+
+ The upper layer driver writer provides the following to the platform
+ vendor:
+
+ 1. Vendor specific GUID for the I2C part
+ 2. Guidance on proper construction of the slave address array when the
+ I2C device uses more than one slave address. The I2C bus protocol
+ uses the SlaveAddressIndex to perform relative to physical address
+ translation to access the blocks of hardware within the I2C device.
+
+ @param[in] This Pointer to an EFI_I2C_IO_PROTOCOL structure.
+ @param[in] SlaveAddressIndex Index value into an array of slave addresses
+ for the I2C device. The values in the array
+ are specified by the board designer, with the
+ third party I2C device driver writer providing
+ the slave address order.
+
+ For devices that have a single slave address,
+ this value must be zero. If the I2C device
+ uses more than one slave address then the
+ third party (upper level) I2C driver writer
+ needs to specify the order of entries in the
+ slave address array.
+
+ \ref ThirdPartyI2cDrivers "Third Party I2C
+ Drivers" section in I2cMaster.h.
+ @param[in] Event Event to signal for asynchronous transactions,
+ NULL for synchronous transactions
+ @param[in] RequestPacket Pointer to an EFI_I2C_REQUEST_PACKET structure
+ describing the I2C transaction
+ @param[out] I2cStatus Optional buffer to receive the I2C transaction
+ completion status
+
+ @retval EFI_SUCCESS The asynchronous transaction was successfully
+ queued when Event is not NULL.
+ @retval EFI_SUCCESS The transaction completed successfully when
+ Event is NULL.
+ @retval EFI_ABORTED The request did not complete because the driver
+ binding Stop() routine was called.
+ @retval EFI_BAD_BUFFER_SIZE The RequestPacket->LengthInBytes value is too
+ large.
+ @retval EFI_DEVICE_ERROR There was an I2C error (NACK) during the
+ transaction.
+ @retval EFI_INVALID_PARAMETER RequestPacket is NULL
+ @retval EFI_NOT_FOUND Reserved bit set in the SlaveAddress parameter
+ @retval EFI_NO_MAPPING The EFI_I2C_HOST_PROTOCOL could not set the
+ bus configuration required to access this I2C
+ device.
+ @retval EFI_NO_RESPONSE The I2C device is not responding to the slave
+ address selected by SlaveAddressIndex.
+ EFI_DEVICE_ERROR will be returned if the
+ controller cannot distinguish when the NACK
+ occurred.
+ @retval EFI_OUT_OF_RESOURCES Insufficient memory for I2C transaction
+ @retval EFI_UNSUPPORTED The controller does not support the requested
+ transaction.
+
+**/
+EFI_STATUS
+EFIAPI
+I2cBusQueueRequest (
+ IN CONST EFI_I2C_IO_PROTOCOL *This,
+ IN UINTN SlaveAddressIndex,
+ IN EFI_EVENT Event OPTIONAL,
+ IN EFI_I2C_REQUEST_PACKET *RequestPacket,
+ OUT EFI_STATUS *I2cStatus OPTIONAL
+ )
+{
+ CONST EFI_I2C_DEVICE *I2cDevice;
+ I2C_BUS_CONTEXT *I2cBusContext;
+ CONST EFI_I2C_HOST_PROTOCOL *I2cHost;
+ I2C_DEVICE_CONTEXT *I2cDeviceContext;
+ EFI_STATUS Status;
+
+ if (RequestPacket == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Validate the I2C slave index
+ //
+ I2cDeviceContext = I2C_DEVICE_CONTEXT_FROM_PROTOCOL (This);
+ I2cDevice = I2cDeviceContext->I2cDevice;
+ if ( SlaveAddressIndex >= I2cDevice->SlaveAddressCount ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Locate the I2c Host Protocol to queue request
+ //
+ I2cBusContext = I2cDeviceContext->I2cBusContext;
+ I2cHost = I2cBusContext->I2cHost;
+
+ //
+ // Start the I2C operation
+ //
+ Status = I2cHost->QueueRequest (
+ I2cHost,
+ I2cDevice->I2cBusConfiguration,
+ I2cDevice->SlaveAddressArray [SlaveAddressIndex],
+ Event,
+ RequestPacket,
+ I2cStatus
+ );
+
+ return Status;
+}
+
+/**
+ Release all the resources allocated for the I2C device.
+
+ This function releases all the resources allocated for the I2C device.
+
+ @param I2cDeviceContext The I2C child device involved for the operation.
+
+**/
+VOID
+ReleaseI2cDeviceContext (
+ IN I2C_DEVICE_CONTEXT *I2cDeviceContext
+ )
+{
+ if (I2cDeviceContext == NULL) {
+ return;
+ }
+
+ if (I2cDeviceContext->DevicePath != NULL) {
+ FreePool (I2cDeviceContext->DevicePath);
+ }
+
+ FreePool (I2cDeviceContext);
+}
+
+/**
+ Unregister an I2C device.
+
+ This function removes the protocols installed on the controller handle and
+ frees the resources allocated for the I2C device.
+
+ @param This The pointer to EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param Controller The controller handle of the I2C device.
+ @param Handle The child handle.
+
+ @retval EFI_SUCCESS The I2C device is successfully unregistered.
+ @return Others Some error occurs when unregistering the I2C device.
+
+**/
+EFI_STATUS
+UnRegisterI2cDevice (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_HANDLE Handle
+ )
+{
+ EFI_STATUS Status;
+ I2C_DEVICE_CONTEXT *I2cDeviceContext;
+ EFI_I2C_IO_PROTOCOL *I2cIo;
+ EFI_I2C_HOST_PROTOCOL *I2cHost;
+
+ I2cIo = NULL;
+
+ Status = gBS->OpenProtocol (
+ Handle,
+ &gEfiI2cIoProtocolGuid,
+ (VOID **) &I2cIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Get I2c device context data.
+ //
+ I2cDeviceContext = I2C_DEVICE_CONTEXT_FROM_PROTOCOL (I2cIo);
+
+ //
+ // Close the child handle
+ //
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiI2cHostProtocolGuid,
+ This->DriverBindingHandle,
+ Handle
+ );
+
+ //
+ // The I2C Bus driver installs the I2C Io and Device Path Protocol in the DriverBindingStart().
+ // Here should uninstall them.
+ //
+ Status = gBS->UninstallMultipleProtocolInterfaces (
+ Handle,
+ &gEfiDevicePathProtocolGuid,
+ I2cDeviceContext->DevicePath,
+ &gEfiI2cIoProtocolGuid,
+ &I2cDeviceContext->I2cIo,
+ NULL
+ );
+
+ if (EFI_ERROR (Status)) {
+ //
+ // Keep parent and child relationship
+ //
+ gBS->OpenProtocol (
+ Controller,
+ &gEfiI2cHostProtocolGuid,
+ (VOID **) &I2cHost,
+ This->DriverBindingHandle,
+ Handle,
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
+ );
+ return Status;
+ }
+
+ //
+ // Free resources for this I2C device
+ //
+ ReleaseI2cDeviceContext (I2cDeviceContext);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Create a path for the I2C device
+
+ Append the I2C slave path to the I2C master controller path.
+
+ @param[in] I2cDeviceContext Address of an I2C_DEVICE_CONTEXT structure.
+ @param[in] BuildControllerNode Flag to build controller node in device path.
+
+ @retval EFI_SUCCESS The I2C device path is built successfully.
+ @return Others It is failed to built device path.
+
+**/
+EFI_STATUS
+I2cBusDevicePathAppend (
+ IN I2C_DEVICE_CONTEXT *I2cDeviceContext,
+ IN BOOLEAN BuildControllerNode
+ )
+{
+ EFI_DEVICE_PATH_PROTOCOL *PreviousDevicePath;
+
+ PreviousDevicePath = NULL;
+
+ //
+ // Build vendor device path
+ //
+ CopyMem (&gVendorDevicePathTemplate.Guid, I2cDeviceContext->I2cDevice->DeviceGuid, sizeof (EFI_GUID));
+ I2cDeviceContext->DevicePath = AppendDevicePathNode (
+ I2cDeviceContext->I2cBusContext->ParentDevicePath,
+ (EFI_DEVICE_PATH_PROTOCOL *) &gVendorDevicePathTemplate
+ );
+ ASSERT (I2cDeviceContext->DevicePath != NULL);
+ if (I2cDeviceContext->DevicePath == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ if ((BuildControllerNode) && (I2cDeviceContext->DevicePath != NULL)) {
+ //
+ // Build the final I2C device path with controller node
+ //
+ PreviousDevicePath = I2cDeviceContext->DevicePath;
+ gControllerDevicePathTemplate.ControllerNumber = I2cDeviceContext->I2cDevice->DeviceIndex;
+ I2cDeviceContext->DevicePath = AppendDevicePathNode (
+ I2cDeviceContext->DevicePath,
+ (EFI_DEVICE_PATH_PROTOCOL *) &gControllerDevicePathTemplate
+ );
+ gBS->FreePool (PreviousDevicePath);
+ ASSERT (I2cDeviceContext->DevicePath != NULL);
+ if (I2cDeviceContext->DevicePath == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ The user entry point for the I2C bus module. The user code starts with
+ this function.
+
+ @param[in] ImageHandle The firmware allocated handle for the EFI image.
+ @param[in] SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The entry point is executed successfully.
+ @retval other Some error occurs when executing this entry point.
+
+**/
+EFI_STATUS
+EFIAPI
+InitializeI2cBus(
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Install driver model protocol(s).
+ //
+ Status = EfiLibInstallDriverBindingComponentName2 (
+ ImageHandle,
+ SystemTable,
+ &gI2cBusDriverBinding,
+ NULL,
+ &gI2cBusComponentName,
+ &gI2cBusComponentName2
+ );
+ ASSERT_EFI_ERROR (Status);
+
+
+ return Status;
+}
+
+/**
+ This is the unload handle for I2C bus module.
+
+ Disconnect the driver specified by ImageHandle from all the devices in the handle database.
+ Uninstall all the protocols installed in the driver entry point.
+
+ @param[in] ImageHandle The drivers' driver image.
+
+ @retval EFI_SUCCESS The image is unloaded.
+ @retval Others Failed to unload the image.
+
+**/
+EFI_STATUS
+EFIAPI
+I2cBusUnload (
+ IN EFI_HANDLE ImageHandle
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE *DeviceHandleBuffer;
+ UINTN DeviceHandleCount;
+ UINTN Index;
+
+ //
+ // Get the list of all I2C Controller handles in the handle database.
+ // If there is an error getting the list, then the unload
+ // operation fails.
+ //
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiI2cHostProtocolGuid,
+ NULL,
+ &DeviceHandleCount,
+ &DeviceHandleBuffer
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Disconnect the driver specified by Driver BindingHandle from all
+ // the devices in the handle database.
+ //
+ for (Index = 0; Index < DeviceHandleCount; Index++) {
+ Status = gBS->DisconnectController (
+ DeviceHandleBuffer[Index],
+ gI2cBusDriverBinding.DriverBindingHandle,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+ }
+
+ //
+ // Uninstall all the protocols installed in the driver entry point
+ //
+ Status = gBS->UninstallMultipleProtocolInterfaces (
+ gI2cBusDriverBinding.DriverBindingHandle,
+ &gEfiDriverBindingProtocolGuid,
+ &gI2cBusDriverBinding,
+ &gEfiComponentNameProtocolGuid,
+ &gI2cBusComponentName,
+ &gEfiComponentName2ProtocolGuid,
+ &gI2cBusComponentName2,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+Done:
+ //
+ // Free the buffer containing the list of handles from the handle database
+ //
+ if (DeviceHandleBuffer != NULL) {
+ gBS->FreePool (DeviceHandleBuffer);
+ }
+
+ return Status;
+}
diff --git a/MdeModulePkg/Bus/I2c/I2cDxe/I2cBusDxe.inf b/MdeModulePkg/Bus/I2c/I2cDxe/I2cBusDxe.inf
new file mode 100644
index 000000000..12b42ab41
--- /dev/null
+++ b/MdeModulePkg/Bus/I2c/I2cDxe/I2cBusDxe.inf
@@ -0,0 +1,54 @@
+## @file
+# This driver enumerates I2C devices on I2C bus and produce I2C
+# IO Protocol on I2C devices.
+#
+# Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>
+#
+# 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]
+ INF_VERSION = 0x00010005
+ BASE_NAME = I2cBusDxe
+ FILE_GUID = 0C34B372-2622-4A13-A46E-BFD0DEB48BFF
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = InitializeI2cBus
+ UNLOAD_IMAGE = I2cBusUnload
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources.common]
+ I2cDxe.h
+ I2cBus.c
+
+[LibraryClasses]
+ BaseMemoryLib
+ DebugLib
+ DevicePathLib
+ MemoryAllocationLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+ UefiLib
+
+[Packages]
+ MdePkg/MdePkg.dec
+
+[Protocols]
+ gEfiI2cIoProtocolGuid ## BY_START
+ gEfiI2cHostProtocolGuid ## BY_START
+ gEfiI2cMasterProtocolGuid ## TO_START
+ gEfiI2cEnumerateProtocolGuid ## TO_START
+ gEfiI2cBusConfigurationManagementProtocolGuid ## TO_START
+ gEfiI2cHostProtocolGuid ## TO_START
diff --git a/MdeModulePkg/Bus/I2c/I2cDxe/I2cDxe.c b/MdeModulePkg/Bus/I2c/I2cDxe/I2cDxe.c
new file mode 100644
index 000000000..fb985f96e
--- /dev/null
+++ b/MdeModulePkg/Bus/I2c/I2cDxe/I2cDxe.c
@@ -0,0 +1,75 @@
+/** @file
+ This file implements the entrypoint and unload function for I2C DXE module.
+
+ Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>
+ 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 "I2cDxe.h"
+
+/**
+ The user Entry Point for I2C module. The user code starts with this function.
+
+ @param[in] ImageHandle The firmware allocated handle for the EFI image.
+ @param[in] SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The entry point is executed successfully.
+ @retval other Some error occurs when executing this entry point.
+
+**/
+EFI_STATUS
+EFIAPI
+InitializeI2c(
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Install driver model protocol(s).
+ //
+ Status = InitializeI2cHost ( ImageHandle, SystemTable );
+ if ( !EFI_ERROR ( Status ))
+ {
+ Status = InitializeI2cBus ( ImageHandle, SystemTable );
+ }
+ return Status;
+}
+
+/**
+ This is the unload handle for I2C module.
+
+ Disconnect the driver specified by ImageHandle from all the devices in the handle database.
+ Uninstall all the protocols installed in the driver entry point.
+
+ @param[in] ImageHandle The drivers' driver image.
+
+ @retval EFI_SUCCESS The image is unloaded.
+ @retval Others Failed to unload the image.
+
+**/
+EFI_STATUS
+EFIAPI
+I2cUnload (
+ IN EFI_HANDLE ImageHandle
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Disconnect the drivers
+ //
+ Status = I2cBusUnload ( ImageHandle );
+ if ( !EFI_ERROR ( Status )) {
+ Status = I2cHostUnload ( ImageHandle );
+ }
+ return Status;
+}
diff --git a/MdeModulePkg/Bus/I2c/I2cDxe/I2cDxe.h b/MdeModulePkg/Bus/I2c/I2cDxe/I2cDxe.h
new file mode 100644
index 000000000..1490d4283
--- /dev/null
+++ b/MdeModulePkg/Bus/I2c/I2cDxe/I2cDxe.h
@@ -0,0 +1,1097 @@
+/** @file
+ Private data structures for the I2C DXE driver.
+
+ This file defines common data structures, macro definitions and some module
+ internal function header files.
+
+ Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>
+ 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 __I2C_DXE_H__
+#define __I2C_DXE_H__
+
+#include <Uefi.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/TimerLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiLib.h>
+
+#include <Protocol/DriverBinding.h>
+#include <Protocol/I2cEnumerate.h>
+#include <Protocol/I2cHost.h>
+#include <Protocol/I2cIo.h>
+#include <Protocol/I2cMaster.h>
+#include <Protocol/I2cBusConfigurationManagement.h>
+#include <Protocol/LoadedImage.h>
+
+#define I2C_DEVICE_SIGNATURE SIGNATURE_32 ('I', '2', 'C', 'D')
+#define I2C_HOST_SIGNATURE SIGNATURE_32 ('I', '2', 'C', 'H')
+#define I2C_REQUEST_SIGNATURE SIGNATURE_32 ('I', '2', 'C', 'R')
+
+//
+// Synchronize access to the list of requests
+//
+#define TPL_I2C_SYNC TPL_NOTIFY
+
+//
+// I2C bus context
+//
+typedef struct {
+ EFI_I2C_ENUMERATE_PROTOCOL *I2cEnumerate;
+ EFI_I2C_HOST_PROTOCOL *I2cHost;
+ EFI_HANDLE Controller;
+ EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
+ EFI_HANDLE DriverBindingHandle;
+} I2C_BUS_CONTEXT;
+
+//
+// I2C device context
+//
+typedef struct {
+ //
+ // Structure identification
+ //
+ UINT32 Signature;
+
+ //
+ // I2c device handle
+ //
+ EFI_HANDLE Handle;
+
+ //
+ // Upper level API to support the I2C device I/O
+ //
+ EFI_I2C_IO_PROTOCOL I2cIo;
+
+ //
+ // Device path for this device
+ //
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+
+ //
+ // Platform specific data for this device
+ //
+ CONST EFI_I2C_DEVICE *I2cDevice;
+
+ //
+ // Context for the common I/O support including the
+ // lower level API to the host controller.
+ //
+ I2C_BUS_CONTEXT *I2cBusContext;
+} I2C_DEVICE_CONTEXT;
+
+#define I2C_DEVICE_CONTEXT_FROM_PROTOCOL(a) CR (a, I2C_DEVICE_CONTEXT, I2cIo, I2C_DEVICE_SIGNATURE)
+
+//
+// I2C Request
+//
+typedef struct {
+ //
+ // Signature
+ //
+ UINT32 Signature;
+
+ //
+ // Next request in the pending request list
+ //
+ LIST_ENTRY Link;
+
+ //
+ // I2C bus configuration for the operation
+ //
+ UINTN I2cBusConfiguration;
+
+ //
+ // I2C slave address for the operation
+ //
+ UINTN SlaveAddress;
+
+ //
+ // Event to set for asynchronous operations, NULL for
+ // synchronous operations
+ //
+ EFI_EVENT Event;
+
+ //
+ // I2C operation description
+ //
+ EFI_I2C_REQUEST_PACKET *RequestPacket;
+
+ //
+ // Optional buffer to receive the I2C operation completion status
+ //
+ EFI_STATUS *Status;
+} I2C_REQUEST;
+
+#define I2C_REQUEST_FROM_ENTRY(a) CR (a, I2C_REQUEST, Link, I2C_REQUEST_SIGNATURE);
+
+//
+// I2C host context
+//
+typedef struct {
+ //
+ // Structure identification
+ //
+ UINTN Signature;
+
+ //
+ // Current I2C bus configuration
+ //
+ UINTN I2cBusConfiguration;
+
+ //
+ // I2C bus configuration management event
+ //
+ EFI_EVENT I2cBusConfigurationEvent;
+
+ //
+ // I2C operation completion event
+ //
+ EFI_EVENT I2cEvent;
+
+ //
+ // I2C operation and I2C bus configuration management status
+ //
+ EFI_STATUS Status;
+
+ //
+ // I2C bus configuration management operation pending
+ //
+ BOOLEAN I2cBusConfigurationManagementPending;
+
+ //
+ // I2C request list maintained by I2C Host
+ //
+ LIST_ENTRY RequestList;
+
+ //
+ // Upper level API
+ //
+ EFI_I2C_HOST_PROTOCOL I2cHost;
+
+ //
+ // I2C bus configuration management protocol
+ //
+ EFI_I2C_BUS_CONFIGURATION_MANAGEMENT_PROTOCOL *I2cBusConfigurationManagement;
+
+ //
+ // Lower level API for I2C master (controller)
+ //
+ EFI_I2C_MASTER_PROTOCOL *I2cMaster;
+} I2C_HOST_CONTEXT;
+
+#define I2C_HOST_CONTEXT_FROM_PROTOCOL(a) CR (a, I2C_HOST_CONTEXT, I2cHost, I2C_HOST_SIGNATURE)
+
+//
+// Global Variables
+//
+extern EFI_COMPONENT_NAME_PROTOCOL gI2cBusComponentName;
+extern EFI_COMPONENT_NAME2_PROTOCOL gI2cBusComponentName2;
+extern EFI_DRIVER_BINDING_PROTOCOL gI2cBusDriverBinding;
+
+extern EFI_COMPONENT_NAME_PROTOCOL gI2cHostComponentName;
+extern EFI_COMPONENT_NAME2_PROTOCOL gI2cHostComponentName2;
+extern EFI_DRIVER_BINDING_PROTOCOL gI2cHostDriverBinding;
+
+/**
+ Start the I2C driver
+
+ This routine allocates the necessary resources for the driver.
+
+ This routine is called by I2cBusDriverStart to complete the driver
+ initialization.
+
+ @param[in] I2cBus Address of an I2C_BUS_CONTEXT structure
+ @param[in] Controller Handle to the controller
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path.
+
+ @retval EFI_SUCCESS Driver API properly initialized
+
+**/
+EFI_STATUS
+RegisterI2cDevice (
+ IN I2C_BUS_CONTEXT *I2cBus,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ );
+
+/**
+ Unregister an I2C device.
+
+ This function removes the protocols installed on the controller handle and
+ frees the resources allocated for the I2C device.
+
+ @param This The pointer to EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param Controller The controller handle of the I2C device.
+ @param Handle The child handle.
+
+ @retval EFI_SUCCESS The I2C device is successfully unregistered.
+ @return Others Some error occurs when unregistering the I2C device.
+
+**/
+EFI_STATUS
+UnRegisterI2cDevice (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_HANDLE Handle
+ );
+
+/**
+ Create a path for the I2C device
+
+ Append the I2C slave path to the I2C master controller path.
+
+ @param[in] I2cDeviceContext Address of an I2C_DEVICE_CONTEXT structure.
+ @param[in] BuildControllerNode Flag to build controller node in device path.
+
+ @retval EFI_SUCCESS The I2C device path is built successfully.
+ @return Others It is failed to built device path.
+
+**/
+EFI_STATUS
+I2cBusDevicePathAppend (
+ IN I2C_DEVICE_CONTEXT *I2cDeviceContext,
+ IN BOOLEAN BuildControllerNode
+ );
+
+/**
+ Queue an I2C transaction for execution on the I2C device.
+
+ This routine must be called at or below TPL_NOTIFY. For synchronous
+ requests this routine must be called at or below TPL_CALLBACK.
+
+ This routine queues an I2C transaction to the I2C controller for
+ execution on the I2C bus.
+
+ When Event is NULL, QueueRequest() operates synchronously and returns
+ the I2C completion status as its return value.
+
+ When Event is not NULL, QueueRequest() synchronously returns EFI_SUCCESS
+ indicating that the asynchronous I2C transaction was queued. The values
+ above are returned in the buffer pointed to by I2cStatus upon the
+ completion of the I2C transaction when I2cStatus is not NULL.
+
+ The upper layer driver writer provides the following to the platform
+ vendor:
+
+ 1. Vendor specific GUID for the I2C part
+ 2. Guidance on proper construction of the slave address array when the
+ I2C device uses more than one slave address. The I2C bus protocol
+ uses the SlaveAddressIndex to perform relative to physical address
+ translation to access the blocks of hardware within the I2C device.
+
+ @param[in] This Pointer to an EFI_I2C_IO_PROTOCOL structure.
+ @param[in] SlaveAddressIndex Index value into an array of slave addresses
+ for the I2C device. The values in the array
+ are specified by the board designer, with the
+ third party I2C device driver writer providing
+ the slave address order.
+
+ For devices that have a single slave address,
+ this value must be zero. If the I2C device
+ uses more than one slave address then the
+ third party (upper level) I2C driver writer
+ needs to specify the order of entries in the
+ slave address array.
+
+ \ref ThirdPartyI2cDrivers "Third Party I2C
+ Drivers" section in I2cMaster.h.
+ @param[in] Event Event to signal for asynchronous transactions,
+ NULL for synchronous transactions
+ @param[in] RequestPacket Pointer to an EFI_I2C_REQUEST_PACKET structure
+ describing the I2C transaction
+ @param[out] I2cStatus Optional buffer to receive the I2C transaction
+ completion status
+
+ @retval EFI_SUCCESS The asynchronous transaction was successfully
+ queued when Event is not NULL.
+ @retval EFI_SUCCESS The transaction completed successfully when
+ Event is NULL.
+ @retval EFI_ABORTED The request did not complete because the driver
+ binding Stop() routine was called.
+ @retval EFI_BAD_BUFFER_SIZE The RequestPacket->LengthInBytes value is too
+ large.
+ @retval EFI_DEVICE_ERROR There was an I2C error (NACK) during the
+ transaction.
+ @retval EFI_INVALID_PARAMETER RequestPacket is NULL
+ @retval EFI_NOT_FOUND Reserved bit set in the SlaveAddress parameter
+ @retval EFI_NO_MAPPING The EFI_I2C_HOST_PROTOCOL could not set the
+ bus configuration required to access this I2C
+ device.
+ @retval EFI_NO_RESPONSE The I2C device is not responding to the slave
+ address selected by SlaveAddressIndex.
+ EFI_DEVICE_ERROR will be returned if the
+ controller cannot distinguish when the NACK
+ occurred.
+ @retval EFI_OUT_OF_RESOURCES Insufficient memory for I2C transaction
+ @retval EFI_UNSUPPORTED The controller does not support the requested
+ transaction.
+
+**/
+EFI_STATUS
+EFIAPI
+I2cBusQueueRequest (
+ IN CONST EFI_I2C_IO_PROTOCOL *This,
+ IN UINTN SlaveAddressIndex,
+ IN EFI_EVENT Event OPTIONAL,
+ IN EFI_I2C_REQUEST_PACKET *RequestPacket,
+ OUT EFI_STATUS *I2cStatus OPTIONAL
+ );
+
+/**
+ Tests to see if this driver supports a given controller. If a child device is provided,
+ it further tests to see if this driver supports creating a handle for the specified child device.
+
+ This function checks to see if the driver specified by This supports the device specified by
+ ControllerHandle. Drivers will typically use the device path attached to
+ ControllerHandle and/or the services from the bus I/O abstraction attached to
+ ControllerHandle to determine if the driver supports ControllerHandle. This function
+ may be called many times during platform initialization. In order to reduce boot times, the tests
+ performed by this function must be very small, and take as little time as possible to execute. This
+ function must not change the state of any hardware devices, and this function must be aware that the
+ device specified by ControllerHandle may already be managed by the same driver or a
+ different driver. This function must match its calls to AllocatePages() with FreePages(),
+ AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
+ Since ControllerHandle may have been previously started by the same driver, if a protocol is
+ already in the opened state, then it must not be closed with CloseProtocol(). This is required
+ to guarantee the state of ControllerHandle is not modified by this function.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of the controller to test. This handle
+ must support a protocol interface that supplies
+ an I/O abstraction to the driver.
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
+ parameter is ignored by device drivers, and is optional for bus
+ drivers. For bus drivers, if this parameter is not NULL, then
+ the bus driver must determine if the bus controller specified
+ by ControllerHandle and the child controller specified
+ by RemainingDevicePath are both supported by this
+ bus driver.
+
+ @retval EFI_SUCCESS The device specified by ControllerHandle and
+ RemainingDevicePath is supported by the driver specified by This.
+ @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
+ RemainingDevicePath is already being managed by the driver
+ specified by This.
+ @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
+ RemainingDevicePath is already being managed by a different
+ driver or an application that requires exclusive access.
+ Currently not implemented.
+ @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
+ RemainingDevicePath is not supported by the driver specified by This.
+**/
+EFI_STATUS
+EFIAPI
+I2cBusDriverSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ );
+
+/**
+ Starts a device controller or a bus controller.
+
+ The Start() function is designed to be invoked from the EFI boot service ConnectController().
+ As a result, much of the error checking on the parameters to Start() has been moved into this
+ common boot service. It is legal to call Start() from other locations,
+ but the following calling restrictions must be followed or the system behavior will not be deterministic.
+ 1. ControllerHandle must be a valid EFI_HANDLE.
+ 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
+ EFI_DEVICE_PATH_PROTOCOL.
+ 3. Prior to calling Start(), the Supported() function for the driver specified by This must
+ have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of the controller to start. This handle
+ must support a protocol interface that supplies
+ an I/O abstraction to the driver.
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
+ parameter is ignored by device drivers, and is optional for bus
+ drivers. For a bus driver, if this parameter is NULL, then handles
+ for all the children of Controller are created by this driver.
+ If this parameter is not NULL and the first Device Path Node is
+ not the End of Device Path Node, then only the handle for the
+ child device specified by the first Device Path Node of
+ RemainingDevicePath is created by this driver.
+ If the first Device Path Node of RemainingDevicePath is
+ the End of Device Path Node, no child handle is created by this
+ driver.
+
+ @retval EFI_SUCCESS The device was started.
+ @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ @retval Others The driver failded to start the device.
+
+**/
+EFI_STATUS
+EFIAPI
+I2cBusDriverStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ );
+
+/**
+ Stops a device controller or a bus controller.
+
+ The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
+ As a result, much of the error checking on the parameters to Stop() has been moved
+ into this common boot service. It is legal to call Stop() from other locations,
+ but the following calling restrictions must be followed or the system behavior will not be deterministic.
+ 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
+ same driver's Start() function.
+ 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
+ EFI_HANDLE. In addition, all of these handles must have been created in this driver's
+ Start() function, and the Start() function must have called OpenProtocol() on
+ ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle A handle to the device being stopped. The handle must
+ support a bus specific I/O protocol for the driver
+ to use to stop the device.
+ @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
+ @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
+ if NumberOfChildren is 0.
+
+ @retval EFI_SUCCESS The device was stopped.
+ @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
+
+**/
+EFI_STATUS
+EFIAPI
+I2cBusDriverStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ );
+
+/**
+ Retrieves a Unicode string that is the user readable name of the driver.
+
+ This function retrieves the user readable name of a driver in the form of a
+ Unicode string. If the driver specified by This has a user readable name in
+ the language specified by Language, then a pointer to the driver name is
+ returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
+ by This does not support the language specified by Language,
+ then EFI_UNSUPPORTED is returned.
+
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param Language[in] A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified
+ in RFC 4646 or ISO 639-2 language code format.
+
+ @param DriverName[out] A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ driver specified by This in the language
+ specified by Language.
+
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by
+ This and the language specified by Language was
+ returned in DriverName.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER DriverName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+I2cBusComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME2_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ );
+
+/**
+ Retrieves a Unicode string that is the user readable name of the controller
+ that is being managed by a driver.
+
+ This function retrieves the user readable name of the controller specified by
+ ControllerHandle and ChildHandle in the form of a Unicode string. If the
+ driver specified by This has a user readable name in the language specified by
+ Language, then a pointer to the controller name is returned in ControllerName,
+ and EFI_SUCCESS is returned. If the driver specified by This is not currently
+ managing the controller specified by ControllerHandle and ChildHandle,
+ then EFI_UNSUPPORTED is returned. If the driver specified by This does not
+ support the language specified by Language, then EFI_UNSUPPORTED is returned.
+
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param ControllerHandle[in] The handle of a controller that the driver
+ specified by This is managing. This handle
+ specifies the controller whose name is to be
+ returned.
+
+ @param ChildHandle[in] The handle of the child controller to retrieve
+ the name of. This is an optional parameter that
+ may be NULL. It will be NULL for device
+ drivers. It will also be NULL for a bus drivers
+ that wish to retrieve the name of the bus
+ controller. It will not be NULL for a bus
+ driver that wishes to retrieve the name of a
+ child controller.
+
+ @param Language[in] A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified in
+ RFC 4646 or ISO 639-2 language code format.
+
+ @param ControllerName[out] A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ controller specified by ControllerHandle and
+ ChildHandle in the language specified by
+ Language from the point of view of the driver
+ specified by This.
+
+ @retval EFI_SUCCESS The Unicode string for the user readable name in
+ the language specified by Language for the
+ driver specified by This was returned in
+ DriverName.
+
+ @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
+
+ @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
+ EFI_HANDLE.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This is not currently
+ managing the controller specified by
+ ControllerHandle and ChildHandle.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+I2cBusComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME2_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ );
+
+/**
+ The user entry point for the I2C bus module. The user code starts with
+ this function.
+
+ @param[in] ImageHandle The firmware allocated handle for the EFI image.
+ @param[in] SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The entry point is executed successfully.
+ @retval other Some error occurs when executing this entry point.
+
+**/
+EFI_STATUS
+EFIAPI
+InitializeI2cBus(
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ This is the unload handle for I2C bus module.
+
+ Disconnect the driver specified by ImageHandle from all the devices in the handle database.
+ Uninstall all the protocols installed in the driver entry point.
+
+ @param[in] ImageHandle The drivers' driver image.
+
+ @retval EFI_SUCCESS The image is unloaded.
+ @retval Others Failed to unload the image.
+
+**/
+EFI_STATUS
+EFIAPI
+I2cBusUnload (
+ IN EFI_HANDLE ImageHandle
+ );
+
+/**
+ Release all the resources allocated for the I2C device.
+
+ This function releases all the resources allocated for the I2C device.
+
+ @param I2cDeviceContext The I2C child device involved for the operation.
+
+**/
+VOID
+ReleaseI2cDeviceContext (
+ IN I2C_DEVICE_CONTEXT *I2cDeviceContext
+ );
+
+/**
+ Complete the current request
+
+ @param[in] I2cHost Address of an I2C_HOST_CONTEXT structure.
+ @param[in] Status Status of the I<sub>2</sub>C operation.
+
+ @return This routine returns the input status value.
+
+**/
+EFI_STATUS
+I2cHostRequestComplete (
+ I2C_HOST_CONTEXT *I2cHost,
+ EFI_STATUS Status
+ );
+
+/**
+ Enable access to the I2C bus configuration
+
+ @param[in] I2cHostContext Address of an I2C_HOST_CONTEXT structure
+
+ @retval EFI_SUCCESS The operation completed successfully.
+ @retval EFI_ABORTED The request did not complete because the driver
+ was shutdown.
+ @retval EFI_BAD_BUFFER_SIZE The WriteBytes or ReadBytes buffer size is too large.
+ @retval EFI_DEVICE_ERROR There was an I2C error (NACK) during the operation.
+ This could indicate the slave device is not present.
+ @retval EFI_INVALID_PARAMETER RequestPacket is NULL
+ @retval EFI_NO_MAPPING Invalid I2cBusConfiguration value
+ @retval EFI_NO_RESPONSE The I2C device is not responding to the
+ slave address. EFI_DEVICE_ERROR may also be
+ returned if the controller can not distinguish
+ when the NACK occurred.
+ @retval EFI_NOT_FOUND I2C slave address exceeds maximum address
+ @retval EFI_NOT_READY I2C bus is busy or operation pending, wait for
+ the event and then read status.
+ @retval EFI_OUT_OF_RESOURCES Insufficient memory for I2C operation
+ @retval EFI_TIMEOUT The transaction did not complete within an internally
+ specified timeout period.
+
+**/
+EFI_STATUS
+I2cHostRequestEnable (
+ I2C_HOST_CONTEXT *I2cHost
+ );
+
+/**
+ Tests to see if this driver supports a given controller. If a child device is provided,
+ it further tests to see if this driver supports creating a handle for the specified child device.
+
+ This function checks to see if the driver specified by This supports the device specified by
+ ControllerHandle. Drivers will typically use the device path attached to
+ ControllerHandle and/or the services from the bus I/O abstraction attached to
+ ControllerHandle to determine if the driver supports ControllerHandle. This function
+ may be called many times during platform initialization. In order to reduce boot times, the tests
+ performed by this function must be very small, and take as little time as possible to execute. This
+ function must not change the state of any hardware devices, and this function must be aware that the
+ device specified by ControllerHandle may already be managed by the same driver or a
+ different driver. This function must match its calls to AllocatePages() with FreePages(),
+ AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
+ Since ControllerHandle may have been previously started by the same driver, if a protocol is
+ already in the opened state, then it must not be closed with CloseProtocol(). This is required
+ to guarantee the state of ControllerHandle is not modified by this function.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of the controller to test. This handle
+ must support a protocol interface that supplies
+ an I/O abstraction to the driver.
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
+ parameter is ignored by device drivers, and is optional for bus
+ drivers. For bus drivers, if this parameter is not NULL, then
+ the bus driver must determine if the bus controller specified
+ by ControllerHandle and the child controller specified
+ by RemainingDevicePath are both supported by this
+ bus driver.
+
+ @retval EFI_SUCCESS The device specified by ControllerHandle and
+ RemainingDevicePath is supported by the driver specified by This.
+ @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
+ RemainingDevicePath is already being managed by the driver
+ specified by This.
+ @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
+ RemainingDevicePath is already being managed by a different
+ driver or an application that requires exclusive access.
+ Currently not implemented.
+ @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
+ RemainingDevicePath is not supported by the driver specified by This.
+**/
+EFI_STATUS
+EFIAPI
+I2cHostDriverSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ );
+
+/**
+ Starts a device controller or a bus controller.
+
+ The Start() function is designed to be invoked from the EFI boot service ConnectController().
+ As a result, much of the error checking on the parameters to Start() has been moved into this
+ common boot service. It is legal to call Start() from other locations,
+ but the following calling restrictions must be followed, or the system behavior will not be deterministic.
+ 1. ControllerHandle must be a valid EFI_HANDLE.
+ 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
+ EFI_DEVICE_PATH_PROTOCOL.
+ 3. Prior to calling Start(), the Supported() function for the driver specified by This must
+ have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of the controller to start. This handle
+ must support a protocol interface that supplies
+ an I/O abstraction to the driver.
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
+ parameter is ignored by device drivers, and is optional for bus
+ drivers. For a bus driver, if this parameter is NULL, then handles
+ for all the children of Controller are created by this driver.
+ If this parameter is not NULL and the first Device Path Node is
+ not the End of Device Path Node, then only the handle for the
+ child device specified by the first Device Path Node of
+ RemainingDevicePath is created by this driver.
+ If the first Device Path Node of RemainingDevicePath is
+ the End of Device Path Node, no child handle is created by this
+ driver.
+
+ @retval EFI_SUCCESS The device was started.
+ @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ @retval Others The driver failded to start the device.
+
+**/
+EFI_STATUS
+EFIAPI
+I2cHostDriverStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ );
+
+/**
+ Stops a device controller or a bus controller.
+
+ The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
+ As a result, much of the error checking on the parameters to Stop() has been moved
+ into this common boot service. It is legal to call Stop() from other locations,
+ but the following calling restrictions must be followed, or the system behavior will not be deterministic.
+ 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
+ same driver's Start() function.
+ 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
+ EFI_HANDLE. In addition, all of these handles must have been created in this driver's
+ Start() function, and the Start() function must have called OpenProtocol() on
+ ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle A handle to the device being stopped. The handle must
+ support a bus specific I/O protocol for the driver
+ to use to stop the device.
+ @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
+ @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
+ if NumberOfChildren is 0.
+
+ @retval EFI_SUCCESS The device was stopped.
+ @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
+
+**/
+EFI_STATUS
+EFIAPI
+I2cHostDriverStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ );
+
+/**
+ Retrieves a Unicode string that is the user readable name of the driver.
+
+ This function retrieves the user readable name of a driver in the form of a
+ Unicode string. If the driver specified by This has a user readable name in
+ the language specified by Language, then a pointer to the driver name is
+ returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
+ by This does not support the language specified by Language,
+ then EFI_UNSUPPORTED is returned.
+
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param Language[in] A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified
+ in RFC 4646 or ISO 639-2 language code format.
+
+ @param DriverName[out] A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ driver specified by This in the language
+ specified by Language.
+
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by
+ This and the language specified by Language was
+ returned in DriverName.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER DriverName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+I2cHostComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME2_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ );
+
+/**
+ Retrieves a Unicode string that is the user readable name of the controller
+ that is being managed by a driver.
+
+ This function retrieves the user readable name of the controller specified by
+ ControllerHandle and ChildHandle in the form of a Unicode string. If the
+ driver specified by This has a user readable name in the language specified by
+ Language, then a pointer to the controller name is returned in ControllerName,
+ and EFI_SUCCESS is returned. If the driver specified by This is not currently
+ managing the controller specified by ControllerHandle and ChildHandle,
+ then EFI_UNSUPPORTED is returned. If the driver specified by This does not
+ support the language specified by Language, then EFI_UNSUPPORTED is returned.
+
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param ControllerHandle[in] The handle of a controller that the driver
+ specified by This is managing. This handle
+ specifies the controller whose name is to be
+ returned.
+
+ @param ChildHandle[in] The handle of the child controller to retrieve
+ the name of. This is an optional parameter that
+ may be NULL. It will be NULL for device
+ drivers. It will also be NULL for a bus drivers
+ that wish to retrieve the name of the bus
+ controller. It will not be NULL for a bus
+ driver that wishes to retrieve the name of a
+ child controller.
+
+ @param Language[in] A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified in
+ RFC 4646 or ISO 639-2 language code format.
+
+ @param ControllerName[out] A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ controller specified by ControllerHandle and
+ ChildHandle in the language specified by
+ Language from the point of view of the driver
+ specified by This.
+
+ @retval EFI_SUCCESS The Unicode string for the user readable name in
+ the language specified by Language for the
+ driver specified by This was returned in
+ DriverName.
+
+ @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
+
+ @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
+ EFI_HANDLE.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This is not currently
+ managing the controller specified by
+ ControllerHandle and ChildHandle.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+I2cHostComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME2_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ );
+
+/**
+ Handle the bus available event
+
+ This routine is called at TPL_I2C_SYNC.
+
+ @param[in] Event Address of an EFI_EVENT handle
+ @param[in] Context Address of an I2C_HOST_CONTEXT structure
+
+**/
+VOID
+EFIAPI
+I2cHostRequestCompleteEvent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+/**
+ Handle the I2C bus configuration available event
+
+ This routine is called at TPL_I2C_SYNC.
+
+ @param[in] Event Address of an EFI_EVENT handle
+ @param[in] Context Address of an I2C_HOST_CONTEXT structure
+
+**/
+VOID
+EFIAPI
+I2cHostI2cBusConfigurationAvailable (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+/**
+ Queue an I2C operation for execution on the I2C controller.
+
+ This routine must be called at or below TPL_NOTIFY. For synchronous
+ requests this routine must be called at or below TPL_CALLBACK.
+
+ N.B. The typical consumers of this API are the I2C bus driver and
+ on rare occasions the I2C test application. Extreme care must be
+ taken by other consumers of this API to prevent confusing the
+ third party I2C drivers due to a state change at the I2C device
+ which the third party I2C drivers did not initiate. I2C platform
+ drivers may use this API within these guidelines.
+
+ This layer uses the concept of I2C bus configurations to describe
+ the I2C bus. An I2C bus configuration is defined as a unique
+ setting of the multiplexers and switches in the I2C bus which
+ enable access to one or more I2C devices. When using a switch
+ to divide a bus, due to speed differences, the I2C platform layer
+ would define an I2C bus configuration for the I2C devices on each
+ side of the switch. When using a multiplexer, the I2C platform
+ layer defines an I2C bus configuration for each of the selector
+ values required to control the multiplexer. See Figure 1 in the
+ <a href="http://www.nxp.com/documents/user_manual/UM10204.pdf">I<sup>2</sup>C
+ Specification</a> for a complex I2C bus configuration.
+
+ The I2C host driver processes all operations in FIFO order. Prior to
+ performing the operation, the I2C host driver calls the I2C platform
+ driver to reconfigure the switches and multiplexers in the I2C bus
+ enabling access to the specified I2C device. The I2C platform driver
+ also selects the maximum bus speed for the device. After the I2C bus
+ is configured, the I2C host driver calls the I2C port driver to
+ initialize the I2C controller and start the I2C operation.
+
+ @param[in] This Address of an EFI_I2C_HOST_PROTOCOL instance.
+ @param[in] I2cBusConfiguration I2C bus configuration to access the I2C
+ device.
+ @param[in] SlaveAddress Address of the device on the I2C bus.
+ @param[in] Event Event to set for asynchronous operations,
+ NULL for synchronous operations
+ @param[in] RequestPacket Address of an EFI_I2C_REQUEST_PACKET
+ structure describing the I2C operation
+ @param[out] I2cStatus Optional buffer to receive the I2C operation
+ completion status
+
+ @retval EFI_SUCCESS The operation completed successfully.
+ @retval EFI_ABORTED The request did not complete because the driver
+ was shutdown.
+ @retval EFI_BAD_BUFFER_SIZE The WriteBytes or ReadBytes buffer size is too large.
+ @retval EFI_DEVICE_ERROR There was an I2C error (NACK) during the operation.
+ This could indicate the slave device is not present.
+ @retval EFI_INVALID_PARAMETER RequestPacket is NULL
+ @retval EFI_INVALID_PARAMETER TPL is too high
+ @retval EFI_NO_MAPPING Invalid I2cBusConfiguration value
+ @retval EFI_NO_RESPONSE The I2C device is not responding to the
+ slave address. EFI_DEVICE_ERROR may also be
+ returned if the controller can not distinguish
+ when the NACK occurred.
+ @retval EFI_NOT_FOUND I2C slave address exceeds maximum address
+ @retval EFI_NOT_READY I2C bus is busy or operation pending, wait for
+ the event and then read status pointed to by
+ the request packet.
+ @retval EFI_OUT_OF_RESOURCES Insufficient memory for I2C operation
+ @retval EFI_TIMEOUT The transaction did not complete within an internally
+ specified timeout period.
+
+**/
+EFI_STATUS
+EFIAPI
+I2cHostQueueRequest (
+ IN CONST EFI_I2C_HOST_PROTOCOL *This,
+ IN UINTN I2cBusConfiguration,
+ IN UINTN SlaveAddress,
+ IN EFI_EVENT Event OPTIONAL,
+ IN EFI_I2C_REQUEST_PACKET *RequestPacket,
+ OUT EFI_STATUS *I2cStatus OPTIONAL
+ );
+
+/**
+ The user Entry Point for I2C host module. The user code starts with this function.
+
+ @param[in] ImageHandle The firmware allocated handle for the EFI image.
+ @param[in] SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The entry point is executed successfully.
+ @retval other Some error occurs when executing this entry point.
+
+**/
+EFI_STATUS
+EFIAPI
+InitializeI2cHost(
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ This is the unload handle for I2C host module.
+
+ Disconnect the driver specified by ImageHandle from all the devices in the handle database.
+ Uninstall all the protocols installed in the driver entry point.
+
+ @param[in] ImageHandle The drivers' driver image.
+
+ @retval EFI_SUCCESS The image is unloaded.
+ @retval Others Failed to unload the image.
+
+**/
+EFI_STATUS
+EFIAPI
+I2cHostUnload (
+ IN EFI_HANDLE ImageHandle
+ );
+
+#endif // __I2C_DXE_H__
diff --git a/MdeModulePkg/Bus/I2c/I2cDxe/I2cDxe.inf b/MdeModulePkg/Bus/I2c/I2cDxe/I2cDxe.inf
new file mode 100644
index 000000000..8600531a9
--- /dev/null
+++ b/MdeModulePkg/Bus/I2c/I2cDxe/I2cDxe.inf
@@ -0,0 +1,56 @@
+## @file
+# This driver produce I2C Host Protocol on I2C controller handle, enumerate I2C
+# devices on I2C bus and produce I2C IO Protocol on I2C devices.
+#
+# Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>
+#
+# 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]
+ INF_VERSION = 0x00010005
+ BASE_NAME = I2cDxe
+ FILE_GUID = ECA2AE9E-7594-4901-871C-449DA1A11660
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = InitializeI2c
+ UNLOAD_IMAGE = I2cUnload
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources.common]
+ I2cDxe.c
+ I2cDxe.h
+ I2cHost.c
+ I2cBus.c
+
+[LibraryClasses]
+ BaseMemoryLib
+ DebugLib
+ DevicePathLib
+ MemoryAllocationLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+ UefiLib
+
+[Packages]
+ MdePkg/MdePkg.dec
+
+[Protocols]
+ gEfiI2cIoProtocolGuid ## BY_START
+ gEfiI2cHostProtocolGuid ## BY_START
+ gEfiI2cMasterProtocolGuid ## TO_START
+ gEfiI2cEnumerateProtocolGuid ## TO_START
+ gEfiI2cBusConfigurationManagementProtocolGuid ## TO_START
+ gEfiI2cHostProtocolGuid ## TO_START
diff --git a/MdeModulePkg/Bus/I2c/I2cDxe/I2cHost.c b/MdeModulePkg/Bus/I2c/I2cDxe/I2cHost.c
new file mode 100644
index 000000000..e153a4dc2
--- /dev/null
+++ b/MdeModulePkg/Bus/I2c/I2cDxe/I2cHost.c
@@ -0,0 +1,1169 @@
+/** @file
+ This file implements I2C Host Protocol which provides callers with the ability to
+ do I/O transactions to all of the devices on the I2C bus.
+
+ Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>
+ 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 "I2cDxe.h"
+
+EFI_DRIVER_BINDING_PROTOCOL gI2cHostDriverBinding = {
+ I2cHostDriverSupported,
+ I2cHostDriverStart,
+ I2cHostDriverStop,
+ 0x10,
+ NULL,
+ NULL
+};
+
+//
+// Driver name table
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mI2cHostDriverNameTable[] = {
+ { "eng;en", L"I2c Host Driver" },
+ { NULL , NULL }
+};
+
+//
+// EFI Component Name Protocol
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gI2cHostComponentName = {
+ (EFI_COMPONENT_NAME_GET_DRIVER_NAME) I2cHostComponentNameGetDriverName,
+ (EFI_COMPONENT_NAME_GET_CONTROLLER_NAME) I2cHostComponentNameGetControllerName,
+ "eng"
+};
+
+//
+// EFI Component Name 2 Protocol
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gI2cHostComponentName2 = {
+ I2cHostComponentNameGetDriverName,
+ I2cHostComponentNameGetControllerName,
+ "en"
+};
+
+/**
+ Retrieves a Unicode string that is the user readable name of the driver.
+
+ This function retrieves the user readable name of a driver in the form of a
+ Unicode string. If the driver specified by This has a user readable name in
+ the language specified by Language, then a pointer to the driver name is
+ returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
+ by This does not support the language specified by Language,
+ then EFI_UNSUPPORTED is returned.
+
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param Language[in] A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified
+ in RFC 4646 or ISO 639-2 language code format.
+
+ @param DriverName[out] A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ driver specified by This in the language
+ specified by Language.
+
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by
+ This and the language specified by Language was
+ returned in DriverName.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER DriverName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+I2cHostComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME2_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ )
+{
+ return LookupUnicodeString2 (
+ Language,
+ This->SupportedLanguages,
+ mI2cHostDriverNameTable,
+ DriverName,
+ (BOOLEAN)(This != &gI2cHostComponentName2)
+ );
+}
+
+/**
+ Retrieves a Unicode string that is the user readable name of the controller
+ that is being managed by a driver.
+
+ This function retrieves the user readable name of the controller specified by
+ ControllerHandle and ChildHandle in the form of a Unicode string. If the
+ driver specified by This has a user readable name in the language specified by
+ Language, then a pointer to the controller name is returned in ControllerName,
+ and EFI_SUCCESS is returned. If the driver specified by This is not currently
+ managing the controller specified by ControllerHandle and ChildHandle,
+ then EFI_UNSUPPORTED is returned. If the driver specified by This does not
+ support the language specified by Language, then EFI_UNSUPPORTED is returned.
+
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param ControllerHandle[in] The handle of a controller that the driver
+ specified by This is managing. This handle
+ specifies the controller whose name is to be
+ returned.
+
+ @param ChildHandle[in] The handle of the child controller to retrieve
+ the name of. This is an optional parameter that
+ may be NULL. It will be NULL for device
+ drivers. It will also be NULL for a bus drivers
+ that wish to retrieve the name of the bus
+ controller. It will not be NULL for a bus
+ driver that wishes to retrieve the name of a
+ child controller.
+
+ @param Language[in] A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified in
+ RFC 4646 or ISO 639-2 language code format.
+
+ @param ControllerName[out] A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ controller specified by ControllerHandle and
+ ChildHandle in the language specified by
+ Language from the point of view of the driver
+ specified by This.
+
+ @retval EFI_SUCCESS The Unicode string for the user readable name in
+ the language specified by Language for the
+ driver specified by This was returned in
+ DriverName.
+
+ @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
+
+ @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
+ EFI_HANDLE.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This is not currently
+ managing the controller specified by
+ ControllerHandle and ChildHandle.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+I2cHostComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME2_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ Tests to see if this driver supports a given controller. If a child device is provided,
+ it further tests to see if this driver supports creating a handle for the specified child device.
+
+ This function checks to see if the driver specified by This supports the device specified by
+ ControllerHandle. Drivers will typically use the device path attached to
+ ControllerHandle and/or the services from the bus I/O abstraction attached to
+ ControllerHandle to determine if the driver supports ControllerHandle. This function
+ may be called many times during platform initialization. In order to reduce boot times, the tests
+ performed by this function must be very small, and take as little time as possible to execute. This
+ function must not change the state of any hardware devices, and this function must be aware that the
+ device specified by ControllerHandle may already be managed by the same driver or a
+ different driver. This function must match its calls to AllocatePages() with FreePages(),
+ AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
+ Since ControllerHandle may have been previously started by the same driver, if a protocol is
+ already in the opened state, then it must not be closed with CloseProtocol(). This is required
+ to guarantee the state of ControllerHandle is not modified by this function.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of the controller to test. This handle
+ must support a protocol interface that supplies
+ an I/O abstraction to the driver.
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
+ parameter is ignored by device drivers, and is optional for bus
+ drivers. For bus drivers, if this parameter is not NULL, then
+ the bus driver must determine if the bus controller specified
+ by ControllerHandle and the child controller specified
+ by RemainingDevicePath are both supported by this
+ bus driver.
+
+ @retval EFI_SUCCESS The device specified by ControllerHandle and
+ RemainingDevicePath is supported by the driver specified by This.
+ @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
+ RemainingDevicePath is already being managed by the driver
+ specified by This.
+ @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
+ RemainingDevicePath is already being managed by a different
+ driver or an application that requires exclusive access.
+ Currently not implemented.
+ @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
+ RemainingDevicePath is not supported by the driver specified by This.
+**/
+EFI_STATUS
+EFIAPI
+I2cHostDriverSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+{
+ EFI_I2C_MASTER_PROTOCOL *I2cMaster;
+ EFI_I2C_BUS_CONFIGURATION_MANAGEMENT_PROTOCOL *I2cBusConfigurationManagement;
+ EFI_STATUS Status;
+
+ //
+ // Locate I2C Bus Configuration Management Protocol
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiI2cBusConfigurationManagementProtocolGuid,
+ (VOID **)&I2cBusConfigurationManagement,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Close the protocol because we don't use it here
+ //
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiI2cBusConfigurationManagementProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ //
+ // Locate I2C Master Protocol
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiI2cMasterProtocolGuid,
+ (VOID **)&I2cMaster,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Starts a device controller or a bus controller.
+
+ The Start() function is designed to be invoked from the EFI boot service ConnectController().
+ As a result, much of the error checking on the parameters to Start() has been moved into this
+ common boot service. It is legal to call Start() from other locations,
+ but the following calling restrictions must be followed, or the system behavior will not be deterministic.
+ 1. ControllerHandle must be a valid EFI_HANDLE.
+ 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
+ EFI_DEVICE_PATH_PROTOCOL.
+ 3. Prior to calling Start(), the Supported() function for the driver specified by This must
+ have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of the controller to start. This handle
+ must support a protocol interface that supplies
+ an I/O abstraction to the driver.
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
+ parameter is ignored by device drivers, and is optional for bus
+ drivers. For a bus driver, if this parameter is NULL, then handles
+ for all the children of Controller are created by this driver.
+ If this parameter is not NULL and the first Device Path Node is
+ not the End of Device Path Node, then only the handle for the
+ child device specified by the first Device Path Node of
+ RemainingDevicePath is created by this driver.
+ If the first Device Path Node of RemainingDevicePath is
+ the End of Device Path Node, no child handle is created by this
+ driver.
+
+ @retval EFI_SUCCESS The device was started.
+ @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ @retval Others The driver failded to start the device.
+
+**/
+EFI_STATUS
+EFIAPI
+I2cHostDriverStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+{
+ EFI_STATUS Status;
+ EFI_I2C_MASTER_PROTOCOL *I2cMaster;
+ EFI_I2C_BUS_CONFIGURATION_MANAGEMENT_PROTOCOL *I2cBusConfigurationManagement;
+ I2C_HOST_CONTEXT *I2cHostContext;
+
+ I2cMaster = NULL;
+ I2cHostContext = NULL;
+ I2cBusConfigurationManagement = NULL;
+
+ //
+ // Locate I2C Bus Configuration Management Protocol
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiI2cBusConfigurationManagementProtocolGuid,
+ (VOID **)&I2cBusConfigurationManagement,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "I2cHost: Open I2C bus configuration error, Status = %r\n", Status));
+ return Status;
+ }
+
+ //
+ // Locate I2C Master Protocol
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiI2cMasterProtocolGuid,
+ (VOID **)&I2cMaster,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "I2cHost: Open I2C master error, Status = %r\n", Status));
+ goto Exit;
+ }
+
+ //
+ // Allocate the I2C Host Context structure
+ //
+ I2cHostContext = AllocateZeroPool (sizeof (I2C_HOST_CONTEXT));
+ if (I2cHostContext == NULL) {
+ DEBUG ((EFI_D_ERROR, "I2cHost: there is no enough memory to allocate.\n"));
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Exit;
+ }
+
+ //
+ // Initialize the context structure for the current I2C Controller
+ //
+ I2cHostContext->Signature = I2C_HOST_SIGNATURE;
+ I2cHostContext->I2cMaster = I2cMaster;
+ I2cHostContext->I2cBusConfigurationManagement = I2cBusConfigurationManagement;
+ I2cHostContext->I2cBusConfiguration = (UINTN) -1;
+ InitializeListHead(&I2cHostContext->RequestList);
+
+ //
+ // Reset the controller
+ //
+ Status = I2cMaster->Reset (I2cMaster);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "I2cHost: I2C controller reset failed!\n"));
+ goto Exit;
+ }
+
+ //
+ // Create the I2C transaction complete event
+ //
+ Status = gBS->CreateEvent (
+ EVT_NOTIFY_SIGNAL,
+ TPL_I2C_SYNC,
+ I2cHostRequestCompleteEvent,
+ I2cHostContext,
+ &I2cHostContext->I2cEvent
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "I2cHost: create complete event error, Status = %r\n", Status));
+ goto Exit;
+ }
+
+ //
+ // Get the bus management event
+ //
+ Status = gBS->CreateEvent (
+ EVT_NOTIFY_SIGNAL,
+ TPL_I2C_SYNC,
+ I2cHostI2cBusConfigurationAvailable,
+ I2cHostContext,
+ &I2cHostContext->I2cBusConfigurationEvent
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "I2cHost: create bus available event error, Status = %r\n", Status));
+ goto Exit;
+ }
+
+ //
+ // Build the I2C host protocol for the current I2C controller
+ //
+ I2cHostContext->I2cHost.QueueRequest = I2cHostQueueRequest;
+ I2cHostContext->I2cHost.I2cControllerCapabilities = I2cMaster->I2cControllerCapabilities;
+
+ //
+ // Install the driver protocol
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &Controller,
+ &gEfiI2cHostProtocolGuid,
+ &I2cHostContext->I2cHost,
+ NULL
+ );
+Exit:
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "I2cHost: Start() function failed, Status = %r\n", Status));
+ if (I2cBusConfigurationManagement != NULL) {
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiI2cBusConfigurationManagementProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ }
+
+ if ((I2cHostContext != NULL) && (I2cHostContext->I2cEvent != NULL)) {
+ gBS->CloseEvent (I2cHostContext->I2cEvent);
+ I2cHostContext->I2cEvent = NULL;
+ }
+
+ if ((I2cHostContext != NULL) && (I2cHostContext->I2cBusConfigurationEvent != NULL)) {
+ gBS->CloseEvent (I2cHostContext->I2cBusConfigurationEvent);
+ I2cHostContext->I2cBusConfigurationEvent = NULL;
+ }
+
+ //
+ // Release the context structure upon failure
+ //
+ if (I2cHostContext != NULL) {
+ FreePool (I2cHostContext);
+ }
+ }
+
+ //
+ // Return the operation status.
+ //
+ return Status;
+}
+
+/**
+ Stops a device controller or a bus controller.
+
+ The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
+ As a result, much of the error checking on the parameters to Stop() has been moved
+ into this common boot service. It is legal to call Stop() from other locations,
+ but the following calling restrictions must be followed, or the system behavior will not be deterministic.
+ 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
+ same driver's Start() function.
+ 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
+ EFI_HANDLE. In addition, all of these handles must have been created in this driver's
+ Start() function, and the Start() function must have called OpenProtocol() on
+ ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle A handle to the device being stopped. The handle must
+ support a bus specific I/O protocol for the driver
+ to use to stop the device.
+ @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
+ @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
+ if NumberOfChildren is 0.
+
+ @retval EFI_SUCCESS The device was stopped.
+ @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
+
+**/
+EFI_STATUS
+EFIAPI
+I2cHostDriverStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ )
+{
+ EFI_STATUS Status;
+ I2C_HOST_CONTEXT *I2cHostContext;
+ EFI_I2C_HOST_PROTOCOL *I2cHost;
+ EFI_TPL TplPrevious;
+
+ TplPrevious = EfiGetCurrentTpl ();
+ if (TplPrevious > TPL_I2C_SYNC) {
+ DEBUG ((EFI_D_ERROR, "I2cHost: TPL %d is too high in Stop.\n", TplPrevious));
+ return EFI_DEVICE_ERROR;
+ }
+
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiI2cHostProtocolGuid,
+ (VOID **) &I2cHost,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ I2cHostContext = I2C_HOST_CONTEXT_FROM_PROTOCOL (I2cHost);
+
+ //
+ // Raise TPL for critical section
+ //
+ TplPrevious = gBS->RaiseTPL (TPL_I2C_SYNC);
+
+ //
+ // If there is pending request or pending bus configuration, do not stop
+ //
+ Status = EFI_DEVICE_ERROR;
+ if (( !I2cHostContext->I2cBusConfigurationManagementPending )
+ && IsListEmpty (&I2cHostContext->RequestList)) {
+
+ //
+ // Remove the I2C host protocol
+ //
+ Status = gBS->UninstallMultipleProtocolInterfaces (
+ Controller,
+ &gEfiI2cHostProtocolGuid,
+ I2cHost,
+ NULL
+ );
+ }
+
+ //
+ // Leave critical section
+ //
+ gBS->RestoreTPL (TplPrevious);
+ if (!EFI_ERROR (Status)) {
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiI2cBusConfigurationManagementProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ //
+ // Release I2c Host resources
+ //
+ if (I2cHostContext->I2cBusConfigurationEvent != NULL) {
+ gBS->CloseEvent (I2cHostContext->I2cBusConfigurationEvent);
+ I2cHostContext->I2cBusConfigurationEvent = NULL;
+ }
+
+ if (I2cHostContext->I2cEvent != NULL) {
+ gBS->CloseEvent (I2cHostContext->I2cEvent);
+ I2cHostContext->I2cEvent = NULL;
+ }
+
+ FreePool (I2cHostContext);
+ }
+
+ //
+ // Return the stop status
+ //
+ return Status;
+}
+
+/**
+ Handle the I2C bus configuration available event
+
+ This routine is called at TPL_I2C_SYNC.
+
+ @param[in] Event Address of an EFI_EVENT handle
+ @param[in] Context Address of an I2C_HOST_CONTEXT structure
+
+**/
+VOID
+EFIAPI
+I2cHostI2cBusConfigurationAvailable (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ I2C_HOST_CONTEXT *I2cHostContext;
+ EFI_I2C_MASTER_PROTOCOL *I2cMaster;
+ I2C_REQUEST *I2cRequest;
+ LIST_ENTRY *EntryHeader;
+ LIST_ENTRY *Entry;
+ EFI_STATUS Status;
+
+ //
+ // Mark this I2C bus configuration management operation as complete
+ //
+ I2cHostContext = (I2C_HOST_CONTEXT *)Context;
+ I2cMaster = I2cHostContext->I2cMaster;
+ ASSERT (I2cMaster != NULL);
+ //
+ // Clear flag to indicate I2C bus configuration is finished
+ //
+ I2cHostContext->I2cBusConfigurationManagementPending = FALSE;
+
+ //
+ // Validate the completion status
+ //
+ if (EFI_ERROR (I2cHostContext->Status)) {
+ //
+ // Setting I2C bus configuration failed before
+ //
+ I2cHostRequestComplete (I2cHostContext, I2cHostContext->Status);
+
+ //
+ // Unknown I2C bus configuration
+ // Force next operation to enable the I2C bus configuration
+ //
+ I2cHostContext->I2cBusConfiguration = (UINTN) -1;
+
+ //
+ // Do not continue current I2C request
+ //
+ return;
+ }
+
+ //
+ // Get the first request in the link with FIFO order
+ //
+ EntryHeader = &I2cHostContext->RequestList;
+ Entry = GetFirstNode (EntryHeader);
+ I2cRequest = I2C_REQUEST_FROM_ENTRY (Entry);
+
+ //
+ // Update the I2C bus configuration of the current I2C request
+ //
+ I2cHostContext->I2cBusConfiguration = I2cRequest->I2cBusConfiguration;
+
+ //
+ // Start an I2C operation on the host, the status is returned by I2cHostContext->Status
+ //
+ Status = I2cMaster->StartRequest (
+ I2cMaster,
+ I2cRequest->SlaveAddress,
+ I2cRequest->RequestPacket,
+ I2cHostContext->I2cEvent,
+ &I2cHostContext->Status
+ );
+}
+
+/**
+ Complete the current request
+
+ This routine is called at TPL_I2C_SYNC.
+
+ @param[in] I2cHostContext Address of an I2C_HOST_CONTEXT structure.
+ @param[in] Status Status of the I2C operation.
+
+ @return This routine returns the input status value.
+
+**/
+EFI_STATUS
+I2cHostRequestComplete (
+ I2C_HOST_CONTEXT *I2cHostContext,
+ EFI_STATUS Status
+ )
+{
+ I2C_REQUEST *I2cRequest;
+ LIST_ENTRY *EntryHeader;
+ LIST_ENTRY *Entry;
+
+ //
+ // Remove the current I2C request from the list
+ //
+ EntryHeader = &I2cHostContext->RequestList;
+ Entry = GetFirstNode (EntryHeader);
+ I2cRequest = I2C_REQUEST_FROM_ENTRY (Entry);
+
+ //
+ // Save the status for QueueRequest
+ //
+ if ( NULL != I2cRequest->Status ) {
+ *I2cRequest->Status = Status;
+ }
+
+ //
+ // Notify the user of the I2C request completion
+ //
+ if ( NULL != I2cRequest->Event ) {
+ gBS->SignalEvent (I2cRequest->Event);
+ }
+
+ //
+ // Done with this request, remove the current request from list
+ //
+ RemoveEntryList (&I2cRequest->Link);
+ FreePool (I2cRequest->RequestPacket);
+ FreePool (I2cRequest);
+
+ //
+ // If there is more I2C request, start next one
+ //
+ if(!IsListEmpty (EntryHeader)) {
+ I2cHostRequestEnable (I2cHostContext);
+ }
+
+ return Status;
+}
+
+/**
+ Handle the bus available event
+
+ This routine is called at TPL_I2C_SYNC.
+
+ @param[in] Event Address of an EFI_EVENT handle
+ @param[in] Context Address of an I2C_HOST_CONTEXT structure
+
+**/
+VOID
+EFIAPI
+I2cHostRequestCompleteEvent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ I2C_HOST_CONTEXT *I2cHostContext;
+
+ //
+ // Handle the completion event
+ //
+ I2cHostContext = (I2C_HOST_CONTEXT *)Context;
+ I2cHostRequestComplete (I2cHostContext, I2cHostContext->Status);
+}
+
+/**
+ Enable access to the I2C bus configuration
+
+ @param[in] I2cHostContext Address of an I2C_HOST_CONTEXT structure
+
+ @retval EFI_SUCCESS The operation completed successfully.
+ @retval EFI_ABORTED The request did not complete because the driver
+ was shutdown.
+ @retval EFI_BAD_BUFFER_SIZE The WriteBytes or ReadBytes buffer size is too large.
+ @retval EFI_DEVICE_ERROR There was an I2C error (NACK) during the operation.
+ This could indicate the slave device is not present.
+ @retval EFI_INVALID_PARAMETER RequestPacket is NULL
+ @retval EFI_NO_MAPPING Invalid I2cBusConfiguration value
+ @retval EFI_NO_RESPONSE The I2C device is not responding to the
+ slave address. EFI_DEVICE_ERROR may also be
+ returned if the controller can not distinguish
+ when the NACK occurred.
+ @retval EFI_NOT_FOUND I2C slave address exceeds maximum address
+ @retval EFI_NOT_READY I2C bus is busy or operation pending, wait for
+ the event and then read status.
+ @retval EFI_OUT_OF_RESOURCES Insufficient memory for I2C operation
+ @retval EFI_TIMEOUT The transaction did not complete within an internally
+ specified timeout period.
+
+**/
+EFI_STATUS
+I2cHostRequestEnable (
+ I2C_HOST_CONTEXT *I2cHostContext
+ )
+{
+ UINTN I2cBusConfiguration;
+ CONST EFI_I2C_BUS_CONFIGURATION_MANAGEMENT_PROTOCOL *I2cBusConfigurationManagement;
+ I2C_REQUEST *I2cRequest;
+ EFI_STATUS Status;
+ EFI_TPL TplPrevious;
+ LIST_ENTRY *EntryHeader;
+ LIST_ENTRY *Entry;
+
+ //
+ // Assume pending request
+ //
+ Status = EFI_NOT_READY;
+
+ I2cBusConfigurationManagement = I2cHostContext->I2cBusConfigurationManagement;
+
+ //
+ // Validate the I2c bus configuration
+ //
+ EntryHeader = &I2cHostContext->RequestList;
+ Entry = GetFirstNode (EntryHeader);
+ I2cRequest = I2C_REQUEST_FROM_ENTRY (Entry);
+
+ I2cBusConfiguration = I2cRequest->I2cBusConfiguration;
+
+ if (I2cHostContext->I2cBusConfiguration != I2cBusConfiguration ) {
+ //
+ // Set flag to indicate I2C bus configuration is in progress
+ //
+ I2cHostContext->I2cBusConfigurationManagementPending = TRUE;
+ //
+ // Update bus configuration for this device's requesting bus configuration
+ //
+ Status = I2cBusConfigurationManagement->EnableI2cBusConfiguration (
+ I2cBusConfigurationManagement,
+ I2cBusConfiguration,
+ I2cHostContext->I2cBusConfigurationEvent,
+ &I2cHostContext->Status
+ );
+ } else {
+ //
+ // I2C bus configuration is same, no need change configuration and start I2c transaction directly
+ //
+ TplPrevious = gBS->RaiseTPL ( TPL_I2C_SYNC );
+
+ //
+ // Same I2C bus configuration
+ //
+ I2cHostContext->Status = EFI_SUCCESS;
+ I2cHostI2cBusConfigurationAvailable (I2cHostContext->I2cBusConfigurationEvent, I2cHostContext);
+
+ //
+ // Release the thread synchronization
+ //
+ gBS->RestoreTPL ( TplPrevious );
+ }
+ return Status;
+}
+
+/**
+ Queue an I2C operation for execution on the I2C controller.
+
+ This routine must be called at or below TPL_NOTIFY. For synchronous
+ requests this routine must be called at or below TPL_CALLBACK.
+
+ N.B. The typical consumers of this API are the I2C bus driver and
+ on rare occasions the I2C test application. Extreme care must be
+ taken by other consumers of this API to prevent confusing the
+ third party I2C drivers due to a state change at the I2C device
+ which the third party I2C drivers did not initiate. I2C platform
+ drivers may use this API within these guidelines.
+
+ This layer uses the concept of I2C bus configurations to describe
+ the I2C bus. An I2C bus configuration is defined as a unique
+ setting of the multiplexers and switches in the I2C bus which
+ enable access to one or more I2C devices. When using a switch
+ to divide a bus, due to speed differences, the I2C platform layer
+ would define an I2C bus configuration for the I2C devices on each
+ side of the switch. When using a multiplexer, the I2C platform
+ layer defines an I2C bus configuration for each of the selector
+ values required to control the multiplexer. See Figure 1 in the
+ <a href="http://www.nxp.com/documents/user_manual/UM10204.pdf">I<sup>2</sup>C
+ Specification</a> for a complex I2C bus configuration.
+
+ The I2C host driver processes all operations in FIFO order. Prior to
+ performing the operation, the I2C host driver calls the I2C platform
+ driver to reconfigure the switches and multiplexers in the I2C bus
+ enabling access to the specified I2C device. The I2C platform driver
+ also selects the maximum bus speed for the device. After the I2C bus
+ is configured, the I2C host driver calls the I2C port driver to
+ initialize the I2C controller and start the I2C operation.
+
+ @param[in] This Address of an EFI_I2C_HOST_PROTOCOL instance.
+ @param[in] I2cBusConfiguration I2C bus configuration to access the I2C
+ device.
+ @param[in] SlaveAddress Address of the device on the I2C bus.
+ @param[in] Event Event to set for asynchronous operations,
+ NULL for synchronous operations
+ @param[in] RequestPacket Address of an EFI_I2C_REQUEST_PACKET
+ structure describing the I2C operation
+ @param[out] I2cStatus Optional buffer to receive the I2C operation
+ completion status
+
+ @retval EFI_SUCCESS The operation completed successfully.
+ @retval EFI_ABORTED The request did not complete because the driver
+ was shutdown.
+ @retval EFI_BAD_BUFFER_SIZE The WriteBytes or ReadBytes buffer size is too large.
+ @retval EFI_DEVICE_ERROR There was an I2C error (NACK) during the operation.
+ This could indicate the slave device is not present.
+ @retval EFI_INVALID_PARAMETER RequestPacket is NULL
+ @retval EFI_INVALID_PARAMETER TPL is too high
+ @retval EFI_NO_MAPPING Invalid I2cBusConfiguration value
+ @retval EFI_NO_RESPONSE The I2C device is not responding to the
+ slave address. EFI_DEVICE_ERROR may also be
+ returned if the controller can not distinguish
+ when the NACK occurred.
+ @retval EFI_NOT_FOUND I2C slave address exceeds maximum address
+ @retval EFI_NOT_READY I2C bus is busy or operation pending, wait for
+ the event and then read status pointed to by
+ the request packet.
+ @retval EFI_OUT_OF_RESOURCES Insufficient memory for I2C operation
+ @retval EFI_TIMEOUT The transaction did not complete within an internally
+ specified timeout period.
+
+**/
+EFI_STATUS
+EFIAPI
+I2cHostQueueRequest (
+ IN CONST EFI_I2C_HOST_PROTOCOL *This,
+ IN UINTN I2cBusConfiguration,
+ IN UINTN SlaveAddress,
+ IN EFI_EVENT Event OPTIONAL,
+ IN EFI_I2C_REQUEST_PACKET *RequestPacket,
+ OUT EFI_STATUS *I2cStatus OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ EFI_EVENT SyncEvent;
+ EFI_TPL TplPrevious;
+ I2C_REQUEST *I2cRequest;
+ I2C_HOST_CONTEXT *I2cHostContext;
+ BOOLEAN FirstRequest;
+ UINTN RequestPacketSize;
+
+ SyncEvent = NULL;
+ FirstRequest = FALSE;
+ Status = EFI_SUCCESS;
+
+ if (RequestPacket == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ I2cHostContext = I2C_HOST_CONTEXT_FROM_PROTOCOL (This);
+
+ if (Event == NULL) {
+ //
+ // For synchronous transaction, register an event used to wait for finishing synchronous transaction
+ //
+ Status = gBS->CreateEvent (
+ 0,
+ TPL_I2C_SYNC,
+ NULL,
+ NULL,
+ &SyncEvent
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ //
+ // TPL should be at or below TPL_NOTIFY.
+ // For synchronous requests this routine must be called at or below TPL_CALLBACK.
+ //
+ TplPrevious = EfiGetCurrentTpl ();
+ if ((TplPrevious > TPL_I2C_SYNC) || ((Event == NULL) && (TplPrevious > TPL_CALLBACK))) {
+ DEBUG ((EFI_D_ERROR, "ERROR - TPL %d is too high!\n", TplPrevious));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Allocate the request structure
+ //
+ I2cRequest = AllocateZeroPool (sizeof (I2C_REQUEST));
+ if (I2cRequest == NULL) {
+ DEBUG ((EFI_D_ERROR, "WARNING - Failed to allocate I2C_REQUEST!\n"));
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Initialize the request
+ //
+ I2cRequest->Signature = I2C_REQUEST_SIGNATURE;
+ I2cRequest->I2cBusConfiguration = I2cBusConfiguration;
+ I2cRequest->SlaveAddress = SlaveAddress;
+ I2cRequest->Event = (Event == NULL) ? SyncEvent : Event;
+ I2cRequest->Status = I2cStatus;
+
+ //
+ // Copy request packet into private buffer, as RequestPacket may be freed during asynchronous transaction
+ //
+ RequestPacketSize = sizeof (UINTN) + RequestPacket->OperationCount * sizeof (EFI_I2C_OPERATION);
+ I2cRequest->RequestPacket = AllocateZeroPool (RequestPacketSize);
+ CopyMem (I2cRequest->RequestPacket, RequestPacket, RequestPacketSize);
+
+ //
+ // Synchronize with the other threads
+ //
+ gBS->RaiseTPL ( TPL_I2C_SYNC );
+
+ FirstRequest = IsListEmpty (&I2cHostContext->RequestList);
+
+ //
+ // Insert new I2C request in the list
+ //
+ InsertTailList (&I2cHostContext->RequestList, &I2cRequest->Link);
+
+ //
+ // Release the thread synchronization
+ //
+ gBS->RestoreTPL (TplPrevious);
+
+ if (FirstRequest) {
+ //
+ // Start the first I2C request, then the subsequent of I2C request will continue
+ //
+ Status = I2cHostRequestEnable (I2cHostContext);
+ }
+
+ if (Event != NULL) {
+ //
+ // For asynchronous, return EFI_SUCCESS indicating that the asynchronously I2C transaction was queued.
+ // No real I2C operation status in I2cStatus
+ //
+ return EFI_SUCCESS;
+ }
+
+ //
+ // For synchronous transaction, wait for the operation completion
+ //
+ do {
+ Status = gBS->CheckEvent (SyncEvent);
+ } while (Status == EFI_NOT_READY);
+
+ //
+ // Get the I2C operation status
+ //
+ Status = I2cHostContext->Status;
+
+ //
+ // Return the I2C operation status
+ //
+ if (I2cStatus != NULL) {
+ *I2cStatus = Status;
+ }
+
+ //
+ // Close the event if necessary
+ //
+ if (SyncEvent != NULL) {
+ gBS->CloseEvent (SyncEvent);
+ }
+
+ return Status;
+}
+
+/**
+ The user Entry Point for I2C host module. The user code starts with this function.
+
+ @param[in] ImageHandle The firmware allocated handle for the EFI image.
+ @param[in] SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The entry point is executed successfully.
+ @retval other Some error occurs when executing this entry point.
+
+**/
+EFI_STATUS
+EFIAPI
+InitializeI2cHost(
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Install driver model protocol(s).
+ //
+ Status = EfiLibInstallDriverBindingComponentName2 (
+ ImageHandle,
+ SystemTable,
+ &gI2cHostDriverBinding,
+ ImageHandle,
+ &gI2cHostComponentName,
+ &gI2cHostComponentName2
+ );
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
+
+/**
+ This is the unload handle for I2C host module.
+
+ Disconnect the driver specified by ImageHandle from all the devices in the handle database.
+ Uninstall all the protocols installed in the driver entry point.
+
+ @param[in] ImageHandle The drivers' driver image.
+
+ @retval EFI_SUCCESS The image is unloaded.
+ @retval Others Failed to unload the image.
+
+**/
+EFI_STATUS
+EFIAPI
+I2cHostUnload (
+ IN EFI_HANDLE ImageHandle
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE *DeviceHandleBuffer;
+ UINTN DeviceHandleCount;
+ UINTN Index;
+
+ //
+ // Get the list of all I2C Controller handles in the handle database.
+ // If there is an error getting the list, then the unload
+ // operation fails.
+ //
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiI2cHostProtocolGuid,
+ NULL,
+ &DeviceHandleCount,
+ &DeviceHandleBuffer
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Disconnect the driver specified by ImageHandle from all
+ // the devices in the handle database.
+ //
+ for (Index = 0; Index < DeviceHandleCount; Index++) {
+ Status = gBS->DisconnectController (
+ DeviceHandleBuffer[Index],
+ ImageHandle,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+ }
+
+ //
+ // Uninstall all the protocols installed in the driver entry point
+ //
+ Status = gBS->UninstallMultipleProtocolInterfaces (
+ gI2cHostDriverBinding.DriverBindingHandle,
+ &gEfiDriverBindingProtocolGuid,
+ &gI2cHostDriverBinding,
+ &gEfiComponentNameProtocolGuid,
+ &gI2cHostComponentName,
+ &gEfiComponentName2ProtocolGuid,
+ &gI2cHostComponentName2,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+Done:
+ //
+ // Free the buffer containing the list of handles from the handle database
+ //
+ if (DeviceHandleBuffer != NULL) {
+ gBS->FreePool (DeviceHandleBuffer);
+ }
+
+ return Status;
+}
diff --git a/MdeModulePkg/Bus/I2c/I2cDxe/I2cHostDxe.inf b/MdeModulePkg/Bus/I2c/I2cDxe/I2cHostDxe.inf
new file mode 100644
index 000000000..ebd9fcac4
--- /dev/null
+++ b/MdeModulePkg/Bus/I2c/I2cDxe/I2cHostDxe.inf
@@ -0,0 +1,53 @@
+## @file
+# This driver produce I2C Host Protocol on I2C controller handle.
+#
+# Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>
+#
+# 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]
+ INF_VERSION = 0x00010005
+ BASE_NAME = I2cHostDxe
+ FILE_GUID = CDEC3671-816E-43DC-A002-DCD645229338
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = InitializeI2cHost
+ UNLOAD_IMAGE = I2cHostUnload
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources.common]
+ I2cDxe.h
+ I2cHost.c
+
+[LibraryClasses]
+ BaseMemoryLib
+ DebugLib
+ DevicePathLib
+ MemoryAllocationLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+ UefiLib
+
+[Packages]
+ MdePkg/MdePkg.dec
+
+[Protocols]
+ gEfiI2cIoProtocolGuid ## BY_START
+ gEfiI2cHostProtocolGuid ## BY_START
+ gEfiI2cMasterProtocolGuid ## TO_START
+ gEfiI2cEnumerateProtocolGuid ## TO_START
+ gEfiI2cBusConfigurationManagementProtocolGuid ## TO_START
+ gEfiI2cHostProtocolGuid ## TO_START
diff --git a/MdeModulePkg/Bus/Pci/EhciDxe/EhciDebug.c b/MdeModulePkg/Bus/Pci/EhciDxe/EhciDebug.c
index 54b56de9f..76368b474 100644
--- a/MdeModulePkg/Bus/Pci/EhciDxe/EhciDebug.c
+++ b/MdeModulePkg/Bus/Pci/EhciDxe/EhciDebug.c
@@ -2,7 +2,7 @@
This file provides the information dump support for EHCI when in debug mode.
-Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2007 - 2013, Intel Corporation. All rights reserved.<BR>
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
@@ -28,38 +28,38 @@ EhcDumpStatus (
)
{
if (EHC_BIT_IS_SET (State, QTD_STAT_DO_PING)) {
- DEBUG ((EFI_D_INFO, " Do_Ping"));
+ DEBUG ((EFI_D_VERBOSE, " Do_Ping"));
} else {
- DEBUG ((EFI_D_INFO, " Do_Out"));
+ DEBUG ((EFI_D_VERBOSE, " Do_Out"));
}
if (EHC_BIT_IS_SET (State, QTD_STAT_DO_CS)) {
- DEBUG ((EFI_D_INFO, " Do_CS"));
+ DEBUG ((EFI_D_VERBOSE, " Do_CS"));
} else {
- DEBUG ((EFI_D_INFO, " Do_SS"));
+ DEBUG ((EFI_D_VERBOSE, " Do_SS"));
}
if (EHC_BIT_IS_SET (State, QTD_STAT_TRANS_ERR)) {
- DEBUG ((EFI_D_INFO, " Transfer_Error"));
+ DEBUG ((EFI_D_VERBOSE, " Transfer_Error"));
}
if (EHC_BIT_IS_SET (State, QTD_STAT_BABBLE_ERR)) {
- DEBUG ((EFI_D_INFO, " Babble_Error"));
+ DEBUG ((EFI_D_VERBOSE, " Babble_Error"));
}
if (EHC_BIT_IS_SET (State, QTD_STAT_BUFF_ERR)) {
- DEBUG ((EFI_D_INFO, " Buffer_Error"));
+ DEBUG ((EFI_D_VERBOSE, " Buffer_Error"));
}
if (EHC_BIT_IS_SET (State, QTD_STAT_HALTED)) {
- DEBUG ((EFI_D_INFO, " Halted"));
+ DEBUG ((EFI_D_VERBOSE, " Halted"));
}
if (EHC_BIT_IS_SET (State, QTD_STAT_ACTIVE)) {
- DEBUG ((EFI_D_INFO, " Active"));
+ DEBUG ((EFI_D_VERBOSE, " Active"));
}
- DEBUG ((EFI_D_INFO, "\n"));
+ DEBUG ((EFI_D_VERBOSE, "\n"));
}
@@ -80,37 +80,37 @@ EhcDumpQtd (
UINTN Index;
if (Msg != NULL) {
- DEBUG ((EFI_D_INFO, Msg));
+ DEBUG ((EFI_D_VERBOSE, Msg));
}
- DEBUG ((EFI_D_INFO, "Queue TD @ 0x%p, data length %d\n", Qtd, (UINT32)Qtd->DataLen));
+ DEBUG ((EFI_D_VERBOSE, "Queue TD @ 0x%p, data length %d\n", Qtd, (UINT32)Qtd->DataLen));
QtdHw = &Qtd->QtdHw;
- DEBUG ((EFI_D_INFO, "Next QTD : %x\n", QtdHw->NextQtd));
- DEBUG ((EFI_D_INFO, "AltNext QTD : %x\n", QtdHw->AltNext));
- DEBUG ((EFI_D_INFO, "Status : %x\n", QtdHw->Status));
+ DEBUG ((EFI_D_VERBOSE, "Next QTD : %x\n", QtdHw->NextQtd));
+ DEBUG ((EFI_D_VERBOSE, "AltNext QTD : %x\n", QtdHw->AltNext));
+ DEBUG ((EFI_D_VERBOSE, "Status : %x\n", QtdHw->Status));
EhcDumpStatus (QtdHw->Status);
if (QtdHw->Pid == QTD_PID_SETUP) {
- DEBUG ((EFI_D_INFO, "PID : Setup\n"));
+ DEBUG ((EFI_D_VERBOSE, "PID : Setup\n"));
} else if (QtdHw->Pid == QTD_PID_INPUT) {
- DEBUG ((EFI_D_INFO, "PID : IN\n"));
+ DEBUG ((EFI_D_VERBOSE, "PID : IN\n"));
} else if (QtdHw->Pid == QTD_PID_OUTPUT) {
- DEBUG ((EFI_D_INFO, "PID : OUT\n"));
+ DEBUG ((EFI_D_VERBOSE, "PID : OUT\n"));
}
- DEBUG ((EFI_D_INFO, "Error Count : %d\n", QtdHw->ErrCnt));
- DEBUG ((EFI_D_INFO, "Current Page : %d\n", QtdHw->CurPage));
- DEBUG ((EFI_D_INFO, "IOC : %d\n", QtdHw->Ioc));
- DEBUG ((EFI_D_INFO, "Total Bytes : %d\n", QtdHw->TotalBytes));
- DEBUG ((EFI_D_INFO, "Data Toggle : %d\n", QtdHw->DataToggle));
+ DEBUG ((EFI_D_VERBOSE, "Error Count : %d\n", QtdHw->ErrCnt));
+ DEBUG ((EFI_D_VERBOSE, "Current Page : %d\n", QtdHw->CurPage));
+ DEBUG ((EFI_D_VERBOSE, "IOC : %d\n", QtdHw->Ioc));
+ DEBUG ((EFI_D_VERBOSE, "Total Bytes : %d\n", QtdHw->TotalBytes));
+ DEBUG ((EFI_D_VERBOSE, "Data Toggle : %d\n", QtdHw->DataToggle));
for (Index = 0; Index < 5; Index++) {
- DEBUG ((EFI_D_INFO, "Page[%d] : 0x%x\n", (UINT32)Index, QtdHw->Page[Index]));
+ DEBUG ((EFI_D_VERBOSE, "Page[%d] : 0x%x\n", (UINT32)Index, QtdHw->Page[Index]));
}
}
@@ -136,60 +136,60 @@ EhcDumpQh (
UINTN Index;
if (Msg != NULL) {
- DEBUG ((EFI_D_INFO, Msg));
+ DEBUG ((EFI_D_VERBOSE, Msg));
}
- DEBUG ((EFI_D_INFO, "Queue head @ 0x%p, interval %ld, next qh %p\n",
+ DEBUG ((EFI_D_VERBOSE, "Queue head @ 0x%p, interval %ld, next qh %p\n",
Qh, (UINT64)Qh->Interval, Qh->NextQh));
QhHw = &Qh->QhHw;
- DEBUG ((EFI_D_INFO, "Hoziontal link: %x\n", QhHw->HorizonLink));
- DEBUG ((EFI_D_INFO, "Device address: %d\n", QhHw->DeviceAddr));
- DEBUG ((EFI_D_INFO, "Inactive : %d\n", QhHw->Inactive));
- DEBUG ((EFI_D_INFO, "EP number : %d\n", QhHw->EpNum));
- DEBUG ((EFI_D_INFO, "EP speed : %d\n", QhHw->EpSpeed));
- DEBUG ((EFI_D_INFO, "DT control : %d\n", QhHw->DtCtrl));
- DEBUG ((EFI_D_INFO, "Reclaim head : %d\n", QhHw->ReclaimHead));
- DEBUG ((EFI_D_INFO, "Max packet len: %d\n", QhHw->MaxPacketLen));
- DEBUG ((EFI_D_INFO, "Ctrl EP : %d\n", QhHw->CtrlEp));
- DEBUG ((EFI_D_INFO, "Nak reload : %d\n", QhHw->NakReload));
-
- DEBUG ((EFI_D_INFO, "SMask : %x\n", QhHw->SMask));
- DEBUG ((EFI_D_INFO, "CMask : %x\n", QhHw->CMask));
- DEBUG ((EFI_D_INFO, "Hub address : %d\n", QhHw->HubAddr));
- DEBUG ((EFI_D_INFO, "Hub port : %d\n", QhHw->PortNum));
- DEBUG ((EFI_D_INFO, "Multiplier : %d\n", QhHw->Multiplier));
-
- DEBUG ((EFI_D_INFO, "Cur QTD : %x\n", QhHw->CurQtd));
-
- DEBUG ((EFI_D_INFO, "Next QTD : %x\n", QhHw->NextQtd));
- DEBUG ((EFI_D_INFO, "AltNext QTD : %x\n", QhHw->AltQtd));
- DEBUG ((EFI_D_INFO, "Status : %x\n", QhHw->Status));
+ DEBUG ((EFI_D_VERBOSE, "Hoziontal link: %x\n", QhHw->HorizonLink));
+ DEBUG ((EFI_D_VERBOSE, "Device address: %d\n", QhHw->DeviceAddr));
+ DEBUG ((EFI_D_VERBOSE, "Inactive : %d\n", QhHw->Inactive));
+ DEBUG ((EFI_D_VERBOSE, "EP number : %d\n", QhHw->EpNum));
+ DEBUG ((EFI_D_VERBOSE, "EP speed : %d\n", QhHw->EpSpeed));
+ DEBUG ((EFI_D_VERBOSE, "DT control : %d\n", QhHw->DtCtrl));
+ DEBUG ((EFI_D_VERBOSE, "Reclaim head : %d\n", QhHw->ReclaimHead));
+ DEBUG ((EFI_D_VERBOSE, "Max packet len: %d\n", QhHw->MaxPacketLen));
+ DEBUG ((EFI_D_VERBOSE, "Ctrl EP : %d\n", QhHw->CtrlEp));
+ DEBUG ((EFI_D_VERBOSE, "Nak reload : %d\n", QhHw->NakReload));
+
+ DEBUG ((EFI_D_VERBOSE, "SMask : %x\n", QhHw->SMask));
+ DEBUG ((EFI_D_VERBOSE, "CMask : %x\n", QhHw->CMask));
+ DEBUG ((EFI_D_VERBOSE, "Hub address : %d\n", QhHw->HubAddr));
+ DEBUG ((EFI_D_VERBOSE, "Hub port : %d\n", QhHw->PortNum));
+ DEBUG ((EFI_D_VERBOSE, "Multiplier : %d\n", QhHw->Multiplier));
+
+ DEBUG ((EFI_D_VERBOSE, "Cur QTD : %x\n", QhHw->CurQtd));
+
+ DEBUG ((EFI_D_VERBOSE, "Next QTD : %x\n", QhHw->NextQtd));
+ DEBUG ((EFI_D_VERBOSE, "AltNext QTD : %x\n", QhHw->AltQtd));
+ DEBUG ((EFI_D_VERBOSE, "Status : %x\n", QhHw->Status));
EhcDumpStatus (QhHw->Status);
if (QhHw->Pid == QTD_PID_SETUP) {
- DEBUG ((EFI_D_INFO, "PID : Setup\n"));
+ DEBUG ((EFI_D_VERBOSE, "PID : Setup\n"));
} else if (QhHw->Pid == QTD_PID_INPUT) {
- DEBUG ((EFI_D_INFO, "PID : IN\n"));
+ DEBUG ((EFI_D_VERBOSE, "PID : IN\n"));
} else if (QhHw->Pid == QTD_PID_OUTPUT) {
- DEBUG ((EFI_D_INFO, "PID : OUT\n"));
+ DEBUG ((EFI_D_VERBOSE, "PID : OUT\n"));
}
- DEBUG ((EFI_D_INFO, "Error Count : %d\n", QhHw->ErrCnt));
- DEBUG ((EFI_D_INFO, "Current Page : %d\n", QhHw->CurPage));
- DEBUG ((EFI_D_INFO, "IOC : %d\n", QhHw->Ioc));
- DEBUG ((EFI_D_INFO, "Total Bytes : %d\n", QhHw->TotalBytes));
- DEBUG ((EFI_D_INFO, "Data Toggle : %d\n", QhHw->DataToggle));
+ DEBUG ((EFI_D_VERBOSE, "Error Count : %d\n", QhHw->ErrCnt));
+ DEBUG ((EFI_D_VERBOSE, "Current Page : %d\n", QhHw->CurPage));
+ DEBUG ((EFI_D_VERBOSE, "IOC : %d\n", QhHw->Ioc));
+ DEBUG ((EFI_D_VERBOSE, "Total Bytes : %d\n", QhHw->TotalBytes));
+ DEBUG ((EFI_D_VERBOSE, "Data Toggle : %d\n", QhHw->DataToggle));
for (Index = 0; Index < 5; Index++) {
- DEBUG ((EFI_D_INFO, "Page[%d] : 0x%x\n", Index, QhHw->Page[Index]));
+ DEBUG ((EFI_D_VERBOSE, "Page[%d] : 0x%x\n", Index, QhHw->Page[Index]));
}
- DEBUG ((EFI_D_INFO, "\n"));
+ DEBUG ((EFI_D_VERBOSE, "\n"));
EFI_LIST_FOR_EACH (Entry, &Qh->Qtds) {
Qtd = EFI_LIST_CONTAINER (Entry, EHC_QTD, QtdList);
@@ -219,13 +219,13 @@ EhcDumpBuf (
for (Index = 0; Index < Len; Index++) {
if (Index % 16 == 0) {
- DEBUG ((EFI_D_INFO,"\n"));
+ DEBUG ((EFI_D_VERBOSE,"\n"));
}
- DEBUG ((EFI_D_INFO, "%02x ", Buf[Index]));
+ DEBUG ((EFI_D_VERBOSE, "%02x ", Buf[Index]));
}
- DEBUG ((EFI_D_INFO, "\n"));
+ DEBUG ((EFI_D_VERBOSE, "\n"));
}
/**
@@ -241,18 +241,18 @@ EhcDumpRegs (
{
UINT8 Index;
- DEBUG ((EFI_D_INFO, " EHC_CAPLENGTH_OFFSET = 0x%08x\n", EhcReadCapRegister (Ehc, EHC_CAPLENGTH_OFFSET)));
- DEBUG ((EFI_D_INFO, " EHC_HCSPARAMS_OFFSET = 0x%08x\n", EhcReadCapRegister (Ehc, EHC_HCSPARAMS_OFFSET)));
- DEBUG ((EFI_D_INFO, " EHC_HCCPARAMS_OFFSET = 0x%08x\n", EhcReadCapRegister (Ehc, EHC_HCCPARAMS_OFFSET)));
- DEBUG ((EFI_D_INFO, " EHC_USBCMD_OFFSET = 0x%08x\n", EhcReadOpReg (Ehc, EHC_USBCMD_OFFSET)));
- DEBUG ((EFI_D_INFO, " EHC_USBSTS_OFFSET = 0x%08x\n", EhcReadOpReg (Ehc, EHC_USBSTS_OFFSET)));
- DEBUG ((EFI_D_INFO, " EHC_USBINTR_OFFSET = 0x%08x\n", EhcReadOpReg (Ehc, EHC_USBINTR_OFFSET)));
- DEBUG ((EFI_D_INFO, " EHC_FRINDEX_OFFSET = 0x%08x\n", EhcReadOpReg (Ehc, EHC_FRINDEX_OFFSET)));
- DEBUG ((EFI_D_INFO, " EHC_CTRLDSSEG_OFFSET = 0x%08x\n", EhcReadOpReg (Ehc, EHC_CTRLDSSEG_OFFSET)));
- DEBUG ((EFI_D_INFO, " EHC_FRAME_BASE_OFFSET = 0x%08x\n", EhcReadOpReg (Ehc, EHC_FRAME_BASE_OFFSET)));
- DEBUG ((EFI_D_INFO, " EHC_ASYNC_HEAD_OFFSET = 0x%08x\n", EhcReadOpReg (Ehc, EHC_ASYNC_HEAD_OFFSET)));
- DEBUG ((EFI_D_INFO, " EHC_CONFIG_FLAG_OFFSET = 0x%08x\n", EhcReadOpReg (Ehc, EHC_CONFIG_FLAG_OFFSET)));
+ DEBUG ((EFI_D_VERBOSE, " EHC_CAPLENGTH_OFFSET = 0x%08x\n", EhcReadCapRegister (Ehc, EHC_CAPLENGTH_OFFSET)));
+ DEBUG ((EFI_D_VERBOSE, " EHC_HCSPARAMS_OFFSET = 0x%08x\n", EhcReadCapRegister (Ehc, EHC_HCSPARAMS_OFFSET)));
+ DEBUG ((EFI_D_VERBOSE, " EHC_HCCPARAMS_OFFSET = 0x%08x\n", EhcReadCapRegister (Ehc, EHC_HCCPARAMS_OFFSET)));
+ DEBUG ((EFI_D_VERBOSE, " EHC_USBCMD_OFFSET = 0x%08x\n", EhcReadOpReg (Ehc, EHC_USBCMD_OFFSET)));
+ DEBUG ((EFI_D_VERBOSE, " EHC_USBSTS_OFFSET = 0x%08x\n", EhcReadOpReg (Ehc, EHC_USBSTS_OFFSET)));
+ DEBUG ((EFI_D_VERBOSE, " EHC_USBINTR_OFFSET = 0x%08x\n", EhcReadOpReg (Ehc, EHC_USBINTR_OFFSET)));
+ DEBUG ((EFI_D_VERBOSE, " EHC_FRINDEX_OFFSET = 0x%08x\n", EhcReadOpReg (Ehc, EHC_FRINDEX_OFFSET)));
+ DEBUG ((EFI_D_VERBOSE, " EHC_CTRLDSSEG_OFFSET = 0x%08x\n", EhcReadOpReg (Ehc, EHC_CTRLDSSEG_OFFSET)));
+ DEBUG ((EFI_D_VERBOSE, " EHC_FRAME_BASE_OFFSET = 0x%08x\n", EhcReadOpReg (Ehc, EHC_FRAME_BASE_OFFSET)));
+ DEBUG ((EFI_D_VERBOSE, " EHC_ASYNC_HEAD_OFFSET = 0x%08x\n", EhcReadOpReg (Ehc, EHC_ASYNC_HEAD_OFFSET)));
+ DEBUG ((EFI_D_VERBOSE, " EHC_CONFIG_FLAG_OFFSET = 0x%08x\n", EhcReadOpReg (Ehc, EHC_CONFIG_FLAG_OFFSET)));
for (Index = 0; Index < (UINT8) (Ehc->HcStructParams & HCSP_NPORTS); Index++) {
- DEBUG ((EFI_D_INFO, " EHC_PORT_STAT_OFFSET(%d) = 0x%08x\n", Index, EhcReadOpReg (Ehc, EHC_PORT_STAT_OFFSET + (4 * Index))));
+ DEBUG ((EFI_D_VERBOSE, " EHC_PORT_STAT_OFFSET(%d) = 0x%08x\n", Index, EhcReadOpReg (Ehc, EHC_PORT_STAT_OFFSET + (4 * Index))));
}
}
diff --git a/MdeModulePkg/Bus/Pci/EhciDxe/EhciSched.c b/MdeModulePkg/Bus/Pci/EhciDxe/EhciSched.c
index 4dc8e1abf..5594e6699 100644
--- a/MdeModulePkg/Bus/Pci/EhciDxe/EhciSched.c
+++ b/MdeModulePkg/Bus/Pci/EhciDxe/EhciSched.c
@@ -2,7 +2,7 @@
EHCI transfer scheduling routines.
-Copyright (c) 2007 - 2011, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2007 - 2013, Intel Corporation. All rights reserved.<BR>
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
@@ -641,13 +641,13 @@ EhcCheckUrbResult (
//
PciAddr = UsbHcGetPciAddressForHostMem (Ehc->MemPool, Ehc->ShortReadStop, sizeof (EHC_QTD));
if (QtdHw->AltNext == QTD_LINK (PciAddr, FALSE)) {
- DEBUG ((EFI_D_INFO, "EhcCheckUrbResult: Short packet read, break\n"));
+ DEBUG ((EFI_D_VERBOSE, "EhcCheckUrbResult: Short packet read, break\n"));
Finished = TRUE;
goto ON_EXIT;
}
- DEBUG ((EFI_D_INFO, "EhcCheckUrbResult: Short packet read, continue\n"));
+ DEBUG ((EFI_D_VERBOSE, "EhcCheckUrbResult: Short packet read, continue\n"));
}
}
}
@@ -694,7 +694,7 @@ EhcExecTransfer (
BOOLEAN InfiniteLoop;
Status = EFI_SUCCESS;
- Loop = (TimeOut * EHC_1_MILLISECOND / EHC_SYNC_POLL_INTERVAL) + 1;
+ Loop = TimeOut * EHC_1_MILLISECOND;
Finished = FALSE;
InfiniteLoop = FALSE;
@@ -714,7 +714,7 @@ EhcExecTransfer (
break;
}
- gBS->Stall (EHC_SYNC_POLL_INTERVAL);
+ gBS->Stall (EHC_1_MICROSECOND);
}
if (!Finished) {
diff --git a/MdeModulePkg/Bus/Pci/EhciDxe/UsbHcMem.c b/MdeModulePkg/Bus/Pci/EhciDxe/UsbHcMem.c
index baac29df6..28be3803f 100644
--- a/MdeModulePkg/Bus/Pci/EhciDxe/UsbHcMem.c
+++ b/MdeModulePkg/Bus/Pci/EhciDxe/UsbHcMem.c
@@ -2,7 +2,7 @@
Routine procedures for memory allocate/free.
-Copyright (c) 2007 - 2009, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2007 - 2013, Intel Corporation. All rights reserved.<BR>
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
@@ -476,7 +476,7 @@ UsbHcAllocateMem (
NewBlock = UsbHcAllocMemBlock (Pool, Pages);
if (NewBlock == NULL) {
- DEBUG ((EFI_D_INFO, "UsbHcAllocateMem: failed to allocate block\n"));
+ DEBUG ((EFI_D_ERROR, "UsbHcAllocateMem: failed to allocate block\n"));
return NULL;
}
diff --git a/MdeModulePkg/Bus/Pci/EhciPei/EhcPeim.c b/MdeModulePkg/Bus/Pci/EhciPei/EhcPeim.c
index cefdf0991..09769eaf2 100644
--- a/MdeModulePkg/Bus/Pci/EhciPei/EhcPeim.c
+++ b/MdeModulePkg/Bus/Pci/EhciPei/EhcPeim.c
@@ -2,7 +2,7 @@
PEIM to produce gPeiUsb2HostControllerPpiGuid based on gPeiUsbControllerPpiGuid
which is used to enable recovery function from USB Drivers.
-Copyright (c) 2010 - 2012, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2010 - 2013, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions
@@ -532,6 +532,8 @@ EhcInitHC (
the subsequent bulk transfer.
@param TimeOut Indicates the maximum time, in millisecond, which the
transfer is allowed to complete.
+ If Timeout is 0, then the caller must wait for the function
+ to be completed until EFI_SUCCESS or EFI_DEVICE_ERROR is returned.
@param Translator A pointr to the transaction translator data.
@param TransferResult A pointer to the detailed result information of the
bulk transfer.
@@ -995,6 +997,8 @@ ON_EXIT:
@param Data Data buffer to be transmitted or received from USB device.
@param DataLength The size (in bytes) of the data buffer.
@param TimeOut Indicates the maximum timeout, in millisecond.
+ If Timeout is 0, then the caller must wait for the function
+ to be completed until EFI_SUCCESS or EFI_DEVICE_ERROR is returned.
@param Translator Transaction translator to be used by this device.
@param TransferResult Return the result of this control transfer.
diff --git a/MdeModulePkg/Bus/Pci/EhciPei/EhciSched.c b/MdeModulePkg/Bus/Pci/EhciPei/EhciSched.c
index 1821a278d..e992d4f28 100644
--- a/MdeModulePkg/Bus/Pci/EhciPei/EhciSched.c
+++ b/MdeModulePkg/Bus/Pci/EhciPei/EhciSched.c
@@ -2,7 +2,7 @@
PEIM to produce gPeiUsb2HostControllerPpiGuid based on gPeiUsbControllerPpiGuid
which is used to enable recovery function from USB Drivers.
-Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2010 - 2013, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions
@@ -425,19 +425,29 @@ EhcExecTransfer (
UINTN Index;
UINTN Loop;
BOOLEAN Finished;
+ BOOLEAN InfiniteLoop;
Status = EFI_SUCCESS;
- Loop = (TimeOut * EHC_1_MILLISECOND / EHC_SYNC_POLL_INTERVAL) + 1;
- Finished = FALSE;
+ Loop = TimeOut * EHC_1_MILLISECOND;
+ Finished = FALSE;
+ InfiniteLoop = FALSE;
- for (Index = 0; Index < Loop; Index++) {
+ //
+ // If Timeout is 0, then the caller must wait for the function to be completed
+ // until EFI_SUCCESS or EFI_DEVICE_ERROR is returned.
+ //
+ if (TimeOut == 0) {
+ InfiniteLoop = TRUE;
+ }
+
+ for (Index = 0; InfiniteLoop || (Index < Loop); Index++) {
Finished = EhcCheckUrbResult (Ehc, Urb);
if (Finished) {
break;
}
- MicroSecondDelay (EHC_SYNC_POLL_INTERVAL);
+ MicroSecondDelay (EHC_1_MICROSECOND);
}
if (!Finished) {
diff --git a/MdeModulePkg/Bus/Pci/NvmExpressDxe/ComponentName.c b/MdeModulePkg/Bus/Pci/NvmExpressDxe/ComponentName.c
new file mode 100644
index 000000000..60849aea0
--- /dev/null
+++ b/MdeModulePkg/Bus/Pci/NvmExpressDxe/ComponentName.c
@@ -0,0 +1,233 @@
+/** @file
+ NvmExpressDxe driver is used to manage non-volatile memory subsystem which follows
+ NVM Express specification.
+
+ Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>
+ 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 "NvmExpress.h"
+
+//
+// EFI Component Name Protocol
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gNvmExpressComponentName = {
+ NvmExpressComponentNameGetDriverName,
+ NvmExpressComponentNameGetControllerName,
+ "eng"
+};
+
+//
+// EFI Component Name 2 Protocol
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gNvmExpressComponentName2 = {
+ (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) NvmExpressComponentNameGetDriverName,
+ (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) NvmExpressComponentNameGetControllerName,
+ "en"
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mNvmExpressDriverNameTable[] = {
+ { "eng;en", L"NVM Express Driver" },
+ { NULL, NULL }
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mNvmExpressControllerNameTable[] = {
+ { "eng;en", L"NVM Express Controller" },
+ { NULL, NULL }
+};
+
+/**
+ Retrieves a Unicode string that is the user readable name of the driver.
+
+ This function retrieves the user readable name of a driver in the form of a
+ Unicode string. If the driver specified by This has a user readable name in
+ the language specified by Language, then a pointer to the driver name is
+ returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
+ by This does not support the language specified by Language,
+ then EFI_UNSUPPORTED is returned.
+
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param Language[in] A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified
+ in RFC 4646 or ISO 639-2 language code format.
+
+ @param DriverName[out] A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ driver specified by This in the language
+ specified by Language.
+
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by
+ This and the language specified by Language was
+ returned in DriverName.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER DriverName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+NvmExpressComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ )
+{
+ return LookupUnicodeString2 (
+ Language,
+ This->SupportedLanguages,
+ mNvmExpressDriverNameTable,
+ DriverName,
+ (BOOLEAN)(This == &gNvmExpressComponentName)
+ );
+}
+
+/**
+ Retrieves a Unicode string that is the user readable name of the controller
+ that is being managed by a driver.
+
+ This function retrieves the user readable name of the controller specified by
+ ControllerHandle and ChildHandle in the form of a Unicode string. If the
+ driver specified by This has a user readable name in the language specified by
+ Language, then a pointer to the controller name is returned in ControllerName,
+ and EFI_SUCCESS is returned. If the driver specified by This is not currently
+ managing the controller specified by ControllerHandle and ChildHandle,
+ then EFI_UNSUPPORTED is returned. If the driver specified by This does not
+ support the language specified by Language, then EFI_UNSUPPORTED is returned.
+
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param ControllerHandle[in] The handle of a controller that the driver
+ specified by This is managing. This handle
+ specifies the controller whose name is to be
+ returned.
+
+ @param ChildHandle[in] The handle of the child controller to retrieve
+ the name of. This is an optional parameter that
+ may be NULL. It will be NULL for device
+ drivers. It will also be NULL for a bus drivers
+ that wish to retrieve the name of the bus
+ controller. It will not be NULL for a bus
+ driver that wishes to retrieve the name of a
+ child controller.
+
+ @param Language[in] A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified in
+ RFC 4646 or ISO 639-2 language code format.
+
+ @param ControllerName[out] A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ controller specified by ControllerHandle and
+ ChildHandle in the language specified by
+ Language from the point of view of the driver
+ specified by This.
+
+ @retval EFI_SUCCESS The Unicode string for the user readable name in
+ the language specified by Language for the
+ driver specified by This was returned in
+ DriverName.
+
+ @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
+
+ @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
+ EFI_HANDLE.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This is not currently
+ managing the controller specified by
+ ControllerHandle and ChildHandle.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+NvmExpressComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ )
+{
+ EFI_STATUS Status;
+ EFI_BLOCK_IO_PROTOCOL *BlockIo;
+ NVME_DEVICE_PRIVATE_DATA *Device;
+ EFI_UNICODE_STRING_TABLE *ControllerNameTable;
+
+ //
+ // Make sure this driver is currently managing ControllHandle
+ //
+ Status = EfiTestManagedDevice (
+ ControllerHandle,
+ gNvmExpressDriverBinding.DriverBindingHandle,
+ &gEfiPciIoProtocolGuid
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ ControllerNameTable = mNvmExpressControllerNameTable;
+ if (ChildHandle != NULL) {
+ Status = EfiTestChildHandle (
+ ControllerHandle,
+ ChildHandle,
+ &gEfiPciIoProtocolGuid
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Get the child context
+ //
+ Status = gBS->OpenProtocol (
+ ChildHandle,
+ &gEfiBlockIoProtocolGuid,
+ (VOID **) &BlockIo,
+ gNvmExpressDriverBinding.DriverBindingHandle,
+ ChildHandle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+ Device = NVME_DEVICE_PRIVATE_DATA_FROM_BLOCK_IO (BlockIo);
+ ControllerNameTable = Device->ControllerNameTable;
+ }
+
+ return LookupUnicodeString2 (
+ Language,
+ This->SupportedLanguages,
+ ControllerNameTable,
+ ControllerName,
+ (BOOLEAN)(This == &gNvmExpressComponentName)
+ );
+
+}
diff --git a/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpress.c b/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpress.c
new file mode 100644
index 000000000..b6729ce71
--- /dev/null
+++ b/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpress.c
@@ -0,0 +1,1057 @@
+/** @file
+ NvmExpressDxe driver is used to manage non-volatile memory subsystem which follows
+ NVM Express specification.
+
+ Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>
+ 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 "NvmExpress.h"
+
+//
+// NVM Express Driver Binding Protocol Instance
+//
+EFI_DRIVER_BINDING_PROTOCOL gNvmExpressDriverBinding = {
+ NvmExpressDriverBindingSupported,
+ NvmExpressDriverBindingStart,
+ NvmExpressDriverBindingStop,
+ 0x10,
+ NULL,
+ NULL
+};
+
+//
+// NVM Express EFI Driver Supported EFI Version Protocol Instance
+//
+EFI_DRIVER_SUPPORTED_EFI_VERSION_PROTOCOL gNvmExpressDriverSupportedEfiVersion = {
+ sizeof (EFI_DRIVER_SUPPORTED_EFI_VERSION_PROTOCOL), // Size of Protocol structure.
+ 0 // Version number to be filled at start up.
+};
+
+/**
+ Check if the specified Nvm Express device namespace is active, and create child handles
+ for them with BlockIo and DiskInfo protocol instances.
+
+ @param[in] Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
+ @param[in] NamespaceId The NVM Express namespace ID for which a device path node is to be
+ allocated and built. Caller must set the NamespaceId to zero if the
+ device path node will contain a valid UUID.
+ @param[in] NamespaceUuid The NVM Express namespace UUID for which a device path node is to be
+ allocated and built. UUID will only be valid of the Namespace ID is zero.
+
+ @retval EFI_SUCCESS All the namespaces in the device are successfully enumerated.
+ @return Others Some error occurs when enumerating the namespaces.
+
+**/
+EFI_STATUS
+EnumerateNvmeDevNamespace (
+ IN NVME_CONTROLLER_PRIVATE_DATA *Private,
+ UINT32 NamespaceId,
+ UINT64 NamespaceUuid
+ )
+{
+ NVME_ADMIN_NAMESPACE_DATA *NamespaceData;
+ EFI_DEVICE_PATH_PROTOCOL *NewDevicePathNode;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ EFI_HANDLE DeviceHandle;
+ EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath;
+ NVME_DEVICE_PRIVATE_DATA *Device;
+ EFI_STATUS Status;
+ UINT32 Lbads;
+ UINT32 Flbas;
+ UINT32 LbaFmtIdx;
+
+ NewDevicePathNode = NULL;
+ DevicePath = NULL;
+ Device = NULL;
+
+ //
+ // Allocate a buffer for Identify Namespace data
+ //
+ NamespaceData = AllocateZeroPool(sizeof (NVME_ADMIN_NAMESPACE_DATA));
+ if(NamespaceData == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ ParentDevicePath = Private->ParentDevicePath;
+ //
+ // Identify Namespace
+ //
+ Status = NvmeIdentifyNamespace (
+ Private,
+ NamespaceId,
+ (VOID *)NamespaceData
+ );
+ if (EFI_ERROR(Status)) {
+ goto Exit;
+ }
+ //
+ // Validate Namespace
+ //
+ if (NamespaceData->Ncap == 0) {
+ Status = EFI_DEVICE_ERROR;
+ } else {
+ //
+ // allocate device private data for each discovered namespace
+ //
+ Device = AllocateZeroPool(sizeof(NVME_DEVICE_PRIVATE_DATA));
+ if (Device == NULL) {
+ goto Exit;
+ }
+
+ //
+ // Initialize SSD namespace instance data
+ //
+ Device->Signature = NVME_DEVICE_PRIVATE_DATA_SIGNATURE;
+ Device->NamespaceId = NamespaceId;
+ Device->NamespaceUuid = NamespaceData->Eui64;
+
+ Device->ControllerHandle = Private->ControllerHandle;
+ Device->DriverBindingHandle = Private->DriverBindingHandle;
+ Device->Controller = Private;
+
+ //
+ // Build BlockIo media structure
+ //
+ Device->Media.MediaId = 0;
+ Device->Media.RemovableMedia = FALSE;
+ Device->Media.MediaPresent = TRUE;
+ Device->Media.LogicalPartition = FALSE;
+ Device->Media.ReadOnly = FALSE;
+ Device->Media.WriteCaching = FALSE;
+
+ Flbas = NamespaceData->Flbas;
+ LbaFmtIdx = Flbas & 3;
+ Lbads = NamespaceData->LbaFormat[LbaFmtIdx].Lbads;
+ Device->Media.BlockSize = (UINT32)1 << Lbads;
+
+ Device->Media.LastBlock = NamespaceData->Nsze - 1;
+ Device->Media.LogicalBlocksPerPhysicalBlock = 1;
+ Device->Media.LowestAlignedLba = 1;
+
+ //
+ // Create BlockIo Protocol instance
+ //
+ Device->BlockIo.Revision = EFI_BLOCK_IO_PROTOCOL_REVISION2;
+ Device->BlockIo.Media = &Device->Media;
+ Device->BlockIo.Reset = NvmeBlockIoReset;
+ Device->BlockIo.ReadBlocks = NvmeBlockIoReadBlocks;
+ Device->BlockIo.WriteBlocks = NvmeBlockIoWriteBlocks;
+ Device->BlockIo.FlushBlocks = NvmeBlockIoFlushBlocks;
+
+ //
+ // Create DiskInfo Protocol instance
+ //
+ InitializeDiskInfo (Device);
+
+ //
+ // Create a Nvm Express Namespace Device Path Node
+ //
+ Status = Private->Passthru.BuildDevicePath (
+ &Private->Passthru,
+ Device->NamespaceId,
+ Device->NamespaceUuid,
+ &NewDevicePathNode
+ );
+
+ if (EFI_ERROR(Status)) {
+ goto Exit;
+ }
+
+ //
+ // Append the SSD node to the controller's device path
+ //
+ DevicePath = AppendDevicePathNode (ParentDevicePath, NewDevicePathNode);
+ if (DevicePath == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Exit;
+ }
+
+ DeviceHandle = NULL;
+ RemainingDevicePath = DevicePath;
+ Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &RemainingDevicePath, &DeviceHandle);
+ if (!EFI_ERROR (Status) && (DeviceHandle != NULL) && IsDevicePathEnd(RemainingDevicePath)) {
+ Status = EFI_ALREADY_STARTED;
+ FreePool (DevicePath);
+ goto Exit;
+ }
+
+ Device->DevicePath = DevicePath;
+
+ //
+ // Make sure the handle is NULL so we create a new handle
+ //
+ Device->DeviceHandle = NULL;
+
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &Device->DeviceHandle,
+ &gEfiDevicePathProtocolGuid,
+ Device->DevicePath,
+ &gEfiBlockIoProtocolGuid,
+ &Device->BlockIo,
+ &gEfiDiskInfoProtocolGuid,
+ &Device->DiskInfo,
+ NULL
+ );
+
+ if(EFI_ERROR(Status)) {
+ goto Exit;
+ }
+ gBS->OpenProtocol (
+ Private->ControllerHandle,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &Private->PciIo,
+ Private->DriverBindingHandle,
+ Device->DeviceHandle,
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
+ );
+
+ //
+ // Build controller name for Component Name (2) protocol.
+ //
+ UnicodeSPrintAsciiFormat (Device->ModelName, sizeof (Device->ModelName), "%a-%a-%x", Private->ControllerData->Sn, Private->ControllerData->Mn, NamespaceData->Eui64);
+
+ AddUnicodeString2 (
+ "eng",
+ gNvmExpressComponentName.SupportedLanguages,
+ &Device->ControllerNameTable,
+ Device->ModelName,
+ TRUE
+ );
+
+ AddUnicodeString2 (
+ "en",
+ gNvmExpressComponentName2.SupportedLanguages,
+ &Device->ControllerNameTable,
+ Device->ModelName,
+ FALSE
+ );
+ }
+
+Exit:
+ if(NamespaceData != NULL) {
+ FreePool (NamespaceData);
+ }
+
+ if(EFI_ERROR(Status) && (Device != NULL) && (Device->DevicePath != NULL)) {
+ FreePool (Device->DevicePath);
+ }
+ if(EFI_ERROR(Status) && (Device != NULL)) {
+ FreePool (Device);
+ }
+ return Status;
+}
+
+/**
+ Discover all Nvm Express device namespaces, and create child handles for them with BlockIo
+ and DiskInfo protocol instances.
+
+ @param[in] Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
+
+ @retval EFI_SUCCESS All the namespaces in the device are successfully enumerated.
+ @return Others Some error occurs when enumerating the namespaces.
+
+**/
+EFI_STATUS
+DiscoverAllNamespaces (
+ IN NVME_CONTROLLER_PRIVATE_DATA *Private
+ )
+{
+ EFI_STATUS Status;
+ UINT32 NamespaceId;
+ UINT64 NamespaceUuid;
+ NVM_EXPRESS_PASS_THRU_PROTOCOL *Passthru;
+
+ NamespaceId = 0xFFFFFFFF;
+ NamespaceUuid = 0;
+ Passthru = &Private->Passthru;
+
+ while (TRUE) {
+ Status = Passthru->GetNextNamespace (
+ Passthru,
+ (UINT32 *)&NamespaceId,
+ (UINT64 *)&NamespaceUuid
+ );
+
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+
+ Status = EnumerateNvmeDevNamespace (
+ Private,
+ NamespaceId,
+ NamespaceUuid
+ );
+
+ if (EFI_ERROR(Status)) {
+ continue;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Unregisters a Nvm Express device namespace.
+
+ This function removes the protocols installed on the controller handle and
+ frees the resources allocated for the namespace.
+
+ @param This The pointer to EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param Controller The controller handle of the namespace.
+ @param Handle The child handle.
+
+ @retval EFI_SUCCESS The namespace is successfully unregistered.
+ @return Others Some error occurs when unregistering the namespace.
+
+**/
+EFI_STATUS
+UnregisterNvmeNamespace (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_HANDLE Handle
+ )
+{
+ EFI_STATUS Status;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ EFI_BLOCK_IO_PROTOCOL *BlockIo;
+ NVME_DEVICE_PRIVATE_DATA *Device;
+
+ BlockIo = NULL;
+
+ Status = gBS->OpenProtocol (
+ Handle,
+ &gEfiBlockIoProtocolGuid,
+ (VOID **) &BlockIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Device = NVME_DEVICE_PRIVATE_DATA_FROM_BLOCK_IO (BlockIo);
+
+ //
+ // Close the child handle
+ //
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Handle
+ );
+
+ //
+ // The Nvm Express driver installs the BlockIo and DiskInfo in the DriverBindingStart().
+ // Here should uninstall both of them.
+ //
+ Status = gBS->UninstallMultipleProtocolInterfaces (
+ Handle,
+ &gEfiDevicePathProtocolGuid,
+ Device->DevicePath,
+ &gEfiBlockIoProtocolGuid,
+ &Device->BlockIo,
+ &gEfiDiskInfoProtocolGuid,
+ &Device->DiskInfo,
+ NULL
+ );
+
+ if (EFI_ERROR (Status)) {
+ gBS->OpenProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIo,
+ This->DriverBindingHandle,
+ Handle,
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
+ );
+ return Status;
+ }
+
+ if(Device->DevicePath != NULL) {
+ FreePool (Device->DevicePath);
+ }
+
+ if (Device->ControllerNameTable != NULL) {
+ FreeUnicodeStringTable (Device->ControllerNameTable);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Tests to see if this driver supports a given controller. If a child device is provided,
+ it further tests to see if this driver supports creating a handle for the specified child device.
+
+ This function checks to see if the driver specified by This supports the device specified by
+ ControllerHandle. Drivers will typically use the device path attached to
+ ControllerHandle and/or the services from the bus I/O abstraction attached to
+ ControllerHandle to determine if the driver supports ControllerHandle. This function
+ may be called many times during platform initialization. In order to reduce boot times, the tests
+ performed by this function must be very small, and take as little time as possible to execute. This
+ function must not change the state of any hardware devices, and this function must be aware that the
+ device specified by ControllerHandle may already be managed by the same driver or a
+ different driver. This function must match its calls to AllocatePages() with FreePages(),
+ AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
+ Since ControllerHandle may have been previously started by the same driver, if a protocol is
+ already in the opened state, then it must not be closed with CloseProtocol(). This is required
+ to guarantee the state of ControllerHandle is not modified by this function.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of the controller to test. This handle
+ must support a protocol interface that supplies
+ an I/O abstraction to the driver.
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
+ parameter is ignored by device drivers, and is optional for bus
+ drivers. For bus drivers, if this parameter is not NULL, then
+ the bus driver must determine if the bus controller specified
+ by ControllerHandle and the child controller specified
+ by RemainingDevicePath are both supported by this
+ bus driver.
+
+ @retval EFI_SUCCESS The device specified by ControllerHandle and
+ RemainingDevicePath is supported by the driver specified by This.
+ @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
+ RemainingDevicePath is already being managed by the driver
+ specified by This.
+ @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
+ RemainingDevicePath is already being managed by a different
+ driver or an application that requires exclusive access.
+ Currently not implemented.
+ @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
+ RemainingDevicePath is not supported by the driver specified by This.
+**/
+EFI_STATUS
+EFIAPI
+NvmExpressDriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+{
+ EFI_STATUS Status;
+ EFI_DEV_PATH_PTR DevicePathNode;
+ EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ UINT8 ClassCode[3];
+
+ //
+ // Check whether device path is valid
+ //
+ if (RemainingDevicePath != NULL) {
+ //
+ // Check if RemainingDevicePath is the End of Device Path Node,
+ // if yes, go on checking other conditions
+ //
+ if (!IsDevicePathEnd (RemainingDevicePath)) {
+ //
+ // If RemainingDevicePath isn't the End of Device Path Node,
+ // check its validation
+ //
+ DevicePathNode.DevPath = RemainingDevicePath;
+
+ if ((DevicePathNode.DevPath->Type != MESSAGING_DEVICE_PATH) ||
+ (DevicePathNode.DevPath->SubType != MSG_NVME_NAMESPACE_DP) ||
+ DevicePathNodeLength(DevicePathNode.DevPath) != sizeof(NVME_NAMESPACE_DEVICE_PATH)) {
+ return EFI_UNSUPPORTED;
+ }
+ }
+ }
+
+ //
+ // Open the EFI Device Path protocol needed to perform the supported test
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ (VOID **) &ParentDevicePath,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (Status == EFI_ALREADY_STARTED) {
+ return EFI_SUCCESS;
+ }
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Close protocol, don't use device path protocol in the Support() function
+ //
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ //
+ // Attempt to Open PCI I/O Protocol
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (Status == EFI_ALREADY_STARTED) {
+ return EFI_SUCCESS;
+ }
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Now further check the PCI header: Base class (offset 0x0B) and Sub Class (offset 0x0A).
+ // This controller should be a Nvm Express controller.
+ //
+ Status = PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint8,
+ PCI_CLASSCODE_OFFSET,
+ sizeof (ClassCode),
+ ClassCode
+ );
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ //
+ // Examine Nvm Express controller PCI Configuration table fields
+ //
+ if ((ClassCode[0] != PCI_IF_NVMHCI) || (ClassCode[1] != PCI_CLASS_MASS_STORAGE_NVM) || (ClassCode[2] != PCI_CLASS_MASS_STORAGE)) {
+ Status = EFI_UNSUPPORTED;
+ }
+
+Done:
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ return Status;
+}
+
+
+/**
+ Starts a device controller or a bus controller.
+
+ The Start() function is designed to be invoked from the EFI boot service ConnectController().
+ As a result, much of the error checking on the parameters to Start() has been moved into this
+ common boot service. It is legal to call Start() from other locations,
+ but the following calling restrictions must be followed or the system behavior will not be deterministic.
+ 1. ControllerHandle must be a valid EFI_HANDLE.
+ 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
+ EFI_DEVICE_PATH_PROTOCOL.
+ 3. Prior to calling Start(), the Supported() function for the driver specified by This must
+ have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of the controller to start. This handle
+ must support a protocol interface that supplies
+ an I/O abstraction to the driver.
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
+ parameter is ignored by device drivers, and is optional for bus
+ drivers. For a bus driver, if this parameter is NULL, then handles
+ for all the children of Controller are created by this driver.
+ If this parameter is not NULL and the first Device Path Node is
+ not the End of Device Path Node, then only the handle for the
+ child device specified by the first Device Path Node of
+ RemainingDevicePath is created by this driver.
+ If the first Device Path Node of RemainingDevicePath is
+ the End of Device Path Node, no child handle is created by this
+ driver.
+
+ @retval EFI_SUCCESS The device was started.
+ @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ @retval Others The driver failded to start the device.
+
+**/
+EFI_STATUS
+EFIAPI
+NvmExpressDriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+{
+ EFI_STATUS Status;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ NVME_CONTROLLER_PRIVATE_DATA *Private;
+ EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
+ UINT32 NamespaceId;
+ UINT64 NamespaceUuid;
+ EFI_PHYSICAL_ADDRESS MappedAddr;
+ UINTN Bytes;
+
+ DEBUG ((EFI_D_INFO, "NvmExpressDriverBindingStart: start\n"));
+
+ Private = NULL;
+ ParentDevicePath = NULL;
+
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ (VOID **) &ParentDevicePath,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if ((EFI_ERROR (Status)) && (Status != EFI_ALREADY_STARTED)) {
+ return Status;
+ }
+
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+
+ if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {
+ return Status;
+ }
+
+ //
+ // Check EFI_ALREADY_STARTED to reuse the original NVME_CONTROLLER_PRIVATE_DATA.
+ //
+ if (Status != EFI_ALREADY_STARTED) {
+ Private = AllocateZeroPool (sizeof (NVME_CONTROLLER_PRIVATE_DATA));
+
+ if (Private == NULL) {
+ DEBUG ((EFI_D_ERROR, "NvmExpressDriverBindingStart: allocating pool for Nvme Private Data failed!\n"));
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Exit2;
+ }
+
+ //
+ // 4 x 4kB aligned buffers will be carved out of this buffer.
+ // 1st 4kB boundary is the start of the admin submission queue.
+ // 2nd 4kB boundary is the start of the admin completion queue.
+ // 3rd 4kB boundary is the start of I/O submission queue #1.
+ // 4th 4kB boundary is the start of I/O completion queue #1.
+ //
+ // Allocate 4 pages of memory, then map it for bus master read and write.
+ //
+ Status = PciIo->AllocateBuffer (
+ PciIo,
+ AllocateAnyPages,
+ EfiBootServicesData,
+ 6,
+ (VOID**)&Private->Buffer,
+ 0
+ );
+ if (EFI_ERROR (Status)) {
+ goto Exit2;
+ }
+
+ Bytes = EFI_PAGES_TO_SIZE (4);
+ Status = PciIo->Map (
+ PciIo,
+ EfiPciIoOperationBusMasterCommonBuffer,
+ Private->Buffer,
+ &Bytes,
+ &MappedAddr,
+ &Private->Mapping
+ );
+
+ if (EFI_ERROR (Status) || (Bytes != EFI_PAGES_TO_SIZE (4))) {
+ goto Exit2;
+ }
+
+ Private->BufferPciAddr = (UINT8 *)(UINTN)MappedAddr;
+ ZeroMem (Private->Buffer, EFI_PAGES_TO_SIZE (4));
+
+ Private->Signature = NVME_CONTROLLER_PRIVATE_DATA_SIGNATURE;
+ Private->ControllerHandle = Controller;
+ Private->ImageHandle = This->DriverBindingHandle;
+ Private->DriverBindingHandle = This->DriverBindingHandle;
+ Private->PciIo = PciIo;
+ Private->ParentDevicePath = ParentDevicePath;
+ Private->Passthru.Mode = &Private->PassThruMode;
+ Private->Passthru.PassThru = NvmExpressPassThru;
+ Private->Passthru.GetNextNamespace = NvmExpressGetNextNamespace;
+ Private->Passthru.BuildDevicePath = NvmExpressBuildDevicePath;
+ Private->Passthru.GetNamespace = NvmExpressGetNamespace;
+ Private->PassThruMode.Attributes = NVM_EXPRESS_PASS_THRU_ATTRIBUTES_PHYSICAL;
+
+ Status = NvmeControllerInit (Private);
+
+ if (EFI_ERROR(Status)) {
+ goto Exit2;
+ }
+
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &Controller,
+ &gEfiCallerIdGuid,
+ Private,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ goto Exit2;
+ }
+ } else {
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiCallerIdGuid,
+ (VOID **) &Private,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ Private = NULL;
+ goto Exit1;
+ }
+ }
+
+ if (RemainingDevicePath == NULL) {
+ //
+ // Enumerate all NVME namespaces in the controller
+ //
+ Status = DiscoverAllNamespaces (
+ Private
+ );
+
+ } else if (!IsDevicePathEnd (RemainingDevicePath)) {
+ //
+ // Enumerate the specified NVME namespace
+ //
+ Status = Private->Passthru.GetNamespace (
+ &Private->Passthru,
+ RemainingDevicePath,
+ &NamespaceId,
+ &NamespaceUuid
+ );
+
+ if (!EFI_ERROR (Status)) {
+ Status = EnumerateNvmeDevNamespace (
+ Private,
+ NamespaceId,
+ NamespaceUuid
+ );
+ }
+ }
+
+ DEBUG ((EFI_D_INFO, "NvmExpressDriverBindingStart: end successfully\n"));
+ return EFI_SUCCESS;
+
+Exit1:
+ gBS->UninstallMultipleProtocolInterfaces (
+ Controller,
+ &gEfiCallerIdGuid,
+ Private,
+ NULL
+ );
+Exit2:
+ if ((Private != NULL) && (Private->Mapping != NULL)) {
+ PciIo->Unmap (PciIo, Private->Mapping);
+ }
+
+ if ((Private != NULL) && (Private->Buffer != NULL)) {
+ PciIo->FreeBuffer (PciIo, 4, Private->Buffer);
+ }
+
+ if (Private != NULL) {
+ FreePool (Private);
+ }
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ DEBUG ((EFI_D_INFO, "NvmExpressDriverBindingStart: end with %r\n", Status));
+
+ return Status;
+}
+
+
+/**
+ Stops a device controller or a bus controller.
+
+ The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
+ As a result, much of the error checking on the parameters to Stop() has been moved
+ into this common boot service. It is legal to call Stop() from other locations,
+ but the following calling restrictions must be followed or the system behavior will not be deterministic.
+ 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
+ same driver's Start() function.
+ 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
+ EFI_HANDLE. In addition, all of these handles must have been created in this driver's
+ Start() function, and the Start() function must have called OpenProtocol() on
+ ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle A handle to the device being stopped. The handle must
+ support a bus specific I/O protocol for the driver
+ to use to stop the device.
+ @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
+ @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
+ if NumberOfChildren is 0.
+
+ @retval EFI_SUCCESS The device was stopped.
+ @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
+
+**/
+EFI_STATUS
+EFIAPI
+NvmExpressDriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ )
+{
+ EFI_STATUS Status;
+ BOOLEAN AllChildrenStopped;
+ UINTN Index;
+ NVME_CONTROLLER_PRIVATE_DATA *Private;
+
+ if (NumberOfChildren == 0) {
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiCallerIdGuid,
+ (VOID **) &Private,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+
+ if (!EFI_ERROR (Status)) {
+ gBS->UninstallMultipleProtocolInterfaces (
+ Controller,
+ &gEfiCallerIdGuid,
+ Private,
+ NULL
+ );
+
+ if (Private->Mapping != NULL) {
+ Private->PciIo->Unmap (Private->PciIo, Private->Mapping);
+ }
+
+ if (Private->Buffer != NULL) {
+ Private->PciIo->FreeBuffer (Private->PciIo, 4, Private->Buffer);
+ }
+
+ FreePool (Private->ControllerData);
+ FreePool (Private);
+ }
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ return EFI_SUCCESS;
+ }
+
+ AllChildrenStopped = TRUE;
+
+ for (Index = 0; Index < NumberOfChildren; Index++) {
+ Status = UnregisterNvmeNamespace (This, Controller, ChildHandleBuffer[Index]);
+ if (EFI_ERROR (Status)) {
+ AllChildrenStopped = FALSE;
+ }
+ }
+
+ if (!AllChildrenStopped) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This is the unload handle for the NVM Express driver.
+
+ Disconnect the driver specified by ImageHandle from the NVMe device in the handle database.
+ Uninstall all the protocols installed in the driver.
+
+ @param[in] ImageHandle The drivers' driver image.
+
+ @retval EFI_SUCCESS The image is unloaded.
+ @retval Others Failed to unload the image.
+
+**/
+EFI_STATUS
+EFIAPI
+NvmExpressUnload (
+ IN EFI_HANDLE ImageHandle
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE *DeviceHandleBuffer;
+ UINTN DeviceHandleCount;
+ UINTN Index;
+ EFI_DRIVER_BINDING_PROTOCOL *DriverBinding;
+ EFI_COMPONENT_NAME_PROTOCOL *ComponentName;
+ EFI_COMPONENT_NAME2_PROTOCOL *ComponentName2;
+
+ //
+ // Get the list of all the handles in the handle database.
+ // If there is an error getting the list, then the unload
+ // operation fails.
+ //
+ Status = gBS->LocateHandleBuffer (
+ AllHandles,
+ NULL,
+ NULL,
+ &DeviceHandleCount,
+ &DeviceHandleBuffer
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Disconnect the driver specified by ImageHandle from all
+ // the devices in the handle database.
+ //
+ for (Index = 0; Index < DeviceHandleCount; Index++) {
+ Status = gBS->DisconnectController (
+ DeviceHandleBuffer[Index],
+ ImageHandle,
+ NULL
+ );
+ }
+
+ //
+ // Uninstall all the protocols installed in the driver entry point
+ //
+ for (Index = 0; Index < DeviceHandleCount; Index++) {
+ Status = gBS->HandleProtocol (
+ DeviceHandleBuffer[Index],
+ &gEfiDriverBindingProtocolGuid,
+ (VOID **) &DriverBinding
+ );
+
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ if (DriverBinding->ImageHandle != ImageHandle) {
+ continue;
+ }
+
+ gBS->UninstallProtocolInterface (
+ ImageHandle,
+ &gEfiDriverBindingProtocolGuid,
+ DriverBinding
+ );
+
+ Status = gBS->HandleProtocol (
+ DeviceHandleBuffer[Index],
+ &gEfiComponentNameProtocolGuid,
+ (VOID **) &ComponentName
+ );
+ if (!EFI_ERROR (Status)) {
+ gBS->UninstallProtocolInterface (
+ ImageHandle,
+ &gEfiComponentNameProtocolGuid,
+ ComponentName
+ );
+ }
+
+ Status = gBS->HandleProtocol (
+ DeviceHandleBuffer[Index],
+ &gEfiComponentName2ProtocolGuid,
+ (VOID **) &ComponentName2
+ );
+ if (!EFI_ERROR (Status)) {
+ gBS->UninstallProtocolInterface (
+ ImageHandle,
+ &gEfiComponentName2ProtocolGuid,
+ ComponentName2
+ );
+ }
+ }
+
+ //
+ // Free the buffer containing the list of handles from the handle database
+ //
+ if (DeviceHandleBuffer != NULL) {
+ gBS->FreePool (DeviceHandleBuffer);
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ The entry point for Nvm Express driver, used to install Nvm Express driver on the ImageHandle.
+
+ @param ImageHandle The firmware allocated handle for this driver image.
+ @param SystemTable Pointer to the EFI system table.
+
+ @retval EFI_SUCCESS Driver loaded.
+ @retval other Driver not loaded.
+
+**/
+EFI_STATUS
+EFIAPI
+NvmExpressDriverEntry (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ Status = EfiLibInstallDriverBindingComponentName2 (
+ ImageHandle,
+ SystemTable,
+ &gNvmExpressDriverBinding,
+ ImageHandle,
+ &gNvmExpressComponentName,
+ &gNvmExpressComponentName2
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Install EFI Driver Supported EFI Version Protocol required for
+ // EFI drivers that are on PCI and other plug in cards.
+ //
+ gNvmExpressDriverSupportedEfiVersion.FirmwareVersion = 0x00020028;
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &ImageHandle,
+ &gEfiDriverSupportedEfiVersionProtocolGuid,
+ &gNvmExpressDriverSupportedEfiVersion,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
diff --git a/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpress.h b/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpress.h
new file mode 100644
index 000000000..d39b62e10
--- /dev/null
+++ b/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpress.h
@@ -0,0 +1,614 @@
+/** @file
+ NvmExpressDxe driver is used to manage non-volatile memory subsystem which follows
+ NVM Express specification.
+
+ Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>
+ 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 _EFI_NVM_EXPRESS_H_
+#define _EFI_NVM_EXPRESS_H_
+
+#include <Uefi.h>
+
+#include <IndustryStandard/Pci.h>
+
+#include <Protocol/ComponentName.h>
+#include <Protocol/ComponentName2.h>
+#include <Protocol/DriverBinding.h>
+#include <Protocol/LoadedImage.h>
+#include <Protocol/DevicePath.h>
+#include <Protocol/PciIo.h>
+#include <Protocol/BlockIo.h>
+#include <Protocol/DiskInfo.h>
+#include <Protocol/DriverSupportedEfiVersion.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PrintLib.h>
+#include <Library/UefiLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+
+typedef struct _NVME_CONTROLLER_PRIVATE_DATA NVME_CONTROLLER_PRIVATE_DATA;
+typedef struct _NVME_DEVICE_PRIVATE_DATA NVME_DEVICE_PRIVATE_DATA;
+
+#include "NvmExpressPassthru.h"
+#include "NvmExpressBlockIo.h"
+#include "NvmExpressDiskInfo.h"
+#include "NvmExpressHci.h"
+
+extern EFI_DRIVER_BINDING_PROTOCOL gNvmExpressDriverBinding;
+extern EFI_COMPONENT_NAME_PROTOCOL gNvmExpressComponentName;
+extern EFI_COMPONENT_NAME2_PROTOCOL gNvmExpressComponentName2;
+extern EFI_DRIVER_SUPPORTED_EFI_VERSION_PROTOCOL gNvmExpressDriverSupportedEfiVersion;
+
+#define PCI_CLASS_MASS_STORAGE_NVM 0x08 // mass storage sub-class non-volatile memory.
+#define PCI_IF_NVMHCI 0x02 // mass storage programming interface NVMHCI.
+
+#define NVME_ASQ_SIZE 2 // Number of admin submission queue entries
+#define NVME_ACQ_SIZE 2 // Number of admin completion queue entries
+
+#define NVME_CSQ_SIZE 2 // Number of I/O submission queue entries
+#define NVME_CCQ_SIZE 2 // Number of I/O completion queue entries
+
+#define NVME_MAX_IO_QUEUES 2 // Number of I/O queues supported by the driver
+
+#define NVME_CONTROLLER_ID 0
+
+//
+// Time out value for Nvme transaction execution
+//
+#define NVME_GENERIC_TIMEOUT EFI_TIMER_PERIOD_SECONDS (5)
+
+//
+// Unique signature for private data structure.
+//
+#define NVME_CONTROLLER_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('N','V','M','E')
+
+//
+// Nvme private data structure.
+//
+struct _NVME_CONTROLLER_PRIVATE_DATA {
+ UINT32 Signature;
+
+ EFI_HANDLE ControllerHandle;
+ EFI_HANDLE ImageHandle;
+ EFI_HANDLE DriverBindingHandle;
+
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ UINT64 PciAttributes;
+
+ EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
+
+ NVM_EXPRESS_PASS_THRU_MODE PassThruMode;
+ NVM_EXPRESS_PASS_THRU_PROTOCOL Passthru;
+
+ //
+ // pointer to identify controller data
+ //
+ NVME_ADMIN_CONTROLLER_DATA *ControllerData;
+
+ //
+ // 6 x 4kB aligned buffers will be carved out of this buffer.
+ // 1st 4kB boundary is the start of the admin submission queue.
+ // 2nd 4kB boundary is the start of submission queue #1.
+ // 3rd 4kB boundary is the start of the admin completion queue.
+ // 4th 4kB boundary is the start of completion queue #1.
+ // 5th 4kB boundary is the start of the first PRP list page.
+ // 6th 4kB boundary is the start of the second PRP list page.
+ //
+ UINT8 *Buffer;
+ UINT8 *BufferPciAddr;
+
+ //
+ // Pointers to 4kB aligned submission & completion queues.
+ //
+ NVME_SQ *SqBuffer[NVME_MAX_IO_QUEUES];
+ NVME_CQ *CqBuffer[NVME_MAX_IO_QUEUES];
+ NVME_SQ *SqBufferPciAddr[NVME_MAX_IO_QUEUES];
+ NVME_CQ *CqBufferPciAddr[NVME_MAX_IO_QUEUES];
+
+ //
+ // Submission and completion queue indices.
+ //
+ NVME_SQTDBL SqTdbl[NVME_MAX_IO_QUEUES];
+ NVME_CQHDBL CqHdbl[NVME_MAX_IO_QUEUES];
+
+ UINT8 Pt[2];
+ UINT16 Cid[2];
+
+ //
+ // Nvme controller capabilities
+ //
+ NVME_CAP Cap;
+
+ VOID *Mapping;
+};
+
+#define NVME_CONTROLLER_PRIVATE_DATA_FROM_PASS_THRU(a) \
+ CR (a, \
+ NVME_CONTROLLER_PRIVATE_DATA, \
+ Passthru, \
+ NVME_CONTROLLER_PRIVATE_DATA_SIGNATURE \
+ )
+
+//
+// Unique signature for private data structure.
+//
+#define NVME_DEVICE_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('X','S','S','D')
+
+//
+// Nvme device private data structure
+//
+struct _NVME_DEVICE_PRIVATE_DATA {
+ UINT32 Signature;
+
+ EFI_HANDLE DeviceHandle;
+ EFI_HANDLE ControllerHandle;
+ EFI_HANDLE DriverBindingHandle;
+
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+
+ EFI_UNICODE_STRING_TABLE *ControllerNameTable;
+
+ UINT32 NamespaceId;
+ UINT64 NamespaceUuid;
+
+ EFI_BLOCK_IO_MEDIA Media;
+ EFI_BLOCK_IO_PROTOCOL BlockIo;
+ EFI_DISK_INFO_PROTOCOL DiskInfo;
+
+ EFI_LBA NumBlocks;
+
+ CHAR16 ModelName[80];
+ NVME_ADMIN_NAMESPACE_DATA NamespaceData;
+
+ NVME_CONTROLLER_PRIVATE_DATA *Controller;
+
+};
+
+//
+// Statments to retrieve the private data from produced protocols.
+//
+#define NVME_DEVICE_PRIVATE_DATA_FROM_BLOCK_IO(a) \
+ CR (a, \
+ NVME_DEVICE_PRIVATE_DATA, \
+ BlockIo, \
+ NVME_DEVICE_PRIVATE_DATA_SIGNATURE \
+ )
+
+#define NVME_DEVICE_PRIVATE_DATA_FROM_DISK_INFO(a) \
+ CR (a, \
+ NVME_DEVICE_PRIVATE_DATA, \
+ DiskInfo, \
+ NVME_DEVICE_PRIVATE_DATA_SIGNATURE \
+ )
+
+/**
+ Retrieves a Unicode string that is the user readable name of the driver.
+
+ This function retrieves the user readable name of a driver in the form of a
+ Unicode string. If the driver specified by This has a user readable name in
+ the language specified by Language, then a pointer to the driver name is
+ returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
+ by This does not support the language specified by Language,
+ then EFI_UNSUPPORTED is returned.
+
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param Language[in] A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified
+ in RFC 4646 or ISO 639-2 language code format.
+
+ @param DriverName[out] A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ driver specified by This in the language
+ specified by Language.
+
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by
+ This and the language specified by Language was
+ returned in DriverName.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER DriverName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+NvmExpressComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ );
+
+/**
+ Retrieves a Unicode string that is the user readable name of the controller
+ that is being managed by a driver.
+
+ This function retrieves the user readable name of the controller specified by
+ ControllerHandle and ChildHandle in the form of a Unicode string. If the
+ driver specified by This has a user readable name in the language specified by
+ Language, then a pointer to the controller name is returned in ControllerName,
+ and EFI_SUCCESS is returned. If the driver specified by This is not currently
+ managing the controller specified by ControllerHandle and ChildHandle,
+ then EFI_UNSUPPORTED is returned. If the driver specified by This does not
+ support the language specified by Language, then EFI_UNSUPPORTED is returned.
+
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param ControllerHandle[in] The handle of a controller that the driver
+ specified by This is managing. This handle
+ specifies the controller whose name is to be
+ returned.
+
+ @param ChildHandle[in] The handle of the child controller to retrieve
+ the name of. This is an optional parameter that
+ may be NULL. It will be NULL for device
+ drivers. It will also be NULL for a bus drivers
+ that wish to retrieve the name of the bus
+ controller. It will not be NULL for a bus
+ driver that wishes to retrieve the name of a
+ child controller.
+
+ @param Language[in] A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified in
+ RFC 4646 or ISO 639-2 language code format.
+
+ @param ControllerName[out] A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ controller specified by ControllerHandle and
+ ChildHandle in the language specified by
+ Language from the point of view of the driver
+ specified by This.
+
+ @retval EFI_SUCCESS The Unicode string for the user readable name in
+ the language specified by Language for the
+ driver specified by This was returned in
+ DriverName.
+
+ @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
+
+ @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
+ EFI_HANDLE.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This is not currently
+ managing the controller specified by
+ ControllerHandle and ChildHandle.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+NvmExpressComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ );
+
+/**
+ Tests to see if this driver supports a given controller. If a child device is provided,
+ it further tests to see if this driver supports creating a handle for the specified child device.
+
+ This function checks to see if the driver specified by This supports the device specified by
+ ControllerHandle. Drivers will typically use the device path attached to
+ ControllerHandle and/or the services from the bus I/O abstraction attached to
+ ControllerHandle to determine if the driver supports ControllerHandle. This function
+ may be called many times during platform initialization. In order to reduce boot times, the tests
+ performed by this function must be very small, and take as little time as possible to execute. This
+ function must not change the state of any hardware devices, and this function must be aware that the
+ device specified by ControllerHandle may already be managed by the same driver or a
+ different driver. This function must match its calls to AllocatePages() with FreePages(),
+ AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
+ Since ControllerHandle may have been previously started by the same driver, if a protocol is
+ already in the opened state, then it must not be closed with CloseProtocol(). This is required
+ to guarantee the state of ControllerHandle is not modified by this function.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of the controller to test. This handle
+ must support a protocol interface that supplies
+ an I/O abstraction to the driver.
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
+ parameter is ignored by device drivers, and is optional for bus
+ drivers. For bus drivers, if this parameter is not NULL, then
+ the bus driver must determine if the bus controller specified
+ by ControllerHandle and the child controller specified
+ by RemainingDevicePath are both supported by this
+ bus driver.
+
+ @retval EFI_SUCCESS The device specified by ControllerHandle and
+ RemainingDevicePath is supported by the driver specified by This.
+ @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
+ RemainingDevicePath is already being managed by the driver
+ specified by This.
+ @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
+ RemainingDevicePath is already being managed by a different
+ driver or an application that requires exclusive access.
+ Currently not implemented.
+ @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
+ RemainingDevicePath is not supported by the driver specified by This.
+**/
+EFI_STATUS
+EFIAPI
+NvmExpressDriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ );
+
+/**
+ Starts a device controller or a bus controller.
+
+ The Start() function is designed to be invoked from the EFI boot service ConnectController().
+ As a result, much of the error checking on the parameters to Start() has been moved into this
+ common boot service. It is legal to call Start() from other locations,
+ but the following calling restrictions must be followed or the system behavior will not be deterministic.
+ 1. ControllerHandle must be a valid EFI_HANDLE.
+ 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
+ EFI_DEVICE_PATH_PROTOCOL.
+ 3. Prior to calling Start(), the Supported() function for the driver specified by This must
+ have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of the controller to start. This handle
+ must support a protocol interface that supplies
+ an I/O abstraction to the driver.
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
+ parameter is ignored by device drivers, and is optional for bus
+ drivers. For a bus driver, if this parameter is NULL, then handles
+ for all the children of Controller are created by this driver.
+ If this parameter is not NULL and the first Device Path Node is
+ not the End of Device Path Node, then only the handle for the
+ child device specified by the first Device Path Node of
+ RemainingDevicePath is created by this driver.
+ If the first Device Path Node of RemainingDevicePath is
+ the End of Device Path Node, no child handle is created by this
+ driver.
+
+ @retval EFI_SUCCESS The device was started.
+ @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ @retval Others The driver failded to start the device.
+
+**/
+EFI_STATUS
+EFIAPI
+NvmExpressDriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ );
+
+/**
+ Stops a device controller or a bus controller.
+
+ The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
+ As a result, much of the error checking on the parameters to Stop() has been moved
+ into this common boot service. It is legal to call Stop() from other locations,
+ but the following calling restrictions must be followed or the system behavior will not be deterministic.
+ 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
+ same driver's Start() function.
+ 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
+ EFI_HANDLE. In addition, all of these handles must have been created in this driver's
+ Start() function, and the Start() function must have called OpenProtocol() on
+ ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle A handle to the device being stopped. The handle must
+ support a bus specific I/O protocol for the driver
+ to use to stop the device.
+ @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
+ @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
+ if NumberOfChildren is 0.
+
+ @retval EFI_SUCCESS The device was stopped.
+ @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
+
+**/
+EFI_STATUS
+EFIAPI
+NvmExpressDriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ );
+
+/**
+ Sends an NVM Express Command Packet to an NVM Express controller or namespace. This function supports
+ both blocking I/O and nonblocking I/O. The blocking I/O functionality is required, and the nonblocking
+ I/O functionality is optional.
+
+ @param[in] This A pointer to the NVM_EXPRESS_PASS_THRU_PROTOCOL instance.
+ @param[in] NamespaceId Is a 32 bit Namespace ID to which the Express HCI command packet will be sent.
+ A value of 0 denotes the NVM Express controller, a value of all 0FFh in the namespace
+ ID specifies that the command packet should be sent to all valid namespaces.
+ @param[in] NamespaceUuid Is a 64 bit Namespace UUID to which the Express HCI command packet will be sent.
+ A value of 0 denotes the NVM Express controller, a value of all 0FFh in the namespace
+ UUID specifies that the command packet should be sent to all valid namespaces.
+ @param[in,out] Packet A pointer to the NVM Express HCI Command Packet to send to the NVMe namespace specified
+ by NamespaceId.
+ @param[in] Event If nonblocking I/O is not supported then Event is ignored, and blocking I/O is performed.
+ If Event is NULL, then blocking I/O is performed. If Event is not NULL and non blocking I/O
+ is supported, then nonblocking I/O is performed, and Event will be signaled when the NVM
+ Express Command Packet completes.
+
+ @retval EFI_SUCCESS The NVM Express Command Packet was sent by the host. TransferLength bytes were transferred
+ to, or from DataBuffer.
+ @retval EFI_BAD_BUFFER_SIZE The NVM Express Command Packet was not executed. The number of bytes that could be transferred
+ is returned in TransferLength.
+ @retval EFI_NOT_READY The NVM Express Command Packet could not be sent because the controller is not ready. The caller
+ may retry again later.
+ @retval EFI_DEVICE_ERROR A device error occurred while attempting to send the NVM Express Command Packet.
+ @retval EFI_INVALID_PARAMETER Namespace, or the contents of NVM_EXPRESS_PASS_THRU_COMMAND_PACKET are invalid. The NVM
+ Express Command Packet was not sent, so no additional status information is available.
+ @retval EFI_UNSUPPORTED The command described by the NVM Express Command Packet is not supported by the host adapter.
+ The NVM Express Command Packet was not sent, so no additional status information is available.
+ @retval EFI_TIMEOUT A timeout occurred while waiting for the NVM Express Command Packet to execute.
+
+**/
+EFI_STATUS
+EFIAPI
+NvmExpressPassThru (
+ IN NVM_EXPRESS_PASS_THRU_PROTOCOL *This,
+ IN UINT32 NamespaceId,
+ IN UINT64 NamespaceUuid,
+ IN OUT NVM_EXPRESS_PASS_THRU_COMMAND_PACKET *Packet,
+ IN EFI_EVENT Event OPTIONAL
+ );
+
+/**
+ Used to retrieve the list of namespaces defined on an NVM Express controller.
+
+ The NVM_EXPRESS_PASS_THRU_PROTOCOL.GetNextNamespace() function retrieves a list of namespaces
+ defined on an NVM Express controller. If on input a NamespaceID is specified by all 0xFF in the
+ namespace buffer, then the first namespace defined on the NVM Express controller is returned in
+ NamespaceID, and a status of EFI_SUCCESS is returned.
+
+ If NamespaceId is a Namespace value that was returned on a previous call to GetNextNamespace(),
+ then the next valid NamespaceId for an NVM Express SSD namespace on the NVM Express controller
+ is returned in NamespaceId, and EFI_SUCCESS is returned.
+
+ If Namespace array is not a 0xFFFFFFFF and NamespaceId was not returned on a previous call to
+ GetNextNamespace(), then EFI_INVALID_PARAMETER is returned.
+
+ If NamespaceId is the NamespaceId of the last SSD namespace on the NVM Express controller, then
+ EFI_NOT_FOUND is returned
+
+ @param[in] This A pointer to the NVM_EXPRESS_PASS_THRU_PROTOCOL instance.
+ @param[in,out] NamespaceId On input, a pointer to a legal NamespaceId for an NVM Express
+ namespace present on the NVM Express controller. On output, a
+ pointer to the next NamespaceId of an NVM Express namespace on
+ an NVM Express controller. An input value of 0xFFFFFFFF retrieves
+ the first NamespaceId for an NVM Express namespace present on an
+ NVM Express controller.
+ @param[out] NamespaceUuid On output, the UUID associated with the next namespace, if a UUID
+ is defined for that NamespaceId, otherwise, zero is returned in
+ this parameter. If the caller does not require a UUID, then a NULL
+ pointer may be passed.
+
+ @retval EFI_SUCCESS The NamespaceId of the next Namespace was returned.
+ @retval EFI_NOT_FOUND There are no more namespaces defined on this controller.
+ @retval EFI_INVALID_PARAMETER Namespace array is not a 0xFFFFFFFF and NamespaceId was not returned
+ on a previous call to GetNextNamespace().
+
+**/
+EFI_STATUS
+EFIAPI
+NvmExpressGetNextNamespace (
+ IN NVM_EXPRESS_PASS_THRU_PROTOCOL *This,
+ IN OUT UINT32 *NamespaceId,
+ OUT UINT64 *NamespaceUuid OPTIONAL
+ );
+
+/**
+ Used to translate a device path node to a Target ID and LUN.
+
+ The NVM_EXPRESS_PASS_THRU_PROTOCOL.GetNamwspace() function determines the Namespace ID and Namespace UUID
+ associated with the NVM Express SSD namespace described by DevicePath. If DevicePath is a device path node type
+ that the NVM Express Pass Thru driver supports, then the NVM Express Pass Thru driver will attempt to translate
+ the contents DevicePath into a Namespace ID and UUID. If this translation is successful, then that Namespace ID
+ and UUID are returned in NamespaceID and NamespaceUUID, and EFI_SUCCESS is returned.
+
+ @param[in] This A pointer to the NVM_EXPRESS_PASS_THRU_PROTOCOL instance.
+ @param[in] DevicePath A pointer to the device path node that describes an NVM Express namespace on
+ the NVM Express controller.
+ @param[out] NamespaceId The NVM Express namespace ID contained in the device path node.
+ @param[out] NamespaceUuid The NVM Express namespace contained in the device path node.
+
+ @retval EFI_SUCCESS DevicePath was successfully translated to NamespaceId and NamespaceUuid.
+ @retval EFI_INVALID_PARAMETER If DevicePath, NamespaceId, or NamespaceUuid are NULL, then EFI_INVALID_PARAMETER
+ is returned.
+ @retval EFI_UNSUPPORTED If DevicePath is not a device path node type that the NVM Express Pass Thru driver
+ supports, then EFI_UNSUPPORTED is returned.
+ @retval EFI_NOT_FOUND If DevicePath is a device path node type that the Nvm Express Pass Thru driver
+ supports, but there is not a valid translation from DevicePath to a NamespaceID
+ and NamespaceUuid, then EFI_NOT_FOUND is returned.
+**/
+EFI_STATUS
+EFIAPI
+NvmExpressGetNamespace (
+ IN NVM_EXPRESS_PASS_THRU_PROTOCOL *This,
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ OUT UINT32 *NamespaceId,
+ OUT UINT64 *NamespaceUuid
+ );
+
+/**
+ Used to allocate and build a device path node for an NVM Express namespace on an NVM Express controller.
+
+ The NVM_EXPRESS_PASS_THRU_PROTOCOL.BuildDevicePath() function allocates and builds a single device
+ path node for the NVM Express namespace specified by NamespaceId.
+
+ If the namespace device specified by NamespaceId is not valid , then EFI_NOT_FOUND is returned.
+
+ If DevicePath is NULL, then EFI_INVALID_PARAMETER is returned.
+
+ If there are not enough resources to allocate the device path node, then EFI_OUT_OF_RESOURCES is returned.
+
+ Otherwise, DevicePath is allocated with the boot service AllocatePool(), the contents of DevicePath are
+ initialized to describe the NVM Express namespace specified by NamespaceId, and EFI_SUCCESS is returned.
+
+ @param[in] This A pointer to the NVM_EXPRESS_PASS_THRU_PROTOCOL instance.
+ @param[in] NamespaceId The NVM Express namespace ID for which a device path node is to be
+ allocated and built. Caller must set the NamespaceId to zero if the
+ device path node will contain a valid UUID.
+ @param[in] NamespaceUuid The NVM Express namespace UUID for which a device path node is to be
+ allocated and built. UUID will only be valid of the Namespace ID is zero.
+ @param[in,out] DevicePath A pointer to a single device path node that describes the NVM Express
+ namespace specified by NamespaceId. This function is responsible for
+ allocating the buffer DevicePath with the boot service AllocatePool().
+ It is the caller's responsibility to free DevicePath when the caller
+ is finished with DevicePath.
+ @retval EFI_SUCCESS The device path node that describes the NVM Express namespace specified
+ by NamespaceId was allocated and returned in DevicePath.
+ @retval EFI_NOT_FOUND The NVM Express namespace specified by NamespaceId does not exist on the
+ NVM Express controller.
+ @retval EFI_INVALID_PARAMETER DevicePath is NULL.
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources to allocate the DevicePath node.
+
+**/
+EFI_STATUS
+EFIAPI
+NvmExpressBuildDevicePath (
+ IN NVM_EXPRESS_PASS_THRU_PROTOCOL *This,
+ IN UINT32 NamespaceId,
+ IN UINT64 NamespaceUuid,
+ IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath
+ );
+
+#endif
diff --git a/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressBlockIo.c b/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressBlockIo.c
new file mode 100644
index 000000000..458afd232
--- /dev/null
+++ b/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressBlockIo.c
@@ -0,0 +1,559 @@
+/** @file
+ NvmExpressDxe driver is used to manage non-volatile memory subsystem which follows
+ NVM Express specification.
+
+ Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>
+ 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 "NvmExpress.h"
+
+/**
+ Read some sectors from the device.
+
+ @param Device The pointer to the NVME_DEVICE_PRIVATE_DATA data structure.
+ @param Buffer The buffer used to store the data read from the device.
+ @param Lba The start block number.
+ @param Blocks Total block number to be read.
+
+ @retval EFI_SUCCESS Datum are read from the device.
+ @retval Others Fail to read all the datum.
+
+**/
+EFI_STATUS
+ReadSectors (
+ IN NVME_DEVICE_PRIVATE_DATA *Device,
+ IN UINT64 Buffer,
+ IN UINT64 Lba,
+ IN UINT32 Blocks
+ )
+{
+ NVME_CONTROLLER_PRIVATE_DATA *Controller;
+ UINT32 Bytes;
+ NVM_EXPRESS_PASS_THRU_COMMAND_PACKET CommandPacket;
+ NVM_EXPRESS_COMMAND Command;
+ NVM_EXPRESS_RESPONSE Response;
+ EFI_STATUS Status;
+ UINT32 BlockSize;
+
+ Controller = Device->Controller;
+ BlockSize = Device->Media.BlockSize;
+ Bytes = Blocks * BlockSize;
+
+ ZeroMem (&CommandPacket, sizeof(NVM_EXPRESS_PASS_THRU_COMMAND_PACKET));
+ ZeroMem (&Command, sizeof(NVM_EXPRESS_COMMAND));
+ ZeroMem (&Response, sizeof(NVM_EXPRESS_RESPONSE));
+
+ CommandPacket.NvmeCmd = &Command;
+ CommandPacket.NvmeResponse = &Response;
+
+ CommandPacket.NvmeCmd->Cdw0.Opcode = NVME_IO_READ_OPC;
+ CommandPacket.NvmeCmd->Cdw0.Cid = Controller->Cid[1]++;
+ CommandPacket.NvmeCmd->Nsid = Device->NamespaceId;
+ CommandPacket.TransferBuffer = (VOID *)(UINTN)Buffer;
+
+ CommandPacket.TransferLength = Bytes;
+ CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT;
+ CommandPacket.QueueId = NVME_IO_QUEUE;
+
+ CommandPacket.NvmeCmd->Cdw10 = (UINT32)Lba;
+ CommandPacket.NvmeCmd->Cdw11 = (UINT32)(Lba >> 32);
+ CommandPacket.NvmeCmd->Cdw12 = (Blocks - 1) & 0xFFFF;
+
+ CommandPacket.NvmeCmd->Flags = CDW10_VALID | CDW11_VALID | CDW12_VALID;
+
+ Status = Controller->Passthru.PassThru (
+ &Controller->Passthru,
+ Device->NamespaceId,
+ 0,
+ &CommandPacket,
+ NULL
+ );
+
+ return Status;
+}
+
+/**
+ Write some sectors to the device.
+
+ @param Device The pointer to the NVME_DEVICE_PRIVATE_DATA data structure.
+ @param Buffer The buffer to be written into the device.
+ @param Lba The start block number.
+ @param Blocks Total block number to be written.
+
+ @retval EFI_SUCCESS Datum are written into the buffer.
+ @retval Others Fail to write all the datum.
+
+**/
+EFI_STATUS
+WriteSectors (
+ IN NVME_DEVICE_PRIVATE_DATA *Device,
+ IN UINT64 Buffer,
+ IN UINT64 Lba,
+ IN UINT32 Blocks
+ )
+{
+ NVME_CONTROLLER_PRIVATE_DATA *Controller;
+ NVM_EXPRESS_PASS_THRU_COMMAND_PACKET CommandPacket;
+ NVM_EXPRESS_COMMAND Command;
+ NVM_EXPRESS_RESPONSE Response;
+ EFI_STATUS Status;
+ UINT32 Bytes;
+ UINT32 BlockSize;
+
+ Controller = Device->Controller;
+ BlockSize = Device->Media.BlockSize;
+ Bytes = Blocks * BlockSize;
+
+ ZeroMem (&CommandPacket, sizeof(NVM_EXPRESS_PASS_THRU_COMMAND_PACKET));
+ ZeroMem (&Command, sizeof(NVM_EXPRESS_COMMAND));
+ ZeroMem (&Response, sizeof(NVM_EXPRESS_RESPONSE));
+
+ CommandPacket.NvmeCmd = &Command;
+ CommandPacket.NvmeResponse = &Response;
+
+ CommandPacket.NvmeCmd->Cdw0.Opcode = NVME_IO_WRITE_OPC;
+ CommandPacket.NvmeCmd->Cdw0.Cid = Controller->Cid[1]++;
+ CommandPacket.NvmeCmd->Nsid = Device->NamespaceId;
+ CommandPacket.TransferBuffer = (VOID *)(UINTN)Buffer;
+
+ CommandPacket.TransferLength = Bytes;
+ CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT;
+ CommandPacket.QueueId = NVME_IO_QUEUE;
+
+ CommandPacket.NvmeCmd->Cdw10 = (UINT32)Lba;
+ CommandPacket.NvmeCmd->Cdw11 = (UINT32)(Lba >> 32);
+ CommandPacket.NvmeCmd->Cdw12 = (Blocks - 1) & 0xFFFF;
+
+ CommandPacket.MetadataBuffer = NULL;
+ CommandPacket.MetadataLength = 0;
+
+ CommandPacket.NvmeCmd->Flags = CDW10_VALID | CDW11_VALID | CDW12_VALID;
+
+ Status = Controller->Passthru.PassThru (
+ &Controller->Passthru,
+ Device->NamespaceId,
+ 0,
+ &CommandPacket,
+ NULL
+ );
+
+ return Status;
+}
+
+/**
+ Read some blocks from the device.
+
+ @param Device The pointer to the NVME_DEVICE_PRIVATE_DATA data structure.
+ @param Buffer The buffer used to store the data read from the device.
+ @param Lba The start block number.
+ @param Blocks Total block number to be read.
+
+ @retval EFI_SUCCESS Datum are read from the device.
+ @retval Others Fail to read all the datum.
+
+**/
+EFI_STATUS
+NvmeRead (
+ IN NVME_DEVICE_PRIVATE_DATA *Device,
+ OUT VOID *Buffer,
+ IN UINT64 Lba,
+ IN UINTN Blocks
+ )
+{
+ EFI_STATUS Status;
+ UINT32 BlockSize;
+ NVME_CONTROLLER_PRIVATE_DATA *Controller;
+ UINT32 MaxTransferBlocks;
+
+ Status = EFI_SUCCESS;
+ Controller = Device->Controller;
+ BlockSize = Device->Media.BlockSize;
+
+ if (Controller->ControllerData->Mdts != 0) {
+ MaxTransferBlocks = (1 << (Controller->ControllerData->Mdts)) * (1 << (Controller->Cap.Mpsmin + 12)) / BlockSize;
+ } else {
+ MaxTransferBlocks = 1024;
+ }
+
+ while (Blocks > 0) {
+ if (Blocks > MaxTransferBlocks) {
+ Status = ReadSectors (Device, (UINT64)(UINTN)Buffer, Lba, MaxTransferBlocks);
+
+ Blocks -= MaxTransferBlocks;
+ Buffer = (VOID *)(UINTN)((UINT64)(UINTN)Buffer + MaxTransferBlocks * BlockSize);
+ Lba += MaxTransferBlocks;
+ } else {
+ Status = ReadSectors (Device, (UINT64)(UINTN)Buffer, Lba, (UINT32)Blocks);
+ Blocks = 0;
+ }
+
+ if (EFI_ERROR(Status)) {
+ break;
+ }
+ }
+
+ DEBUG ((EFI_D_INFO, "NvmeRead() Lba = %8d, Blocks = %8d, BlockSize = %d Status = %r\n", Lba, Blocks, BlockSize, Status));
+
+ return Status;
+}
+
+/**
+ Write some blocks to the device.
+
+ @param Device The pointer to the NVME_DEVICE_PRIVATE_DATA data structure.
+ @param Buffer The buffer to be written into the device.
+ @param Lba The start block number.
+ @param Blocks Total block number to be written.
+
+ @retval EFI_SUCCESS Datum are written into the buffer.
+ @retval Others Fail to write all the datum.
+
+**/
+EFI_STATUS
+NvmeWrite (
+ IN NVME_DEVICE_PRIVATE_DATA *Device,
+ IN VOID *Buffer,
+ IN UINT64 Lba,
+ IN UINTN Blocks
+ )
+{
+ EFI_STATUS Status;
+ UINT32 BlockSize;
+ NVME_CONTROLLER_PRIVATE_DATA *Controller;
+ UINT32 MaxTransferBlocks;
+
+ Status = EFI_SUCCESS;
+ Controller = Device->Controller;
+ BlockSize = Device->Media.BlockSize;
+
+ if (Controller->ControllerData->Mdts != 0) {
+ MaxTransferBlocks = (1 << (Controller->ControllerData->Mdts)) * (1 << (Controller->Cap.Mpsmin + 12)) / BlockSize;
+ } else {
+ MaxTransferBlocks = 1024;
+ }
+
+ while (Blocks > 0) {
+ if (Blocks > MaxTransferBlocks) {
+ Status = WriteSectors (Device, (UINT64)(UINTN)Buffer, Lba, MaxTransferBlocks);
+
+ Blocks -= MaxTransferBlocks;
+ Buffer = (VOID *)(UINTN)((UINT64)(UINTN)Buffer + MaxTransferBlocks * BlockSize);
+ Lba += MaxTransferBlocks;
+ } else {
+ Status = WriteSectors (Device, (UINT64)(UINTN)Buffer, Lba, (UINT32)Blocks);
+ Blocks = 0;
+ }
+
+ if (EFI_ERROR(Status)) {
+ break;
+ }
+ }
+
+ DEBUG ((EFI_D_INFO, "NvmeWrite() Lba = %8d, Blocks = %8d, BlockSize = %d Status = %r\n", Lba, Blocks, BlockSize, Status));
+
+ return Status;
+}
+
+/**
+ Flushes all modified data to the device.
+
+ @param Device The pointer to the NVME_DEVICE_PRIVATE_DATA data structure.
+
+ @retval EFI_SUCCESS Datum are written into the buffer.
+ @retval Others Fail to write all the datum.
+
+**/
+EFI_STATUS
+NvmeFlush (
+ IN NVME_DEVICE_PRIVATE_DATA *Device
+ )
+{
+ NVME_CONTROLLER_PRIVATE_DATA *Controller;
+ NVM_EXPRESS_PASS_THRU_COMMAND_PACKET CommandPacket;
+ NVM_EXPRESS_COMMAND Command;
+ NVM_EXPRESS_RESPONSE Response;
+ EFI_STATUS Status;
+
+ Controller = Device->Controller;
+
+ ZeroMem (&CommandPacket, sizeof(NVM_EXPRESS_PASS_THRU_COMMAND_PACKET));
+ ZeroMem (&Command, sizeof(NVM_EXPRESS_COMMAND));
+ ZeroMem (&Response, sizeof(NVM_EXPRESS_RESPONSE));
+
+ CommandPacket.NvmeCmd = &Command;
+ CommandPacket.NvmeResponse = &Response;
+
+ CommandPacket.NvmeCmd->Cdw0.Opcode = NVME_IO_FLUSH_OPC;
+ CommandPacket.NvmeCmd->Cdw0.Cid = Controller->Cid[1]++;
+ CommandPacket.NvmeCmd->Nsid = Device->NamespaceId;
+ CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT;
+ CommandPacket.QueueId = NVME_IO_QUEUE;
+
+ Status = Controller->Passthru.PassThru (
+ &Controller->Passthru,
+ Device->NamespaceId,
+ 0,
+ &CommandPacket,
+ NULL
+ );
+
+ return Status;
+}
+
+
+/**
+ Reset the Block Device.
+
+ @param This Indicates a pointer to the calling context.
+ @param ExtendedVerification Driver may perform diagnostics on reset.
+
+ @retval EFI_SUCCESS The device was reset.
+ @retval EFI_DEVICE_ERROR The device is not functioning properly and could
+ not be reset.
+
+**/
+EFI_STATUS
+EFIAPI
+NvmeBlockIoReset (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+ )
+{
+ EFI_TPL OldTpl;
+ NVME_CONTROLLER_PRIVATE_DATA *Private;
+ NVME_DEVICE_PRIVATE_DATA *Device;
+ EFI_STATUS Status;
+
+ if (This == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // For Nvm Express subsystem, reset block device means reset controller.
+ //
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
+
+ Device = NVME_DEVICE_PRIVATE_DATA_FROM_BLOCK_IO (This);
+
+ Private = Device->Controller;
+
+ Status = NvmeControllerInit (Private);
+
+ gBS->RestoreTPL (OldTpl);
+
+ return Status;
+}
+
+/**
+ Read BufferSize bytes from Lba into Buffer.
+
+ @param This Indicates a pointer to the calling context.
+ @param MediaId Id of the media, changes every time the media is replaced.
+ @param Lba The starting Logical Block Address to read from.
+ @param BufferSize Size of Buffer, must be a multiple of device block size.
+ @param Buffer A pointer to the destination buffer for the data. The caller is
+ responsible for either having implicit or explicit ownership of the buffer.
+
+ @retval EFI_SUCCESS The data was read correctly from the device.
+ @retval EFI_DEVICE_ERROR The device reported an error while performing the read.
+ @retval EFI_NO_MEDIA There is no media in the device.
+ @retval EFI_MEDIA_CHANGED The MediaId does not matched the current device.
+ @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
+ @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid,
+ or the buffer is not on proper alignment.
+
+**/
+EFI_STATUS
+EFIAPI
+NvmeBlockIoReadBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA Lba,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ )
+{
+ NVME_DEVICE_PRIVATE_DATA *Device;
+ EFI_STATUS Status;
+ EFI_BLOCK_IO_MEDIA *Media;
+ UINTN BlockSize;
+ UINTN NumberOfBlocks;
+ UINTN IoAlign;
+ EFI_TPL OldTpl;
+
+ //
+ // Check parameters.
+ //
+ if (This == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Media = This->Media;
+
+ if (MediaId != Media->MediaId) {
+ return EFI_MEDIA_CHANGED;
+ }
+
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (BufferSize == 0) {
+ return EFI_SUCCESS;
+ }
+
+ BlockSize = Media->BlockSize;
+ if ((BufferSize % BlockSize) != 0) {
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ NumberOfBlocks = BufferSize / BlockSize;
+ if ((Lba + NumberOfBlocks - 1) > Media->LastBlock) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ IoAlign = Media->IoAlign;
+ if (IoAlign > 0 && (((UINTN) Buffer & (IoAlign - 1)) != 0)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
+
+ Device = NVME_DEVICE_PRIVATE_DATA_FROM_BLOCK_IO (This);
+
+ Status = NvmeRead (Device, Buffer, Lba, NumberOfBlocks);
+
+ gBS->RestoreTPL (OldTpl);
+ return Status;
+}
+
+/**
+ Write BufferSize bytes from Lba into Buffer.
+
+ @param This Indicates a pointer to the calling context.
+ @param MediaId The media ID that the write request is for.
+ @param Lba The starting logical block address to be written. The caller is
+ responsible for writing to only legitimate locations.
+ @param BufferSize Size of Buffer, must be a multiple of device block size.
+ @param Buffer A pointer to the source buffer for the data.
+
+ @retval EFI_SUCCESS The data was written correctly to the device.
+ @retval EFI_WRITE_PROTECTED The device can not be written to.
+ @retval EFI_DEVICE_ERROR The device reported an error while performing the write.
+ @retval EFI_NO_MEDIA There is no media in the device.
+ @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device.
+ @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
+ @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid,
+ or the buffer is not on proper alignment.
+
+**/
+EFI_STATUS
+EFIAPI
+NvmeBlockIoWriteBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA Lba,
+ IN UINTN BufferSize,
+ IN VOID *Buffer
+ )
+{
+ NVME_DEVICE_PRIVATE_DATA *Device;
+ EFI_STATUS Status;
+ EFI_BLOCK_IO_MEDIA *Media;
+ UINTN BlockSize;
+ UINTN NumberOfBlocks;
+ UINTN IoAlign;
+ EFI_TPL OldTpl;
+
+ //
+ // Check parameters.
+ //
+ if (This == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Media = This->Media;
+
+ if (MediaId != Media->MediaId) {
+ return EFI_MEDIA_CHANGED;
+ }
+
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (BufferSize == 0) {
+ return EFI_SUCCESS;
+ }
+
+ BlockSize = Media->BlockSize;
+ if ((BufferSize % BlockSize) != 0) {
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ NumberOfBlocks = BufferSize / BlockSize;
+ if ((Lba + NumberOfBlocks - 1) > Media->LastBlock) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ IoAlign = Media->IoAlign;
+ if (IoAlign > 0 && (((UINTN) Buffer & (IoAlign - 1)) != 0)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
+
+ Device = NVME_DEVICE_PRIVATE_DATA_FROM_BLOCK_IO (This);
+
+ Status = NvmeWrite (Device, Buffer, Lba, NumberOfBlocks);
+
+ gBS->RestoreTPL (OldTpl);
+
+ return Status;
+}
+
+/**
+ Flush the Block Device.
+
+ @param This Indicates a pointer to the calling context.
+
+ @retval EFI_SUCCESS All outstanding data was written to the device.
+ @retval EFI_DEVICE_ERROR The device reported an error while writing back the data.
+ @retval EFI_NO_MEDIA There is no media in the device.
+
+**/
+EFI_STATUS
+EFIAPI
+NvmeBlockIoFlushBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This
+ )
+{
+ NVME_DEVICE_PRIVATE_DATA *Device;
+ EFI_STATUS Status;
+ EFI_TPL OldTpl;
+
+ //
+ // Check parameters.
+ //
+ if (This == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
+
+ Device = NVME_DEVICE_PRIVATE_DATA_FROM_BLOCK_IO (This);
+
+ Status = NvmeFlush (Device);
+
+ gBS->RestoreTPL (OldTpl);
+
+ return Status;
+}
diff --git a/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressBlockIo.h b/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressBlockIo.h
new file mode 100644
index 000000000..5f896fed8
--- /dev/null
+++ b/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressBlockIo.h
@@ -0,0 +1,111 @@
+/** @file
+ Header file for EFI_BLOCK_IO_PROTOCOL interface.
+
+Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>
+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 _EFI_NVME_BLOCKIO_H_
+#define _EFI_NVME_BLOCKIO_H_
+
+/**
+ Reset the Block Device.
+
+ @param This Indicates a pointer to the calling context.
+ @param ExtendedVerification Driver may perform diagnostics on reset.
+
+ @retval EFI_SUCCESS The device was reset.
+ @retval EFI_DEVICE_ERROR The device is not functioning properly and could
+ not be reset.
+
+**/
+EFI_STATUS
+EFIAPI
+NvmeBlockIoReset (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+ );
+
+/**
+ Read BufferSize bytes from Lba into Buffer.
+
+ @param This Indicates a pointer to the calling context.
+ @param MediaId Id of the media, changes every time the media is replaced.
+ @param Lba The starting Logical Block Address to read from
+ @param BufferSize Size of Buffer, must be a multiple of device block size.
+ @param Buffer A pointer to the destination buffer for the data. The caller is
+ responsible for either having implicit or explicit ownership of the buffer.
+
+ @retval EFI_SUCCESS The data was read correctly from the device.
+ @retval EFI_DEVICE_ERROR The device reported an error while performing the read.
+ @retval EFI_NO_MEDIA There is no media in the device.
+ @retval EFI_MEDIA_CHANGED The MediaId does not matched the current device.
+ @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
+ @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid,
+ or the buffer is not on proper alignment.
+
+**/
+EFI_STATUS
+EFIAPI
+NvmeBlockIoReadBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA Lba,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ );
+
+/**
+ Write BufferSize bytes from Lba into Buffer.
+
+ @param This Indicates a pointer to the calling context.
+ @param MediaId The media ID that the write request is for.
+ @param Lba The starting logical block address to be written. The caller is
+ responsible for writing to only legitimate locations.
+ @param BufferSize Size of Buffer, must be a multiple of device block size.
+ @param Buffer A pointer to the source buffer for the data.
+
+ @retval EFI_SUCCESS The data was written correctly to the device.
+ @retval EFI_WRITE_PROTECTED The device can not be written to.
+ @retval EFI_DEVICE_ERROR The device reported an error while performing the write.
+ @retval EFI_NO_MEDIA There is no media in the device.
+ @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device.
+ @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
+ @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid,
+ or the buffer is not on proper alignment.
+
+**/
+EFI_STATUS
+EFIAPI
+NvmeBlockIoWriteBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA Lba,
+ IN UINTN BufferSize,
+ IN VOID *Buffer
+ );
+
+/**
+ Flush the Block Device.
+
+ @param This Indicates a pointer to the calling context.
+
+ @retval EFI_SUCCESS All outstanding data was written to the device
+ @retval EFI_DEVICE_ERROR The device reported an error while writing back the data
+ @retval EFI_NO_MEDIA There is no media in the device.
+
+**/
+EFI_STATUS
+EFIAPI
+NvmeBlockIoFlushBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This
+ );
+
+#endif
diff --git a/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressDiskInfo.c b/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressDiskInfo.c
new file mode 100644
index 000000000..66af1906c
--- /dev/null
+++ b/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressDiskInfo.c
@@ -0,0 +1,162 @@
+/** @file
+ This file is used to implement the EFI_DISK_INFO_PROTOCOL interface..
+
+ Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>
+ 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 "NvmExpress.h"
+
+EFI_DISK_INFO_PROTOCOL gNvmExpressDiskInfoProtocolTemplate = {
+ EFI_DISK_INFO_NVME_INTERFACE_GUID,
+ NvmExpressDiskInfoInquiry,
+ NvmExpressDiskInfoIdentify,
+ NvmExpressDiskInfoSenseData,
+ NvmExpressDiskInfoWhichIde
+};
+
+/**
+ Initialize the installation of DiskInfo protocol.
+
+ This function prepares for the installation of DiskInfo protocol on the child handle.
+ By default, it installs DiskInfo protocol with NVME interface GUID.
+
+ @param[in] Device The pointer of NVME_DEVICE_PRIVATE_DATA.
+
+**/
+VOID
+InitializeDiskInfo (
+ IN NVME_DEVICE_PRIVATE_DATA *Device
+ )
+{
+ CopyMem (&Device->DiskInfo, &gNvmExpressDiskInfoProtocolTemplate, sizeof (EFI_DISK_INFO_PROTOCOL));
+}
+
+
+/**
+ Provides inquiry information for the controller type.
+
+ This function is used to get inquiry data. Data format
+ of Identify data is defined by the Interface GUID.
+
+ @param[in] This Pointer to the EFI_DISK_INFO_PROTOCOL instance.
+ @param[in, out] InquiryData Pointer to a buffer for the inquiry data.
+ @param[in, out] InquiryDataSize Pointer to the value for the inquiry data size.
+
+ @retval EFI_SUCCESS The command was accepted without any errors.
+ @retval EFI_NOT_FOUND Device does not support this data class
+ @retval EFI_DEVICE_ERROR Error reading InquiryData from device
+ @retval EFI_BUFFER_TOO_SMALL InquiryDataSize not big enough
+
+**/
+EFI_STATUS
+EFIAPI
+NvmExpressDiskInfoInquiry (
+ IN EFI_DISK_INFO_PROTOCOL *This,
+ IN OUT VOID *InquiryData,
+ IN OUT UINT32 *InquiryDataSize
+ )
+{
+ return EFI_NOT_FOUND;
+}
+
+
+/**
+ Provides identify information for the controller type.
+
+ This function is used to get identify data. Data format
+ of Identify data is defined by the Interface GUID.
+
+ @param[in] This Pointer to the EFI_DISK_INFO_PROTOCOL
+ instance.
+ @param[in, out] IdentifyData Pointer to a buffer for the identify data.
+ @param[in, out] IdentifyDataSize Pointer to the value for the identify data
+ size.
+
+ @retval EFI_SUCCESS The command was accepted without any errors.
+ @retval EFI_NOT_FOUND Device does not support this data class
+ @retval EFI_DEVICE_ERROR Error reading IdentifyData from device
+ @retval EFI_BUFFER_TOO_SMALL IdentifyDataSize not big enough
+
+**/
+EFI_STATUS
+EFIAPI
+NvmExpressDiskInfoIdentify (
+ IN EFI_DISK_INFO_PROTOCOL *This,
+ IN OUT VOID *IdentifyData,
+ IN OUT UINT32 *IdentifyDataSize
+ )
+{
+ EFI_STATUS Status;
+ NVME_DEVICE_PRIVATE_DATA *Device;
+
+ Device = NVME_DEVICE_PRIVATE_DATA_FROM_DISK_INFO (This);
+
+ Status = EFI_BUFFER_TOO_SMALL;
+ if (*IdentifyDataSize >= sizeof (Device->NamespaceData)) {
+ Status = EFI_SUCCESS;
+ CopyMem (IdentifyData, &Device->NamespaceData, sizeof (Device->NamespaceData));
+ }
+ *IdentifyDataSize = sizeof (Device->NamespaceData);
+ return Status;
+}
+
+/**
+ Provides sense data information for the controller type.
+
+ This function is used to get sense data.
+ Data format of Sense data is defined by the Interface GUID.
+
+ @param[in] This Pointer to the EFI_DISK_INFO_PROTOCOL instance.
+ @param[in, out] SenseData Pointer to the SenseData.
+ @param[in, out] SenseDataSize Size of SenseData in bytes.
+ @param[out] SenseDataNumber Pointer to the value for the sense data size.
+
+ @retval EFI_SUCCESS The command was accepted without any errors.
+ @retval EFI_NOT_FOUND Device does not support this data class.
+ @retval EFI_DEVICE_ERROR Error reading SenseData from device.
+ @retval EFI_BUFFER_TOO_SMALL SenseDataSize not big enough.
+
+**/
+EFI_STATUS
+EFIAPI
+NvmExpressDiskInfoSenseData (
+ IN EFI_DISK_INFO_PROTOCOL *This,
+ IN OUT VOID *SenseData,
+ IN OUT UINT32 *SenseDataSize,
+ OUT UINT8 *SenseDataNumber
+ )
+{
+ return EFI_NOT_FOUND;
+}
+
+
+/**
+ This function is used to get controller information.
+
+ @param[in] This Pointer to the EFI_DISK_INFO_PROTOCOL instance.
+ @param[out] IdeChannel Pointer to the Ide Channel number. Primary or secondary.
+ @param[out] IdeDevice Pointer to the Ide Device number. Master or slave.
+
+ @retval EFI_SUCCESS IdeChannel and IdeDevice are valid.
+ @retval EFI_UNSUPPORTED This is not an IDE device.
+
+**/
+EFI_STATUS
+EFIAPI
+NvmExpressDiskInfoWhichIde (
+ IN EFI_DISK_INFO_PROTOCOL *This,
+ OUT UINT32 *IdeChannel,
+ OUT UINT32 *IdeDevice
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
diff --git a/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressDiskInfo.h b/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressDiskInfo.h
new file mode 100644
index 000000000..7db3dff47
--- /dev/null
+++ b/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressDiskInfo.h
@@ -0,0 +1,129 @@
+/** @file
+ Header file for EFI_DISK_INFO_PROTOCOL interface.
+
+Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>
+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 _NVME_DISKINFO_H_
+#define _NVME_DISKINFO_H_
+
+/**
+ Initialize the installation of DiskInfo protocol.
+
+ This function prepares for the installation of DiskInfo protocol on the child handle.
+ By default, it installs DiskInfo protocol with NVME interface GUID.
+
+ @param[in] Device The pointer of NVME_DEVICE_PRIVATE_DATA.
+
+**/
+VOID
+InitializeDiskInfo (
+ IN NVME_DEVICE_PRIVATE_DATA *Device
+ );
+
+
+/**
+ Provides inquiry information for the controller type.
+
+ This function is used to get inquiry data. Data format
+ of Identify data is defined by the Interface GUID.
+
+ @param[in] This Pointer to the EFI_DISK_INFO_PROTOCOL instance.
+ @param[in, out] InquiryData Pointer to a buffer for the inquiry data.
+ @param[in, out] InquiryDataSize Pointer to the value for the inquiry data size.
+
+ @retval EFI_SUCCESS The command was accepted without any errors.
+ @retval EFI_NOT_FOUND Device does not support this data class
+ @retval EFI_DEVICE_ERROR Error reading InquiryData from device
+ @retval EFI_BUFFER_TOO_SMALL InquiryDataSize not big enough
+
+**/
+EFI_STATUS
+EFIAPI
+NvmExpressDiskInfoInquiry (
+ IN EFI_DISK_INFO_PROTOCOL *This,
+ IN OUT VOID *InquiryData,
+ IN OUT UINT32 *InquiryDataSize
+ );
+
+/**
+ Provides identify information for the controller type.
+
+ This function is used to get identify data. Data format
+ of Identify data is defined by the Interface GUID.
+
+ @param[in] This Pointer to the EFI_DISK_INFO_PROTOCOL
+ instance.
+ @param[in, out] IdentifyData Pointer to a buffer for the identify data.
+ @param[in, out] IdentifyDataSize Pointer to the value for the identify data
+ size.
+
+ @retval EFI_SUCCESS The command was accepted without any errors.
+ @retval EFI_NOT_FOUND Device does not support this data class
+ @retval EFI_DEVICE_ERROR Error reading IdentifyData from device
+ @retval EFI_BUFFER_TOO_SMALL IdentifyDataSize not big enough
+
+**/
+EFI_STATUS
+EFIAPI
+NvmExpressDiskInfoIdentify (
+ IN EFI_DISK_INFO_PROTOCOL *This,
+ IN OUT VOID *IdentifyData,
+ IN OUT UINT32 *IdentifyDataSize
+ );
+
+/**
+ Provides sense data information for the controller type.
+
+ This function is used to get sense data.
+ Data format of Sense data is defined by the Interface GUID.
+
+ @param[in] This Pointer to the EFI_DISK_INFO_PROTOCOL instance.
+ @param[in, out] SenseData Pointer to the SenseData.
+ @param[in, out] SenseDataSize Size of SenseData in bytes.
+ @param[out] SenseDataNumber Pointer to the value for the sense data size.
+
+ @retval EFI_SUCCESS The command was accepted without any errors.
+ @retval EFI_NOT_FOUND Device does not support this data class.
+ @retval EFI_DEVICE_ERROR Error reading SenseData from device.
+ @retval EFI_BUFFER_TOO_SMALL SenseDataSize not big enough.
+
+**/
+EFI_STATUS
+EFIAPI
+NvmExpressDiskInfoSenseData (
+ IN EFI_DISK_INFO_PROTOCOL *This,
+ IN OUT VOID *SenseData,
+ IN OUT UINT32 *SenseDataSize,
+ OUT UINT8 *SenseDataNumber
+ );
+
+
+/**
+ This function is used to get controller information.
+
+ @param[in] This Pointer to the EFI_DISK_INFO_PROTOCOL instance.
+ @param[out] IdeChannel Pointer to the Ide Channel number. Primary or secondary.
+ @param[out] IdeDevice Pointer to the Ide Device number. Master or slave.
+
+ @retval EFI_SUCCESS IdeChannel and IdeDevice are valid.
+ @retval EFI_UNSUPPORTED This is not an IDE device.
+
+**/
+EFI_STATUS
+EFIAPI
+NvmExpressDiskInfoWhichIde (
+ IN EFI_DISK_INFO_PROTOCOL *This,
+ OUT UINT32 *IdeChannel,
+ OUT UINT32 *IdeDevice
+ );
+
+#endif
diff --git a/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressDxe.inf b/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressDxe.inf
new file mode 100644
index 000000000..3ed185a1f
--- /dev/null
+++ b/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressDxe.inf
@@ -0,0 +1,68 @@
+## @file
+# Component Description File For NVM Express Host Controller Module.
+#
+# NvmExpressDxe driver is used to manage non-volatile memory subsystem which follows
+# NVM Express specification.
+#
+# Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>
+#
+# 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]
+ INF_VERSION = 0x00010005
+ BASE_NAME = NvmExpressDxe
+ FILE_GUID = 5BE3BDF4-53CF-46a3-A6A9-73C34A6E5EE3
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = NvmExpressDriverEntry
+ UNLOAD_IMAGE = NvmExpressUnload
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+# DRIVER_BINDING = gNvmExpressDriverBinding
+# COMPONENT_NAME = gNvmExpressComponentName
+# COMPONENT_NAME2 = gNvmExpressComponentName2
+
+[Sources]
+ NvmExpressBlockIo.c
+ NvmExpressBlockIo.h
+ ComponentName.c
+ NvmExpress.c
+ NvmExpress.h
+ NvmExpressDiskInfo.c
+ NvmExpressDiskInfo.h
+ NvmExpressHci.c
+ NvmExpressHci.h
+ NvmExpressPassthru.c
+ NvmExpressPassthru.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+
+[LibraryClasses]
+ BaseMemoryLib
+ BaseLib
+ DebugLib
+ DevicePathLib
+ MemoryAllocationLib
+ UefiDriverEntryPoint
+ UefiBootServicesTableLib
+ UefiLib
+ PrintLib
+
+[Protocols]
+ gEfiPciIoProtocolGuid ## TO_START
+ gEfiDevicePathProtocolGuid ## TO_START
+ gEfiBlockIoProtocolGuid ## BY_START
+ gEfiDiskInfoProtocolGuid ## BY_START
+ gEfiDriverSupportedEfiVersionProtocolGuid ## BY_START \ No newline at end of file
diff --git a/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressHci.c b/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressHci.c
new file mode 100644
index 000000000..157e10127
--- /dev/null
+++ b/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressHci.c
@@ -0,0 +1,926 @@
+/** @file
+ NvmExpressDxe driver is used to manage non-volatile memory subsystem which follows
+ NVM Express specification.
+
+ Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>
+ 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 "NvmExpress.h"
+
+/**
+ Read Nvm Express controller capability register.
+
+ @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
+ @param Cap The buffer used to store capability register content.
+
+ @return EFI_SUCCESS Successfully read the controller capability register content.
+ @return EFI_DEVICE_ERROR Fail to read the controller capability register.
+
+**/
+EFI_STATUS
+ReadNvmeControllerCapabilities (
+ IN NVME_CONTROLLER_PRIVATE_DATA *Private,
+ IN NVME_CAP *Cap
+ )
+{
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ EFI_STATUS Status;
+
+ PciIo = Private->PciIo;
+ Status = PciIo->Mem.Read (
+ PciIo,
+ EfiPciIoWidthUint64,
+ NVME_BAR,
+ NVME_CAP_OFFSET,
+ 1,
+ Cap
+ );
+
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Read Nvm Express controller configuration register.
+
+ @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
+ @param Cc The buffer used to store configuration register content.
+
+ @return EFI_SUCCESS Successfully read the controller configuration register content.
+ @return EFI_DEVICE_ERROR Fail to read the controller configuration register.
+
+**/
+EFI_STATUS
+ReadNvmeControllerConfiguration (
+ IN NVME_CONTROLLER_PRIVATE_DATA *Private,
+ IN NVME_CC *Cc
+ )
+{
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ EFI_STATUS Status;
+
+ PciIo = Private->PciIo;
+ Status = PciIo->Mem.Read (
+ PciIo,
+ EfiPciIoWidthUint32,
+ NVME_BAR,
+ NVME_CC_OFFSET,
+ 1,
+ Cc
+ );
+
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Write Nvm Express controller configuration register.
+
+ @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
+ @param Cc The buffer used to store the content to be written into configuration register.
+
+ @return EFI_SUCCESS Successfully write data into the controller configuration register.
+ @return EFI_DEVICE_ERROR Fail to write data into the controller configuration register.
+
+**/
+EFI_STATUS
+WriteNvmeControllerConfiguration (
+ IN NVME_CONTROLLER_PRIVATE_DATA *Private,
+ IN NVME_CC *Cc
+ )
+{
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ EFI_STATUS Status;
+
+ PciIo = Private->PciIo;
+ Status = PciIo->Mem.Write (
+ PciIo,
+ EfiPciIoWidthUint32,
+ NVME_BAR,
+ NVME_CC_OFFSET,
+ 1,
+ Cc
+ );
+
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ DEBUG ((EFI_D_INFO, "Cc.En: %d\n", Cc->En));
+ DEBUG ((EFI_D_INFO, "Cc.Css: %d\n", Cc->Css));
+ DEBUG ((EFI_D_INFO, "Cc.Mps: %d\n", Cc->Mps));
+ DEBUG ((EFI_D_INFO, "Cc.Ams: %d\n", Cc->Ams));
+ DEBUG ((EFI_D_INFO, "Cc.Shn: %d\n", Cc->Shn));
+ DEBUG ((EFI_D_INFO, "Cc.Iosqes: %d\n", Cc->Iosqes));
+ DEBUG ((EFI_D_INFO, "Cc.Iocqes: %d\n", Cc->Iocqes));
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Read Nvm Express controller status register.
+
+ @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
+ @param Csts The buffer used to store status register content.
+
+ @return EFI_SUCCESS Successfully read the controller status register content.
+ @return EFI_DEVICE_ERROR Fail to read the controller status register.
+
+**/
+EFI_STATUS
+ReadNvmeControllerStatus (
+ IN NVME_CONTROLLER_PRIVATE_DATA *Private,
+ IN NVME_CSTS *Csts
+ )
+{
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ EFI_STATUS Status;
+
+ PciIo = Private->PciIo;
+ Status = PciIo->Mem.Read (
+ PciIo,
+ EfiPciIoWidthUint32,
+ NVME_BAR,
+ NVME_CSTS_OFFSET,
+ 1,
+ Csts
+ );
+
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Read Nvm Express admin queue attributes register.
+
+ @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
+ @param Aqa The buffer used to store admin queue attributes register content.
+
+ @return EFI_SUCCESS Successfully read the admin queue attributes register content.
+ @return EFI_DEVICE_ERROR Fail to read the admin queue attributes register.
+
+**/
+EFI_STATUS
+ReadNvmeAdminQueueAttributes (
+ IN NVME_CONTROLLER_PRIVATE_DATA *Private,
+ IN NVME_AQA *Aqa
+ )
+{
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ EFI_STATUS Status;
+
+ PciIo = Private->PciIo;
+ Status = PciIo->Mem.Read (
+ PciIo,
+ EfiPciIoWidthUint32,
+ NVME_BAR,
+ NVME_AQA_OFFSET,
+ 1,
+ Aqa
+ );
+
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Write Nvm Express admin queue attributes register.
+
+ @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
+ @param Aqa The buffer used to store the content to be written into admin queue attributes register.
+
+ @return EFI_SUCCESS Successfully write data into the admin queue attributes register.
+ @return EFI_DEVICE_ERROR Fail to write data into the admin queue attributes register.
+
+**/
+EFI_STATUS
+WriteNvmeAdminQueueAttributes (
+ IN NVME_CONTROLLER_PRIVATE_DATA *Private,
+ IN NVME_AQA *Aqa
+ )
+{
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ EFI_STATUS Status;
+
+ PciIo = Private->PciIo;
+ Status = PciIo->Mem.Write (
+ PciIo,
+ EfiPciIoWidthUint32,
+ NVME_BAR,
+ NVME_AQA_OFFSET,
+ 1,
+ Aqa
+ );
+
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ DEBUG ((EFI_D_INFO, "Aqa.Asqs: %d\n", Aqa->Asqs));
+ DEBUG ((EFI_D_INFO, "Aqa.Acqs: %d\n", Aqa->Acqs));
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Read Nvm Express admin submission queue base address register.
+
+ @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
+ @param Asq The buffer used to store admin submission queue base address register content.
+
+ @return EFI_SUCCESS Successfully read the admin submission queue base address register content.
+ @return EFI_DEVICE_ERROR Fail to read the admin submission queue base address register.
+
+**/
+EFI_STATUS
+ReadNvmeAdminSubmissionQueueBaseAddress (
+ IN NVME_CONTROLLER_PRIVATE_DATA *Private,
+ IN NVME_ASQ *Asq
+ )
+{
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ EFI_STATUS Status;
+
+ PciIo = Private->PciIo;
+ Status = PciIo->Mem.Read (
+ PciIo,
+ EfiPciIoWidthUint64,
+ NVME_BAR,
+ NVME_ASQ_OFFSET,
+ 1,
+ Asq
+ );
+
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Write Nvm Express admin submission queue base address register.
+
+ @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
+ @param Asq The buffer used to store the content to be written into admin submission queue base address register.
+
+ @return EFI_SUCCESS Successfully write data into the admin submission queue base address register.
+ @return EFI_DEVICE_ERROR Fail to write data into the admin submission queue base address register.
+
+**/
+EFI_STATUS
+WriteNvmeAdminSubmissionQueueBaseAddress (
+ IN NVME_CONTROLLER_PRIVATE_DATA *Private,
+ IN NVME_ASQ *Asq
+ )
+{
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ EFI_STATUS Status;
+
+ PciIo = Private->PciIo;
+ Status = PciIo->Mem.Write (
+ PciIo,
+ EfiPciIoWidthUint64,
+ NVME_BAR,
+ NVME_ASQ_OFFSET,
+ 1,
+ Asq
+ );
+
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ DEBUG ((EFI_D_INFO, "Asq.Asqb: %lx\n", Asq->Asqb));
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Read Nvm Express admin completion queue base address register.
+
+ @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
+ @param Acq The buffer used to store admin completion queue base address register content.
+
+ @return EFI_SUCCESS Successfully read the admin completion queue base address register content.
+ @return EFI_DEVICE_ERROR Fail to read the admin completion queue base address register.
+
+**/
+EFI_STATUS
+ReadNvmeAdminCompletionQueueBaseAddress (
+ IN NVME_CONTROLLER_PRIVATE_DATA *Private,
+ IN NVME_ACQ *Acq
+ )
+{
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ EFI_STATUS Status;
+
+ PciIo = Private->PciIo;
+ Status = PciIo->Mem.Read (
+ PciIo,
+ EfiPciIoWidthUint64,
+ NVME_BAR,
+ NVME_ACQ_OFFSET,
+ 1,
+ Acq
+ );
+
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Write Nvm Express admin completion queue base address register.
+
+ @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
+ @param Acq The buffer used to store the content to be written into admin completion queue base address register.
+
+ @return EFI_SUCCESS Successfully write data into the admin completion queue base address register.
+ @return EFI_DEVICE_ERROR Fail to write data into the admin completion queue base address register.
+
+**/
+EFI_STATUS
+WriteNvmeAdminCompletionQueueBaseAddress (
+ IN NVME_CONTROLLER_PRIVATE_DATA *Private,
+ IN NVME_ACQ *Acq
+ )
+{
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ EFI_STATUS Status;
+
+ PciIo = Private->PciIo;
+ Status = PciIo->Mem.Write (
+ PciIo,
+ EfiPciIoWidthUint64,
+ NVME_BAR,
+ NVME_ACQ_OFFSET,
+ 1,
+ Acq
+ );
+
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ DEBUG ((EFI_D_INFO, "Acq.Acqb: %lxh\n", Acq->Acqb));
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Disable the Nvm Express controller.
+
+ @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
+
+ @return EFI_SUCCESS Successfully disable the controller.
+ @return EFI_DEVICE_ERROR Fail to disable the controller.
+
+**/
+EFI_STATUS
+NvmeDisableController (
+ IN NVME_CONTROLLER_PRIVATE_DATA *Private
+ )
+{
+ NVME_CC Cc;
+ NVME_CSTS Csts;
+ EFI_STATUS Status;
+
+ //
+ // Read Controller Configuration Register.
+ //
+ Status = ReadNvmeControllerConfiguration (Private, &Cc);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ Cc.En = 0;
+
+ //
+ // Disable the controller.
+ //
+ Status = WriteNvmeControllerConfiguration (Private, &Cc);
+
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ gBS->Stall(10000);
+
+ //
+ // Check if the controller is reset
+ //
+ Status = ReadNvmeControllerStatus (Private, &Csts);
+
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ if (Csts.Rdy != 0) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ DEBUG ((EFI_D_INFO, "NVMe controller is disabled with status [%r].\n", Status));
+ return Status;
+}
+
+/**
+ Enable the Nvm Express controller.
+
+ @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
+
+ @return EFI_SUCCESS Successfully enable the controller.
+ @return EFI_DEVICE_ERROR Fail to enable the controller.
+ @return EFI_TIMEOUT Fail to enable the controller in given time slot.
+
+**/
+EFI_STATUS
+NvmeEnableController (
+ IN NVME_CONTROLLER_PRIVATE_DATA *Private
+ )
+{
+ NVME_CC Cc;
+ NVME_CSTS Csts;
+ EFI_STATUS Status;
+ UINT32 Index;
+ UINT8 Timeout;
+
+ //
+ // Enable the controller
+ //
+ ZeroMem (&Cc, sizeof (NVME_CC));
+ Cc.En = 1;
+ Cc.Iosqes = 6;
+ Cc.Iocqes = 4;
+ Status = WriteNvmeControllerConfiguration (Private, &Cc);
+
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ //
+ // Cap.To specifies max delay time in 500ms increments for Csts.Rdy to set after
+ // Cc.Enable. Loop produces a 1 millisecond delay per itteration, up to 500 * Cap.To.
+ //
+ if (Private->Cap.To == 0) {
+ Timeout = 1;
+ } else {
+ Timeout = Private->Cap.To;
+ }
+
+ for(Index = (Timeout * 500); Index != 0; --Index) {
+ gBS->Stall(1000);
+
+ //
+ // Check if the controller is initialized
+ //
+ Status = ReadNvmeControllerStatus (Private, &Csts);
+
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ if (Csts.Rdy) {
+ break;
+ }
+ }
+
+ if (Index == 0) {
+ Status = EFI_TIMEOUT;
+ }
+
+ DEBUG ((EFI_D_INFO, "NVMe controller is enabled with status [%r].\n", Status));
+ return Status;
+}
+
+/**
+ Get identify controller data.
+
+ @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
+ @param Buffer The buffer used to store the identify controller data.
+
+ @return EFI_SUCCESS Successfully get the identify controller data.
+ @return EFI_DEVICE_ERROR Fail to get the identify controller data.
+
+**/
+EFI_STATUS
+NvmeIdentifyController (
+ IN NVME_CONTROLLER_PRIVATE_DATA *Private,
+ IN VOID *Buffer
+ )
+{
+ NVM_EXPRESS_PASS_THRU_COMMAND_PACKET CommandPacket;
+ NVM_EXPRESS_COMMAND Command;
+ NVM_EXPRESS_RESPONSE Response;
+ EFI_STATUS Status;
+
+ ZeroMem (&CommandPacket, sizeof(NVM_EXPRESS_PASS_THRU_COMMAND_PACKET));
+ ZeroMem (&Command, sizeof(NVM_EXPRESS_COMMAND));
+ ZeroMem (&Response, sizeof(NVM_EXPRESS_RESPONSE));
+
+ Command.Cdw0.Opcode = NVME_ADMIN_IDENTIFY_OPC;
+ Command.Cdw0.Cid = Private->Cid[0]++;
+ //
+ // According to Nvm Express 1.1 spec Figure 38, When not used, the field shall be cleared to 0h.
+ // For the Identify command, the Namespace Identifier is only used for the Namespace data structure.
+ //
+ Command.Nsid = 0;
+
+ CommandPacket.NvmeCmd = &Command;
+ CommandPacket.NvmeResponse = &Response;
+ CommandPacket.TransferBuffer = Buffer;
+ CommandPacket.TransferLength = sizeof (NVME_ADMIN_CONTROLLER_DATA);
+ CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT;
+ CommandPacket.QueueId = NVME_ADMIN_QUEUE;
+ //
+ // Set bit 0 (Cns bit) to 1 to identify a controller
+ //
+ Command.Cdw10 = 1;
+ Command.Flags = CDW10_VALID;
+
+ Status = Private->Passthru.PassThru (
+ &Private->Passthru,
+ NVME_CONTROLLER_ID,
+ 0,
+ &CommandPacket,
+ NULL
+ );
+
+ return Status;
+}
+
+/**
+ Get specified identify namespace data.
+
+ @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
+ @param NamespaceId The specified namespace identifier.
+ @param Buffer The buffer used to store the identify namespace data.
+
+ @return EFI_SUCCESS Successfully get the identify namespace data.
+ @return EFI_DEVICE_ERROR Fail to get the identify namespace data.
+
+**/
+EFI_STATUS
+NvmeIdentifyNamespace (
+ IN NVME_CONTROLLER_PRIVATE_DATA *Private,
+ IN UINT32 NamespaceId,
+ IN VOID *Buffer
+ )
+{
+ NVM_EXPRESS_PASS_THRU_COMMAND_PACKET CommandPacket;
+ NVM_EXPRESS_COMMAND Command;
+ NVM_EXPRESS_RESPONSE Response;
+ EFI_STATUS Status;
+
+ ZeroMem (&CommandPacket, sizeof(NVM_EXPRESS_PASS_THRU_COMMAND_PACKET));
+ ZeroMem (&Command, sizeof(NVM_EXPRESS_COMMAND));
+ ZeroMem (&Response, sizeof(NVM_EXPRESS_RESPONSE));
+
+ CommandPacket.NvmeCmd = &Command;
+ CommandPacket.NvmeResponse = &Response;
+
+ Command.Cdw0.Opcode = NVME_ADMIN_IDENTIFY_OPC;
+ Command.Cdw0.Cid = Private->Cid[0]++;
+ Command.Nsid = NamespaceId;
+ CommandPacket.TransferBuffer = Buffer;
+ CommandPacket.TransferLength = sizeof (NVME_ADMIN_NAMESPACE_DATA);
+ CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT;
+ CommandPacket.QueueId = NVME_ADMIN_QUEUE;
+ //
+ // Set bit 0 (Cns bit) to 1 to identify a namespace
+ //
+ CommandPacket.NvmeCmd->Cdw10 = 0;
+ CommandPacket.NvmeCmd->Flags = CDW10_VALID;
+
+ Status = Private->Passthru.PassThru (
+ &Private->Passthru,
+ NamespaceId,
+ 0,
+ &CommandPacket,
+ NULL
+ );
+
+ return Status;
+}
+
+/**
+ Create io completion queue.
+
+ @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
+
+ @return EFI_SUCCESS Successfully create io completion queue.
+ @return EFI_DEVICE_ERROR Fail to create io completion queue.
+
+**/
+EFI_STATUS
+NvmeCreateIoCompletionQueue (
+ IN NVME_CONTROLLER_PRIVATE_DATA *Private
+ )
+{
+ NVM_EXPRESS_PASS_THRU_COMMAND_PACKET CommandPacket;
+ NVM_EXPRESS_COMMAND Command;
+ NVM_EXPRESS_RESPONSE Response;
+ EFI_STATUS Status;
+ NVME_ADMIN_CRIOCQ CrIoCq;
+
+ ZeroMem (&CommandPacket, sizeof(NVM_EXPRESS_PASS_THRU_COMMAND_PACKET));
+ ZeroMem (&Command, sizeof(NVM_EXPRESS_COMMAND));
+ ZeroMem (&Response, sizeof(NVM_EXPRESS_RESPONSE));
+ ZeroMem (&CrIoCq, sizeof(NVME_ADMIN_CRIOCQ));
+
+ CommandPacket.NvmeCmd = &Command;
+ CommandPacket.NvmeResponse = &Response;
+
+ Command.Cdw0.Opcode = NVME_ADMIN_CRIOCQ_OPC;
+ Command.Cdw0.Cid = Private->Cid[0]++;
+ CommandPacket.TransferBuffer = Private->CqBufferPciAddr[1];
+ CommandPacket.TransferLength = EFI_PAGE_SIZE;
+ CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT;
+ CommandPacket.QueueId = NVME_ADMIN_QUEUE;
+
+ CrIoCq.Qid = NVME_IO_QUEUE;
+ CrIoCq.Qsize = NVME_CCQ_SIZE;
+ CrIoCq.Pc = 1;
+ CopyMem (&CommandPacket.NvmeCmd->Cdw10, &CrIoCq, sizeof (NVME_ADMIN_CRIOCQ));
+ CommandPacket.NvmeCmd->Flags = CDW10_VALID | CDW11_VALID;
+
+ Status = Private->Passthru.PassThru (
+ &Private->Passthru,
+ 0,
+ 0,
+ &CommandPacket,
+ NULL
+ );
+
+ return Status;
+}
+
+/**
+ Create io submission queue.
+
+ @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
+
+ @return EFI_SUCCESS Successfully create io submission queue.
+ @return EFI_DEVICE_ERROR Fail to create io submission queue.
+
+**/
+EFI_STATUS
+NvmeCreateIoSubmissionQueue (
+ IN NVME_CONTROLLER_PRIVATE_DATA *Private
+ )
+{
+ NVM_EXPRESS_PASS_THRU_COMMAND_PACKET CommandPacket;
+ NVM_EXPRESS_COMMAND Command;
+ NVM_EXPRESS_RESPONSE Response;
+ EFI_STATUS Status;
+ NVME_ADMIN_CRIOSQ CrIoSq;
+
+ ZeroMem (&CommandPacket, sizeof(NVM_EXPRESS_PASS_THRU_COMMAND_PACKET));
+ ZeroMem (&Command, sizeof(NVM_EXPRESS_COMMAND));
+ ZeroMem (&Response, sizeof(NVM_EXPRESS_RESPONSE));
+ ZeroMem (&CrIoSq, sizeof(NVME_ADMIN_CRIOSQ));
+
+ CommandPacket.NvmeCmd = &Command;
+ CommandPacket.NvmeResponse = &Response;
+
+ Command.Cdw0.Opcode = NVME_ADMIN_CRIOSQ_OPC;
+ Command.Cdw0.Cid = Private->Cid[0]++;
+ CommandPacket.TransferBuffer = Private->SqBufferPciAddr[1];
+ CommandPacket.TransferLength = EFI_PAGE_SIZE;
+ CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT;
+ CommandPacket.QueueId = NVME_ADMIN_QUEUE;
+
+ CrIoSq.Qid = NVME_IO_QUEUE;
+ CrIoSq.Qsize = NVME_CSQ_SIZE;
+ CrIoSq.Pc = 1;
+ CrIoSq.Cqid = NVME_IO_QUEUE;
+ CrIoSq.Qprio = 0;
+ CopyMem (&CommandPacket.NvmeCmd->Cdw10, &CrIoSq, sizeof (NVME_ADMIN_CRIOSQ));
+ CommandPacket.NvmeCmd->Flags = CDW10_VALID | CDW11_VALID;
+
+ Status = Private->Passthru.PassThru (
+ &Private->Passthru,
+ 0,
+ 0,
+ &CommandPacket,
+ NULL
+ );
+
+ return Status;
+}
+
+/**
+ Initialize the Nvm Express controller.
+
+ @param[in] Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
+
+ @retval EFI_SUCCESS The NVM Express Controller is initialized successfully.
+ @retval Others A device error occurred while initializing the controller.
+
+**/
+EFI_STATUS
+NvmeControllerInit (
+ IN NVME_CONTROLLER_PRIVATE_DATA *Private
+ )
+{
+ EFI_STATUS Status;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ UINT64 Supports;
+ NVME_AQA Aqa;
+ NVME_ASQ Asq;
+ NVME_ACQ Acq;
+
+ //
+ // Save original PCI attributes and enable this controller.
+ //
+ PciIo = Private->PciIo;
+ Status = PciIo->Attributes (
+ PciIo,
+ EfiPciIoAttributeOperationGet,
+ 0,
+ &Private->PciAttributes
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = PciIo->Attributes (
+ PciIo,
+ EfiPciIoAttributeOperationSupported,
+ 0,
+ &Supports
+ );
+
+ if (!EFI_ERROR (Status)) {
+ Supports &= EFI_PCI_DEVICE_ENABLE;
+ Status = PciIo->Attributes (
+ PciIo,
+ EfiPciIoAttributeOperationEnable,
+ Supports,
+ NULL
+ );
+ }
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_INFO, "NvmeControllerInit: failed to enable controller\n"));
+ return Status;
+ }
+
+ //
+ // Read the Controller Capabilities register and verify that the NVM command set is supported
+ //
+ Status = ReadNvmeControllerCapabilities (Private, &Private->Cap);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (Private->Cap.Css != 0x01) {
+ DEBUG ((EFI_D_INFO, "NvmeControllerInit: the controller doesn't support NVMe command set\n"));
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Currently the driver only supports 4k page size.
+ //
+ ASSERT ((Private->Cap.Mpsmin + 12) <= EFI_PAGE_SHIFT);
+
+ Private->Cid[0] = 0;
+ Private->Cid[1] = 0;
+
+ Status = NvmeDisableController (Private);
+
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ //
+ // set number of entries admin submission & completion queues.
+ //
+ Aqa.Asqs = NVME_ASQ_SIZE;
+ Aqa.Acqs = NVME_ACQ_SIZE;
+
+ //
+ // Address of admin submission queue.
+ //
+ Asq.Rsvd1 = 0;
+ Asq.Asqb = (UINT64)(UINTN)(Private->BufferPciAddr) >> 12;
+
+ //
+ // Address of admin completion queue.
+ //
+ Acq.Rsvd1 = 0;
+ Acq.Acqb = (UINT64)(UINTN)(Private->BufferPciAddr + EFI_PAGE_SIZE) >> 12;
+
+ //
+ // Address of I/O submission & completion queue.
+ //
+ Private->SqBuffer[0] = (NVME_SQ *)(UINTN)(Private->Buffer);
+ Private->SqBufferPciAddr[0] = (NVME_SQ *)(UINTN)(Private->BufferPciAddr);
+ Private->CqBuffer[0] = (NVME_CQ *)(UINTN)(Private->Buffer + 1 * EFI_PAGE_SIZE);
+ Private->CqBufferPciAddr[0] = (NVME_CQ *)(UINTN)(Private->BufferPciAddr + 1 * EFI_PAGE_SIZE);
+ Private->SqBuffer[1] = (NVME_SQ *)(UINTN)(Private->Buffer + 2 * EFI_PAGE_SIZE);
+ Private->SqBufferPciAddr[1] = (NVME_SQ *)(UINTN)(Private->BufferPciAddr + 2 * EFI_PAGE_SIZE);
+ Private->CqBuffer[1] = (NVME_CQ *)(UINTN)(Private->Buffer + 3 * EFI_PAGE_SIZE);
+ Private->CqBufferPciAddr[1] = (NVME_CQ *)(UINTN)(Private->BufferPciAddr + 3 * EFI_PAGE_SIZE);
+
+ DEBUG ((EFI_D_INFO, "Private->Buffer = [%016X]\n", (UINT64)(UINTN)Private->Buffer));
+ DEBUG ((EFI_D_INFO, "Admin Submission Queue size (Aqa.Asqs) = [%08X]\n", Aqa.Asqs));
+ DEBUG ((EFI_D_INFO, "Admin Completion Queue size (Aqa.Acqs) = [%08X]\n", Aqa.Acqs));
+ DEBUG ((EFI_D_INFO, "Admin Submission Queue (SqBuffer[0]) = [%016X]\n", Private->SqBuffer[0]));
+ DEBUG ((EFI_D_INFO, "Admin Completion Queue (CqBuffer[0]) = [%016X]\n", Private->CqBuffer[0]));
+ DEBUG ((EFI_D_INFO, "I/O Submission Queue (SqBuffer[1]) = [%016X]\n", Private->SqBuffer[1]));
+ DEBUG ((EFI_D_INFO, "I/O Completion Queue (CqBuffer[1]) = [%016X]\n", Private->CqBuffer[1]));
+
+ //
+ // Program admin queue attributes.
+ //
+ Status = WriteNvmeAdminQueueAttributes (Private, &Aqa);
+
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ //
+ // Program admin submission queue address.
+ //
+ Status = WriteNvmeAdminSubmissionQueueBaseAddress (Private, &Asq);
+
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ //
+ // Program admin completion queue address.
+ //
+ Status = WriteNvmeAdminCompletionQueueBaseAddress (Private, &Acq);
+
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ Status = NvmeEnableController (Private);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ //
+ // Create one I/O completion queue.
+ //
+ Status = NvmeCreateIoCompletionQueue (Private);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ //
+ // Create one I/O Submission queue.
+ //
+ Status = NvmeCreateIoSubmissionQueue (Private);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ //
+ // Allocate buffer for Identify Controller data
+ //
+ Private->ControllerData = (NVME_ADMIN_CONTROLLER_DATA *)AllocateZeroPool (sizeof(NVME_ADMIN_CONTROLLER_DATA));
+
+ if (Private->ControllerData == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Get current Identify Controller Data
+ //
+ Status = NvmeIdentifyController (Private, Private->ControllerData);
+
+ if (EFI_ERROR(Status)) {
+ FreePool(Private->ControllerData);
+ Private->ControllerData = NULL;
+ return EFI_NOT_FOUND;
+ }
+ return Status;
+}
+
diff --git a/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressHci.h b/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressHci.h
new file mode 100644
index 000000000..406cef4f8
--- /dev/null
+++ b/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressHci.h
@@ -0,0 +1,790 @@
+/** @file
+ NvmExpressDxe driver is used to manage non-volatile memory subsystem which follows
+ NVM Express specification.
+
+ Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>
+ 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 _NVME_HCI_H_
+#define _NVME_HCI_H_
+
+#define NVME_BAR 0
+
+//
+// controller register offsets
+//
+#define NVME_CAP_OFFSET 0x0000 // Controller Capabilities
+#define NVME_VER_OFFSET 0x0008 // Version
+#define NVME_INTMS_OFFSET 0x000c // Interrupt Mask Set
+#define NVME_INTMC_OFFSET 0x0010 // Interrupt Mask Clear
+#define NVME_CC_OFFSET 0x0014 // Controller Configuration
+#define NVME_CSTS_OFFSET 0x001c // Controller Status
+#define NVME_AQA_OFFSET 0x0024 // Admin Queue Attributes
+#define NVME_ASQ_OFFSET 0x0028 // Admin Submission Queue Base Address
+#define NVME_ACQ_OFFSET 0x0030 // Admin Completion Queue Base Address
+#define NVME_SQ0_OFFSET 0x1000 // Submission Queue 0 (admin) Tail Doorbell
+#define NVME_CQ0_OFFSET 0x1004 // Completion Queue 0 (admin) Head Doorbell
+
+//
+// These register offsets are defined as 0x1000 + (N * (4 << CAP.DSTRD))
+// Get the doorbell stride bit shift value from the controller capabilities.
+//
+#define NVME_SQTDBL_OFFSET(QID, DSTRD) 0x1000 + ((2 * (QID)) * (4 << (DSTRD))) // Submission Queue y (NVM) Tail Doorbell
+#define NVME_CQHDBL_OFFSET(QID, DSTRD) 0x1000 + (((2 * (QID)) + 1) * (4 << (DSTRD))) // Completion Queue y (NVM) Head Doorbell
+
+
+#pragma pack(1)
+
+//
+// 3.1.1 Offset 00h: CAP - Controller Capabilities
+//
+typedef struct {
+ UINT16 Mqes; // Maximum Queue Entries Supported
+ UINT8 Cqr:1; // Contiguous Queues Required
+ UINT8 Ams:2; // Arbitration Mechanism Supported
+ UINT8 Rsvd1:5;
+ UINT8 To; // Timeout
+ UINT16 Dstrd:4;
+ UINT16 Rsvd2:1;
+ UINT16 Css:4; // Command Sets Supported
+ UINT16 Rsvd3:7;
+ UINT8 Mpsmin:4;
+ UINT8 Mpsmax:4;
+ UINT8 Rsvd4;
+} NVME_CAP;
+
+//
+// 3.1.2 Offset 08h: VS - Version
+//
+typedef struct {
+ UINT16 Mnr; // Minor version number
+ UINT16 Mjr; // Major version number
+} NVME_VER;
+
+//
+// 3.1.5 Offset 14h: CC - Controller Configuration
+//
+typedef struct {
+ UINT16 En:1; // Enable
+ UINT16 Rsvd1:3;
+ UINT16 Css:3; // Command Set Selected
+ UINT16 Mps:4; // Memory Page Size
+ UINT16 Ams:3; // Arbitration Mechanism Selected
+ UINT16 Shn:2; // Shutdown Notification
+ UINT8 Iosqes:4; // I/O Submission Queue Entry Size
+ UINT8 Iocqes:4; // I/O Completion Queue Entry Size
+ UINT8 Rsvd2;
+} NVME_CC;
+
+//
+// 3.1.6 Offset 1Ch: CSTS - Controller Status
+//
+typedef struct {
+ UINT32 Rdy:1; // Ready
+ UINT32 Cfs:1; // Controller Fatal Status
+ UINT32 Shst:2; // Shutdown Status
+ UINT32 Nssro:1; // NVM Subsystem Reset Occurred
+ UINT32 Rsvd1:27;
+} NVME_CSTS;
+
+//
+// 3.1.8 Offset 24h: AQA - Admin Queue Attributes
+//
+typedef struct {
+ UINT16 Asqs:12; // Submission Queue Size
+ UINT16 Rsvd1:4;
+ UINT16 Acqs:12; // Completion Queue Size
+ UINT16 Rsvd2:4;
+} NVME_AQA;
+
+//
+// 3.1.9 Offset 28h: ASQ - Admin Submission Queue Base Address
+//
+typedef struct {
+ UINT64 Rsvd1:12;
+ UINT64 Asqb:52; // Admin Submission Queue Base Address
+} NVME_ASQ;
+
+//
+// 3.1.10 Offset 30h: ACQ - Admin Completion Queue Base Address
+//
+typedef struct {
+ UINT64 Rsvd1:12;
+ UINT64 Acqb:52; // Admin Completion Queue Base Address
+} NVME_ACQ;
+
+//
+// 3.1.11 Offset (1000h + ((2y) * (4 << CAP.DSTRD))): SQyTDBL - Submission Queue y Tail Doorbell
+//
+typedef struct {
+ UINT16 Sqt;
+ UINT16 Rsvd1;
+} NVME_SQTDBL;
+
+//
+// 3.1.12 Offset (1000h + ((2y + 1) * (4 << CAP.DSTRD))): CQyHDBL - Completion Queue y Head Doorbell
+//
+typedef struct {
+ UINT16 Cqh;
+ UINT16 Rsvd1;
+} NVME_CQHDBL;
+
+//
+// NVM command set structures
+//
+// Read Command
+//
+typedef struct {
+ //
+ // CDW 10, 11
+ //
+ UINT64 Slba; /* Starting Sector Address */
+ //
+ // CDW 12
+ //
+ UINT16 Nlb; /* Number of Sectors */
+ UINT16 Rsvd1:10;
+ UINT16 Prinfo:4; /* Protection Info Check */
+ UINT16 Fua:1; /* Force Unit Access */
+ UINT16 Lr:1; /* Limited Retry */
+ //
+ // CDW 13
+ //
+ UINT32 Af:4; /* Access Frequency */
+ UINT32 Al:2; /* Access Latency */
+ UINT32 Sr:1; /* Sequential Request */
+ UINT32 In:1; /* Incompressible */
+ UINT32 Rsvd2:24;
+ //
+ // CDW 14
+ //
+ UINT32 Eilbrt; /* Expected Initial Logical Block Reference Tag */
+ //
+ // CDW 15
+ //
+ UINT16 Elbat; /* Expected Logical Block Application Tag */
+ UINT16 Elbatm; /* Expected Logical Block Application Tag Mask */
+} NVME_READ;
+
+//
+// Write Command
+//
+typedef struct {
+ //
+ // CDW 10, 11
+ //
+ UINT64 Slba; /* Starting Sector Address */
+ //
+ // CDW 12
+ //
+ UINT16 Nlb; /* Number of Sectors */
+ UINT16 Rsvd1:10;
+ UINT16 Prinfo:4; /* Protection Info Check */
+ UINT16 Fua:1; /* Force Unit Access */
+ UINT16 Lr:1; /* Limited Retry */
+ //
+ // CDW 13
+ //
+ UINT32 Af:4; /* Access Frequency */
+ UINT32 Al:2; /* Access Latency */
+ UINT32 Sr:1; /* Sequential Request */
+ UINT32 In:1; /* Incompressible */
+ UINT32 Rsvd2:24;
+ //
+ // CDW 14
+ //
+ UINT32 Ilbrt; /* Initial Logical Block Reference Tag */
+ //
+ // CDW 15
+ //
+ UINT16 Lbat; /* Logical Block Application Tag */
+ UINT16 Lbatm; /* Logical Block Application Tag Mask */
+} NVME_WRITE;
+
+//
+// Flush
+//
+typedef struct {
+ //
+ // CDW 10
+ //
+ UINT32 Flush; /* Flush */
+} NVME_FLUSH;
+
+//
+// Write Uncorrectable command
+//
+typedef struct {
+ //
+ // CDW 10, 11
+ //
+ UINT64 Slba; /* Starting LBA */
+ //
+ // CDW 12
+ //
+ UINT32 Nlb:16; /* Number of Logical Blocks */
+ UINT32 Rsvd1:16;
+} NVME_WRITE_UNCORRECTABLE;
+
+//
+// Write Zeroes command
+//
+typedef struct {
+ //
+ // CDW 10, 11
+ //
+ UINT64 Slba; /* Starting LBA */
+ //
+ // CDW 12
+ //
+ UINT16 Nlb; /* Number of Logical Blocks */
+ UINT16 Rsvd1:10;
+ UINT16 Prinfo:4; /* Protection Info Check */
+ UINT16 Fua:1; /* Force Unit Access */
+ UINT16 Lr:1; /* Limited Retry */
+ //
+ // CDW 13
+ //
+ UINT32 Rsvd2;
+ //
+ // CDW 14
+ //
+ UINT32 Ilbrt; /* Initial Logical Block Reference Tag */
+ //
+ // CDW 15
+ //
+ UINT16 Lbat; /* Logical Block Application Tag */
+ UINT16 Lbatm; /* Logical Block Application Tag Mask */
+} NVME_WRITE_ZEROES;
+
+//
+// Compare command
+//
+typedef struct {
+ //
+ // CDW 10, 11
+ //
+ UINT64 Slba; /* Starting LBA */
+ //
+ // CDW 12
+ //
+ UINT16 Nlb; /* Number of Logical Blocks */
+ UINT16 Rsvd1:10;
+ UINT16 Prinfo:4; /* Protection Info Check */
+ UINT16 Fua:1; /* Force Unit Access */
+ UINT16 Lr:1; /* Limited Retry */
+ //
+ // CDW 13
+ //
+ UINT32 Rsvd2;
+ //
+ // CDW 14
+ //
+ UINT32 Eilbrt; /* Expected Initial Logical Block Reference Tag */
+ //
+ // CDW 15
+ //
+ UINT16 Elbat; /* Expected Logical Block Application Tag */
+ UINT16 Elbatm; /* Expected Logical Block Application Tag Mask */
+} NVME_COMPARE;
+
+typedef union {
+ NVME_READ Read;
+ NVME_WRITE Write;
+ NVME_FLUSH Flush;
+ NVME_WRITE_UNCORRECTABLE WriteUncorrectable;
+ NVME_WRITE_ZEROES WriteZeros;
+ NVME_COMPARE Compare;
+} NVME_CMD;
+
+typedef struct {
+ UINT16 Mp; /* Maximum Power */
+ UINT8 Rsvd1; /* Reserved as of Nvm Express 1.1 Spec */
+ UINT8 Mps:1; /* Max Power Scale */
+ UINT8 Nops:1; /* Non-Operational State */
+ UINT8 Rsvd2:6; /* Reserved as of Nvm Express 1.1 Spec */
+ UINT32 Enlat; /* Entry Latency */
+ UINT32 Exlat; /* Exit Latency */
+ UINT8 Rrt:5; /* Relative Read Throughput */
+ UINT8 Rsvd3:3; /* Reserved as of Nvm Express 1.1 Spec */
+ UINT8 Rrl:5; /* Relative Read Leatency */
+ UINT8 Rsvd4:3; /* Reserved as of Nvm Express 1.1 Spec */
+ UINT8 Rwt:5; /* Relative Write Throughput */
+ UINT8 Rsvd5:3; /* Reserved as of Nvm Express 1.1 Spec */
+ UINT8 Rwl:5; /* Relative Write Leatency */
+ UINT8 Rsvd6:3; /* Reserved as of Nvm Express 1.1 Spec */
+ UINT8 Rsvd7[16]; /* Reserved as of Nvm Express 1.1 Spec */
+} NVME_PSDESCRIPTOR;
+
+//
+// Identify Controller Data
+//
+typedef struct {
+ //
+ // Controller Capabilities and Features 0-255
+ //
+ UINT16 Vid; /* PCI Vendor ID */
+ UINT16 Ssvid; /* PCI sub-system vendor ID */
+ UINT8 Sn[20]; /* Produce serial number */
+
+ UINT8 Mn[40]; /* Proeduct model number */
+ UINT8 Fr[8]; /* Firmware Revision */
+ UINT8 Rab; /* Recommended Arbitration Burst */
+ UINT8 Ieee_oiu[3]; /* Organization Unique Identifier */
+ UINT8 Cmic; /* Multi-interface Capabilities */
+ UINT8 Mdts; /* Maximum Data Transfer Size */
+ UINT8 Cntlid[2]; /* Controller ID */
+ UINT8 Rsvd1[176]; /* Reserved as of Nvm Express 1.1 Spec */
+ //
+ // Admin Command Set Attributes
+ //
+ UINT16 Oacs; /* Optional Admin Command Support */
+ UINT8 Acl; /* Abort Command Limit */
+ UINT8 Aerl; /* Async Event Request Limit */
+ UINT8 Frmw; /* Firmware updates */
+ UINT8 Lpa; /* Log Page Attributes */
+ UINT8 Elpe; /* Error Log Page Entries */
+ UINT8 Npss; /* Number of Power States Support */
+ UINT8 Avscc; /* Admin Vendor Specific Command Configuration */
+ UINT8 Apsta; /* Autonomous Power State Transition Attributes */
+ UINT8 Rsvd2[246]; /* Reserved as of Nvm Express 1.1 Spec */
+ //
+ // NVM Command Set Attributes
+ //
+ UINT8 Sqes; /* Submission Queue Entry Size */
+ UINT8 Cqes; /* Completion Queue Entry Size */
+ UINT16 Rsvd3; /* Reserved as of Nvm Express 1.1 Spec */
+ UINT32 Nn; /* Number of Namespaces */
+ UINT16 Oncs; /* Optional NVM Command Support */
+ UINT16 Fuses; /* Fused Operation Support */
+ UINT8 Fna; /* Format NVM Attributes */
+ UINT8 Vwc; /* Volatile Write Cache */
+ UINT16 Awun; /* Atomic Write Unit Normal */
+ UINT16 Awupf; /* Atomic Write Unit Power Fail */
+ UINT8 Nvscc; /* NVM Vendor Specific Command Configuration */
+ UINT8 Rsvd4; /* Reserved as of Nvm Express 1.1 Spec */
+ UINT16 Acwu; /* Atomic Compare & Write Unit */
+ UINT16 Rsvd5; /* Reserved as of Nvm Express 1.1 Spec */
+ UINT32 Sgls; /* SGL Support */
+ UINT8 Rsvd6[164]; /* Reserved as of Nvm Express 1.1 Spec */
+ //
+ // I/O Command set Attributes
+ //
+ UINT8 Rsvd7[1344]; /* Reserved as of Nvm Express 1.1 Spec */
+ //
+ // Power State Descriptors
+ //
+ NVME_PSDESCRIPTOR PsDescriptor[32];
+
+ UINT8 VendorData[1024]; /* Vendor specific data */
+} NVME_ADMIN_CONTROLLER_DATA;
+
+typedef struct {
+ UINT16 Ms; /* Metadata Size */
+ UINT8 Lbads; /* LBA Data Size */
+ UINT8 Rp:2; /* Relative Performance */
+ #define LBAF_RP_BEST 00b
+ #define LBAF_RP_BETTER 01b
+ #define LBAF_RP_GOOD 10b
+ #define LBAF_RP_DEGRADED 11b
+ UINT8 Rsvd1:6; /* Reserved as of Nvm Express 1.1 Spec */
+} NVME_LBAFORMAT;
+
+//
+// Identify Namespace Data
+//
+typedef struct {
+ //
+ // NVM Command Set Specific
+ //
+ UINT64 Nsze; /* Namespace Size (total number of blocks in formatted namespace) */
+ UINT64 Ncap; /* Namespace Capacity (max number of logical blocks) */
+ UINT64 Nuse; /* Namespace Utilization */
+ UINT8 Nsfeat; /* Namespace Features */
+ UINT8 Nlbaf; /* Number of LBA Formats */
+ UINT8 Flbas; /* Formatted LBA size */
+ UINT8 Mc; /* Metadata Capabilities */
+ UINT8 Dpc; /* End-to-end Data Protection capabilities */
+ UINT8 Dps; /* End-to-end Data Protection Type Settings */
+ UINT8 Nmic; /* Namespace Multi-path I/O and Namespace Sharing Capabilities */
+ UINT8 Rescap; /* Reservation Capabilities */
+ UINT8 Rsvd1[88]; /* Reserved as of Nvm Express 1.1 Spec */
+ UINT64 Eui64; /* IEEE Extended Unique Identifier */
+ //
+ // LBA Format
+ //
+ NVME_LBAFORMAT LbaFormat[16];
+
+ UINT8 Rsvd2[192]; /* Reserved as of Nvm Express 1.1 Spec */
+ UINT8 VendorData[3712]; /* Vendor specific data */
+} NVME_ADMIN_NAMESPACE_DATA;
+
+//
+// NvmExpress Admin Identify Cmd
+//
+typedef struct {
+ //
+ // CDW 10
+ //
+ UINT32 Cns:2;
+ UINT32 Rsvd1:30;
+} NVME_ADMIN_IDENTIFY;
+
+//
+// NvmExpress Admin Create I/O Completion Queue
+//
+typedef struct {
+ //
+ // CDW 10
+ //
+ UINT32 Qid:16; /* Queue Identifier */
+ UINT32 Qsize:16; /* Queue Size */
+
+ //
+ // CDW 11
+ //
+ UINT32 Pc:1; /* Physically Contiguous */
+ UINT32 Ien:1; /* Interrupts Enabled */
+ UINT32 Rsvd1:14; /* reserved as of Nvm Express 1.1 Spec */
+ UINT32 Iv:16; /* Interrupt Vector */
+} NVME_ADMIN_CRIOCQ;
+
+//
+// NvmExpress Admin Create I/O Submission Queue
+//
+typedef struct {
+ //
+ // CDW 10
+ //
+ UINT32 Qid:16; /* Queue Identifier */
+ UINT32 Qsize:16; /* Queue Size */
+
+ //
+ // CDW 11
+ //
+ UINT32 Pc:1; /* Physically Contiguous */
+ UINT32 Qprio:2; /* Queue Priority */
+ UINT32 Rsvd1:13; /* Reserved as of Nvm Express 1.1 Spec */
+ UINT32 Cqid:16; /* Completion Queue ID */
+} NVME_ADMIN_CRIOSQ;
+
+//
+// NvmExpress Admin Delete I/O Completion Queue
+//
+typedef struct {
+ //
+ // CDW 10
+ //
+ UINT16 Qid;
+ UINT16 Rsvd1;
+} NVME_ADMIN_DEIOCQ;
+
+//
+// NvmExpress Admin Delete I/O Submission Queue
+//
+typedef struct {
+ //
+ // CDW 10
+ //
+ UINT16 Qid;
+ UINT16 Rsvd1;
+} NVME_ADMIN_DEIOSQ;
+
+//
+// NvmExpress Admin Abort Command
+//
+typedef struct {
+ //
+ // CDW 10
+ //
+ UINT32 Sqid:16; /* Submission Queue identifier */
+ UINT32 Cid:16; /* Command Identifier */
+} NVME_ADMIN_ABORT;
+
+//
+// NvmExpress Admin Firmware Activate Command
+//
+typedef struct {
+ //
+ // CDW 10
+ //
+ UINT32 Fs:3; /* Submission Queue identifier */
+ UINT32 Aa:2; /* Command Identifier */
+ UINT32 Rsvd1:27;
+} NVME_ADMIN_FIRMWARE_ACTIVATE;
+
+//
+// NvmExpress Admin Firmware Image Download Command
+//
+typedef struct {
+ //
+ // CDW 10
+ //
+ UINT32 Numd; /* Number of Dwords */
+ //
+ // CDW 11
+ //
+ UINT32 Ofst; /* Offset */
+} NVME_ADMIN_FIRMWARE_IMAGE_DOWNLOAD;
+
+//
+// NvmExpress Admin Get Features Command
+//
+typedef struct {
+ //
+ // CDW 10
+ //
+ UINT32 Fid:8; /* Feature Identifier */
+ UINT32 Sel:3; /* Select */
+ UINT32 Rsvd1:21;
+} NVME_ADMIN_GET_FEATURES;
+
+//
+// NvmExpress Admin Get Log Page Command
+//
+typedef struct {
+ //
+ // CDW 10
+ //
+ UINT32 Lid:8; /* Log Page Identifier */
+ #define LID_ERROR_INFO
+ #define LID_SMART_INFO
+ #define LID_FW_SLOT_INFO
+ UINT32 Rsvd1:8;
+ UINT32 Numd:12; /* Number of Dwords */
+ UINT32 Rsvd2:4; /* Reserved as of Nvm Express 1.1 Spec */
+} NVME_ADMIN_GET_LOG_PAGE;
+
+//
+// NvmExpress Admin Set Features Command
+//
+typedef struct {
+ //
+ // CDW 10
+ //
+ UINT32 Fid:8; /* Feature Identifier */
+ UINT32 Rsvd1:23;
+ UINT32 Sv:1; /* Save */
+} NVME_ADMIN_SET_FEATURES;
+
+//
+// NvmExpress Admin Format NVM Command
+//
+typedef struct {
+ //
+ // CDW 10
+ //
+ UINT32 Lbaf:4; /* LBA Format */
+ UINT32 Ms:1; /* Metadata Settings */
+ UINT32 Pi:3; /* Protection Information */
+ UINT32 Pil:1; /* Protection Information Location */
+ UINT32 Ses:3; /* Secure Erase Settings */
+ UINT32 Rsvd1:20;
+} NVME_ADMIN_FORMAT_NVM;
+
+//
+// NvmExpress Admin Security Receive Command
+//
+typedef struct {
+ //
+ // CDW 10
+ //
+ UINT32 Rsvd1:8;
+ UINT32 Spsp:16; /* SP Specific */
+ UINT32 Secp:8; /* Security Protocol */
+ //
+ // CDW 11
+ //
+ UINT32 Al; /* Allocation Length */
+} NVME_ADMIN_SECURITY_RECEIVE;
+
+//
+// NvmExpress Admin Security Send Command
+//
+typedef struct {
+ //
+ // CDW 10
+ //
+ UINT32 Rsvd1:8;
+ UINT32 Spsp:16; /* SP Specific */
+ UINT32 Secp:8; /* Security Protocol */
+ //
+ // CDW 11
+ //
+ UINT32 Tl; /* Transfer Length */
+} NVME_ADMIN_SECURITY_SEND;
+
+typedef union {
+ NVME_ADMIN_IDENTIFY Identify;
+ NVME_ADMIN_CRIOCQ CrIoCq;
+ NVME_ADMIN_CRIOSQ CrIoSq;
+ NVME_ADMIN_DEIOCQ DeIoCq;
+ NVME_ADMIN_DEIOSQ DeIoSq;
+ NVME_ADMIN_ABORT Abort;
+ NVME_ADMIN_FIRMWARE_ACTIVATE Activate;
+ NVME_ADMIN_FIRMWARE_IMAGE_DOWNLOAD FirmwareImageDownload;
+ NVME_ADMIN_GET_FEATURES GetFeatures;
+ NVME_ADMIN_GET_LOG_PAGE GetLogPage;
+ NVME_ADMIN_SET_FEATURES SetFeatures;
+ NVME_ADMIN_FORMAT_NVM FormatNvm;
+ NVME_ADMIN_SECURITY_RECEIVE SecurityReceive;
+ NVME_ADMIN_SECURITY_SEND SecuritySend;
+} NVME_ADMIN_CMD;
+
+typedef struct {
+ UINT32 Cdw10;
+ UINT32 Cdw11;
+ UINT32 Cdw12;
+ UINT32 Cdw13;
+ UINT32 Cdw14;
+ UINT32 Cdw15;
+} NVME_RAW;
+
+typedef union {
+ NVME_ADMIN_CMD Admin; // Union of Admin commands
+ NVME_CMD Nvm; // Union of Nvm commands
+ NVME_RAW Raw;
+} NVME_PAYLOAD;
+
+//
+// Submission Queue
+//
+typedef struct {
+ //
+ // CDW 0, Common to all comnmands
+ //
+ UINT8 Opc; // Opcode
+ UINT8 Fuse:2; // Fused Operation
+ UINT8 Rsvd1:5;
+ UINT8 Psdt:1; // PRP or SGL for Data Transfer
+ UINT16 Cid; // Command Identifier
+
+ //
+ // CDW 1
+ //
+ UINT32 Nsid; // Namespace Identifier
+
+ //
+ // CDW 2,3
+ //
+ UINT64 Rsvd2;
+
+ //
+ // CDW 4,5
+ //
+ UINT64 Mptr; // Metadata Pointer
+
+ //
+ // CDW 6-9
+ //
+ UINT64 Prp[2]; // First and second PRP entries
+
+ NVME_PAYLOAD Payload;
+
+} NVME_SQ;
+
+//
+// Completion Queue
+//
+typedef struct {
+ //
+ // CDW 0
+ //
+ UINT32 Dword0;
+ //
+ // CDW 1
+ //
+ UINT32 Rsvd1;
+ //
+ // CDW 2
+ //
+ UINT16 Sqhd; // Submission Queue Head Pointer
+ UINT16 Sqid; // Submission Queue Identifier
+ //
+ // CDW 3
+ //
+ UINT16 Cid; // Command Identifier
+ UINT16 Pt:1; // Phase Tag
+ UINT16 Sc:8; // Status Code
+ UINT16 Sct:3; // Status Code Type
+ UINT16 Rsvd2:2;
+ UINT16 Mo:1; // More
+ UINT16 Dnr:1; // Retry
+} NVME_CQ;
+
+//
+// Nvm Express Admin cmd opcodes
+//
+#define NVME_ADMIN_CRIOSQ_OPC 1
+#define NVME_ADMIN_CRIOCQ_OPC 5
+#define NVME_ADMIN_IDENTIFY_OPC 6
+
+#define NVME_IO_FLUSH_OPC 0
+#define NVME_IO_WRITE_OPC 1
+#define NVME_IO_READ_OPC 2
+
+//
+// Offset from the beginning of private data queue buffer
+//
+#define NVME_ASQ_BUF_OFFSET EFI_PAGE_SIZE
+
+/**
+ Initialize the Nvm Express controller.
+
+ @param[in] Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
+
+ @retval EFI_SUCCESS The NVM Express Controller is initialized successfully.
+ @retval Others A device error occurred while initializing the controller.
+
+**/
+EFI_STATUS
+NvmeControllerInit (
+ IN NVME_CONTROLLER_PRIVATE_DATA *Private
+ );
+
+/**
+ Get identify controller data.
+
+ @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
+ @param Buffer The buffer used to store the identify controller data.
+
+ @return EFI_SUCCESS Successfully get the identify controller data.
+ @return EFI_DEVICE_ERROR Fail to get the identify controller data.
+
+**/
+EFI_STATUS
+NvmeIdentifyController (
+ IN NVME_CONTROLLER_PRIVATE_DATA *Private,
+ IN VOID *Buffer
+ );
+
+/**
+ Get specified identify namespace data.
+
+ @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
+ @param NamespaceId The specified namespace identifier.
+ @param Buffer The buffer used to store the identify namespace data.
+
+ @return EFI_SUCCESS Successfully get the identify namespace data.
+ @return EFI_DEVICE_ERROR Fail to get the identify namespace data.
+
+**/
+EFI_STATUS
+NvmeIdentifyNamespace (
+ IN NVME_CONTROLLER_PRIVATE_DATA *Private,
+ IN UINT32 NamespaceId,
+ IN VOID *Buffer
+ );
+
+#pragma pack()
+
+#endif
+
diff --git a/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressPassthru.c b/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressPassthru.c
new file mode 100644
index 000000000..d1231aca8
--- /dev/null
+++ b/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressPassthru.c
@@ -0,0 +1,884 @@
+/** @file
+ NvmExpressDxe driver is used to manage non-volatile memory subsystem which follows
+ NVM Express specification.
+
+ Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>
+ 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 "NvmExpress.h"
+
+//
+// Page size should be set in the Controller Configuration register
+// during controller init, and the controller configuration save in
+// the controller's private data. The Max and Min supported page sizes
+// for the controller are specified in the Controller Capabilities register.
+//
+
+GLOBAL_REMOVE_IF_UNREFERENCED NVM_EXPRESS_PASS_THRU_MODE gNvmExpressPassThruMode = {
+ 0,
+ NVM_EXPRESS_PASS_THRU_ATTRIBUTES_PHYSICAL | NVM_EXPRESS_PASS_THRU_ATTRIBUTES_CMD_SET_NVME,
+ sizeof (UINTN),
+ 0x10000,
+ 0,
+ 0
+};
+
+
+/**
+ Dump the execution status from a given completion queue entry.
+
+ @param[in] Cq A pointer to the NVME_CQ item.
+
+**/
+VOID
+NvmeDumpStatus (
+ IN NVME_CQ *Cq
+ )
+{
+ DEBUG ((EFI_D_VERBOSE, "Dump NVMe Completion Entry Status from [0x%x]:\n", Cq));
+
+ DEBUG ((EFI_D_VERBOSE, " SQ Identifier : [0x%x], Phase Tag : [%d], Cmd Identifier : [0x%x]\n", Cq->Sqid, Cq->Pt, Cq->Cid));
+
+ DEBUG ((EFI_D_VERBOSE, " NVMe Cmd Execution Result - "));
+
+ switch (Cq->Sct) {
+ case 0x0:
+ switch (Cq->Sc) {
+ case 0x0:
+ DEBUG ((EFI_D_VERBOSE, "Successful Completion\n"));
+ break;
+ case 0x1:
+ DEBUG ((EFI_D_VERBOSE, "Invalid Command Opcode\n"));
+ break;
+ case 0x2:
+ DEBUG ((EFI_D_VERBOSE, "Invalid Field in Command\n"));
+ break;
+ case 0x3:
+ DEBUG ((EFI_D_VERBOSE, "Command ID Conflict\n"));
+ break;
+ case 0x4:
+ DEBUG ((EFI_D_VERBOSE, "Data Transfer Error\n"));
+ break;
+ case 0x5:
+ DEBUG ((EFI_D_VERBOSE, "Commands Aborted due to Power Loss Notification\n"));
+ break;
+ case 0x6:
+ DEBUG ((EFI_D_VERBOSE, "Internal Device Error\n"));
+ break;
+ case 0x7:
+ DEBUG ((EFI_D_VERBOSE, "Command Abort Requested\n"));
+ break;
+ case 0x8:
+ DEBUG ((EFI_D_VERBOSE, "Command Aborted due to SQ Deletion\n"));
+ break;
+ case 0x9:
+ DEBUG ((EFI_D_VERBOSE, "Command Aborted due to Failed Fused Command\n"));
+ break;
+ case 0xA:
+ DEBUG ((EFI_D_VERBOSE, "Command Aborted due to Missing Fused Command\n"));
+ break;
+ case 0xB:
+ DEBUG ((EFI_D_VERBOSE, "Invalid Namespace or Format\n"));
+ break;
+ case 0xC:
+ DEBUG ((EFI_D_VERBOSE, "Command Sequence Error\n"));
+ break;
+ case 0xD:
+ DEBUG ((EFI_D_VERBOSE, "Invalid SGL Last Segment Descriptor\n"));
+ break;
+ case 0xE:
+ DEBUG ((EFI_D_VERBOSE, "Invalid Number of SGL Descriptors\n"));
+ break;
+ case 0xF:
+ DEBUG ((EFI_D_VERBOSE, "Data SGL Length Invalid\n"));
+ break;
+ case 0x10:
+ DEBUG ((EFI_D_VERBOSE, "Metadata SGL Length Invalid\n"));
+ break;
+ case 0x11:
+ DEBUG ((EFI_D_VERBOSE, "SGL Descriptor Type Invalid\n"));
+ break;
+ case 0x80:
+ DEBUG ((EFI_D_VERBOSE, "LBA Out of Range\n"));
+ break;
+ case 0x81:
+ DEBUG ((EFI_D_VERBOSE, "Capacity Exceeded\n"));
+ break;
+ case 0x82:
+ DEBUG ((EFI_D_VERBOSE, "Namespace Not Ready\n"));
+ break;
+ case 0x83:
+ DEBUG ((EFI_D_VERBOSE, "Reservation Conflict\n"));
+ break;
+ }
+ break;
+
+ case 0x1:
+ switch (Cq->Sc) {
+ case 0x0:
+ DEBUG ((EFI_D_VERBOSE, "Completion Queue Invalid\n"));
+ break;
+ case 0x1:
+ DEBUG ((EFI_D_VERBOSE, "Invalid Queue Identifier\n"));
+ break;
+ case 0x2:
+ DEBUG ((EFI_D_VERBOSE, "Maximum Queue Size Exceeded\n"));
+ break;
+ case 0x3:
+ DEBUG ((EFI_D_VERBOSE, "Abort Command Limit Exceeded\n"));
+ break;
+ case 0x5:
+ DEBUG ((EFI_D_VERBOSE, "Asynchronous Event Request Limit Exceeded\n"));
+ break;
+ case 0x6:
+ DEBUG ((EFI_D_VERBOSE, "Invalid Firmware Slot\n"));
+ break;
+ case 0x7:
+ DEBUG ((EFI_D_VERBOSE, "Invalid Firmware Image\n"));
+ break;
+ case 0x8:
+ DEBUG ((EFI_D_VERBOSE, "Invalid Interrupt Vector\n"));
+ break;
+ case 0x9:
+ DEBUG ((EFI_D_VERBOSE, "Invalid Log Page\n"));
+ break;
+ case 0xA:
+ DEBUG ((EFI_D_VERBOSE, "Invalid Format\n"));
+ break;
+ case 0xB:
+ DEBUG ((EFI_D_VERBOSE, "Firmware Application Requires Conventional Reset\n"));
+ break;
+ case 0xC:
+ DEBUG ((EFI_D_VERBOSE, "Invalid Queue Deletion\n"));
+ break;
+ case 0xD:
+ DEBUG ((EFI_D_VERBOSE, "Feature Identifier Not Saveable\n"));
+ break;
+ case 0xE:
+ DEBUG ((EFI_D_VERBOSE, "Feature Not Changeable\n"));
+ break;
+ case 0xF:
+ DEBUG ((EFI_D_VERBOSE, "Feature Not Namespace Specific\n"));
+ break;
+ case 0x10:
+ DEBUG ((EFI_D_VERBOSE, "Firmware Application Requires NVM Subsystem Reset\n"));
+ break;
+ case 0x80:
+ DEBUG ((EFI_D_VERBOSE, "Conflicting Attributes\n"));
+ break;
+ case 0x81:
+ DEBUG ((EFI_D_VERBOSE, "Invalid Protection Information\n"));
+ break;
+ case 0x82:
+ DEBUG ((EFI_D_VERBOSE, "Attempted Write to Read Only Range\n"));
+ break;
+ }
+ break;
+
+ case 0x2:
+ switch (Cq->Sc) {
+ case 0x80:
+ DEBUG ((EFI_D_VERBOSE, "Write Fault\n"));
+ break;
+ case 0x81:
+ DEBUG ((EFI_D_VERBOSE, "Unrecovered Read Error\n"));
+ break;
+ case 0x82:
+ DEBUG ((EFI_D_VERBOSE, "End-to-end Guard Check Error\n"));
+ break;
+ case 0x83:
+ DEBUG ((EFI_D_VERBOSE, "End-to-end Application Tag Check Error\n"));
+ break;
+ case 0x84:
+ DEBUG ((EFI_D_VERBOSE, "End-to-end Reference Tag Check Error\n"));
+ break;
+ case 0x85:
+ DEBUG ((EFI_D_VERBOSE, "Compare Failure\n"));
+ break;
+ case 0x86:
+ DEBUG ((EFI_D_VERBOSE, "Access Denied\n"));
+ break;
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+/**
+ Create PRP lists for data transfer which is larger than 2 memory pages.
+ Note here we calcuate the number of required PRP lists and allocate them at one time.
+
+ @param[in] PciIo A pointer to the EFI_PCI_IO_PROTOCOL instance.
+ @param[in] PhysicalAddr The physical base address of data buffer.
+ @param[in] Pages The number of pages to be transfered.
+ @param[out] PrpListHost The host base address of PRP lists.
+ @param[in,out] PrpListNo The number of PRP List.
+ @param[out] Mapping The mapping value returned from PciIo.Map().
+
+ @retval The pointer to the first PRP List of the PRP lists.
+
+**/
+VOID*
+NvmeCreatePrpList (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN EFI_PHYSICAL_ADDRESS PhysicalAddr,
+ IN UINTN Pages,
+ OUT VOID **PrpListHost,
+ IN OUT UINTN *PrpListNo,
+ OUT VOID **Mapping
+ )
+{
+ UINTN PrpEntryNo;
+ UINT64 PrpListBase;
+ UINTN PrpListIndex;
+ UINTN PrpEntryIndex;
+ UINT64 Remainder;
+ EFI_PHYSICAL_ADDRESS PrpListPhyAddr;
+ UINTN Bytes;
+ EFI_STATUS Status;
+
+ //
+ // The number of Prp Entry in a memory page.
+ //
+ PrpEntryNo = EFI_PAGE_SIZE / sizeof (UINT64);
+
+ //
+ // Calculate total PrpList number.
+ //
+ *PrpListNo = (UINTN)DivU64x64Remainder ((UINT64)Pages, (UINT64)PrpEntryNo, &Remainder);
+ if (Remainder != 0) {
+ *PrpListNo += 1;
+ }
+
+ Status = PciIo->AllocateBuffer (
+ PciIo,
+ AllocateAnyPages,
+ EfiBootServicesData,
+ *PrpListNo,
+ PrpListHost,
+ 0
+ );
+
+ if (EFI_ERROR (Status)) {
+ return NULL;
+ }
+
+ Bytes = EFI_PAGES_TO_SIZE (*PrpListNo);
+ Status = PciIo->Map (
+ PciIo,
+ EfiPciIoOperationBusMasterCommonBuffer,
+ *PrpListHost,
+ &Bytes,
+ &PrpListPhyAddr,
+ Mapping
+ );
+
+ if (EFI_ERROR (Status) || (Bytes != EFI_PAGES_TO_SIZE (*PrpListNo))) {
+ DEBUG ((EFI_D_ERROR, "NvmeCreatePrpList: create PrpList failure!\n"));
+ goto EXIT;
+ }
+ //
+ // Fill all PRP lists except of last one.
+ //
+ ZeroMem (*PrpListHost, Bytes);
+ for (PrpListIndex = 0; PrpListIndex < *PrpListNo - 1; ++PrpListIndex) {
+ PrpListBase = *(UINT8*)PrpListHost + PrpListIndex * EFI_PAGE_SIZE;
+
+ for (PrpEntryIndex = 0; PrpEntryIndex < PrpEntryNo; ++PrpEntryIndex) {
+ if (PrpEntryIndex != PrpEntryNo - 1) {
+ //
+ // Fill all PRP entries except of last one.
+ //
+ *((UINT64*)(UINTN)PrpListBase + PrpEntryIndex) = PhysicalAddr;
+ PhysicalAddr += EFI_PAGE_SIZE;
+ } else {
+ //
+ // Fill last PRP entries with next PRP List pointer.
+ //
+ *((UINT64*)(UINTN)PrpListBase + PrpEntryIndex) = PrpListPhyAddr + (PrpListIndex + 1) * EFI_PAGE_SIZE;
+ }
+ }
+ }
+ //
+ // Fill last PRP list.
+ //
+ PrpListBase = *(UINT64*)PrpListHost + PrpListIndex * EFI_PAGE_SIZE;
+ for (PrpEntryIndex = 0; PrpEntryIndex < ((Remainder != 0) ? Remainder : PrpEntryNo); ++PrpEntryIndex) {
+ *((UINT64*)(UINTN)PrpListBase + PrpEntryIndex) = PhysicalAddr;
+ PhysicalAddr += EFI_PAGE_SIZE;
+ }
+
+ return (VOID*)(UINTN)PrpListPhyAddr;
+
+EXIT:
+ PciIo->FreeBuffer (PciIo, *PrpListNo, *PrpListHost);
+ return NULL;
+}
+
+
+/**
+ Sends an NVM Express Command Packet to an NVM Express controller or namespace. This function supports
+ both blocking I/O and nonblocking I/O. The blocking I/O functionality is required, and the nonblocking
+ I/O functionality is optional.
+
+ @param[in] This A pointer to the NVM_EXPRESS_PASS_THRU_PROTOCOL instance.
+ @param[in] NamespaceId Is a 32 bit Namespace ID to which the Express HCI command packet will be sent.
+ A value of 0 denotes the NVM Express controller, a value of all 0FFh in the namespace
+ ID specifies that the command packet should be sent to all valid namespaces.
+ @param[in] NamespaceUuid Is a 64 bit Namespace UUID to which the Express HCI command packet will be sent.
+ A value of 0 denotes the NVM Express controller, a value of all 0FFh in the namespace
+ UUID specifies that the command packet should be sent to all valid namespaces.
+ @param[in,out] Packet A pointer to the NVM Express HCI Command Packet to send to the NVMe namespace specified
+ by NamespaceId.
+ @param[in] Event If nonblocking I/O is not supported then Event is ignored, and blocking I/O is performed.
+ If Event is NULL, then blocking I/O is performed. If Event is not NULL and non blocking I/O
+ is supported, then nonblocking I/O is performed, and Event will be signaled when the NVM
+ Express Command Packet completes.
+
+ @retval EFI_SUCCESS The NVM Express Command Packet was sent by the host. TransferLength bytes were transferred
+ to, or from DataBuffer.
+ @retval EFI_BAD_BUFFER_SIZE The NVM Express Command Packet was not executed. The number of bytes that could be transferred
+ is returned in TransferLength.
+ @retval EFI_NOT_READY The NVM Express Command Packet could not be sent because the controller is not ready. The caller
+ may retry again later.
+ @retval EFI_DEVICE_ERROR A device error occurred while attempting to send the NVM Express Command Packet.
+ @retval EFI_INVALID_PARAMETER Namespace, or the contents of NVM_EXPRESS_PASS_THRU_COMMAND_PACKET are invalid. The NVM
+ Express Command Packet was not sent, so no additional status information is available.
+ @retval EFI_UNSUPPORTED The command described by the NVM Express Command Packet is not supported by the host adapter.
+ The NVM Express Command Packet was not sent, so no additional status information is available.
+ @retval EFI_TIMEOUT A timeout occurred while waiting for the NVM Express Command Packet to execute.
+
+**/
+EFI_STATUS
+EFIAPI
+NvmExpressPassThru (
+ IN NVM_EXPRESS_PASS_THRU_PROTOCOL *This,
+ IN UINT32 NamespaceId,
+ IN UINT64 NamespaceUuid,
+ IN OUT NVM_EXPRESS_PASS_THRU_COMMAND_PACKET *Packet,
+ IN EFI_EVENT Event OPTIONAL
+ )
+{
+ NVME_CONTROLLER_PRIVATE_DATA *Private;
+ EFI_STATUS Status;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ NVME_SQ *Sq;
+ NVME_CQ *Cq;
+ UINT8 Qid;
+ UINT32 Bytes;
+ UINT16 Offset;
+ EFI_EVENT TimerEvent;
+ EFI_PCI_IO_PROTOCOL_OPERATION Flag;
+ EFI_PHYSICAL_ADDRESS PhyAddr;
+ VOID *MapData;
+ VOID *MapMeta;
+ VOID *MapPrpList;
+ UINTN MapLength;
+ UINT64 *Prp;
+ VOID *PrpListHost;
+ UINTN PrpListNo;
+
+ //
+ // check the data fields in Packet parameter.
+ //
+ if ((This == NULL) || (Packet == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((Packet->NvmeCmd == NULL) || (Packet->NvmeResponse == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Packet->QueueId != NVME_ADMIN_QUEUE && Packet->QueueId != NVME_IO_QUEUE) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Private = NVME_CONTROLLER_PRIVATE_DATA_FROM_PASS_THRU (This);
+ PciIo = Private->PciIo;
+ MapData = NULL;
+ MapMeta = NULL;
+ MapPrpList = NULL;
+ PrpListHost = NULL;
+ PrpListNo = 0;
+ Prp = NULL;
+ TimerEvent = NULL;
+ Status = EFI_SUCCESS;
+
+ Qid = Packet->QueueId;
+ Sq = Private->SqBuffer[Qid] + Private->SqTdbl[Qid].Sqt;
+ Cq = Private->CqBuffer[Qid] + Private->CqHdbl[Qid].Cqh;
+
+ if (Packet->NvmeCmd->Nsid != NamespaceId) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ZeroMem (Sq, sizeof (NVME_SQ));
+ Sq->Opc = Packet->NvmeCmd->Cdw0.Opcode;
+ Sq->Fuse = Packet->NvmeCmd->Cdw0.FusedOperation;
+ Sq->Cid = Packet->NvmeCmd->Cdw0.Cid;
+ Sq->Nsid = Packet->NvmeCmd->Nsid;
+
+ //
+ // Currently we only support PRP for data transfer, SGL is NOT supported.
+ //
+ ASSERT ((Sq->Opc & BIT15) == 0);
+ if ((Sq->Opc & BIT15) != 0) {
+ DEBUG ((EFI_D_ERROR, "NvmExpressPassThru: doesn't support SGL mechanism\n"));
+ return EFI_UNSUPPORTED;
+ }
+
+ Sq->Prp[0] = (UINT64)(UINTN)Packet->TransferBuffer;
+ //
+ // If the NVMe cmd has data in or out, then mapping the user buffer to the PCI controller specific addresses.
+ // Note here we don't handle data buffer for CreateIOSubmitionQueue and CreateIOCompletionQueue cmds because
+ // these two cmds are special which requires their data buffer must support simultaneous access by both the
+ // processor and a PCI Bus Master. It's caller's responsbility to ensure this.
+ //
+ if (((Sq->Opc & (BIT0 | BIT1)) != 0) && (Sq->Opc != NVME_ADMIN_CRIOCQ_OPC) && (Sq->Opc != NVME_ADMIN_CRIOSQ_OPC)) {
+ if ((Sq->Opc & BIT0) != 0) {
+ Flag = EfiPciIoOperationBusMasterRead;
+ } else {
+ Flag = EfiPciIoOperationBusMasterWrite;
+ }
+
+ MapLength = Packet->TransferLength;
+ Status = PciIo->Map (
+ PciIo,
+ Flag,
+ Packet->TransferBuffer,
+ &MapLength,
+ &PhyAddr,
+ &MapData
+ );
+ if (EFI_ERROR (Status) || (Packet->TransferLength != MapLength)) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Sq->Prp[0] = PhyAddr;
+ Sq->Prp[1] = 0;
+
+ MapLength = Packet->MetadataLength;
+ if(Packet->MetadataBuffer != NULL) {
+ MapLength = Packet->MetadataLength;
+ Status = PciIo->Map (
+ PciIo,
+ Flag,
+ Packet->MetadataBuffer,
+ &MapLength,
+ &PhyAddr,
+ &MapMeta
+ );
+ if (EFI_ERROR (Status) || (Packet->MetadataLength != MapLength)) {
+ PciIo->Unmap (
+ PciIo,
+ MapData
+ );
+
+ return EFI_OUT_OF_RESOURCES;
+ }
+ Sq->Mptr = PhyAddr;
+ }
+ }
+ //
+ // If the buffer size spans more than two memory pages (page size as defined in CC.Mps),
+ // then build a PRP list in the second PRP submission queue entry.
+ //
+ Offset = ((UINT16)Sq->Prp[0]) & (EFI_PAGE_SIZE - 1);
+ Bytes = Packet->TransferLength;
+
+ if ((Offset + Bytes) > (EFI_PAGE_SIZE * 2)) {
+ //
+ // Create PrpList for remaining data buffer.
+ //
+ PhyAddr = (Sq->Prp[0] + EFI_PAGE_SIZE) & ~(EFI_PAGE_SIZE - 1);
+ Prp = NvmeCreatePrpList (PciIo, PhyAddr, EFI_SIZE_TO_PAGES(Offset + Bytes) - 1, &PrpListHost, &PrpListNo, &MapPrpList);
+ if (Prp == NULL) {
+ goto EXIT;
+ }
+
+ Sq->Prp[1] = (UINT64)(UINTN)Prp;
+ } else if ((Offset + Bytes) > EFI_PAGE_SIZE) {
+ Sq->Prp[1] = (Sq->Prp[0] + EFI_PAGE_SIZE) & ~(EFI_PAGE_SIZE - 1);
+ }
+
+ if(Packet->NvmeCmd->Flags & CDW10_VALID) {
+ Sq->Payload.Raw.Cdw10 = Packet->NvmeCmd->Cdw10;
+ }
+ if(Packet->NvmeCmd->Flags & CDW11_VALID) {
+ Sq->Payload.Raw.Cdw11 = Packet->NvmeCmd->Cdw11;
+ }
+ if(Packet->NvmeCmd->Flags & CDW12_VALID) {
+ Sq->Payload.Raw.Cdw12 = Packet->NvmeCmd->Cdw12;
+ }
+ if(Packet->NvmeCmd->Flags & CDW13_VALID) {
+ Sq->Payload.Raw.Cdw13 = Packet->NvmeCmd->Cdw13;
+ }
+ if(Packet->NvmeCmd->Flags & CDW14_VALID) {
+ Sq->Payload.Raw.Cdw14 = Packet->NvmeCmd->Cdw14;
+ }
+ if(Packet->NvmeCmd->Flags & CDW15_VALID) {
+ Sq->Payload.Raw.Cdw15 = Packet->NvmeCmd->Cdw15;
+ }
+
+ //
+ // Ring the submission queue doorbell.
+ //
+ Private->SqTdbl[Qid].Sqt ^= 1;
+
+ PciIo->Mem.Write (
+ PciIo,
+ EfiPciIoWidthUint32,
+ NVME_BAR,
+ NVME_SQTDBL_OFFSET(Qid, Private->Cap.Dstrd),
+ 1,
+ &Private->SqTdbl[Qid]
+ );
+
+ Status = gBS->CreateEvent (
+ EVT_TIMER,
+ TPL_CALLBACK,
+ NULL,
+ NULL,
+ &TimerEvent
+ );
+ if (EFI_ERROR (Status)) {
+ goto EXIT;
+ }
+
+ Status = gBS->SetTimer(TimerEvent, TimerRelative, Packet->CommandTimeout);
+
+ if (EFI_ERROR(Status)) {
+ Packet->ControllerStatus = NVM_EXPRESS_STATUS_CONTROLLER_DEVICE_ERROR;
+ goto EXIT;
+ }
+
+ //
+ // Wait for completion queue to get filled in.
+ //
+ Status = EFI_TIMEOUT;
+ Packet->ControllerStatus = NVM_EXPRESS_STATUS_CONTROLLER_TIMEOUT_COMMAND;
+ while (EFI_ERROR (gBS->CheckEvent (TimerEvent))) {
+ if (Cq->Pt != Private->Pt[Qid]) {
+ Status = EFI_SUCCESS;
+ Packet->ControllerStatus = NVM_EXPRESS_STATUS_CONTROLLER_READY;
+ break;
+ }
+ }
+
+ if ((Private->CqHdbl[Qid].Cqh ^= 1) == 0) {
+ Private->Pt[Qid] ^= 1;
+ }
+
+ //
+ // Copy the Respose Queue entry for this command to the callers response buffer
+ //
+ CopyMem(Packet->NvmeResponse, Cq, sizeof(NVM_EXPRESS_RESPONSE));
+
+ //
+ // Dump every completion entry status for debugging.
+ //
+ DEBUG_CODE_BEGIN();
+ NvmeDumpStatus(Cq);
+ DEBUG_CODE_END();
+
+ PciIo->Mem.Write (
+ PciIo,
+ EfiPciIoWidthUint32,
+ NVME_BAR,
+ NVME_CQHDBL_OFFSET(Qid, Private->Cap.Dstrd),
+ 1,
+ &Private->CqHdbl[Qid]
+ );
+
+EXIT:
+ if (MapData != NULL) {
+ PciIo->Unmap (
+ PciIo,
+ MapData
+ );
+ }
+
+ if (MapMeta != NULL) {
+ PciIo->Unmap (
+ PciIo,
+ MapMeta
+ );
+ }
+
+ if (MapPrpList != NULL) {
+ PciIo->Unmap (
+ PciIo,
+ MapPrpList
+ );
+ }
+
+ if (Prp != NULL) {
+ PciIo->FreeBuffer (PciIo, PrpListNo, PrpListHost);
+ }
+
+ if (TimerEvent != NULL) {
+ gBS->CloseEvent (TimerEvent);
+ }
+ return Status;
+}
+
+/**
+ Used to retrieve the list of namespaces defined on an NVM Express controller.
+
+ The NVM_EXPRESS_PASS_THRU_PROTOCOL.GetNextNamespace() function retrieves a list of namespaces
+ defined on an NVM Express controller. If on input a NamespaceID is specified by all 0xFF in the
+ namespace buffer, then the first namespace defined on the NVM Express controller is returned in
+ NamespaceID, and a status of EFI_SUCCESS is returned.
+
+ If NamespaceId is a Namespace value that was returned on a previous call to GetNextNamespace(),
+ then the next valid NamespaceId for an NVM Express SSD namespace on the NVM Express controller
+ is returned in NamespaceId, and EFI_SUCCESS is returned.
+
+ If Namespace array is not a 0xFFFFFFFF and NamespaceId was not returned on a previous call to
+ GetNextNamespace(), then EFI_INVALID_PARAMETER is returned.
+
+ If NamespaceId is the NamespaceId of the last SSD namespace on the NVM Express controller, then
+ EFI_NOT_FOUND is returned
+
+ @param[in] This A pointer to the NVM_EXPRESS_PASS_THRU_PROTOCOL instance.
+ @param[in,out] NamespaceId On input, a pointer to a legal NamespaceId for an NVM Express
+ namespace present on the NVM Express controller. On output, a
+ pointer to the next NamespaceId of an NVM Express namespace on
+ an NVM Express controller. An input value of 0xFFFFFFFF retrieves
+ the first NamespaceId for an NVM Express namespace present on an
+ NVM Express controller.
+ @param[out] NamespaceUuid On output, the UUID associated with the next namespace, if a UUID
+ is defined for that NamespaceId, otherwise, zero is returned in
+ this parameter. If the caller does not require a UUID, then a NULL
+ pointer may be passed.
+
+ @retval EFI_SUCCESS The NamespaceId of the next Namespace was returned.
+ @retval EFI_NOT_FOUND There are no more namespaces defined on this controller.
+ @retval EFI_INVALID_PARAMETER Namespace array is not a 0xFFFFFFFF and NamespaceId was not returned
+ on a previous call to GetNextNamespace().
+
+**/
+EFI_STATUS
+EFIAPI
+NvmExpressGetNextNamespace (
+ IN NVM_EXPRESS_PASS_THRU_PROTOCOL *This,
+ IN OUT UINT32 *NamespaceId,
+ OUT UINT64 *NamespaceUuid OPTIONAL
+ )
+{
+ NVME_CONTROLLER_PRIVATE_DATA *Private;
+ NVME_ADMIN_NAMESPACE_DATA *NamespaceData;
+ UINT32 NextNamespaceId;
+ EFI_STATUS Status;
+
+ if ((This == NULL) || (NamespaceId == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ NamespaceData = NULL;
+ Status = EFI_NOT_FOUND;
+
+ Private = NVME_CONTROLLER_PRIVATE_DATA_FROM_PASS_THRU (This);
+ //
+ // If the NamespaceId input value is 0xFFFFFFFF, then get the first valid namespace ID
+ //
+ if (*NamespaceId == 0xFFFFFFFF) {
+ //
+ // Start with the first namespace ID
+ //
+ NextNamespaceId = 1;
+ //
+ // Allocate buffer for Identify Namespace data.
+ //
+ NamespaceData = (NVME_ADMIN_NAMESPACE_DATA *)AllocateZeroPool (sizeof (NVME_ADMIN_NAMESPACE_DATA));
+
+ if (NamespaceData == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ Status = NvmeIdentifyNamespace (Private, NextNamespaceId, NamespaceData);
+ if (EFI_ERROR(Status)) {
+ goto Done;
+ }
+
+ *NamespaceId = NextNamespaceId;
+ if (NamespaceUuid != NULL) {
+ *NamespaceUuid = NamespaceData->Eui64;
+ }
+ } else {
+ if (*NamespaceId >= Private->ControllerData->Nn) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ NextNamespaceId = *NamespaceId + 1;
+ //
+ // Allocate buffer for Identify Namespace data.
+ //
+ NamespaceData = (NVME_ADMIN_NAMESPACE_DATA *)AllocateZeroPool (sizeof (NVME_ADMIN_NAMESPACE_DATA));
+ if (NamespaceData == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ Status = NvmeIdentifyNamespace (Private, NextNamespaceId, NamespaceData);
+ if (EFI_ERROR(Status)) {
+ goto Done;
+ }
+
+ *NamespaceId = NextNamespaceId;
+ if (NamespaceUuid != NULL) {
+ *NamespaceUuid = NamespaceData->Eui64;
+ }
+ }
+
+Done:
+ if (NamespaceData != NULL) {
+ FreePool(NamespaceData);
+ }
+
+ return Status;
+}
+
+/**
+ Used to translate a device path node to a Namespace ID and Namespace UUID.
+
+ The NVM_EXPRESS_PASS_THRU_PROTOCOL.GetNamwspace() function determines the Namespace ID and Namespace UUID
+ associated with the NVM Express SSD namespace described by DevicePath. If DevicePath is a device path node type
+ that the NVM Express Pass Thru driver supports, then the NVM Express Pass Thru driver will attempt to translate
+ the contents DevicePath into a Namespace ID and UUID. If this translation is successful, then that Namespace ID
+ and UUID are returned in NamespaceID and NamespaceUUID, and EFI_SUCCESS is returned.
+
+ @param[in] This A pointer to the NVM_EXPRESS_PASS_THRU_PROTOCOL instance.
+ @param[in] DevicePath A pointer to the device path node that describes an NVM Express namespace on
+ the NVM Express controller.
+ @param[out] NamespaceId The NVM Express namespace ID contained in the device path node.
+ @param[out] NamespaceUuid The NVM Express namespace contained in the device path node.
+
+ @retval EFI_SUCCESS DevicePath was successfully translated to NamespaceId and NamespaceUuid.
+ @retval EFI_INVALID_PARAMETER If DevicePath, NamespaceId, or NamespaceUuid are NULL, then EFI_INVALID_PARAMETER
+ is returned.
+ @retval EFI_UNSUPPORTED If DevicePath is not a device path node type that the NVM Express Pass Thru driver
+ supports, then EFI_UNSUPPORTED is returned.
+ @retval EFI_NOT_FOUND If DevicePath is a device path node type that the Nvm Express Pass Thru driver
+ supports, but there is not a valid translation from DevicePath to a NamespaceID
+ and NamespaceUuid, then EFI_NOT_FOUND is returned.
+**/
+EFI_STATUS
+EFIAPI
+NvmExpressGetNamespace (
+ IN NVM_EXPRESS_PASS_THRU_PROTOCOL *This,
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ OUT UINT32 *NamespaceId,
+ OUT UINT64 *NamespaceUuid
+ )
+{
+ NVME_NAMESPACE_DEVICE_PATH *Node;
+
+ if ((This == NULL) || (DevicePath == NULL) || (NamespaceId == NULL) || (NamespaceUuid == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (DevicePath->Type != MESSAGING_DEVICE_PATH) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Node = (NVME_NAMESPACE_DEVICE_PATH *)DevicePath;
+
+ if (DevicePath->SubType == MSG_NVME_NAMESPACE_DP) {
+ if (DevicePathNodeLength(DevicePath) != sizeof(NVME_NAMESPACE_DEVICE_PATH)) {
+ return EFI_NOT_FOUND;
+ }
+
+ *NamespaceId = Node->NamespaceId;
+ *NamespaceUuid = Node->NamespaceUuid;
+
+ return EFI_SUCCESS;
+ } else {
+ return EFI_UNSUPPORTED;
+ }
+}
+
+/**
+ Used to allocate and build a device path node for an NVM Express namespace on an NVM Express controller.
+
+ The NVM_EXPRESS_PASS_THRU_PROTOCOL.BuildDevicePath() function allocates and builds a single device
+ path node for the NVM Express namespace specified by NamespaceId.
+
+ If the namespace device specified by NamespaceId is not valid , then EFI_NOT_FOUND is returned.
+
+ If DevicePath is NULL, then EFI_INVALID_PARAMETER is returned.
+
+ If there are not enough resources to allocate the device path node, then EFI_OUT_OF_RESOURCES is returned.
+
+ Otherwise, DevicePath is allocated with the boot service AllocatePool(), the contents of DevicePath are
+ initialized to describe the NVM Express namespace specified by NamespaceId, and EFI_SUCCESS is returned.
+
+ @param[in] This A pointer to the NVM_EXPRESS_PASS_THRU_PROTOCOL instance.
+ @param[in] NamespaceId The NVM Express namespace ID for which a device path node is to be
+ allocated and built. Caller must set the NamespaceId to zero if the
+ device path node will contain a valid UUID.
+ @param[in] NamespaceUuid The NVM Express namespace UUID for which a device path node is to be
+ allocated and built. UUID will only be valid of the Namespace ID is zero.
+ @param[in,out] DevicePath A pointer to a single device path node that describes the NVM Express
+ namespace specified by NamespaceId. This function is responsible for
+ allocating the buffer DevicePath with the boot service AllocatePool().
+ It is the caller's responsibility to free DevicePath when the caller
+ is finished with DevicePath.
+ @retval EFI_SUCCESS The device path node that describes the NVM Express namespace specified
+ by NamespaceId was allocated and returned in DevicePath.
+ @retval EFI_NOT_FOUND The NVM Express namespace specified by NamespaceId does not exist on the
+ NVM Express controller.
+ @retval EFI_INVALID_PARAMETER DevicePath is NULL.
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources to allocate the DevicePath node.
+
+**/
+EFI_STATUS
+EFIAPI
+NvmExpressBuildDevicePath (
+ IN NVM_EXPRESS_PASS_THRU_PROTOCOL *This,
+ IN UINT32 NamespaceId,
+ IN UINT64 NamespaceUuid,
+ IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath
+ )
+{
+ NVME_CONTROLLER_PRIVATE_DATA *Private;
+ NVME_NAMESPACE_DEVICE_PATH *Node;
+
+ //
+ // Validate parameters
+ //
+ if ((This == NULL) || (DevicePath == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Private = NVME_CONTROLLER_PRIVATE_DATA_FROM_PASS_THRU (This);
+
+ if (NamespaceId == 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ Node = (NVME_NAMESPACE_DEVICE_PATH *)AllocateZeroPool (sizeof (NVME_NAMESPACE_DEVICE_PATH));
+
+ if (Node == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Node->Header.Type = MESSAGING_DEVICE_PATH;
+ Node->Header.SubType = MSG_NVME_NAMESPACE_DP;
+ SetDevicePathNodeLength (&Node->Header, sizeof (NVME_NAMESPACE_DEVICE_PATH));
+ Node->NamespaceId = NamespaceId;
+ Node->NamespaceUuid = NamespaceUuid;
+
+ *DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)Node;
+ return EFI_SUCCESS;
+}
+
diff --git a/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressPassthru.h b/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressPassthru.h
new file mode 100644
index 000000000..cf05bffb8
--- /dev/null
+++ b/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressPassthru.h
@@ -0,0 +1,299 @@
+/** @file
+ NvmExpressDxe driver is used to manage non-volatile memory subsystem which follows
+ NVM Express specification.
+
+ Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>
+ 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 _NVM_EXPRESS_PASS_THRU_H_
+#define _NVM_EXPRESS_PASS_THRU_H_
+
+#define NVM_EXPRESS_PASS_THRU_PROTOCOL_GUID \
+ { \
+ 0xec51ef5c, 0x2cf3, 0x4a55, {0xbf, 0x85, 0xb6, 0x3c, 0xa3, 0xb1, 0x3f, 0x44 } \
+ }
+
+typedef struct _NVM_EXPRESS_PASS_THRU_PROTOCOL NVM_EXPRESS_PASS_THRU_PROTOCOL;
+
+typedef struct {
+ UINT32 AdapterId;
+ UINT32 Attributes;
+ UINT32 IoAlign;
+ UINT32 HciVersion;
+ UINT64 Timeout;
+ UINT32 MaxNamespace;
+} NVM_EXPRESS_PASS_THRU_MODE;
+
+//
+// If this bit is set, then the NVM_EXPRESS_PASS_THRU_PROTOCOL interface is for directly addressable namespaces.
+//
+#define NVM_EXPRESS_PASS_THRU_ATTRIBUTES_PHYSICAL 0x0001
+//
+// If this bit is set, then the NVM_EXPRESS_PASS_THRU_PROTOCOL interface is for a single volume logical namespace
+// comprised of multiple namespaces.
+//
+#define NVM_EXPRESS_PASS_THRU_ATTRIBUTES_LOGICAL 0x0002
+//
+// If this bit is set, then the NVM_EXPRESS_PASS_THRU_PROTOCOL interface supports non blocking I/O.
+//
+#define NVM_EXPRESS_PASS_THRU_ATTRIBUTES_NONBLOCKIO 0x0004
+//
+// If this bit is set, then the NVM_EXPRESS_PASS_THRU_PROTOCOL interface supports NVM command set commands.
+//
+#define NVM_EXPRESS_PASS_THRU_ATTRIBUTES_CMD_SET_NVME 0x0008
+
+//
+// QueueId
+//
+#define NVME_ADMIN_QUEUE 0x00
+#define NVME_IO_QUEUE 0x01
+
+//
+// ControllerStatus
+//
+#define NVM_EXPRESS_STATUS_CONTROLLER_READY 0x00
+#define NVM_EXPRESS_STATUS_CONTROLLER_CMD_ERROR 0x01
+#define NVM_EXPRESS_STATUS_CONTROLLER_FATAL 0x02
+#define NVM_EXPRESS_STATUS_CONTROLLER_CMD_DATA_ERROR 0x04
+#define NVM_EXPRESS_STATUS_CONTROLLER_CMD_ABORT 0x05
+#define NVM_EXPRESS_STATUS_CONTROLLER_DEVICE_ERROR 0x06
+#define NVM_EXPRESS_STATUS_CONTROLLER_TIMEOUT_COMMAND 0x09
+#define NVM_EXPRESS_STATUS_CONTROLLER_INVALID_NAMESPACE 0x0B
+#define NVM_EXPRESS_STATUS_CONTROLLER_NOT_READY 0x0C
+#define NVM_EXPRESS_STATUS_CONTROLLER_OTHER 0x7F
+
+typedef struct {
+ UINT8 Opcode;
+ UINT8 FusedOperation;
+ #define NORMAL_CMD 0x00
+ #define FUSED_FIRST_CMD 0x01
+ #define FUSED_SECOND_CMD 0x02
+ UINT16 Cid;
+} NVME_CDW0;
+
+typedef struct {
+ NVME_CDW0 Cdw0;
+ UINT8 Flags;
+ #define CDW10_VALID 0x01
+ #define CDW11_VALID 0x02
+ #define CDW12_VALID 0x04
+ #define CDW13_VALID 0x08
+ #define CDW14_VALID 0x10
+ #define CDW15_VALID 0x20
+ UINT32 Nsid;
+ UINT32 Cdw10;
+ UINT32 Cdw11;
+ UINT32 Cdw12;
+ UINT32 Cdw13;
+ UINT32 Cdw14;
+ UINT32 Cdw15;
+} NVM_EXPRESS_COMMAND;
+
+typedef struct {
+ UINT32 Cdw0;
+ UINT32 Cdw1;
+ UINT32 Cdw2;
+ UINT32 Cdw3;
+} NVM_EXPRESS_RESPONSE;
+
+typedef struct {
+ UINT64 CommandTimeout;
+ VOID *TransferBuffer;
+ UINT32 TransferLength;
+ VOID *MetadataBuffer;
+ UINT32 MetadataLength;
+ UINT8 QueueId;
+ NVM_EXPRESS_COMMAND *NvmeCmd;
+ NVM_EXPRESS_RESPONSE *NvmeResponse;
+ UINT8 ControllerStatus;
+} NVM_EXPRESS_PASS_THRU_COMMAND_PACKET;
+
+//
+// Protocol funtion prototypes
+//
+/**
+ Sends an NVM Express Command Packet to an NVM Express controller or namespace. This function supports
+ both blocking I/O and nonblocking I/O. The blocking I/O functionality is required, and the nonblocking
+ I/O functionality is optional.
+
+ @param[in] This A pointer to the NVM_EXPRESS_PASS_THRU_PROTOCOL instance.
+ @param[in] NamespaceId Is a 32 bit Namespace ID to which the Express HCI command packet will be sent.
+ A value of 0 denotes the NVM Express controller, a value of all 0FFh in the namespace
+ ID specifies that the command packet should be sent to all valid namespaces.
+ @param[in] NamespaceUuid Is a 64 bit Namespace UUID to which the Express HCI command packet will be sent.
+ A value of 0 denotes the NVM Express controller, a value of all 0FFh in the namespace
+ UUID specifies that the command packet should be sent to all valid namespaces.
+ @param[in,out] Packet A pointer to the NVM Express HCI Command Packet to send to the NVMe namespace specified
+ by NamespaceId.
+ @param[in] Event If nonblocking I/O is not supported then Event is ignored, and blocking I/O is performed.
+ If Event is NULL, then blocking I/O is performed. If Event is not NULL and non blocking I/O
+ is supported, then nonblocking I/O is performed, and Event will be signaled when the NVM
+ Express Command Packet completes.
+
+ @retval EFI_SUCCESS The NVM Express Command Packet was sent by the host. TransferLength bytes were transferred
+ to, or from DataBuffer.
+ @retval EFI_BAD_BUFFER_SIZE The NVM Express Command Packet was not executed. The number of bytes that could be transferred
+ is returned in TransferLength.
+ @retval EFI_NOT_READY The NVM Express Command Packet could not be sent because the controller is not ready. The caller
+ may retry again later.
+ @retval EFI_DEVICE_ERROR A device error occurred while attempting to send the NVM Express Command Packet.
+ @retval EFI_INVALID_PARAMETER Namespace, or the contents of NVM_EXPRESS_PASS_THRU_COMMAND_PACKET are invalid. The NVM
+ Express Command Packet was not sent, so no additional status information is available.
+ @retval EFI_UNSUPPORTED The command described by the NVM Express Command Packet is not supported by the host adapter.
+ The NVM Express Command Packet was not sent, so no additional status information is available.
+ @retval EFI_TIMEOUT A timeout occurred while waiting for the NVM Express Command Packet to execute.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *NVM_EXPRESS_PASS_THRU_PASSTHRU)(
+ IN NVM_EXPRESS_PASS_THRU_PROTOCOL *This,
+ IN UINT32 NamespaceId,
+ IN UINT64 NamespaceUuid,
+ IN OUT NVM_EXPRESS_PASS_THRU_COMMAND_PACKET *Packet,
+ IN EFI_EVENT Event OPTIONAL
+ );
+
+/**
+ Used to retrieve the list of namespaces defined on an NVM Express controller.
+
+ The NVM_EXPRESS_PASS_THRU_PROTOCOL.GetNextNamespace() function retrieves a list of namespaces
+ defined on an NVM Express controller. If on input a NamespaceID is specified by all 0xFF in the
+ namespace buffer, then the first namespace defined on the NVM Express controller is returned in
+ NamespaceID, and a status of EFI_SUCCESS is returned.
+
+ If NamespaceId is a Namespace value that was returned on a previous call to GetNextNamespace(),
+ then the next valid NamespaceId for an NVM Express SSD namespace on the NVM Express controller
+ is returned in NamespaceId, and EFI_SUCCESS is returned.
+
+ If Namespace array is not a 0xFFFFFFFF and NamespaceId was not returned on a previous call to
+ GetNextNamespace(), then EFI_INVALID_PARAMETER is returned.
+
+ If NamespaceId is the NamespaceId of the last SSD namespace on the NVM Express controller, then
+ EFI_NOT_FOUND is returned
+
+ @param[in] This A pointer to the NVM_EXPRESS_PASS_THRU_PROTOCOL instance.
+ @param[in,out] NamespaceId On input, a pointer to a legal NamespaceId for an NVM Express
+ namespace present on the NVM Express controller. On output, a
+ pointer to the next NamespaceId of an NVM Express namespace on
+ an NVM Express controller. An input value of 0xFFFFFFFF retrieves
+ the first NamespaceId for an NVM Express namespace present on an
+ NVM Express controller.
+ @param[out] NamespaceUuid On output, the UUID associated with the next namespace, if a UUID
+ is defined for that NamespaceId, otherwise, zero is returned in
+ this parameter. If the caller does not require a UUID, then a NULL
+ pointer may be passed.
+
+ @retval EFI_SUCCESS The NamespaceId of the next Namespace was returned.
+ @retval EFI_NOT_FOUND There are no more namespaces defined on this controller.
+ @retval EFI_INVALID_PARAMETER Namespace array is not a 0xFFFFFFFF and NamespaceId was not returned
+ on a previous call to GetNextNamespace().
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *NVM_EXPRESS_PASS_THRU_GET_NEXT_NAMESPACE)(
+ IN NVM_EXPRESS_PASS_THRU_PROTOCOL *This,
+ IN OUT UINT32 *NamespaceId,
+ OUT UINT64 *NamespaceUuid OPTIONAL
+ );
+
+/**
+ Used to allocate and build a device path node for an NVM Express namespace on an NVM Express controller.
+
+ The NVM_EXPRESS_PASS_THRU_PROTOCOL.BuildDevicePath() function allocates and builds a single device
+ path node for the NVM Express namespace specified by NamespaceId.
+
+ If the namespace device specified by NamespaceId is not valid , then EFI_NOT_FOUND is returned.
+
+ If DevicePath is NULL, then EFI_INVALID_PARAMETER is returned.
+
+ If there are not enough resources to allocate the device path node, then EFI_OUT_OF_RESOURCES is returned.
+
+ Otherwise, DevicePath is allocated with the boot service AllocatePool(), the contents of DevicePath are
+ initialized to describe the NVM Express namespace specified by NamespaceId, and EFI_SUCCESS is returned.
+
+ @param[in] This A pointer to the NVM_EXPRESS_PASS_THRU_PROTOCOL instance.
+ @param[in] NamespaceId The NVM Express namespace ID for which a device path node is to be
+ allocated and built. Caller must set the NamespaceId to zero if the
+ device path node will contain a valid UUID.
+ @param[in] NamespaceUuid The NVM Express namespace UUID for which a device path node is to be
+ allocated and built. UUID will only be valid of the Namespace ID is zero.
+ @param[in,out] DevicePath A pointer to a single device path node that describes the NVM Express
+ namespace specified by NamespaceId. This function is responsible for
+ allocating the buffer DevicePath with the boot service AllocatePool().
+ It is the caller's responsibility to free DevicePath when the caller
+ is finished with DevicePath.
+ @retval EFI_SUCCESS The device path node that describes the NVM Express namespace specified
+ by NamespaceId was allocated and returned in DevicePath.
+ @retval EFI_NOT_FOUND The NVM Express namespace specified by NamespaceId does not exist on the
+ NVM Express controller.
+ @retval EFI_INVALID_PARAMETER DevicePath is NULL.
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources to allocate the DevicePath node.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *NVM_EXPRESS_PASS_THRU_BUILD_DEVICE_PATH)(
+ IN NVM_EXPRESS_PASS_THRU_PROTOCOL *This,
+ IN UINT32 NamespaceId,
+ IN UINT64 NamespaceUuid,
+ IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath
+ );
+
+/**
+ Used to translate a device path node to a Namespace ID and Namespace UUID.
+
+ The NVM_EXPRESS_PASS_THRU_PROTOCOL.GetNamwspace() function determines the Namespace ID and Namespace UUID
+ associated with the NVM Express SSD namespace described by DevicePath. If DevicePath is a device path node type
+ that the NVM Express Pass Thru driver supports, then the NVM Express Pass Thru driver will attempt to translate
+ the contents DevicePath into a Namespace ID and UUID. If this translation is successful, then that Namespace ID
+ and UUID are returned in NamespaceID and NamespaceUUID, and EFI_SUCCESS is returned.
+
+ @param[in] This A pointer to the NVM_EXPRESS_PASS_THRU_PROTOCOL instance.
+ @param[in] DevicePath A pointer to the device path node that describes an NVM Express namespace on
+ the NVM Express controller.
+ @param[out] NamespaceId The NVM Express namespace ID contained in the device path node.
+ @param[out] NamespaceUuid The NVM Express namespace contained in the device path node.
+
+ @retval EFI_SUCCESS DevicePath was successfully translated to NamespaceId and NamespaceUuid.
+ @retval EFI_INVALID_PARAMETER If DevicePath, NamespaceId, or NamespaceUuid are NULL, then EFI_INVALID_PARAMETER
+ is returned.
+ @retval EFI_UNSUPPORTED If DevicePath is not a device path node type that the NVM Express Pass Thru driver
+ supports, then EFI_UNSUPPORTED is returned.
+ @retval EFI_NOT_FOUND If DevicePath is a device path node type that the Nvm Express Pass Thru driver
+ supports, but there is not a valid translation from DevicePath to a NamespaceID
+ and NamespaceUuid, then EFI_NOT_FOUND is returned.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *NVM_EXPRESS_PASS_THRU_GET_NAMESPACE)(
+ IN NVM_EXPRESS_PASS_THRU_PROTOCOL *This,
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ OUT UINT32 *NamespaceId,
+ OUT UINT64 *NamespaceUuid
+ );
+
+//
+// Protocol Interface Structure
+//
+struct _NVM_EXPRESS_PASS_THRU_PROTOCOL {
+ NVM_EXPRESS_PASS_THRU_MODE *Mode;
+ NVM_EXPRESS_PASS_THRU_PASSTHRU PassThru;
+ NVM_EXPRESS_PASS_THRU_GET_NEXT_NAMESPACE GetNextNamespace;
+ NVM_EXPRESS_PASS_THRU_BUILD_DEVICE_PATH BuildDevicePath;
+ NVM_EXPRESS_PASS_THRU_GET_NAMESPACE GetNamespace;
+};
+
+//extern EFI_GUID gNvmExpressPassThruProtocolGuid;
+
+#endif
+
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
index 348ce392e..fc62a251c 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
@@ -1,7 +1,7 @@
/** @file
Header files and data structures needed by PCI Bus module.
-Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
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
@@ -32,7 +32,6 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include <Protocol/IncompatiblePciDeviceSupport.h>
#include <Protocol/PciOverride.h>
#include <Protocol/PciEnumerationComplete.h>
-#include <Protocol/DevicePathToText.h>
#include <Library/DebugLib.h>
#include <Library/UefiDriverEntryPoint.h>
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
index 8c557f2fd..34eb672df 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
@@ -5,7 +5,7 @@
# space for these devices. Please use PCD feature flag PcdPciBusHotplugDeviceSupport to enable
# hot plug supporting.
#
-# Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
#
# This program and the accompanying materials
# are licensed and made available under the terms and conditions of the BSD License
@@ -97,7 +97,6 @@
gEfiPciRootBridgeIoProtocolGuid ## CONSUMED
gEfiIncompatiblePciDeviceSupportProtocolGuid ## CONSUMED
gEfiLoadFile2ProtocolGuid ## CONSUMED
- gEfiDevicePathToTextProtocolGuid ## CONSUMED
[FeaturePcd]
gEfiMdeModulePkgTokenSpaceGuid.PcdPciBusHotplugDeviceSupport
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.c
index bd1e68046..732914313 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.c
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.c
@@ -29,7 +29,6 @@ PciEnumerator (
IN EFI_HANDLE Controller
)
{
- EFI_HANDLE Handle;
EFI_HANDLE HostBridgeHandle;
EFI_STATUS Status;
EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc;
@@ -82,7 +81,11 @@ PciEnumerator (
//
// Notify the pci bus enumeration is about to begin
//
- NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginEnumeration);
+ Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginEnumeration);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
//
// Start the bus allocation phase
@@ -105,7 +108,11 @@ PciEnumerator (
//
// Notify the pci bus enumeration is about to complete
//
- NotifyPhase (PciResAlloc, EfiPciHostBridgeEndEnumeration);
+ Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeEndEnumeration);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
//
// Process P2C
@@ -126,9 +133,8 @@ PciEnumerator (
gFullEnumeration = FALSE;
- Handle = NULL;
Status = gBS->InstallProtocolInterface (
- &Handle,
+ &HostBridgeHandle,
&gEfiPciEnumerationCompleteProtocolGuid,
EFI_NATIVE_INTERFACE,
NULL
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.c
index 9e1184e00..b3d91a8d3 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.c
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.c
@@ -290,7 +290,6 @@ DumpResourceMap (
PCI_RESOURCE_NODE *ChildPMem32Node;
PCI_RESOURCE_NODE *ChildMem64Node;
PCI_RESOURCE_NODE *ChildPMem64Node;
- EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *ToText;
CHAR16 *Str;
DEBUG ((EFI_D_INFO, "PciBus: Resource Map for "));
@@ -309,19 +308,11 @@ DumpResourceMap (
Bridge->BusNumber, Bridge->DeviceNumber, Bridge->FunctionNumber
));
} else {
- Status = gBS->LocateProtocol (
- &gEfiDevicePathToTextProtocolGuid,
- NULL,
- (VOID **) &ToText
- );
- Str = NULL;
- if (!EFI_ERROR (Status)) {
- Str = ToText->ConvertDevicePathToText (
- DevicePathFromHandle (Bridge->Handle),
- FALSE,
- FALSE
- );
- }
+ Str = ConvertDevicePathToText (
+ DevicePathFromHandle (Bridge->Handle),
+ FALSE,
+ FALSE
+ );
DEBUG ((EFI_D_INFO, "Root Bridge %s\n", Str != NULL ? Str : L""));
if (Str != NULL) {
FreePool (Str);
@@ -759,7 +750,11 @@ PciHostBridgeResourceAllocator (
//
// Notify pci bus driver starts to program the resource
//
- NotifyPhase (PciResAlloc, EfiPciHostBridgeSetResources);
+ Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeSetResources);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
RootBridgeDev = NULL;
@@ -898,9 +893,9 @@ PciHostBridgeResourceAllocator (
//
// Notify the resource allocation phase is to end
//
- NotifyPhase (PciResAlloc, EfiPciHostBridgeEndResourceAllocation);
+ Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeEndResourceAllocation);
- return EFI_SUCCESS;
+ return Status;
}
/**
@@ -1443,7 +1438,11 @@ PciHostBridgeEnumerator (
//
// Notify the bus allocation phase is about to start
//
- NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginBusAllocation);
+ Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginBusAllocation);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
DEBUG((EFI_D_INFO, "PCI Bus First Scanning\n"));
RootBridgeHandle = NULL;
@@ -1531,7 +1530,11 @@ PciHostBridgeEnumerator (
//
// Notify the bus allocation phase is about to start for the 2nd time
//
- NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginBusAllocation);
+ Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginBusAllocation);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
DEBUG((EFI_D_INFO, "PCI Bus Second Scanning\n"));
RootBridgeHandle = NULL;
@@ -1569,7 +1572,11 @@ PciHostBridgeEnumerator (
//
// Notify the resource allocation phase is to start
//
- NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginResourceAllocation);
+ Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginResourceAllocation);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
RootBridgeHandle = NULL;
while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
diff --git a/MdeModulePkg/Bus/Pci/UhciDxe/UhciSched.c b/MdeModulePkg/Bus/Pci/UhciDxe/UhciSched.c
index 0d97bccab..af3f4e5ec 100644
--- a/MdeModulePkg/Bus/Pci/UhciDxe/UhciSched.c
+++ b/MdeModulePkg/Bus/Pci/UhciDxe/UhciSched.c
@@ -2,7 +2,7 @@
The EHCI register operation routines.
-Copyright (c) 2007 - 2011, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2007 - 2013, Intel Corporation. All rights reserved.<BR>
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
@@ -580,7 +580,7 @@ UhciExecuteTransfer (
Finished = FALSE;
Status = EFI_SUCCESS;
- Delay = (TimeOut * UHC_1_MILLISECOND / UHC_SYNC_POLL_INTERVAL) + 1;
+ Delay = TimeOut * UHC_1_MILLISECOND;
InfiniteLoop = FALSE;
//
@@ -602,7 +602,7 @@ UhciExecuteTransfer (
break;
}
- gBS->Stall (UHC_SYNC_POLL_INTERVAL);
+ gBS->Stall (UHC_1_MICROSECOND);
}
if (!Finished) {
diff --git a/MdeModulePkg/Bus/Pci/UhciPei/UhcPeim.c b/MdeModulePkg/Bus/Pci/UhciPei/UhcPeim.c
index f58b6943f..33f8c45d8 100644
--- a/MdeModulePkg/Bus/Pci/UhciPei/UhcPeim.c
+++ b/MdeModulePkg/Bus/Pci/UhciPei/UhcPeim.c
@@ -2,7 +2,7 @@
PEIM to produce gPeiUsbHostControllerPpiGuid based on gPeiUsbControllerPpiGuid
which is used to enable recovery function from USB Drivers.
-Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved. <BR>
+Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved. <BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions
@@ -153,6 +153,8 @@ UhcPeimEntry (
@param Data Data buffer to be transmitted or received from USB device.
@param DataLength The size (in bytes) of the data buffer.
@param TimeOut Indicates the maximum timeout, in millisecond.
+ If Timeout is 0, then the caller must wait for the function
+ to be completed until EFI_SUCCESS or EFI_DEVICE_ERROR is returned.
@param TransferResult Return the result of this control transfer.
@retval EFI_SUCCESS Transfer was completed successfully.
@@ -391,6 +393,8 @@ UhcControlTransfer (
the subsequent bulk transfer.
@param TimeOut Indicates the maximum time, in millisecond, which the
transfer is allowed to complete.
+ If Timeout is 0, then the caller must wait for the function
+ to be completed until EFI_SUCCESS or EFI_DEVICE_ERROR is returned.
@param TransferResult A pointer to the detailed result information of the
bulk transfer.
@@ -2508,12 +2512,21 @@ ExecuteControlTransfer (
{
UINTN ErrTDPos;
UINTN Delay;
+ BOOLEAN InfiniteLoop;
ErrTDPos = 0;
*TransferResult = EFI_USB_NOERROR;
*ActualLen = 0;
+ InfiniteLoop = FALSE;
- Delay = (TimeOut * STALL_1_MILLI_SECOND / 200) + 1;
+ Delay = TimeOut * STALL_1_MILLI_SECOND;
+ //
+ // If Timeout is 0, then the caller must wait for the function to be completed
+ // until EFI_SUCCESS or EFI_DEVICE_ERROR is returned.
+ //
+ if (TimeOut == 0) {
+ InfiniteLoop = TRUE;
+ }
do {
@@ -2525,11 +2538,10 @@ ExecuteControlTransfer (
if ((*TransferResult & EFI_USB_ERR_NOTEXECUTE) != EFI_USB_ERR_NOTEXECUTE) {
break;
}
- MicroSecondDelay (200);
+ MicroSecondDelay (STALL_1_MICRO_SECOND);
Delay--;
- } while (Delay != 0);
-
+ } while (InfiniteLoop || (Delay != 0));
if (*TransferResult != EFI_USB_NOERROR) {
return EFI_DEVICE_ERROR;
@@ -2566,12 +2578,21 @@ ExecBulkTransfer (
UINTN ErrTDPos;
UINTN ScrollNum;
UINTN Delay;
+ BOOLEAN InfiniteLoop;
ErrTDPos = 0;
*TransferResult = EFI_USB_NOERROR;
*ActualLen = 0;
+ InfiniteLoop = FALSE;
- Delay = (TimeOut * STALL_1_MILLI_SECOND / 200) + 1;
+ Delay = TimeOut * STALL_1_MILLI_SECOND;
+ //
+ // If Timeout is 0, then the caller must wait for the function to be completed
+ // until EFI_SUCCESS or EFI_DEVICE_ERROR is returned.
+ //
+ if (TimeOut == 0) {
+ InfiniteLoop = TRUE;
+ }
do {
@@ -2582,10 +2603,10 @@ ExecBulkTransfer (
if ((*TransferResult & EFI_USB_ERR_NOTEXECUTE) != EFI_USB_ERR_NOTEXECUTE) {
break;
}
- MicroSecondDelay (200);
+ MicroSecondDelay (STALL_1_MICRO_SECOND);
Delay--;
- } while (Delay != 0);
+ } while (InfiniteLoop || (Delay != 0));
//
// has error
diff --git a/MdeModulePkg/Bus/Pci/UhciPei/UhcPeim.h b/MdeModulePkg/Bus/Pci/UhciPei/UhcPeim.h
index dc697ce10..460db7eab 100644
--- a/MdeModulePkg/Bus/Pci/UhciPei/UhcPeim.h
+++ b/MdeModulePkg/Bus/Pci/UhciPei/UhcPeim.h
@@ -1,7 +1,7 @@
/** @file
Private Header file for Usb Host Controller PEIM
-Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions
@@ -94,6 +94,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#define OUTPUT_PACKET_ID 0xE1
#define ERROR_PACKET_ID 0x55
+#define STALL_1_MICRO_SECOND 1
#define STALL_1_MILLI_SECOND 1000
diff --git a/MdeModulePkg/Bus/Pci/XhciDxe/UsbHcMem.c b/MdeModulePkg/Bus/Pci/XhciDxe/UsbHcMem.c
new file mode 100644
index 000000000..f07136f36
--- /dev/null
+++ b/MdeModulePkg/Bus/Pci/XhciDxe/UsbHcMem.c
@@ -0,0 +1,758 @@
+/** @file
+
+ Routine procedures for memory allocate/free.
+
+Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>
+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 "Xhci.h"
+
+
+/**
+ Allocate a block of memory to be used by the buffer pool.
+
+ @param Pool The buffer pool to allocate memory for.
+ @param Pages How many pages to allocate.
+
+ @return The allocated memory block or NULL if failed.
+
+**/
+USBHC_MEM_BLOCK *
+UsbHcAllocMemBlock (
+ IN USBHC_MEM_POOL *Pool,
+ IN UINTN Pages
+ )
+{
+ USBHC_MEM_BLOCK *Block;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ VOID *BufHost;
+ VOID *Mapping;
+ EFI_PHYSICAL_ADDRESS MappedAddr;
+ UINTN Bytes;
+ EFI_STATUS Status;
+
+ PciIo = Pool->PciIo;
+
+ Block = AllocateZeroPool (sizeof (USBHC_MEM_BLOCK));
+ if (Block == NULL) {
+ return NULL;
+ }
+
+ //
+ // each bit in the bit array represents USBHC_MEM_UNIT
+ // bytes of memory in the memory block.
+ //
+ ASSERT (USBHC_MEM_UNIT * 8 <= EFI_PAGE_SIZE);
+
+ Block->BufLen = EFI_PAGES_TO_SIZE (Pages);
+ Block->BitsLen = Block->BufLen / (USBHC_MEM_UNIT * 8);
+ Block->Bits = AllocateZeroPool (Block->BitsLen);
+
+ if (Block->Bits == NULL) {
+ gBS->FreePool (Block);
+ return NULL;
+ }
+
+ //
+ // Allocate the number of Pages of memory, then map it for
+ // bus master read and write.
+ //
+ Status = PciIo->AllocateBuffer (
+ PciIo,
+ AllocateAnyPages,
+ EfiBootServicesData,
+ Pages,
+ &BufHost,
+ 0
+ );
+
+ if (EFI_ERROR (Status)) {
+ goto FREE_BITARRAY;
+ }
+
+ Bytes = EFI_PAGES_TO_SIZE (Pages);
+ Status = PciIo->Map (
+ PciIo,
+ EfiPciIoOperationBusMasterCommonBuffer,
+ BufHost,
+ &Bytes,
+ &MappedAddr,
+ &Mapping
+ );
+
+ if (EFI_ERROR (Status) || (Bytes != EFI_PAGES_TO_SIZE (Pages))) {
+ goto FREE_BUFFER;
+ }
+
+ Block->BufHost = BufHost;
+ Block->Buf = (UINT8 *) ((UINTN) MappedAddr);
+ Block->Mapping = Mapping;
+
+ return Block;
+
+FREE_BUFFER:
+ PciIo->FreeBuffer (PciIo, Pages, BufHost);
+
+FREE_BITARRAY:
+ gBS->FreePool (Block->Bits);
+ gBS->FreePool (Block);
+ return NULL;
+}
+
+
+/**
+ Free the memory block from the memory pool.
+
+ @param Pool The memory pool to free the block from.
+ @param Block The memory block to free.
+
+**/
+VOID
+UsbHcFreeMemBlock (
+ IN USBHC_MEM_POOL *Pool,
+ IN USBHC_MEM_BLOCK *Block
+ )
+{
+ EFI_PCI_IO_PROTOCOL *PciIo;
+
+ ASSERT ((Pool != NULL) && (Block != NULL));
+
+ PciIo = Pool->PciIo;
+
+ //
+ // Unmap the common buffer then free the structures
+ //
+ PciIo->Unmap (PciIo, Block->Mapping);
+ PciIo->FreeBuffer (PciIo, EFI_SIZE_TO_PAGES (Block->BufLen), Block->BufHost);
+
+ gBS->FreePool (Block->Bits);
+ gBS->FreePool (Block);
+}
+
+
+/**
+ Alloc some memory from the block.
+
+ @param Block The memory block to allocate memory from.
+ @param Units Number of memory units to allocate.
+
+ @return The pointer to the allocated memory. If couldn't allocate the needed memory,
+ the return value is NULL.
+
+**/
+VOID *
+UsbHcAllocMemFromBlock (
+ IN USBHC_MEM_BLOCK *Block,
+ IN UINTN Units
+ )
+{
+ UINTN Byte;
+ UINT8 Bit;
+ UINTN StartByte;
+ UINT8 StartBit;
+ UINTN Available;
+ UINTN Count;
+
+ ASSERT ((Block != 0) && (Units != 0));
+
+ StartByte = 0;
+ StartBit = 0;
+ Available = 0;
+
+ for (Byte = 0, Bit = 0; Byte < Block->BitsLen;) {
+ //
+ // If current bit is zero, the corresponding memory unit is
+ // available, otherwise we need to restart our searching.
+ // Available counts the consective number of zero bit.
+ //
+ if (!USB_HC_BIT_IS_SET (Block->Bits[Byte], Bit)) {
+ Available++;
+
+ if (Available >= Units) {
+ break;
+ }
+
+ NEXT_BIT (Byte, Bit);
+
+ } else {
+ NEXT_BIT (Byte, Bit);
+
+ Available = 0;
+ StartByte = Byte;
+ StartBit = Bit;
+ }
+ }
+
+ if (Available < Units) {
+ return NULL;
+ }
+
+ //
+ // Mark the memory as allocated
+ //
+ Byte = StartByte;
+ Bit = StartBit;
+
+ for (Count = 0; Count < Units; Count++) {
+ ASSERT (!USB_HC_BIT_IS_SET (Block->Bits[Byte], Bit));
+
+ Block->Bits[Byte] = (UINT8) (Block->Bits[Byte] | USB_HC_BIT (Bit));
+ NEXT_BIT (Byte, Bit);
+ }
+
+ return Block->BufHost + (StartByte * 8 + StartBit) * USBHC_MEM_UNIT;
+}
+
+/**
+ Calculate the corresponding pci bus address according to the Mem parameter.
+
+ @param Pool The memory pool of the host controller.
+ @param Mem The pointer to host memory.
+ @param Size The size of the memory region.
+
+ @return The pci memory address
+
+**/
+EFI_PHYSICAL_ADDRESS
+UsbHcGetPciAddrForHostAddr (
+ IN USBHC_MEM_POOL *Pool,
+ IN VOID *Mem,
+ IN UINTN Size
+ )
+{
+ USBHC_MEM_BLOCK *Head;
+ USBHC_MEM_BLOCK *Block;
+ UINTN AllocSize;
+ EFI_PHYSICAL_ADDRESS PhyAddr;
+ UINTN Offset;
+
+ Head = Pool->Head;
+ AllocSize = USBHC_MEM_ROUND (Size);
+
+ if (Mem == NULL) {
+ return 0;
+ }
+
+ for (Block = Head; Block != NULL; Block = Block->Next) {
+ //
+ // scan the memory block list for the memory block that
+ // completely contains the allocated memory.
+ //
+ if ((Block->BufHost <= (UINT8 *) Mem) && (((UINT8 *) Mem + AllocSize) <= (Block->BufHost + Block->BufLen))) {
+ break;
+ }
+ }
+
+ ASSERT ((Block != NULL));
+ //
+ // calculate the pci memory address for host memory address.
+ //
+ Offset = (UINT8 *)Mem - Block->BufHost;
+ PhyAddr = (EFI_PHYSICAL_ADDRESS)(UINTN) (Block->Buf + Offset);
+ return PhyAddr;
+}
+
+/**
+ Calculate the corresponding host address according to the pci address.
+
+ @param Pool The memory pool of the host controller.
+ @param Mem The pointer to pci memory.
+ @param Size The size of the memory region.
+
+ @return The host memory address
+
+**/
+EFI_PHYSICAL_ADDRESS
+UsbHcGetHostAddrForPciAddr (
+ IN USBHC_MEM_POOL *Pool,
+ IN VOID *Mem,
+ IN UINTN Size
+ )
+{
+ USBHC_MEM_BLOCK *Head;
+ USBHC_MEM_BLOCK *Block;
+ UINTN AllocSize;
+ EFI_PHYSICAL_ADDRESS HostAddr;
+ UINTN Offset;
+
+ Head = Pool->Head;
+ AllocSize = USBHC_MEM_ROUND (Size);
+
+ if (Mem == NULL) {
+ return 0;
+ }
+
+ for (Block = Head; Block != NULL; Block = Block->Next) {
+ //
+ // scan the memory block list for the memory block that
+ // completely contains the allocated memory.
+ //
+ if ((Block->Buf <= (UINT8 *) Mem) && (((UINT8 *) Mem + AllocSize) <= (Block->Buf + Block->BufLen))) {
+ break;
+ }
+ }
+
+ ASSERT ((Block != NULL));
+ //
+ // calculate the pci memory address for host memory address.
+ //
+ Offset = (UINT8 *)Mem - Block->Buf;
+ HostAddr = (EFI_PHYSICAL_ADDRESS)(UINTN) (Block->BufHost + Offset);
+ return HostAddr;
+}
+
+/**
+ Insert the memory block to the pool's list of the blocks.
+
+ @param Head The head of the memory pool's block list.
+ @param Block The memory block to insert.
+
+**/
+VOID
+UsbHcInsertMemBlockToPool (
+ IN USBHC_MEM_BLOCK *Head,
+ IN USBHC_MEM_BLOCK *Block
+ )
+{
+ ASSERT ((Head != NULL) && (Block != NULL));
+ Block->Next = Head->Next;
+ Head->Next = Block;
+}
+
+
+/**
+ Is the memory block empty?
+
+ @param Block The memory block to check.
+
+ @retval TRUE The memory block is empty.
+ @retval FALSE The memory block isn't empty.
+
+**/
+BOOLEAN
+UsbHcIsMemBlockEmpty (
+ IN USBHC_MEM_BLOCK *Block
+ )
+{
+ UINTN Index;
+
+ for (Index = 0; Index < Block->BitsLen; Index++) {
+ if (Block->Bits[Index] != 0) {
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+
+/**
+ Unlink the memory block from the pool's list.
+
+ @param Head The block list head of the memory's pool.
+ @param BlockToUnlink The memory block to unlink.
+
+**/
+VOID
+UsbHcUnlinkMemBlock (
+ IN USBHC_MEM_BLOCK *Head,
+ IN USBHC_MEM_BLOCK *BlockToUnlink
+ )
+{
+ USBHC_MEM_BLOCK *Block;
+
+ ASSERT ((Head != NULL) && (BlockToUnlink != NULL));
+
+ for (Block = Head; Block != NULL; Block = Block->Next) {
+ if (Block->Next == BlockToUnlink) {
+ Block->Next = BlockToUnlink->Next;
+ BlockToUnlink->Next = NULL;
+ break;
+ }
+ }
+}
+
+
+/**
+ Initialize the memory management pool for the host controller.
+
+ @param PciIo The PciIo that can be used to access the host controller.
+
+ @retval EFI_SUCCESS The memory pool is initialized.
+ @retval EFI_OUT_OF_RESOURCE Fail to init the memory pool.
+
+**/
+USBHC_MEM_POOL *
+UsbHcInitMemPool (
+ IN EFI_PCI_IO_PROTOCOL *PciIo
+ )
+{
+ USBHC_MEM_POOL *Pool;
+
+ Pool = AllocatePool (sizeof (USBHC_MEM_POOL));
+
+ if (Pool == NULL) {
+ return Pool;
+ }
+
+ Pool->PciIo = PciIo;
+ Pool->Head = UsbHcAllocMemBlock (Pool, USBHC_MEM_DEFAULT_PAGES);
+
+ if (Pool->Head == NULL) {
+ gBS->FreePool (Pool);
+ Pool = NULL;
+ }
+
+ return Pool;
+}
+
+
+/**
+ Release the memory management pool.
+
+ @param Pool The USB memory pool to free.
+
+ @retval EFI_SUCCESS The memory pool is freed.
+ @retval EFI_DEVICE_ERROR Failed to free the memory pool.
+
+**/
+EFI_STATUS
+UsbHcFreeMemPool (
+ IN USBHC_MEM_POOL *Pool
+ )
+{
+ USBHC_MEM_BLOCK *Block;
+
+ ASSERT (Pool->Head != NULL);
+
+ //
+ // Unlink all the memory blocks from the pool, then free them.
+ // UsbHcUnlinkMemBlock can't be used to unlink and free the
+ // first block.
+ //
+ for (Block = Pool->Head->Next; Block != NULL; Block = Pool->Head->Next) {
+ UsbHcUnlinkMemBlock (Pool->Head, Block);
+ UsbHcFreeMemBlock (Pool, Block);
+ }
+
+ UsbHcFreeMemBlock (Pool, Pool->Head);
+ gBS->FreePool (Pool);
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Allocate some memory from the host controller's memory pool
+ which can be used to communicate with host controller.
+
+ @param Pool The host controller's memory pool.
+ @param Size Size of the memory to allocate.
+
+ @return The allocated memory or NULL.
+
+**/
+VOID *
+UsbHcAllocateMem (
+ IN USBHC_MEM_POOL *Pool,
+ IN UINTN Size
+ )
+{
+ USBHC_MEM_BLOCK *Head;
+ USBHC_MEM_BLOCK *Block;
+ USBHC_MEM_BLOCK *NewBlock;
+ VOID *Mem;
+ UINTN AllocSize;
+ UINTN Pages;
+
+ Mem = NULL;
+ AllocSize = USBHC_MEM_ROUND (Size);
+ Head = Pool->Head;
+ ASSERT (Head != NULL);
+
+ //
+ // First check whether current memory blocks can satisfy the allocation.
+ //
+ for (Block = Head; Block != NULL; Block = Block->Next) {
+ Mem = UsbHcAllocMemFromBlock (Block, AllocSize / USBHC_MEM_UNIT);
+
+ if (Mem != NULL) {
+ ZeroMem (Mem, Size);
+ break;
+ }
+ }
+
+ if (Mem != NULL) {
+ return Mem;
+ }
+
+ //
+ // Create a new memory block if there is not enough memory
+ // in the pool. If the allocation size is larger than the
+ // default page number, just allocate a large enough memory
+ // block. Otherwise allocate default pages.
+ //
+ if (AllocSize > EFI_PAGES_TO_SIZE (USBHC_MEM_DEFAULT_PAGES)) {
+ Pages = EFI_SIZE_TO_PAGES (AllocSize) + 1;
+ } else {
+ Pages = USBHC_MEM_DEFAULT_PAGES;
+ }
+
+ NewBlock = UsbHcAllocMemBlock (Pool, Pages);
+
+ if (NewBlock == NULL) {
+ DEBUG ((EFI_D_ERROR, "UsbHcAllocateMem: failed to allocate block\n"));
+ return NULL;
+ }
+
+ //
+ // Add the new memory block to the pool, then allocate memory from it
+ //
+ UsbHcInsertMemBlockToPool (Head, NewBlock);
+ Mem = UsbHcAllocMemFromBlock (NewBlock, AllocSize / USBHC_MEM_UNIT);
+
+ if (Mem != NULL) {
+ ZeroMem (Mem, Size);
+ }
+
+ return Mem;
+}
+
+
+/**
+ Free the allocated memory back to the memory pool.
+
+ @param Pool The memory pool of the host controller.
+ @param Mem The memory to free.
+ @param Size The size of the memory to free.
+
+**/
+VOID
+UsbHcFreeMem (
+ IN USBHC_MEM_POOL *Pool,
+ IN VOID *Mem,
+ IN UINTN Size
+ )
+{
+ USBHC_MEM_BLOCK *Head;
+ USBHC_MEM_BLOCK *Block;
+ UINT8 *ToFree;
+ UINTN AllocSize;
+ UINTN Byte;
+ UINTN Bit;
+ UINTN Count;
+
+ Head = Pool->Head;
+ AllocSize = USBHC_MEM_ROUND (Size);
+ ToFree = (UINT8 *) Mem;
+
+ for (Block = Head; Block != NULL; Block = Block->Next) {
+ //
+ // scan the memory block list for the memory block that
+ // completely contains the memory to free.
+ //
+ if ((Block->BufHost <= ToFree) && ((ToFree + AllocSize) <= (Block->BufHost + Block->BufLen))) {
+ //
+ // compute the start byte and bit in the bit array
+ //
+ Byte = ((ToFree - Block->BufHost) / USBHC_MEM_UNIT) / 8;
+ Bit = ((ToFree - Block->BufHost) / USBHC_MEM_UNIT) % 8;
+
+ //
+ // reset associated bits in bit arry
+ //
+ for (Count = 0; Count < (AllocSize / USBHC_MEM_UNIT); Count++) {
+ ASSERT (USB_HC_BIT_IS_SET (Block->Bits[Byte], Bit));
+
+ Block->Bits[Byte] = (UINT8) (Block->Bits[Byte] ^ USB_HC_BIT (Bit));
+ NEXT_BIT (Byte, Bit);
+ }
+
+ break;
+ }
+ }
+
+ //
+ // If Block == NULL, it means that the current memory isn't
+ // in the host controller's pool. This is critical because
+ // the caller has passed in a wrong memory point
+ //
+ ASSERT (Block != NULL);
+
+ //
+ // Release the current memory block if it is empty and not the head
+ //
+ if ((Block != Head) && UsbHcIsMemBlockEmpty (Block)) {
+ UsbHcUnlinkMemBlock (Head, Block);
+ UsbHcFreeMemBlock (Pool, Block);
+ }
+
+ return ;
+}
+
+/**
+ Allocates pages at a specified alignment that are suitable for an EfiPciIoOperationBusMasterCommonBuffer mapping.
+
+ If Alignment is not a power of two and Alignment is not zero, then ASSERT().
+
+ @param PciIo The PciIo that can be used to access the host controller.
+ @param Pages The number of pages to allocate.
+ @param Alignment The requested alignment of the allocation. Must be a power of two.
+ @param HostAddress The system memory address to map to the PCI controller.
+ @param DeviceAddress The resulting map address for the bus master PCI controller to
+ use to access the hosts HostAddress.
+ @param Mapping A resulting value to pass to Unmap().
+
+ @retval EFI_SUCCESS Success to allocate aligned pages.
+ @retval EFI_INVALID_PARAMETER Pages or Alignment is not valid.
+ @retval EFI_OUT_OF_RESOURCES Do not have enough resources to allocate memory.
+
+
+**/
+EFI_STATUS
+UsbHcAllocateAlignedPages (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINTN Pages,
+ IN UINTN Alignment,
+ OUT VOID **HostAddress,
+ OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
+ OUT VOID **Mapping
+ )
+{
+ EFI_STATUS Status;
+ VOID *Memory;
+ UINTN AlignedMemory;
+ UINTN AlignmentMask;
+ UINTN UnalignedPages;
+ UINTN RealPages;
+ UINTN Bytes;
+
+ //
+ // Alignment must be a power of two or zero.
+ //
+ ASSERT ((Alignment & (Alignment - 1)) == 0);
+
+ if ((Alignment & (Alignment - 1)) != 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Pages == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if (Alignment > EFI_PAGE_SIZE) {
+ //
+ // Caculate the total number of pages since alignment is larger than page size.
+ //
+ AlignmentMask = Alignment - 1;
+ RealPages = Pages + EFI_SIZE_TO_PAGES (Alignment);
+ //
+ // Make sure that Pages plus EFI_SIZE_TO_PAGES (Alignment) does not overflow.
+ //
+ ASSERT (RealPages > Pages);
+
+ Status = PciIo->AllocateBuffer (
+ PciIo,
+ AllocateAnyPages,
+ EfiBootServicesData,
+ Pages,
+ &Memory,
+ 0
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ AlignedMemory = ((UINTN) Memory + AlignmentMask) & ~AlignmentMask;
+ UnalignedPages = EFI_SIZE_TO_PAGES (AlignedMemory - (UINTN) Memory);
+ if (UnalignedPages > 0) {
+ //
+ // Free first unaligned page(s).
+ //
+ Status = PciIo->FreeBuffer (PciIo, UnalignedPages, Memory);
+ ASSERT_EFI_ERROR (Status);
+ }
+ Memory = (VOID *)(UINTN)(AlignedMemory + EFI_PAGES_TO_SIZE (Pages));
+ UnalignedPages = RealPages - Pages - UnalignedPages;
+ if (UnalignedPages > 0) {
+ //
+ // Free last unaligned page(s).
+ //
+ Status = PciIo->FreeBuffer (PciIo, UnalignedPages, Memory);
+ ASSERT_EFI_ERROR (Status);
+ }
+ } else {
+ //
+ // Do not over-allocate pages in this case.
+ //
+ Status = PciIo->AllocateBuffer (
+ PciIo,
+ AllocateAnyPages,
+ EfiBootServicesData,
+ Pages,
+ &Memory,
+ 0
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ AlignedMemory = (UINTN) Memory;
+ }
+
+ Bytes = EFI_PAGES_TO_SIZE (Pages);
+ Status = PciIo->Map (
+ PciIo,
+ EfiPciIoOperationBusMasterCommonBuffer,
+ (VOID *) AlignedMemory,
+ &Bytes,
+ DeviceAddress,
+ Mapping
+ );
+
+ if (EFI_ERROR (Status) || (Bytes != EFI_PAGES_TO_SIZE (Pages))) {
+ Status = PciIo->FreeBuffer (PciIo, Pages, (VOID *) AlignedMemory);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ *HostAddress = (VOID *) AlignedMemory;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Frees memory that was allocated with UsbHcAllocateAlignedPages().
+
+ @param PciIo The PciIo that can be used to access the host controller.
+ @param HostAddress The system memory address to map to the PCI controller.
+ @param Pages The number of 4 KB pages to free.
+ @param Mapping The mapping value returned from Map().
+
+**/
+VOID
+UsbHcFreeAlignedPages (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN VOID *HostAddress,
+ IN UINTN Pages,
+ VOID *Mapping
+ )
+{
+ EFI_STATUS Status;
+
+ ASSERT (Pages != 0);
+
+ Status = PciIo->Unmap (PciIo, Mapping);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = PciIo->FreeBuffer (
+ PciIo,
+ Pages,
+ HostAddress
+ );
+ ASSERT_EFI_ERROR (Status);
+}
diff --git a/MdeModulePkg/Bus/Pci/XhciDxe/UsbHcMem.h b/MdeModulePkg/Bus/Pci/XhciDxe/UsbHcMem.h
new file mode 100644
index 000000000..1907685dd
--- /dev/null
+++ b/MdeModulePkg/Bus/Pci/XhciDxe/UsbHcMem.h
@@ -0,0 +1,213 @@
+/** @file
+
+ This file contains the definination for host controller memory management routines.
+
+Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>
+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 _EFI_XHCI_MEM_H_
+#define _EFI_XHCI_MEM_H_
+
+#define USB_HC_BIT(a) ((UINTN)(1 << (a)))
+
+#define USB_HC_BIT_IS_SET(Data, Bit) \
+ ((BOOLEAN)(((Data) & USB_HC_BIT(Bit)) == USB_HC_BIT(Bit)))
+
+typedef struct _USBHC_MEM_BLOCK USBHC_MEM_BLOCK;
+struct _USBHC_MEM_BLOCK {
+ UINT8 *Bits; // Bit array to record which unit is allocated
+ UINTN BitsLen;
+ UINT8 *Buf;
+ UINT8 *BufHost;
+ UINTN BufLen; // Memory size in bytes
+ VOID *Mapping;
+ USBHC_MEM_BLOCK *Next;
+};
+
+//
+// USBHC_MEM_POOL is used to manage the memory used by USB
+// host controller. XHCI requires the control memory and transfer
+// data to be on the same 4G memory.
+//
+typedef struct _USBHC_MEM_POOL {
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ BOOLEAN Check4G;
+ UINT32 Which4G;
+ USBHC_MEM_BLOCK *Head;
+} USBHC_MEM_POOL;
+
+//
+// Memory allocation unit, must be 2^n, n>4
+//
+#define USBHC_MEM_UNIT 64
+
+#define USBHC_MEM_UNIT_MASK (USBHC_MEM_UNIT - 1)
+#define USBHC_MEM_DEFAULT_PAGES 16
+
+#define USBHC_MEM_ROUND(Len) (((Len) + USBHC_MEM_UNIT_MASK) & (~USBHC_MEM_UNIT_MASK))
+
+//
+// Advance the byte and bit to the next bit, adjust byte accordingly.
+//
+#define NEXT_BIT(Byte, Bit) \
+ do { \
+ (Bit)++; \
+ if ((Bit) > 7) { \
+ (Byte)++; \
+ (Bit) = 0; \
+ } \
+ } while (0)
+
+
+
+/**
+ Initialize the memory management pool for the host controller.
+
+ @param PciIo The PciIo that can be used to access the host controller.
+
+ @retval EFI_SUCCESS The memory pool is initialized.
+ @retval EFI_OUT_OF_RESOURCE Fail to init the memory pool.
+
+**/
+USBHC_MEM_POOL *
+UsbHcInitMemPool (
+ IN EFI_PCI_IO_PROTOCOL *PciIo
+ );
+
+
+/**
+ Release the memory management pool.
+
+ @param Pool The USB memory pool to free.
+
+ @retval EFI_SUCCESS The memory pool is freed.
+ @retval EFI_DEVICE_ERROR Failed to free the memory pool.
+
+**/
+EFI_STATUS
+UsbHcFreeMemPool (
+ IN USBHC_MEM_POOL *Pool
+ );
+
+
+/**
+ Allocate some memory from the host controller's memory pool
+ which can be used to communicate with host controller.
+
+ @param Pool The host controller's memory pool.
+ @param Size Size of the memory to allocate.
+
+ @return The allocated memory or NULL.
+
+**/
+VOID *
+UsbHcAllocateMem (
+ IN USBHC_MEM_POOL *Pool,
+ IN UINTN Size
+ );
+
+
+/**
+ Free the allocated memory back to the memory pool.
+
+ @param Pool The memory pool of the host controller.
+ @param Mem The memory to free.
+ @param Size The size of the memory to free.
+
+**/
+VOID
+UsbHcFreeMem (
+ IN USBHC_MEM_POOL *Pool,
+ IN VOID *Mem,
+ IN UINTN Size
+ );
+
+/**
+ Calculate the corresponding pci bus address according to the Mem parameter.
+
+ @param Pool The memory pool of the host controller.
+ @param Mem The pointer to host memory.
+ @param Size The size of the memory region.
+
+ @return The pci memory address
+
+**/
+EFI_PHYSICAL_ADDRESS
+UsbHcGetPciAddrForHostAddr (
+ IN USBHC_MEM_POOL *Pool,
+ IN VOID *Mem,
+ IN UINTN Size
+ );
+
+/**
+ Calculate the corresponding host address according to the pci address.
+
+ @param Pool The memory pool of the host controller.
+ @param Mem The pointer to pci memory.
+ @param Size The size of the memory region.
+
+ @return The host memory address
+
+**/
+EFI_PHYSICAL_ADDRESS
+UsbHcGetHostAddrForPciAddr (
+ IN USBHC_MEM_POOL *Pool,
+ IN VOID *Mem,
+ IN UINTN Size
+ );
+
+/**
+ Allocates pages at a specified alignment that are suitable for an EfiPciIoOperationBusMasterCommonBuffer mapping.
+
+ If Alignment is not a power of two and Alignment is not zero, then ASSERT().
+
+ @param PciIo The PciIo that can be used to access the host controller.
+ @param Pages The number of pages to allocate.
+ @param Alignment The requested alignment of the allocation. Must be a power of two.
+ @param HostAddress The system memory address to map to the PCI controller.
+ @param DeviceAddress The resulting map address for the bus master PCI controller to
+ use to access the hosts HostAddress.
+ @param Mapping A resulting value to pass to Unmap().
+
+ @retval EFI_SUCCESS Success to allocate aligned pages.
+ @retval EFI_INVALID_PARAMETER Pages or Alignment is not valid.
+ @retval EFI_OUT_OF_RESOURCES Do not have enough resources to allocate memory.
+
+
+**/
+EFI_STATUS
+UsbHcAllocateAlignedPages (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINTN Pages,
+ IN UINTN Alignment,
+ OUT VOID **HostAddress,
+ OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
+ OUT VOID **Mapping
+ );
+
+/**
+ Frees memory that was allocated with UsbHcAllocateAlignedPages().
+
+ @param PciIo The PciIo that can be used to access the host controller.
+ @param HostAddress The system memory address to map to the PCI controller.
+ @param Pages The number of pages to free.
+ @param Mapping The mapping value returned from Map().
+
+**/
+VOID
+UsbHcFreeAlignedPages (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN VOID *HostAddress,
+ IN UINTN Pages,
+ VOID *Mapping
+ );
+
+#endif
diff --git a/MdeModulePkg/Bus/Pci/XhciDxe/Xhci.c b/MdeModulePkg/Bus/Pci/XhciDxe/Xhci.c
index 8e6bc6ff6..3e578975a 100644
--- a/MdeModulePkg/Bus/Pci/XhciDxe/Xhci.c
+++ b/MdeModulePkg/Bus/Pci/XhciDxe/Xhci.c
@@ -900,13 +900,26 @@ XhcControlTransfer (
Status = EFI_SUCCESS;
} else if (*TransferResult == EFI_USB_ERR_STALL) {
RecoveryStatus = XhcRecoverHaltedEndpoint(Xhc, Urb);
- ASSERT_EFI_ERROR (RecoveryStatus);
+ if (EFI_ERROR (RecoveryStatus)) {
+ DEBUG ((EFI_D_ERROR, "XhcControlTransfer: XhcRecoverHaltedEndpoint failed\n"));
+ }
Status = EFI_DEVICE_ERROR;
goto FREE_URB;
} else {
goto FREE_URB;
}
+ Xhc->PciIo->Flush (Xhc->PciIo);
+
+ if (Urb->DataMap != NULL) {
+ Status = Xhc->PciIo->Unmap (Xhc->PciIo, Urb->DataMap);
+ ASSERT_EFI_ERROR (Status);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto FREE_URB;
+ }
+ }
+
//
// Hook Get_Descriptor request from UsbBus as we need evaluate context and configure endpoint.
// Hook Get_Status request form UsbBus as we need trace device attach/detach event happened at hub.
@@ -936,7 +949,6 @@ XhcControlTransfer (
} else {
Status = XhcEvaluateContext64 (Xhc, SlotId, MaxPacket0);
}
- ASSERT_EFI_ERROR (Status);
} else if (DescriptorType == USB_DESC_TYPE_CONFIG) {
ASSERT (Data != NULL);
if (*DataLength == ((UINT16 *)Data)[1]) {
@@ -972,7 +984,6 @@ XhcControlTransfer (
} else {
Status = XhcConfigHubContext64 (Xhc, SlotId, HubDesc->NumPorts, TTT, MTT);
}
- ASSERT_EFI_ERROR (Status);
}
} else if ((Request->Request == USB_REQ_SET_CONFIG) &&
(Request->RequestType == USB_REQUEST_TYPE (EfiUsbNoData, USB_REQ_TYPE_STANDARD, USB_TARGET_DEVICE))) {
@@ -986,7 +997,6 @@ XhcControlTransfer (
} else {
Status = XhcSetConfigCmd64 (Xhc, SlotId, DeviceSpeed, Xhc->UsbDevContext[SlotId].ConfDesc[Index]);
}
- ASSERT_EFI_ERROR (Status);
break;
}
}
@@ -1181,11 +1191,14 @@ XhcBulkTransfer (
Status = EFI_SUCCESS;
} else if (*TransferResult == EFI_USB_ERR_STALL) {
RecoveryStatus = XhcRecoverHaltedEndpoint(Xhc, Urb);
- ASSERT_EFI_ERROR (RecoveryStatus);
+ if (EFI_ERROR (RecoveryStatus)) {
+ DEBUG ((EFI_D_ERROR, "XhcBulkTransfer: XhcRecoverHaltedEndpoint failed\n"));
+ }
Status = EFI_DEVICE_ERROR;
}
- FreePool (Urb);
+ Xhc->PciIo->Flush (Xhc->PciIo);
+ XhcFreeUrb (Xhc, Urb);
ON_EXIT:
@@ -1351,6 +1364,7 @@ XhcAsyncInterruptTransfer (
Status = RingIntTransferDoorBell (Xhc, Urb);
ON_EXIT:
+ Xhc->PciIo->Flush (Xhc->PciIo);
gBS->RestoreTPL (OldTpl);
return Status;
@@ -1478,11 +1492,14 @@ XhcSyncInterruptTransfer (
Status = EFI_SUCCESS;
} else if (*TransferResult == EFI_USB_ERR_STALL) {
RecoveryStatus = XhcRecoverHaltedEndpoint(Xhc, Urb);
- ASSERT_EFI_ERROR (RecoveryStatus);
+ if (EFI_ERROR (RecoveryStatus)) {
+ DEBUG ((EFI_D_ERROR, "XhcSyncInterruptTransfer: XhcRecoverHaltedEndpoint failed\n"));
+ }
Status = EFI_DEVICE_ERROR;
}
- FreePool (Urb);
+ Xhc->PciIo->Flush (Xhc->PciIo);
+ XhcFreeUrb (Xhc, Urb);
ON_EXIT:
if (EFI_ERROR (Status)) {
diff --git a/MdeModulePkg/Bus/Pci/XhciDxe/Xhci.h b/MdeModulePkg/Bus/Pci/XhciDxe/Xhci.h
index ae56b1e6f..fab6a7296 100644
--- a/MdeModulePkg/Bus/Pci/XhciDxe/Xhci.h
+++ b/MdeModulePkg/Bus/Pci/XhciDxe/Xhci.h
@@ -2,7 +2,7 @@
Provides some data structure definitions used by the XHCI host controller driver.
-Copyright (c) 2011 - 2012, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2011 - 2013, Intel Corporation. All rights reserved.<BR>
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
@@ -40,8 +40,13 @@ typedef struct _USB_DEV_CONTEXT USB_DEV_CONTEXT;
#include "XhciReg.h"
#include "XhciSched.h"
#include "ComponentName.h"
+#include "UsbHcMem.h"
//
+// The unit is microsecond, setting it as 1us.
+//
+#define XHC_1_MICROSECOND (1)
+//
// Convert millisecond to microsecond.
//
#define XHC_1_MILLISECOND (1000)
@@ -197,6 +202,7 @@ struct _USB_XHCI_INSTANCE {
UINT32 Signature;
EFI_PCI_IO_PROTOCOL *PciIo;
UINT64 OriginalPciAttributes;
+ USBHC_MEM_POOL *MemPool;
EFI_USB2_HC_PROTOCOL Usb2Hc;
@@ -219,10 +225,14 @@ struct _USB_XHCI_INSTANCE {
UINT16 MaxInterrupt;
UINT32 PageSize;
UINT64 *ScratchBuf;
+ VOID *ScratchMap;
UINT32 MaxScratchpadBufs;
+ UINT64 *ScratchEntry;
+ UINTN *ScratchEntryMap;
UINT32 ExtCapRegBase;
UINT32 UsbLegSupOffset;
UINT64 *DCBAA;
+ VOID *DCBAAMap;
UINT32 MaxSlotsEn;
//
// Cmd Transfer Ring
diff --git a/MdeModulePkg/Bus/Pci/XhciDxe/XhciDxe.inf b/MdeModulePkg/Bus/Pci/XhciDxe/XhciDxe.inf
index 84dea07a4..8d8fc5b2a 100644
--- a/MdeModulePkg/Bus/Pci/XhciDxe/XhciDxe.inf
+++ b/MdeModulePkg/Bus/Pci/XhciDxe/XhciDxe.inf
@@ -6,7 +6,7 @@
# It implements the interfaces of monitoring the status of all ports and transferring
# Control, Bulk, Interrupt and Isochronous requests to those attached usb LS/FS/HS/SS devices.
#
-# Copyright (c) 2011 - 2012, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2011 - 2013, Intel Corporation. All rights reserved.<BR>
#
# This program and the accompanying materials
# are licensed and made available under the terms and conditions of the BSD License
@@ -42,6 +42,8 @@
Xhci.c
XhciReg.c
XhciSched.c
+ UsbHcMem.c
+ UsbHcMem.h
ComponentName.c
ComponentName.h
Xhci.h
diff --git a/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c b/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c
index e6c0d1564..dea5b1af1 100644
--- a/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c
+++ b/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c
@@ -2,7 +2,7 @@
XHCI transfer scheduling routines.
-Copyright (c) 2011 - 2012, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2011 - 2013, Intel Corporation. All rights reserved.<BR>
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
@@ -109,7 +109,7 @@ XhcCmdTransfer (
Status = EFI_SUCCESS;
}
- FreePool (Urb);
+ XhcFreeUrb (Xhc, Urb);
ON_EXIT:
return Status;
@@ -176,11 +176,40 @@ XhcCreateUrb (
Status = XhcCreateTransferTrb (Xhc, Urb);
ASSERT_EFI_ERROR (Status);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "XhcCreateUrb: XhcCreateTransferTrb Failed, Status = %r\n", Status));
+ FreePool (Urb);
+ Urb = NULL;
+ }
return Urb;
}
/**
+ Free an allocated URB.
+
+ @param Xhc The XHCI device.
+ @param Urb The URB to free.
+
+**/
+VOID
+XhcFreeUrb (
+ IN USB_XHCI_INSTANCE *Xhc,
+ IN URB *Urb
+ )
+{
+ if ((Xhc == NULL) || (Urb == NULL)) {
+ return;
+ }
+
+ if (Urb->DataMap != NULL) {
+ Xhc->PciIo->Unmap (Xhc->PciIo, Urb->DataMap);
+ }
+
+ FreePool (Urb);
+}
+
+/**
Create a transfer TRB.
@param Xhc The XHCI Instance
@@ -204,6 +233,10 @@ XhcCreateTransferTrb (
UINTN TotalLen;
UINTN Len;
UINTN TrbNum;
+ EFI_PCI_IO_PROTOCOL_OPERATION MapOp;
+ EFI_PHYSICAL_ADDRESS PhyAddr;
+ VOID *Map;
+ EFI_STATUS Status;
SlotId = XhcBusDevAddrToSlotId (Xhc, Urb->Ep.BusAddr);
if (SlotId == 0) {
@@ -220,12 +253,31 @@ XhcCreateTransferTrb (
ASSERT (Dci < 32);
EPRing = (TRANSFER_RING *)(UINTN) Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1];
Urb->Ring = EPRing;
- OutputContext = (VOID *)(UINTN)Xhc->DCBAA[SlotId];
+ OutputContext = Xhc->UsbDevContext[SlotId].OutputContext;
if (Xhc->HcCParams.Data.Csz == 0) {
EPType = (UINT8) ((DEVICE_CONTEXT *)OutputContext)->EP[Dci-1].EPType;
} else {
EPType = (UINT8) ((DEVICE_CONTEXT_64 *)OutputContext)->EP[Dci-1].EPType;
}
+
+ if (Urb->Data != NULL) {
+ if (((UINT8) (Urb->Ep.Direction)) == EfiUsbDataIn) {
+ MapOp = EfiPciIoOperationBusMasterWrite;
+ } else {
+ MapOp = EfiPciIoOperationBusMasterRead;
+ }
+
+ Len = Urb->DataLen;
+ Status = Xhc->PciIo->Map (Xhc->PciIo, MapOp, Urb->Data, &Len, &PhyAddr, &Map);
+
+ if (EFI_ERROR (Status) || (Len != Urb->DataLen)) {
+ DEBUG ((EFI_D_ERROR, "XhcCreateTransferTrb: Fail to map Urb->Data.\n"));
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Urb->DataPhy = (VOID *) ((UINTN) PhyAddr);
+ Urb->DataMap = Map;
+ }
//
// Construct the TRB
@@ -267,8 +319,8 @@ XhcCreateTransferTrb (
if (Urb->DataLen > 0) {
XhcSyncTrsRing (Xhc, EPRing);
TrbStart = (TRB *)(UINTN)EPRing->RingEnqueue;
- TrbStart->TrbCtrData.TRBPtrLo = XHC_LOW_32BIT(Urb->Data);
- TrbStart->TrbCtrData.TRBPtrHi = XHC_HIGH_32BIT(Urb->Data);
+ TrbStart->TrbCtrData.TRBPtrLo = XHC_LOW_32BIT(Urb->DataPhy);
+ TrbStart->TrbCtrData.TRBPtrHi = XHC_HIGH_32BIT(Urb->DataPhy);
TrbStart->TrbCtrData.Lenth = (UINT32) Urb->DataLen;
TrbStart->TrbCtrData.TDSize = 0;
TrbStart->TrbCtrData.IntTarget = 0;
@@ -333,8 +385,8 @@ XhcCreateTransferTrb (
Len = 0x10000;
}
TrbStart = (TRB *)(UINTN)EPRing->RingEnqueue;
- TrbStart->TrbNormal.TRBPtrLo = XHC_LOW_32BIT((UINT8 *) Urb->Data + TotalLen);
- TrbStart->TrbNormal.TRBPtrHi = XHC_HIGH_32BIT((UINT8 *) Urb->Data + TotalLen);
+ TrbStart->TrbNormal.TRBPtrLo = XHC_LOW_32BIT((UINT8 *) Urb->DataPhy + TotalLen);
+ TrbStart->TrbNormal.TRBPtrHi = XHC_HIGH_32BIT((UINT8 *) Urb->DataPhy + TotalLen);
TrbStart->TrbNormal.Lenth = (UINT32) Len;
TrbStart->TrbNormal.TDSize = 0;
TrbStart->TrbNormal.IntTarget = 0;
@@ -368,8 +420,8 @@ XhcCreateTransferTrb (
Len = 0x10000;
}
TrbStart = (TRB *)(UINTN)EPRing->RingEnqueue;
- TrbStart->TrbNormal.TRBPtrLo = XHC_LOW_32BIT((UINT8 *) Urb->Data + TotalLen);
- TrbStart->TrbNormal.TRBPtrHi = XHC_HIGH_32BIT((UINT8 *) Urb->Data + TotalLen);
+ TrbStart->TrbNormal.TRBPtrLo = XHC_LOW_32BIT((UINT8 *) Urb->DataPhy + TotalLen);
+ TrbStart->TrbNormal.TRBPtrHi = XHC_HIGH_32BIT((UINT8 *) Urb->DataPhy + TotalLen);
TrbStart->TrbNormal.Lenth = (UINT32) Len;
TrbStart->TrbNormal.TDSize = 0;
TrbStart->TrbNormal.IntTarget = 0;
@@ -412,12 +464,24 @@ XhcInitSched (
)
{
VOID *Dcbaa;
+ EFI_PHYSICAL_ADDRESS DcbaaPhy;
UINT64 CmdRing;
+ EFI_PHYSICAL_ADDRESS CmdRingPhy;
UINTN Entries;
UINT32 MaxScratchpadBufs;
UINT64 *ScratchBuf;
- UINT64 *ScratchEntryBuf;
+ EFI_PHYSICAL_ADDRESS ScratchPhy;
+ UINT64 *ScratchEntry;
+ EFI_PHYSICAL_ADDRESS ScratchEntryPhy;
UINT32 Index;
+ UINTN *ScratchEntryMap;
+ EFI_STATUS Status;
+
+ //
+ // Initialize memory management.
+ //
+ Xhc->MemPool = UsbHcInitMemPool (Xhc->PciIo);
+ ASSERT (Xhc->MemPool != NULL);
//
// Program the Max Device Slots Enabled (MaxSlotsEn) field in the CONFIG register (5.4.7)
@@ -434,7 +498,7 @@ XhcInitSched (
// Software shall set Device Context Base Address Array entries for unallocated Device Slots to '0'.
//
Entries = (Xhc->MaxSlotsEn + 1) * sizeof(UINT64);
- Dcbaa = AllocatePages (EFI_SIZE_TO_PAGES (Entries));
+ Dcbaa = UsbHcAllocateMem (Xhc->MemPool, Entries);
ASSERT (Dcbaa != NULL);
ZeroMem (Dcbaa, Entries);
@@ -447,23 +511,57 @@ XhcInitSched (
Xhc->MaxScratchpadBufs = MaxScratchpadBufs;
ASSERT (MaxScratchpadBufs <= 1023);
if (MaxScratchpadBufs != 0) {
- ScratchBuf = AllocateAlignedPages (EFI_SIZE_TO_PAGES (MaxScratchpadBufs * sizeof (UINT64)), Xhc->PageSize);
- ASSERT (ScratchBuf != NULL);
+ //
+ // Allocate the buffer to record the Mapping for each scratch buffer in order to Unmap them
+ //
+ ScratchEntryMap = AllocateZeroPool (sizeof (UINTN) * MaxScratchpadBufs);
+ ASSERT (ScratchEntryMap != NULL);
+ Xhc->ScratchEntryMap = ScratchEntryMap;
+
+ //
+ // Allocate the buffer to record the host address for each entry
+ //
+ ScratchEntry = AllocateZeroPool (sizeof (UINT64) * MaxScratchpadBufs);
+ ASSERT (ScratchEntry != NULL);
+ Xhc->ScratchEntry = ScratchEntry;
+
+ Status = UsbHcAllocateAlignedPages (
+ Xhc->PciIo,
+ EFI_SIZE_TO_PAGES (MaxScratchpadBufs * sizeof (UINT64)),
+ Xhc->PageSize,
+ (VOID **) &ScratchBuf,
+ &ScratchPhy,
+ &Xhc->ScratchMap
+ );
+ ASSERT_EFI_ERROR (Status);
+
ZeroMem (ScratchBuf, MaxScratchpadBufs * sizeof (UINT64));
Xhc->ScratchBuf = ScratchBuf;
+ //
+ // Allocate each scratch buffer
+ //
for (Index = 0; Index < MaxScratchpadBufs; Index++) {
- ScratchEntryBuf = AllocateAlignedPages (EFI_SIZE_TO_PAGES (Xhc->PageSize), Xhc->PageSize);
- ASSERT (ScratchEntryBuf != NULL);
- ZeroMem (ScratchEntryBuf, Xhc->PageSize);
- *ScratchBuf++ = (UINT64)(UINTN)ScratchEntryBuf;
+ Status = UsbHcAllocateAlignedPages (
+ Xhc->PciIo,
+ EFI_SIZE_TO_PAGES (Xhc->PageSize),
+ Xhc->PageSize,
+ (VOID **) &ScratchEntry[Index],
+ &ScratchEntryPhy,
+ (VOID **) &ScratchEntryMap[Index]
+ );
+ ASSERT_EFI_ERROR (Status);
+ ZeroMem ((VOID *)(UINTN)ScratchEntry[Index], Xhc->PageSize);
+ //
+ // Fill with the PCI device address
+ //
+ *ScratchBuf++ = ScratchEntryPhy;
}
-
//
// The Scratchpad Buffer Array contains pointers to the Scratchpad Buffers. Entry 0 of the
// Device Context Base Address Array points to the Scratchpad Buffer Array.
//
- *(UINT64 *)Dcbaa = (UINT64)(UINTN)Xhc->ScratchBuf;
+ *(UINT64 *)Dcbaa = (UINT64)(UINTN) ScratchPhy;
}
//
@@ -475,8 +573,10 @@ XhcInitSched (
// Some 3rd party XHCI external cards don't support single 64-bytes width register access,
// So divide it to two 32-bytes width register access.
//
- XhcWriteOpReg (Xhc, XHC_DCBAAP_OFFSET, XHC_LOW_32BIT(Xhc->DCBAA));
- XhcWriteOpReg (Xhc, XHC_DCBAAP_OFFSET + 4, XHC_HIGH_32BIT (Xhc->DCBAA));
+ DcbaaPhy = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, Dcbaa, Entries);
+ XhcWriteOpReg (Xhc, XHC_DCBAAP_OFFSET, XHC_LOW_32BIT(DcbaaPhy));
+ XhcWriteOpReg (Xhc, XHC_DCBAAP_OFFSET + 4, XHC_HIGH_32BIT (DcbaaPhy));
+
DEBUG ((EFI_D_INFO, "XhcInitSched:DCBAA=0x%x\n", (UINT64)(UINTN)Xhc->DCBAA));
//
@@ -492,14 +592,15 @@ XhcInitSched (
// So we set RCS as inverted PCS init value to let Command Ring empty
//
CmdRing = (UINT64)(UINTN)Xhc->CmdRing.RingSeg0;
- ASSERT ((CmdRing & 0x3F) == 0);
- CmdRing |= XHC_CRCR_RCS;
+ CmdRingPhy = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, (VOID *)(UINTN) CmdRing, sizeof (TRB_TEMPLATE) * CMD_RING_TRB_NUMBER);
+ ASSERT ((CmdRingPhy & 0x3F) == 0);
+ CmdRingPhy |= XHC_CRCR_RCS;
//
// Some 3rd party XHCI external cards don't support single 64-bytes width register access,
// So divide it to two 32-bytes width register access.
//
- XhcWriteOpReg (Xhc, XHC_CRCR_OFFSET, XHC_LOW_32BIT(CmdRing));
- XhcWriteOpReg (Xhc, XHC_CRCR_OFFSET + 4, XHC_HIGH_32BIT (CmdRing));
+ XhcWriteOpReg (Xhc, XHC_CRCR_OFFSET, XHC_LOW_32BIT(CmdRingPhy));
+ XhcWriteOpReg (Xhc, XHC_CRCR_OFFSET + 4, XHC_HIGH_32BIT (CmdRingPhy));
DEBUG ((EFI_D_INFO, "XhcInitSched:XHC_CRCR=0x%x\n", Xhc->CmdRing.RingSeg0));
@@ -547,6 +648,7 @@ XhcRecoverHaltedEndpoint (
CMD_SET_TR_DEQ_POINTER CmdSetTRDeq;
UINT8 Dci;
UINT8 SlotId;
+ EFI_PHYSICAL_ADDRESS PhyAddr;
Status = EFI_SUCCESS;
SlotId = XhcBusDevAddrToSlotId (Xhc, Urb->Ep.BusAddr);
@@ -572,14 +674,18 @@ XhcRecoverHaltedEndpoint (
XHC_GENERIC_TIMEOUT,
(TRB_TEMPLATE **) (UINTN) &EvtTrb
);
- ASSERT (!EFI_ERROR(Status));
+ if (EFI_ERROR(Status)) {
+ DEBUG ((EFI_D_ERROR, "XhcRecoverHaltedEndpoint: Reset Endpoint Failed, Status = %r\n", Status));
+ goto Done;
+ }
//
// 2)Set dequeue pointer
//
ZeroMem (&CmdSetTRDeq, sizeof (CmdSetTRDeq));
- CmdSetTRDeq.PtrLo = XHC_LOW_32BIT (Urb->Ring->RingEnqueue) | Urb->Ring->RingPCS;
- CmdSetTRDeq.PtrHi = XHC_HIGH_32BIT (Urb->Ring->RingEnqueue);
+ PhyAddr = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, Urb->Ring->RingEnqueue, sizeof (CMD_SET_TR_DEQ_POINTER));
+ CmdSetTRDeq.PtrLo = XHC_LOW_32BIT (PhyAddr) | Urb->Ring->RingPCS;
+ CmdSetTRDeq.PtrHi = XHC_HIGH_32BIT (PhyAddr);
CmdSetTRDeq.CycleBit = 1;
CmdSetTRDeq.Type = TRB_TYPE_SET_TR_DEQUE;
CmdSetTRDeq.Endpoint = Dci;
@@ -590,13 +696,17 @@ XhcRecoverHaltedEndpoint (
XHC_GENERIC_TIMEOUT,
(TRB_TEMPLATE **) (UINTN) &EvtTrb
);
- ASSERT (!EFI_ERROR(Status));
+ if (EFI_ERROR(Status)) {
+ DEBUG ((EFI_D_ERROR, "XhcRecoverHaltedEndpoint: Set Dequeue Pointer Failed, Status = %r\n", Status));
+ goto Done;
+ }
//
// 3)Ring the doorbell to transit from stop to active
//
XhcRingDoorBell (Xhc, SlotId, Dci);
+Done:
return Status;
}
@@ -615,35 +725,45 @@ CreateEventRing (
{
VOID *Buf;
EVENT_RING_SEG_TABLE_ENTRY *ERSTBase;
+ UINTN Size;
+ EFI_PHYSICAL_ADDRESS ERSTPhy;
+ EFI_PHYSICAL_ADDRESS DequeuePhy;
ASSERT (EventRing != NULL);
- Buf = AllocatePages (EFI_SIZE_TO_PAGES (sizeof (TRB_TEMPLATE) * EVENT_RING_TRB_NUMBER));
+ Size = sizeof (TRB_TEMPLATE) * EVENT_RING_TRB_NUMBER;
+ Buf = UsbHcAllocateMem (Xhc->MemPool, Size);
ASSERT (Buf != NULL);
ASSERT (((UINTN) Buf & 0x3F) == 0);
- ZeroMem (Buf, sizeof (TRB_TEMPLATE) * EVENT_RING_TRB_NUMBER);
+ ZeroMem (Buf, Size);
EventRing->EventRingSeg0 = Buf;
EventRing->TrbNumber = EVENT_RING_TRB_NUMBER;
EventRing->EventRingDequeue = (TRB_TEMPLATE *) EventRing->EventRingSeg0;
EventRing->EventRingEnqueue = (TRB_TEMPLATE *) EventRing->EventRingSeg0;
+
+ DequeuePhy = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, Buf, Size);
+
//
// Software maintains an Event Ring Consumer Cycle State (CCS) bit, initializing it to '1'
// and toggling it every time the Event Ring Dequeue Pointer wraps back to the beginning of the Event Ring.
//
EventRing->EventRingCCS = 1;
- Buf = AllocatePages (EFI_SIZE_TO_PAGES (sizeof (EVENT_RING_SEG_TABLE_ENTRY) * ERST_NUMBER));
+ Size = EFI_SIZE_TO_PAGES (sizeof (EVENT_RING_SEG_TABLE_ENTRY) * ERST_NUMBER);
+ Buf = UsbHcAllocateMem (Xhc->MemPool, Size);
ASSERT (Buf != NULL);
ASSERT (((UINTN) Buf & 0x3F) == 0);
- ZeroMem (Buf, sizeof (EVENT_RING_SEG_TABLE_ENTRY) * ERST_NUMBER);
+ ZeroMem (Buf, Size);
ERSTBase = (EVENT_RING_SEG_TABLE_ENTRY *) Buf;
EventRing->ERSTBase = ERSTBase;
- ERSTBase->PtrLo = XHC_LOW_32BIT (EventRing->EventRingSeg0);
- ERSTBase->PtrHi = XHC_HIGH_32BIT (EventRing->EventRingSeg0);
+ ERSTBase->PtrLo = XHC_LOW_32BIT (DequeuePhy);
+ ERSTBase->PtrHi = XHC_HIGH_32BIT (DequeuePhy);
ERSTBase->RingTrbSize = EVENT_RING_TRB_NUMBER;
+ ERSTPhy = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, ERSTBase, Size);
+
//
// Program the Interrupter Event Ring Segment Table Size (ERSTSZ) register (5.5.2.3.1)
//
@@ -661,12 +781,12 @@ CreateEventRing (
XhcWriteRuntimeReg (
Xhc,
XHC_ERDP_OFFSET,
- XHC_LOW_32BIT((UINT64)(UINTN)EventRing->EventRingDequeue)
+ XHC_LOW_32BIT((UINT64)(UINTN)DequeuePhy)
);
XhcWriteRuntimeReg (
Xhc,
XHC_ERDP_OFFSET + 4,
- XHC_HIGH_32BIT((UINT64)(UINTN)EventRing->EventRingDequeue)
+ XHC_HIGH_32BIT((UINT64)(UINTN)DequeuePhy)
);
//
// Program the Interrupter Event Ring Segment Table Base Address (ERSTBA) register(5.5.2.3.2)
@@ -677,12 +797,12 @@ CreateEventRing (
XhcWriteRuntimeReg (
Xhc,
XHC_ERSTBA_OFFSET,
- XHC_LOW_32BIT((UINT64)(UINTN)ERSTBase)
+ XHC_LOW_32BIT((UINT64)(UINTN)ERSTPhy)
);
XhcWriteRuntimeReg (
Xhc,
XHC_ERSTBA_OFFSET + 4,
- XHC_HIGH_32BIT((UINT64)(UINTN)ERSTBase)
+ XHC_HIGH_32BIT((UINT64)(UINTN)ERSTPhy)
);
//
// Need set IMAN IE bit to enble the ring interrupt
@@ -707,8 +827,9 @@ CreateTransferRing (
{
VOID *Buf;
LINK_TRB *EndTrb;
+ EFI_PHYSICAL_ADDRESS PhyAddr;
- Buf = AllocatePages (EFI_SIZE_TO_PAGES (sizeof (TRB_TEMPLATE) * TrbNum));
+ Buf = UsbHcAllocateMem (Xhc->MemPool, sizeof (TRB_TEMPLATE) * TrbNum);
ASSERT (Buf != NULL);
ASSERT (((UINTN) Buf & 0x3F) == 0);
ZeroMem (Buf, sizeof (TRB_TEMPLATE) * TrbNum);
@@ -725,8 +846,9 @@ CreateTransferRing (
//
EndTrb = (LINK_TRB *) ((UINTN)Buf + sizeof (TRB_TEMPLATE) * (TrbNum - 1));
EndTrb->Type = TRB_TYPE_LINK;
- EndTrb->PtrLo = XHC_LOW_32BIT (Buf);
- EndTrb->PtrHi = XHC_HIGH_32BIT (Buf);
+ PhyAddr = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, Buf, sizeof (TRB_TEMPLATE) * TrbNum);
+ EndTrb->PtrLo = XHC_LOW_32BIT (PhyAddr);
+ EndTrb->PtrHi = XHC_HIGH_32BIT (PhyAddr);
//
// Toggle Cycle (TC). When set to '1', the xHC shall toggle its interpretation of the Cycle bit.
//
@@ -751,34 +873,19 @@ XhcFreeEventRing (
IN EVENT_RING *EventRing
)
{
- UINT8 Index;
- EVENT_RING_SEG_TABLE_ENTRY *TablePtr;
- VOID *RingBuf;
- EVENT_RING_SEG_TABLE_ENTRY *EventRingPtr;
-
if(EventRing->EventRingSeg0 == NULL) {
return EFI_SUCCESS;
}
//
- // Get the Event Ring Segment Table base address
+ // Free EventRing Segment 0
//
- TablePtr = (EVENT_RING_SEG_TABLE_ENTRY *)(EventRing->ERSTBase);
+ UsbHcFreeMem (Xhc->MemPool, EventRing->EventRingSeg0, sizeof (TRB_TEMPLATE) * EVENT_RING_TRB_NUMBER);
//
- // Get all the TRBs Ring and release
+ // Free ESRT table
//
- for (Index = 0; Index < ERST_NUMBER; Index++) {
- EventRingPtr = TablePtr + Index;
- RingBuf = (VOID *)(UINTN)(EventRingPtr->PtrLo | LShiftU64 ((UINT64)EventRingPtr->PtrHi, 32));
-
- if(RingBuf != NULL) {
- FreePages (RingBuf, EFI_SIZE_TO_PAGES (sizeof (TRB_TEMPLATE) * EVENT_RING_TRB_NUMBER));
- ZeroMem (EventRingPtr, sizeof (EVENT_RING_SEG_TABLE_ENTRY));
- }
- }
-
- FreePages (TablePtr, EFI_SIZE_TO_PAGES (sizeof (EVENT_RING_SEG_TABLE_ENTRY) * ERST_NUMBER));
+ UsbHcFreeMem (Xhc->MemPool, EventRing->ERSTBase, sizeof (EVENT_RING_SEG_TABLE_ENTRY) * ERST_NUMBER);
return EFI_SUCCESS;
}
@@ -793,28 +900,44 @@ XhcFreeSched (
IN USB_XHCI_INSTANCE *Xhc
)
{
- UINT32 Index;
- UINT64 *ScratchBuf;
-
+ UINT32 Index;
+ UINT64 *ScratchEntry;
+
if (Xhc->ScratchBuf != NULL) {
- ScratchBuf = Xhc->ScratchBuf;
+ ScratchEntry = Xhc->ScratchEntry;
for (Index = 0; Index < Xhc->MaxScratchpadBufs; Index++) {
- FreeAlignedPages ((VOID*)(UINTN)*ScratchBuf++, EFI_SIZE_TO_PAGES (Xhc->PageSize));
+ //
+ // Free Scratchpad Buffers
+ //
+ UsbHcFreeAlignedPages (Xhc->PciIo, (VOID*)(UINTN)ScratchEntry[Index], EFI_SIZE_TO_PAGES (Xhc->PageSize), (VOID *) Xhc->ScratchEntryMap[Index]);
}
- FreeAlignedPages (Xhc->ScratchBuf, EFI_SIZE_TO_PAGES (Xhc->MaxScratchpadBufs * sizeof (UINT64)));
+ //
+ // Free Scratchpad Buffer Array
+ //
+ UsbHcFreeAlignedPages (Xhc->PciIo, Xhc->ScratchBuf, EFI_SIZE_TO_PAGES (Xhc->MaxScratchpadBufs * sizeof (UINT64)), Xhc->ScratchMap);
+ FreePool (Xhc->ScratchEntryMap);
+ FreePool (Xhc->ScratchEntry);
}
+ if (Xhc->CmdRing.RingSeg0 != NULL) {
+ UsbHcFreeMem (Xhc->MemPool, Xhc->CmdRing.RingSeg0, sizeof (TRB_TEMPLATE) * CMD_RING_TRB_NUMBER);
+ Xhc->CmdRing.RingSeg0 = NULL;
+ }
+
+ XhcFreeEventRing (Xhc,&Xhc->EventRing);
+
if (Xhc->DCBAA != NULL) {
- FreePages (Xhc->DCBAA, EFI_SIZE_TO_PAGES((Xhc->MaxSlotsEn + 1) * sizeof(UINT64)));
+ UsbHcFreeMem (Xhc->MemPool, Xhc->DCBAA, (Xhc->MaxSlotsEn + 1) * sizeof(UINT64));
Xhc->DCBAA = NULL;
}
-
- if (Xhc->CmdRing.RingSeg0 != NULL){
- FreePages (Xhc->CmdRing.RingSeg0, EFI_SIZE_TO_PAGES (sizeof (TRB_TEMPLATE) * CMD_RING_TRB_NUMBER));
- Xhc->CmdRing.RingSeg0 = NULL;
+
+ //
+ // Free memory pool at last
+ //
+ if (Xhc->MemPool != NULL) {
+ UsbHcFreeMemPool (Xhc->MemPool);
+ Xhc->MemPool = NULL;
}
-
- XhcFreeEventRing (Xhc,&Xhc->EventRing);
}
/**
@@ -918,6 +1041,7 @@ XhcCheckUrbResult (
UINT64 XhcDequeue;
UINT32 High;
UINT32 Low;
+ EFI_PHYSICAL_ADDRESS PhyAddr;
ASSERT ((Xhc != NULL) && (Urb != NULL));
@@ -955,8 +1079,12 @@ XhcCheckUrbResult (
if ((EvtTrb->Type != TRB_TYPE_COMMAND_COMPLT_EVENT) && (EvtTrb->Type != TRB_TYPE_TRANS_EVENT)) {
continue;
}
-
- TRBPtr = (TRB_TEMPLATE *)(UINTN)(EvtTrb->TRBPtrLo | LShiftU64 ((UINT64) EvtTrb->TRBPtrHi, 32));
+
+ //
+ // Need convert pci device address to host address
+ //
+ PhyAddr = (EFI_PHYSICAL_ADDRESS)(EvtTrb->TRBPtrLo | LShiftU64 ((UINT64) EvtTrb->TRBPtrHi, 32));
+ TRBPtr = (TRB_TEMPLATE *)(UINTN) UsbHcGetHostAddrForPciAddr (Xhc->MemPool, (VOID *)(UINTN) PhyAddr, sizeof (TRB_TEMPLATE));
//
// Update the status of Urb according to the finished event regardless of whether
@@ -1048,13 +1176,15 @@ EXIT:
High = XhcReadRuntimeReg (Xhc, XHC_ERDP_OFFSET + 4);
XhcDequeue = (UINT64)(LShiftU64((UINT64)High, 32) | Low);
- if ((XhcDequeue & (~0x0F)) != ((UINT64)(UINTN)Xhc->EventRing.EventRingDequeue & (~0x0F))) {
+ PhyAddr = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, Xhc->EventRing.EventRingDequeue, sizeof (TRB_TEMPLATE));
+
+ if ((XhcDequeue & (~0x0F)) != (PhyAddr & (~0x0F))) {
//
// Some 3rd party XHCI external cards don't support single 64-bytes width register access,
// So divide it to two 32-bytes width register access.
//
- XhcWriteRuntimeReg (Xhc, XHC_ERDP_OFFSET, XHC_LOW_32BIT (Xhc->EventRing.EventRingDequeue) | BIT3);
- XhcWriteRuntimeReg (Xhc, XHC_ERDP_OFFSET + 4, XHC_HIGH_32BIT (Xhc->EventRing.EventRingDequeue));
+ XhcWriteRuntimeReg (Xhc, XHC_ERDP_OFFSET, XHC_LOW_32BIT (PhyAddr) | BIT3);
+ XhcWriteRuntimeReg (Xhc, XHC_ERDP_OFFSET + 4, XHC_HIGH_32BIT (PhyAddr));
}
return Status;
@@ -1101,7 +1231,7 @@ XhcExecTransfer (
}
Status = EFI_SUCCESS;
- Loop = (Timeout * XHC_1_MILLISECOND / XHC_POLL_DELAY) + 1;
+ Loop = Timeout * XHC_1_MILLISECOND;
if (Timeout == 0) {
Loop = 0xFFFFFFFF;
}
@@ -1113,7 +1243,7 @@ XhcExecTransfer (
if (Urb->Finished) {
break;
}
- gBS->Stall (XHC_POLL_DELAY);
+ gBS->Stall (XHC_1_MICROSECOND);
}
if (Index == Loop) {
@@ -1159,7 +1289,7 @@ XhciDelAsyncIntTransfer (
(Urb->Ep.Direction == Direction)) {
RemoveEntryList (&Urb->UrbList);
FreePool (Urb->Data);
- FreePool (Urb);
+ XhcFreeUrb (Xhc, Urb);
return EFI_SUCCESS;
}
}
@@ -1186,7 +1316,7 @@ XhciDelAllAsyncIntTransfers (
Urb = EFI_LIST_CONTAINER (Entry, URB, UrbList);
RemoveEntryList (&Urb->UrbList);
FreePool (Urb->Data);
- FreePool (Urb);
+ XhcFreeUrb (Xhc, Urb);
}
}
@@ -1217,6 +1347,60 @@ XhcUpdateAsyncRequest (
}
}
+/**
+ Flush data from PCI controller specific address to mapped system
+ memory address.
+
+ @param Xhc The XHCI device.
+ @param Urb The URB to unmap.
+
+ @retval EFI_SUCCESS Success to flush data to mapped system memory.
+ @retval EFI_DEVICE_ERROR Fail to flush data to mapped system memory.
+
+**/
+EFI_STATUS
+XhcFlushAsyncIntMap (
+ IN USB_XHCI_INSTANCE *Xhc,
+ IN URB *Urb
+ )
+{
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS PhyAddr;
+ EFI_PCI_IO_PROTOCOL_OPERATION MapOp;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ UINTN Len;
+ VOID *Map;
+
+ PciIo = Xhc->PciIo;
+ Len = Urb->DataLen;
+
+ if (Urb->Ep.Direction == EfiUsbDataIn) {
+ MapOp = EfiPciIoOperationBusMasterWrite;
+ } else {
+ MapOp = EfiPciIoOperationBusMasterRead;
+ }
+
+ if (Urb->DataMap != NULL) {
+ Status = PciIo->Unmap (PciIo, Urb->DataMap);
+ if (EFI_ERROR (Status)) {
+ goto ON_ERROR;
+ }
+ }
+
+ Urb->DataMap = NULL;
+
+ Status = PciIo->Map (PciIo, MapOp, Urb->Data, &Len, &PhyAddr, &Map);
+ if (EFI_ERROR (Status) || (Len != Urb->DataLen)) {
+ goto ON_ERROR;
+ }
+
+ Urb->DataPhy = (VOID *) ((UINTN) PhyAddr);
+ Urb->DataMap = Map;
+ return EFI_SUCCESS;
+
+ON_ERROR:
+ return EFI_DEVICE_ERROR;
+}
/**
Interrupt transfer periodic check handler.
@@ -1238,6 +1422,7 @@ XhcMonitorAsyncRequests (
UINT8 *ProcBuf;
URB *Urb;
UINT8 SlotId;
+ EFI_STATUS Status;
EFI_TPL OldTpl;
OldTpl = gBS->RaiseTPL (XHC_TPL);
@@ -1266,6 +1451,15 @@ XhcMonitorAsyncRequests (
}
//
+ // Flush any PCI posted write transactions from a PCI host
+ // bridge to system memory.
+ //
+ Status = XhcFlushAsyncIntMap (Xhc, Urb);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "XhcMonitorAsyncRequests: Fail to Flush AsyncInt Mapped Memeory\n"));
+ }
+
+ //
// Allocate a buffer then copy the transferred data for user.
// If failed to allocate the buffer, update the URB for next
// round of transfer. Ignore the data of this round.
@@ -1378,7 +1572,6 @@ XhcPollPortStatusChange (
} else {
Status = XhcInitializeDeviceSlot64 (Xhc, ParentRouteChart, Port, RouteChart, Speed);
}
- ASSERT_EFI_ERROR (Status);
}
} else if ((PortState->PortStatus & USB_PORT_STAT_CONNECTION) == 0) {
//
@@ -1391,7 +1584,6 @@ XhcPollPortStatusChange (
} else {
Status = XhcDisableSlotCmd64 (Xhc, SlotId);
}
- ASSERT_EFI_ERROR (Status);
}
}
return Status;
@@ -1582,7 +1774,7 @@ XhcSyncTrsRing (
// Toggle PCS maintained by software
//
TrsRing->RingPCS = (TrsRing->RingPCS & BIT0) ? 0 : 1;
- TrsTrb = (TRB_TEMPLATE *)(UINTN)((TrsTrb->Parameter1 | LShiftU64 ((UINT64)TrsTrb->Parameter2, 32)) & ~0x0F);
+ TrsTrb = (TRB_TEMPLATE *) TrsRing->RingSeg0; // Use host address
}
}
@@ -1727,6 +1919,7 @@ XhcInitializeDeviceSlot (
UINT8 SlotId;
UINT8 ParentSlotId;
DEVICE_CONTEXT *ParentDeviceContext;
+ EFI_PHYSICAL_ADDRESS PhyAddr;
ZeroMem (&CmdTrb, sizeof (CMD_TRB_ENABLE_SLOT));
CmdTrb.CycleBit = 1;
@@ -1738,7 +1931,10 @@ XhcInitializeDeviceSlot (
XHC_GENERIC_TIMEOUT,
(TRB_TEMPLATE **) (UINTN) &EvtTrb
);
- ASSERT_EFI_ERROR (Status);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "XhcInitializeDeviceSlot: Enable Slot Failed, Status = %r\n", Status));
+ return Status;
+ }
ASSERT (EvtTrb->SlotId <= Xhc->MaxSlotsEn);
DEBUG ((EFI_D_INFO, "Enable Slot Successfully, The Slot ID = 0x%x\n", EvtTrb->SlotId));
SlotId = (UINT8)EvtTrb->SlotId;
@@ -1754,7 +1950,7 @@ XhcInitializeDeviceSlot (
// 4.3.3 Device Slot Initialization
// 1) Allocate an Input Context data structure (6.2.5) and initialize all fields to '0'.
//
- InputContext = AllocatePages (EFI_SIZE_TO_PAGES (sizeof (INPUT_CONTEXT)));
+ InputContext = UsbHcAllocateMem (Xhc->MemPool, sizeof (INPUT_CONTEXT));
ASSERT (InputContext != NULL);
ASSERT (((UINTN) InputContext & 0x3F) == 0);
ZeroMem (InputContext, sizeof (INPUT_CONTEXT));
@@ -1843,13 +2039,18 @@ XhcInitializeDeviceSlot (
//
// Init the DCS(dequeue cycle state) as the transfer ring's CCS
//
- InputContext->EP[0].PtrLo = XHC_LOW_32BIT (((TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[0])->RingSeg0) | BIT0;
- InputContext->EP[0].PtrHi = XHC_HIGH_32BIT (((TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[0])->RingSeg0);
+ PhyAddr = UsbHcGetPciAddrForHostAddr (
+ Xhc->MemPool,
+ ((TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[0])->RingSeg0,
+ sizeof (TRB_TEMPLATE) * TR_RING_TRB_NUMBER
+ );
+ InputContext->EP[0].PtrLo = XHC_LOW_32BIT (PhyAddr) | BIT0;
+ InputContext->EP[0].PtrHi = XHC_HIGH_32BIT (PhyAddr);
//
// 6) Allocate the Output Device Context data structure (6.2.1) and initialize it to '0'.
//
- OutputContext = AllocatePages (EFI_SIZE_TO_PAGES (sizeof (DEVICE_CONTEXT)));
+ OutputContext = UsbHcAllocateMem (Xhc->MemPool, sizeof (DEVICE_CONTEXT));
ASSERT (OutputContext != NULL);
ASSERT (((UINTN) OutputContext & 0x3F) == 0);
ZeroMem (OutputContext, sizeof (DEVICE_CONTEXT));
@@ -1859,15 +2060,20 @@ XhcInitializeDeviceSlot (
// 7) Load the appropriate (Device Slot ID) entry in the Device Context Base Address Array (5.4.6) with
// a pointer to the Output Device Context data structure (6.2.1).
//
- Xhc->DCBAA[SlotId] = (UINT64) (UINTN) OutputContext;
+ PhyAddr = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, OutputContext, sizeof (DEVICE_CONTEXT));
+ //
+ // Fill DCBAA with PCI device address
+ //
+ Xhc->DCBAA[SlotId] = (UINT64) (UINTN) PhyAddr;
//
// 8) Issue an Address Device Command for the Device Slot, where the command points to the Input
// Context data structure described above.
//
ZeroMem (&CmdTrbAddr, sizeof (CmdTrbAddr));
- CmdTrbAddr.PtrLo = XHC_LOW_32BIT (Xhc->UsbDevContext[SlotId].InputContext);
- CmdTrbAddr.PtrHi = XHC_HIGH_32BIT (Xhc->UsbDevContext[SlotId].InputContext);
+ PhyAddr = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, Xhc->UsbDevContext[SlotId].InputContext, sizeof (INPUT_CONTEXT));
+ CmdTrbAddr.PtrLo = XHC_LOW_32BIT (PhyAddr);
+ CmdTrbAddr.PtrHi = XHC_HIGH_32BIT (PhyAddr);
CmdTrbAddr.CycleBit = 1;
CmdTrbAddr.Type = TRB_TYPE_ADDRESS_DEV;
CmdTrbAddr.SlotId = Xhc->UsbDevContext[SlotId].SlotId;
@@ -1877,12 +2083,11 @@ XhcInitializeDeviceSlot (
XHC_GENERIC_TIMEOUT,
(TRB_TEMPLATE **) (UINTN) &EvtTrb
);
- ASSERT (!EFI_ERROR(Status));
-
- DeviceAddress = (UINT8) ((DEVICE_CONTEXT *) OutputContext)->Slot.DeviceAddress;
- DEBUG ((EFI_D_INFO, " Address %d assigned successfully\n", DeviceAddress));
-
- Xhc->UsbDevContext[SlotId].XhciDevAddr = DeviceAddress;
+ if (!EFI_ERROR (Status)) {
+ DeviceAddress = (UINT8) ((DEVICE_CONTEXT *) OutputContext)->Slot.DeviceAddress;
+ DEBUG ((EFI_D_INFO, " Address %d assigned successfully\n", DeviceAddress));
+ Xhc->UsbDevContext[SlotId].XhciDevAddr = DeviceAddress;
+ }
return Status;
}
@@ -1920,6 +2125,7 @@ XhcInitializeDeviceSlot64 (
UINT8 SlotId;
UINT8 ParentSlotId;
DEVICE_CONTEXT_64 *ParentDeviceContext;
+ EFI_PHYSICAL_ADDRESS PhyAddr;
ZeroMem (&CmdTrb, sizeof (CMD_TRB_ENABLE_SLOT));
CmdTrb.CycleBit = 1;
@@ -1931,7 +2137,10 @@ XhcInitializeDeviceSlot64 (
XHC_GENERIC_TIMEOUT,
(TRB_TEMPLATE **) (UINTN) &EvtTrb
);
- ASSERT_EFI_ERROR (Status);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "XhcInitializeDeviceSlot64: Enable Slot Failed, Status = %r\n", Status));
+ return Status;
+ }
ASSERT (EvtTrb->SlotId <= Xhc->MaxSlotsEn);
DEBUG ((EFI_D_INFO, "Enable Slot Successfully, The Slot ID = 0x%x\n", EvtTrb->SlotId));
SlotId = (UINT8)EvtTrb->SlotId;
@@ -1947,7 +2156,7 @@ XhcInitializeDeviceSlot64 (
// 4.3.3 Device Slot Initialization
// 1) Allocate an Input Context data structure (6.2.5) and initialize all fields to '0'.
//
- InputContext = AllocatePages (EFI_SIZE_TO_PAGES (sizeof (INPUT_CONTEXT_64)));
+ InputContext = UsbHcAllocateMem (Xhc->MemPool, sizeof (INPUT_CONTEXT_64));
ASSERT (InputContext != NULL);
ASSERT (((UINTN) InputContext & 0x3F) == 0);
ZeroMem (InputContext, sizeof (INPUT_CONTEXT_64));
@@ -2036,13 +2245,18 @@ XhcInitializeDeviceSlot64 (
//
// Init the DCS(dequeue cycle state) as the transfer ring's CCS
//
- InputContext->EP[0].PtrLo = XHC_LOW_32BIT (((TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[0])->RingSeg0) | BIT0;
- InputContext->EP[0].PtrHi = XHC_HIGH_32BIT (((TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[0])->RingSeg0);
+ PhyAddr = UsbHcGetPciAddrForHostAddr (
+ Xhc->MemPool,
+ ((TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[0])->RingSeg0,
+ sizeof (TRB_TEMPLATE) * TR_RING_TRB_NUMBER
+ );
+ InputContext->EP[0].PtrLo = XHC_LOW_32BIT (PhyAddr) | BIT0;
+ InputContext->EP[0].PtrHi = XHC_HIGH_32BIT (PhyAddr);
//
// 6) Allocate the Output Device Context data structure (6.2.1) and initialize it to '0'.
//
- OutputContext = AllocatePages (EFI_SIZE_TO_PAGES (sizeof (DEVICE_CONTEXT_64)));
+ OutputContext = UsbHcAllocateMem (Xhc->MemPool, sizeof (DEVICE_CONTEXT_64));
ASSERT (OutputContext != NULL);
ASSERT (((UINTN) OutputContext & 0x3F) == 0);
ZeroMem (OutputContext, sizeof (DEVICE_CONTEXT_64));
@@ -2052,15 +2266,20 @@ XhcInitializeDeviceSlot64 (
// 7) Load the appropriate (Device Slot ID) entry in the Device Context Base Address Array (5.4.6) with
// a pointer to the Output Device Context data structure (6.2.1).
//
- Xhc->DCBAA[SlotId] = (UINT64) (UINTN) OutputContext;
+ PhyAddr = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, OutputContext, sizeof (DEVICE_CONTEXT_64));
+ //
+ // Fill DCBAA with PCI device address
+ //
+ Xhc->DCBAA[SlotId] = (UINT64) (UINTN) PhyAddr;
//
// 8) Issue an Address Device Command for the Device Slot, where the command points to the Input
// Context data structure described above.
//
ZeroMem (&CmdTrbAddr, sizeof (CmdTrbAddr));
- CmdTrbAddr.PtrLo = XHC_LOW_32BIT (Xhc->UsbDevContext[SlotId].InputContext);
- CmdTrbAddr.PtrHi = XHC_HIGH_32BIT (Xhc->UsbDevContext[SlotId].InputContext);
+ PhyAddr = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, Xhc->UsbDevContext[SlotId].InputContext, sizeof (INPUT_CONTEXT_64));
+ CmdTrbAddr.PtrLo = XHC_LOW_32BIT (PhyAddr);
+ CmdTrbAddr.PtrHi = XHC_HIGH_32BIT (PhyAddr);
CmdTrbAddr.CycleBit = 1;
CmdTrbAddr.Type = TRB_TYPE_ADDRESS_DEV;
CmdTrbAddr.SlotId = Xhc->UsbDevContext[SlotId].SlotId;
@@ -2070,13 +2289,11 @@ XhcInitializeDeviceSlot64 (
XHC_GENERIC_TIMEOUT,
(TRB_TEMPLATE **) (UINTN) &EvtTrb
);
- ASSERT (!EFI_ERROR(Status));
-
- DeviceAddress = (UINT8) ((DEVICE_CONTEXT_64 *) OutputContext)->Slot.DeviceAddress;
- DEBUG ((EFI_D_INFO, " Address %d assigned successfully\n", DeviceAddress));
-
- Xhc->UsbDevContext[SlotId].XhciDevAddr = DeviceAddress;
-
+ if (!EFI_ERROR (Status)) {
+ DeviceAddress = (UINT8) ((DEVICE_CONTEXT_64 *) OutputContext)->Slot.DeviceAddress;
+ DEBUG ((EFI_D_INFO, " Address %d assigned successfully\n", DeviceAddress));
+ Xhc->UsbDevContext[SlotId].XhciDevAddr = DeviceAddress;
+ }
return Status;
}
@@ -2137,7 +2354,10 @@ XhcDisableSlotCmd (
XHC_GENERIC_TIMEOUT,
(TRB_TEMPLATE **) (UINTN) &EvtTrb
);
- ASSERT_EFI_ERROR(Status);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "XhcDisableSlotCmd: Disable Slot Command Failed, Status = %r\n", Status));
+ return Status;
+ }
//
// Free the slot's device context entry
//
@@ -2150,9 +2370,10 @@ XhcDisableSlotCmd (
if (Xhc->UsbDevContext[SlotId].EndpointTransferRing[Index] != NULL) {
RingSeg = ((TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Index])->RingSeg0;
if (RingSeg != NULL) {
- FreePages (RingSeg, EFI_SIZE_TO_PAGES (sizeof (TRB_TEMPLATE) * TR_RING_TRB_NUMBER));
+ UsbHcFreeMem (Xhc->MemPool, RingSeg, sizeof (TRB_TEMPLATE) * TR_RING_TRB_NUMBER);
}
FreePool (Xhc->UsbDevContext[SlotId].EndpointTransferRing[Index]);
+ Xhc->UsbDevContext[SlotId].EndpointTransferRing[Index] = NULL;
}
}
@@ -2163,11 +2384,11 @@ XhcDisableSlotCmd (
}
if (Xhc->UsbDevContext[SlotId].InputContext != NULL) {
- FreePages (Xhc->UsbDevContext[SlotId].InputContext, EFI_SIZE_TO_PAGES (sizeof (INPUT_CONTEXT)));
+ UsbHcFreeMem (Xhc->MemPool, Xhc->UsbDevContext[SlotId].InputContext, sizeof (INPUT_CONTEXT));
}
if (Xhc->UsbDevContext[SlotId].OutputContext != NULL) {
- FreePages (Xhc->UsbDevContext[SlotId].OutputContext, EFI_SIZE_TO_PAGES (sizeof (DEVICE_CONTEXT)));
+ UsbHcFreeMem (Xhc->MemPool, Xhc->UsbDevContext[SlotId].OutputContext, sizeof (DEVICE_CONTEXT));
}
//
// Doesn't zero the entry because XhcAsyncInterruptTransfer() may be invoked to remove the established
@@ -2236,7 +2457,10 @@ XhcDisableSlotCmd64 (
XHC_GENERIC_TIMEOUT,
(TRB_TEMPLATE **) (UINTN) &EvtTrb
);
- ASSERT_EFI_ERROR(Status);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "XhcDisableSlotCmd: Disable Slot Command Failed, Status = %r\n", Status));
+ return Status;
+ }
//
// Free the slot's device context entry
//
@@ -2249,9 +2473,10 @@ XhcDisableSlotCmd64 (
if (Xhc->UsbDevContext[SlotId].EndpointTransferRing[Index] != NULL) {
RingSeg = ((TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Index])->RingSeg0;
if (RingSeg != NULL) {
- FreePages (RingSeg, EFI_SIZE_TO_PAGES (sizeof (TRB_TEMPLATE) * TR_RING_TRB_NUMBER));
+ UsbHcFreeMem (Xhc->MemPool, RingSeg, sizeof (TRB_TEMPLATE) * TR_RING_TRB_NUMBER);
}
FreePool (Xhc->UsbDevContext[SlotId].EndpointTransferRing[Index]);
+ Xhc->UsbDevContext[SlotId].EndpointTransferRing[Index] = NULL;
}
}
@@ -2262,11 +2487,11 @@ XhcDisableSlotCmd64 (
}
if (Xhc->UsbDevContext[SlotId].InputContext != NULL) {
- FreePages (Xhc->UsbDevContext[SlotId].InputContext, EFI_SIZE_TO_PAGES (sizeof (INPUT_CONTEXT_64)));
+ UsbHcFreeMem (Xhc->MemPool, Xhc->UsbDevContext[SlotId].InputContext, sizeof (INPUT_CONTEXT_64));
}
if (Xhc->UsbDevContext[SlotId].OutputContext != NULL) {
- FreePages (Xhc->UsbDevContext[SlotId].OutputContext, EFI_SIZE_TO_PAGES (sizeof (DEVICE_CONTEXT_64)));
+ UsbHcFreeMem (Xhc->MemPool, Xhc->UsbDevContext[SlotId].OutputContext, sizeof (DEVICE_CONTEXT_64));
}
//
// Doesn't zero the entry because XhcAsyncInterruptTransfer() may be invoked to remove the established
@@ -2301,7 +2526,6 @@ XhcSetConfigCmd (
)
{
EFI_STATUS Status;
-
USB_INTERFACE_DESCRIPTOR *IfDesc;
USB_ENDPOINT_DESCRIPTOR *EpDesc;
UINT8 Index;
@@ -2311,7 +2535,7 @@ XhcSetConfigCmd (
UINT8 Direction;
UINT8 Dci;
UINT8 MaxDci;
- UINT32 PhyAddr;
+ EFI_PHYSICAL_ADDRESS PhyAddr;
UINT8 Interval;
TRANSFER_RING *EndpointTransferRing;
@@ -2438,11 +2662,15 @@ XhcSetConfigCmd (
break;
}
- PhyAddr = XHC_LOW_32BIT (((TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1])->RingSeg0);
+ PhyAddr = UsbHcGetPciAddrForHostAddr (
+ Xhc->MemPool,
+ ((TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1])->RingSeg0,
+ sizeof (TRB_TEMPLATE) * TR_RING_TRB_NUMBER
+ );
PhyAddr &= ~(0x0F);
PhyAddr |= ((TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1])->RingPCS;
- InputContext->EP[Dci-1].PtrLo = PhyAddr;
- InputContext->EP[Dci-1].PtrHi = XHC_HIGH_32BIT (((TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1])->RingSeg0);
+ InputContext->EP[Dci-1].PtrLo = XHC_LOW_32BIT (PhyAddr);
+ InputContext->EP[Dci-1].PtrHi = XHC_HIGH_32BIT (PhyAddr);
EpDesc = (USB_ENDPOINT_DESCRIPTOR *)((UINTN)EpDesc + EpDesc->Length);
}
@@ -2455,8 +2683,9 @@ XhcSetConfigCmd (
// configure endpoint
//
ZeroMem (&CmdTrbCfgEP, sizeof (CmdTrbCfgEP));
- CmdTrbCfgEP.PtrLo = XHC_LOW_32BIT (InputContext);
- CmdTrbCfgEP.PtrHi = XHC_HIGH_32BIT (InputContext);
+ PhyAddr = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, InputContext, sizeof (INPUT_CONTEXT));
+ CmdTrbCfgEP.PtrLo = XHC_LOW_32BIT (PhyAddr);
+ CmdTrbCfgEP.PtrHi = XHC_HIGH_32BIT (PhyAddr);
CmdTrbCfgEP.CycleBit = 1;
CmdTrbCfgEP.Type = TRB_TYPE_CON_ENDPOINT;
CmdTrbCfgEP.SlotId = Xhc->UsbDevContext[SlotId].SlotId;
@@ -2467,8 +2696,9 @@ XhcSetConfigCmd (
XHC_GENERIC_TIMEOUT,
(TRB_TEMPLATE **) (UINTN) &EvtTrb
);
- ASSERT_EFI_ERROR(Status);
-
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "XhcSetConfigCmd: Config Endpoint Failed, Status = %r\n", Status));
+ }
return Status;
}
@@ -2493,7 +2723,6 @@ XhcSetConfigCmd64 (
)
{
EFI_STATUS Status;
-
USB_INTERFACE_DESCRIPTOR *IfDesc;
USB_ENDPOINT_DESCRIPTOR *EpDesc;
UINT8 Index;
@@ -2503,7 +2732,7 @@ XhcSetConfigCmd64 (
UINT8 Direction;
UINT8 Dci;
UINT8 MaxDci;
- UINT32 PhyAddr;
+ EFI_PHYSICAL_ADDRESS PhyAddr;
UINT8 Interval;
TRANSFER_RING *EndpointTransferRing;
@@ -2630,11 +2859,17 @@ XhcSetConfigCmd64 (
break;
}
- PhyAddr = XHC_LOW_32BIT (((TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1])->RingSeg0);
+ PhyAddr = UsbHcGetPciAddrForHostAddr (
+ Xhc->MemPool,
+ ((TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1])->RingSeg0,
+ sizeof (TRB_TEMPLATE) * TR_RING_TRB_NUMBER
+ );
+
PhyAddr &= ~(0x0F);
PhyAddr |= ((TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1])->RingPCS;
- InputContext->EP[Dci-1].PtrLo = PhyAddr;
- InputContext->EP[Dci-1].PtrHi = XHC_HIGH_32BIT (((TRANSFER_RING *)(UINTN)Xhc->UsbDevContext[SlotId].EndpointTransferRing[Dci-1])->RingSeg0);
+
+ InputContext->EP[Dci-1].PtrLo = XHC_LOW_32BIT (PhyAddr);
+ InputContext->EP[Dci-1].PtrHi = XHC_HIGH_32BIT (PhyAddr);
EpDesc = (USB_ENDPOINT_DESCRIPTOR *)((UINTN)EpDesc + EpDesc->Length);
}
@@ -2647,8 +2882,9 @@ XhcSetConfigCmd64 (
// configure endpoint
//
ZeroMem (&CmdTrbCfgEP, sizeof (CmdTrbCfgEP));
- CmdTrbCfgEP.PtrLo = XHC_LOW_32BIT (InputContext);
- CmdTrbCfgEP.PtrHi = XHC_HIGH_32BIT (InputContext);
+ PhyAddr = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, InputContext, sizeof (INPUT_CONTEXT_64));
+ CmdTrbCfgEP.PtrLo = XHC_LOW_32BIT (PhyAddr);
+ CmdTrbCfgEP.PtrHi = XHC_HIGH_32BIT (PhyAddr);
CmdTrbCfgEP.CycleBit = 1;
CmdTrbCfgEP.Type = TRB_TYPE_CON_ENDPOINT;
CmdTrbCfgEP.SlotId = Xhc->UsbDevContext[SlotId].SlotId;
@@ -2659,7 +2895,9 @@ XhcSetConfigCmd64 (
XHC_GENERIC_TIMEOUT,
(TRB_TEMPLATE **) (UINTN) &EvtTrb
);
- ASSERT_EFI_ERROR(Status);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "XhcSetConfigCmd64: Config Endpoint Failed, Status = %r\n", Status));
+ }
return Status;
}
@@ -2687,6 +2925,7 @@ XhcEvaluateContext (
CMD_TRB_EVALUATE_CONTEXT CmdTrbEvalu;
EVT_TRB_COMMAND_COMPLETION *EvtTrb;
INPUT_CONTEXT *InputContext;
+ EFI_PHYSICAL_ADDRESS PhyAddr;
ASSERT (Xhc->UsbDevContext[SlotId].SlotId != 0);
@@ -2700,8 +2939,9 @@ XhcEvaluateContext (
InputContext->EP[0].MaxPacketSize = MaxPacketSize;
ZeroMem (&CmdTrbEvalu, sizeof (CmdTrbEvalu));
- CmdTrbEvalu.PtrLo = XHC_LOW_32BIT (InputContext);
- CmdTrbEvalu.PtrHi = XHC_HIGH_32BIT (InputContext);
+ PhyAddr = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, InputContext, sizeof (INPUT_CONTEXT));
+ CmdTrbEvalu.PtrLo = XHC_LOW_32BIT (PhyAddr);
+ CmdTrbEvalu.PtrHi = XHC_HIGH_32BIT (PhyAddr);
CmdTrbEvalu.CycleBit = 1;
CmdTrbEvalu.Type = TRB_TYPE_EVALU_CONTXT;
CmdTrbEvalu.SlotId = Xhc->UsbDevContext[SlotId].SlotId;
@@ -2712,8 +2952,9 @@ XhcEvaluateContext (
XHC_GENERIC_TIMEOUT,
(TRB_TEMPLATE **) (UINTN) &EvtTrb
);
- ASSERT (!EFI_ERROR(Status));
-
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "XhcEvaluateContext: Evaluate Context Failed, Status = %r\n", Status));
+ }
return Status;
}
@@ -2739,6 +2980,7 @@ XhcEvaluateContext64 (
CMD_TRB_EVALUATE_CONTEXT CmdTrbEvalu;
EVT_TRB_COMMAND_COMPLETION *EvtTrb;
INPUT_CONTEXT_64 *InputContext;
+ EFI_PHYSICAL_ADDRESS PhyAddr;
ASSERT (Xhc->UsbDevContext[SlotId].SlotId != 0);
@@ -2752,8 +2994,9 @@ XhcEvaluateContext64 (
InputContext->EP[0].MaxPacketSize = MaxPacketSize;
ZeroMem (&CmdTrbEvalu, sizeof (CmdTrbEvalu));
- CmdTrbEvalu.PtrLo = XHC_LOW_32BIT (InputContext);
- CmdTrbEvalu.PtrHi = XHC_HIGH_32BIT (InputContext);
+ PhyAddr = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, InputContext, sizeof (INPUT_CONTEXT_64));
+ CmdTrbEvalu.PtrLo = XHC_LOW_32BIT (PhyAddr);
+ CmdTrbEvalu.PtrHi = XHC_HIGH_32BIT (PhyAddr);
CmdTrbEvalu.CycleBit = 1;
CmdTrbEvalu.Type = TRB_TYPE_EVALU_CONTXT;
CmdTrbEvalu.SlotId = Xhc->UsbDevContext[SlotId].SlotId;
@@ -2764,8 +3007,9 @@ XhcEvaluateContext64 (
XHC_GENERIC_TIMEOUT,
(TRB_TEMPLATE **) (UINTN) &EvtTrb
);
- ASSERT (!EFI_ERROR(Status));
-
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "XhcEvaluateContext64: Evaluate Context Failed, Status = %r\n", Status));
+ }
return Status;
}
@@ -2792,11 +3036,11 @@ XhcConfigHubContext (
)
{
EFI_STATUS Status;
-
EVT_TRB_COMMAND_COMPLETION *EvtTrb;
INPUT_CONTEXT *InputContext;
DEVICE_CONTEXT *OutputContext;
CMD_TRB_CONFIG_ENDPOINT CmdTrbCfgEP;
+ EFI_PHYSICAL_ADDRESS PhyAddr;
ASSERT (Xhc->UsbDevContext[SlotId].SlotId != 0);
InputContext = Xhc->UsbDevContext[SlotId].InputContext;
@@ -2819,8 +3063,9 @@ XhcConfigHubContext (
InputContext->Slot.MTT = MTT;
ZeroMem (&CmdTrbCfgEP, sizeof (CmdTrbCfgEP));
- CmdTrbCfgEP.PtrLo = XHC_LOW_32BIT (InputContext);
- CmdTrbCfgEP.PtrHi = XHC_HIGH_32BIT (InputContext);
+ PhyAddr = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, InputContext, sizeof (INPUT_CONTEXT));
+ CmdTrbCfgEP.PtrLo = XHC_LOW_32BIT (PhyAddr);
+ CmdTrbCfgEP.PtrHi = XHC_HIGH_32BIT (PhyAddr);
CmdTrbCfgEP.CycleBit = 1;
CmdTrbCfgEP.Type = TRB_TYPE_CON_ENDPOINT;
CmdTrbCfgEP.SlotId = Xhc->UsbDevContext[SlotId].SlotId;
@@ -2831,8 +3076,9 @@ XhcConfigHubContext (
XHC_GENERIC_TIMEOUT,
(TRB_TEMPLATE **) (UINTN) &EvtTrb
);
- ASSERT (!EFI_ERROR(Status));
-
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "XhcConfigHubContext: Config Endpoint Failed, Status = %r\n", Status));
+ }
return Status;
}
@@ -2858,11 +3104,11 @@ XhcConfigHubContext64 (
)
{
EFI_STATUS Status;
-
EVT_TRB_COMMAND_COMPLETION *EvtTrb;
INPUT_CONTEXT_64 *InputContext;
DEVICE_CONTEXT_64 *OutputContext;
CMD_TRB_CONFIG_ENDPOINT CmdTrbCfgEP;
+ EFI_PHYSICAL_ADDRESS PhyAddr;
ASSERT (Xhc->UsbDevContext[SlotId].SlotId != 0);
InputContext = Xhc->UsbDevContext[SlotId].InputContext;
@@ -2885,8 +3131,9 @@ XhcConfigHubContext64 (
InputContext->Slot.MTT = MTT;
ZeroMem (&CmdTrbCfgEP, sizeof (CmdTrbCfgEP));
- CmdTrbCfgEP.PtrLo = XHC_LOW_32BIT (InputContext);
- CmdTrbCfgEP.PtrHi = XHC_HIGH_32BIT (InputContext);
+ PhyAddr = UsbHcGetPciAddrForHostAddr (Xhc->MemPool, InputContext, sizeof (INPUT_CONTEXT_64));
+ CmdTrbCfgEP.PtrLo = XHC_LOW_32BIT (PhyAddr);
+ CmdTrbCfgEP.PtrHi = XHC_HIGH_32BIT (PhyAddr);
CmdTrbCfgEP.CycleBit = 1;
CmdTrbCfgEP.Type = TRB_TYPE_CON_ENDPOINT;
CmdTrbCfgEP.SlotId = Xhc->UsbDevContext[SlotId].SlotId;
@@ -2897,8 +3144,9 @@ XhcConfigHubContext64 (
XHC_GENERIC_TIMEOUT,
(TRB_TEMPLATE **) (UINTN) &EvtTrb
);
- ASSERT (!EFI_ERROR(Status));
-
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "XhcConfigHubContext64: Config Endpoint Failed, Status = %r\n", Status));
+ }
return Status;
}
diff --git a/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.h b/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.h
index 227b45523..fa8bab43f 100644
--- a/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.h
+++ b/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.h
@@ -2,7 +2,7 @@
This file contains the definition for XHCI host controller schedule routines.
-Copyright (c) 2011 - 2012, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2011 - 2013, Intel Corporation. All rights reserved.<BR>
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
@@ -172,6 +172,8 @@ typedef struct _URB {
EFI_USB_DEVICE_REQUEST *Request;
VOID *Data;
UINTN DataLen;
+ VOID *DataPhy;
+ VOID *DataMap;
EFI_ASYNC_USB_TRANSFER_CALLBACK Callback;
VOID *Context;
//
@@ -1306,6 +1308,19 @@ XhcCreateUrb (
);
/**
+ Free an allocated URB.
+
+ @param Xhc The XHCI device.
+ @param Urb The URB to free.
+
+**/
+VOID
+XhcFreeUrb (
+ IN USB_XHCI_INSTANCE *Xhc,
+ IN URB *Urb
+ );
+
+/**
Create a transfer TRB.
@param Xhc The XHCI Instance
diff --git a/MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBus.c b/MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBus.c
index a0833cfaf..3e49ffba6 100644
--- a/MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBus.c
+++ b/MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBus.c
@@ -2,7 +2,7 @@
SCSI Bus driver that layers on every SCSI Pass Thru and
Extended SCSI Pass Thru protocol in the system.
-Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
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
@@ -1293,7 +1293,7 @@ DiscoverScsiDevice (
for (Index = 0; Index < MaxRetry; Index++) {
Status = ScsiInquiryCommand (
&ScsiIoDevice->ScsiIo,
- EFI_TIMER_PERIOD_SECONDS (1),
+ SCSI_BUS_TIMEOUT,
NULL,
&SenseDataLength,
&HostAdapterStatus,
diff --git a/MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBus.h b/MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBus.h
index ed90a6d45..babf86f2c 100644
--- a/MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBus.h
+++ b/MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBus.h
@@ -1,7 +1,7 @@
/** @file
Header file for SCSI Bus Driver.
-Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
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
@@ -61,6 +61,11 @@ typedef struct {
#define SCSI_BUS_DEVICE_SIGNATURE SIGNATURE_32 ('s', 'c', 's', 'i')
//
+// SCSI Bus Timeout Experience Value
+//
+#define SCSI_BUS_TIMEOUT EFI_TIMER_PERIOD_SECONDS (3)
+
+//
// The ScsiBusProtocol is just used to locate ScsiBusDev
// structure in the SCSIBusDriverBindingStop(). Then we can
// Close all opened protocols and release this structure.
diff --git a/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.c b/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.c
index c6d96caeb..223dd4c47 100644
--- a/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.c
+++ b/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.c
@@ -1,7 +1,7 @@
/** @file
SCSI disk driver that layers on every SCSI IO protocol in the system.
-Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
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
@@ -957,7 +957,7 @@ ScsiDiskInquiryDevice (
Status = ScsiInquiryCommand (
ScsiDiskDevice->ScsiIo,
- EFI_TIMER_PERIOD_SECONDS (1),
+ SCSI_DISK_TIMEOUT,
NULL,
&SenseDataLength,
&HostAdapterStatus,
@@ -986,7 +986,7 @@ ScsiDiskInquiryDevice (
SenseDataLength = 0;
Status = ScsiInquiryCommandEx (
ScsiDiskDevice->ScsiIo,
- EFI_TIMER_PERIOD_SECONDS (1),
+ SCSI_DISK_TIMEOUT,
NULL,
&SenseDataLength,
&HostAdapterStatus,
@@ -1020,7 +1020,7 @@ ScsiDiskInquiryDevice (
SenseDataLength = 0;
Status = ScsiInquiryCommandEx (
ScsiDiskDevice->ScsiIo,
- EFI_TIMER_PERIOD_SECONDS (1),
+ SCSI_DISK_TIMEOUT,
NULL,
&SenseDataLength,
&HostAdapterStatus,
@@ -1157,7 +1157,7 @@ ScsiDiskTestUnitReady (
//
Status = ScsiTestUnitReadyCommand (
ScsiDiskDevice->ScsiIo,
- EFI_TIMER_PERIOD_SECONDS (1),
+ SCSI_DISK_TIMEOUT,
NULL,
&SenseDataLength,
&HostAdapterStatus,
@@ -1376,7 +1376,7 @@ ScsiDiskReadCapacity (
//
CommandStatus = ScsiReadCapacityCommand (
ScsiDiskDevice->ScsiIo,
- EFI_TIMER_PERIOD_SECONDS(1),
+ SCSI_DISK_TIMEOUT,
NULL,
&SenseDataLength,
&HostAdapterStatus,
@@ -1399,7 +1399,7 @@ ScsiDiskReadCapacity (
//
CommandStatus = ScsiReadCapacity16Command (
ScsiDiskDevice->ScsiIo,
- EFI_TIMER_PERIOD_SECONDS (1),
+ SCSI_DISK_TIMEOUT,
NULL,
&SenseDataLength,
&HostAdapterStatus,
@@ -1623,7 +1623,7 @@ ScsiDiskRequestSenseKeys (
for (SenseReq = TRUE; SenseReq;) {
Status = ScsiRequestSenseCommand (
ScsiDiskDevice->ScsiIo,
- EFI_TIMER_PERIOD_SECONDS (2),
+ SCSI_DISK_TIMEOUT,
PtrSenseData,
&SenseDataLength,
&HostAdapterStatus,
@@ -1843,8 +1843,11 @@ ScsiDiskReadSectors (
// As ScsiDisk and ScsiBus driver are used to manage SCSI or ATAPI devices, we have to use
// the lowest transfer rate to calculate the possible maximum timeout value for each operation.
// From the above table, we could know 2.1Mbytes per second is lowest one.
+ // The timout value is rounded up to nearest integar and here an additional 30s is added
+ // to follow ATA spec in which it mentioned that the device may take up to 30s to respond
+ // commands in the Standby/Idle mode.
//
- Timeout = EFI_TIMER_PERIOD_SECONDS (ByteCount / 2100000 + 1);
+ Timeout = EFI_TIMER_PERIOD_SECONDS (ByteCount / 2100000 + 31);
MaxRetry = 2;
for (Index = 0; Index < MaxRetry; Index++) {
@@ -1994,8 +1997,11 @@ ScsiDiskWriteSectors (
// As ScsiDisk and ScsiBus driver are used to manage SCSI or ATAPI devices, we have to use
// the lowest transfer rate to calculate the possible maximum timeout value for each operation.
// From the above table, we could know 2.1Mbytes per second is lowest one.
+ // The timout value is rounded up to nearest integar and here an additional 30s is added
+ // to follow ATA spec in which it mentioned that the device may take up to 30s to respond
+ // commands in the Standby/Idle mode.
//
- Timeout = EFI_TIMER_PERIOD_SECONDS (ByteCount / 2100000 + 1);
+ Timeout = EFI_TIMER_PERIOD_SECONDS (ByteCount / 2100000 + 31);
MaxRetry = 2;
for (Index = 0; Index < MaxRetry; Index++) {
if (!ScsiDiskDevice->Cdb16Byte) {
@@ -2925,7 +2931,7 @@ AtapiIdentifyDevice (
ZeroMem (Cdb, sizeof (Cdb));
Cdb[0] = ATA_CMD_IDENTIFY_DEVICE;
- CommandPacket.Timeout = EFI_TIMER_PERIOD_SECONDS (1);
+ CommandPacket.Timeout = SCSI_DISK_TIMEOUT;
CommandPacket.Cdb = Cdb;
CommandPacket.CdbLength = (UINT8) sizeof (Cdb);
CommandPacket.InDataBuffer = &ScsiDiskDevice->IdentifyData;
diff --git a/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.h b/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.h
index fc966b36a..21dcbd32d 100644
--- a/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.h
+++ b/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.h
@@ -1,7 +1,7 @@
/** @file
Header file for SCSI Disk Driver.
-Copyright (c) 2004 - 2011, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2004 - 2013, Intel Corporation. All rights reserved.<BR>
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
@@ -98,6 +98,10 @@ extern EFI_COMPONENT_NAME2_PROTOCOL gScsiDiskComponentName2;
#define SCSI_COMMAND_VERSION_2 0x02
#define SCSI_COMMAND_VERSION_3 0x03
+//
+// SCSI Disk Timeout Experience Value
+//
+#define SCSI_DISK_TIMEOUT EFI_TIMER_PERIOD_SECONDS (3)
/**
Test to see if this driver supports ControllerHandle.
diff --git a/MdeModulePkg/Bus/Usb/UsbBusPei/UsbIoPeim.c b/MdeModulePkg/Bus/Usb/UsbBusPei/UsbIoPeim.c
index 897b22896..e647cc46d 100644
--- a/MdeModulePkg/Bus/Usb/UsbBusPei/UsbIoPeim.c
+++ b/MdeModulePkg/Bus/Usb/UsbBusPei/UsbIoPeim.c
@@ -1,7 +1,7 @@
/** @file
The module is used to implement Usb Io PPI interfaces.
-Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved. <BR>
+Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved. <BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions
@@ -24,7 +24,9 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
@param This The pointer of PEI_USB_IO_PPI.
@param Request USB device request to send.
@param Direction Specifies the data direction for the data stage.
- @param Timeout Indicates the maximum timeout, in millisecond.
+ @param Timeout Indicates the maximum timeout, in millisecond. If Timeout
+ is 0, then the caller must wait for the function to be
+ completed until EFI_SUCCESS or EFI_DEVICE_ERROR is returned.
@param Data Data buffer to be transmitted or received from USB device.
@param DataLength The size (in bytes) of the data buffer.
@@ -96,7 +98,9 @@ PeiUsbControlTransfer (
from or receive into.
@param DataLength The lenght of the data buffer.
@param Timeout Indicates the maximum time, in millisecond, which the
- transfer is allowed to complete.
+ transfer is allowed to complete. If Timeout is 0, then
+ the caller must wait for the function to be completed
+ until EFI_SUCCESS or EFI_DEVICE_ERROR is returned.
@retval EFI_SUCCESS The transfer was completed successfully.
@retval EFI_OUT_OF_RESOURCES The transfer failed due to lack of resource.
diff --git a/MdeModulePkg/Bus/Usb/UsbBusPei/UsbPeim.h b/MdeModulePkg/Bus/Usb/UsbBusPei/UsbPeim.h
index c9e75bad5..336a6373a 100644
--- a/MdeModulePkg/Bus/Usb/UsbBusPei/UsbPeim.h
+++ b/MdeModulePkg/Bus/Usb/UsbBusPei/UsbPeim.h
@@ -1,7 +1,7 @@
/** @file
Usb Peim definition.
-Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved. <BR>
+Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved. <BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions
@@ -71,7 +71,9 @@ typedef struct {
@param This The pointer of PEI_USB_IO_PPI.
@param Request USB device request to send.
@param Direction Specifies the data direction for the data stage.
- @param Timeout Indicates the maximum timeout, in millisecond.
+ @param Timeout Indicates the maximum timeout, in millisecond. If Timeout
+ is 0, then the caller must wait for the function to be
+ completed until EFI_SUCCESS or EFI_DEVICE_ERROR is returned.
@param Data Data buffer to be transmitted or received from USB device.
@param DataLength The size (in bytes) of the data buffer.
@@ -104,7 +106,9 @@ PeiUsbControlTransfer (
from or receive into.
@param DataLength The lenght of the data buffer.
@param Timeout Indicates the maximum time, in millisecond, which the
- transfer is allowed to complete.
+ transfer is allowed to complete. If Timeout is 0, then
+ the caller must wait for the function to be completed
+ until EFI_SUCCESS or EFI_DEVICE_ERROR is returned.
@retval EFI_SUCCESS The transfer was completed successfully.
@retval EFI_OUT_OF_RESOURCES The transfer failed due to lack of resource.
diff --git a/MdeModulePkg/Core/Dxe/DxeMain.h b/MdeModulePkg/Core/Dxe/DxeMain.h
index 79e6517e3..1e057a5d9 100644
--- a/MdeModulePkg/Core/Dxe/DxeMain.h
+++ b/MdeModulePkg/Core/Dxe/DxeMain.h
@@ -2,7 +2,7 @@
The internal header file includes the common header files, defines
internal structure and functions used by DxeCore module.
-Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
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
@@ -673,8 +673,12 @@ CoreInstallProtocolInterfaceNotify (
arguments to InstallProtocolInterface(). All the
protocols are added to Handle.
+ @retval EFI_SUCCESS All the protocol interface was installed.
+ @retval EFI_OUT_OF_RESOURCES There was not enough memory in pool to install all the protocols.
+ @retval EFI_ALREADY_STARTED A Device Path Protocol instance was passed in that is already present in
+ the handle database.
@retval EFI_INVALID_PARAMETER Handle is NULL.
- @retval EFI_SUCCESS Protocol interfaces successfully installed.
+ @retval EFI_INVALID_PARAMETER Protocol is already installed on the handle specified by Handle.
**/
EFI_STATUS
diff --git a/MdeModulePkg/Core/Dxe/Hand/Handle.c b/MdeModulePkg/Core/Dxe/Hand/Handle.c
index 6708ef872..1c2552167 100644
--- a/MdeModulePkg/Core/Dxe/Hand/Handle.c
+++ b/MdeModulePkg/Core/Dxe/Hand/Handle.c
@@ -1,7 +1,7 @@
/** @file
UEFI handle & protocol handling.
-Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
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
@@ -513,8 +513,12 @@ Done:
arguments to InstallProtocolInterface(). All the
protocols are added to Handle.
+ @retval EFI_SUCCESS All the protocol interface was installed.
+ @retval EFI_OUT_OF_RESOURCES There was not enough memory in pool to install all the protocols.
+ @retval EFI_ALREADY_STARTED A Device Path Protocol instance was passed in that is already present in
+ the handle database.
@retval EFI_INVALID_PARAMETER Handle is NULL.
- @retval EFI_SUCCESS Protocol interfaces successfully installed.
+ @retval EFI_INVALID_PARAMETER Protocol is already installed on the handle specified by Handle.
**/
EFI_STATUS
diff --git a/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf b/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf
index f39251f3c..986250bdc 100644
--- a/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf
+++ b/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf
@@ -28,7 +28,7 @@
#
# The following information is for reference only and not required by the build tools.
#
-# VALID_ARCHITECTURES = IA32 X64 IPF EBC (EBC is for build only)
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC (EBC is for build only) AARCH64
#
[Sources]
@@ -53,7 +53,7 @@
[Sources.EBC]
Ebc/DxeLoadFunc.c
-[Sources.ARM]
+[Sources.ARM, Sources.AARCH64]
Arm/DxeLoadFunc.c
[Packages]
diff --git a/MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c b/MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c
index 0392cfe1e..2063fa4db 100644
--- a/MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c
+++ b/MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c
@@ -1,7 +1,7 @@
/** @file
EFI PEI Core dispatch services
-Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
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
@@ -305,7 +305,7 @@ PeiLoadFixAddressHook(
//
// If range described in this hob is not system memory or heigher than MAX_ADDRESS, ignored.
//
- if (ResourceHob->ResourceType != EFI_RESOURCE_SYSTEM_MEMORY &&
+ if (ResourceHob->ResourceType != EFI_RESOURCE_SYSTEM_MEMORY ||
ResourceHob->PhysicalStart + ResourceHob->ResourceLength > MAX_ADDRESS) {
continue;
}
@@ -375,7 +375,7 @@ PeiLoadFixAddressHook(
//
// If range described in this hob is not system memory or heigher than MAX_ADDRESS, ignored.
//
- if (NextResourceHob->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY && NextResourceHob->PhysicalStart + NextResourceHob->ResourceLength > MAX_ADDRESS) {
+ if (NextResourceHob->ResourceType != EFI_RESOURCE_SYSTEM_MEMORY || NextResourceHob->PhysicalStart + NextResourceHob->ResourceLength > MAX_ADDRESS) {
continue;
}
//
diff --git a/MdeModulePkg/Include/Guid/FaultTolerantWrite.h b/MdeModulePkg/Include/Guid/FaultTolerantWrite.h
new file mode 100644
index 000000000..cb7b454b2
--- /dev/null
+++ b/MdeModulePkg/Include/Guid/FaultTolerantWrite.h
@@ -0,0 +1,54 @@
+/** @file
+ Define the GUID gEdkiiFaultTolerantWriteGuid that will be used to build
+ FAULT_TOLERANT_WRITE_LAST_WRITE_DATA GUID hob and install PPI to inform the check
+ for FTW last write data has been done. The GUID hob will be only built if FTW last write was
+ still in progress with SpareComplete set and DestinationComplete not set.
+
+Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that 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 _FAULT_TOLERANT_WRITE_H_
+#define _FAULT_TOLERANT_WRITE_H_
+
+#define EDKII_FAULT_TOLERANT_WRITE_GUID \
+ { \
+ 0x1d3e9cb8, 0x43af, 0x490b, { 0x83, 0xa, 0x35, 0x16, 0xaa, 0x53, 0x20, 0x47 } \
+ }
+
+//
+// FTW Last write data. It will be used as gEdkiiFaultTolerantWriteGuid GUID hob data.
+//
+typedef struct {
+ ///
+ /// Target address to be updated in FTW last write.
+ ///
+ EFI_PHYSICAL_ADDRESS TargetAddress;
+ ///
+ /// Spare address to back up the updated buffer.
+ ///
+ EFI_PHYSICAL_ADDRESS SpareAddress;
+ ///
+ /// The length of data that have been backed up in spare block.
+ /// It is also the length of target block that has been erased.
+ ///
+ UINT64 Length;
+} FAULT_TOLERANT_WRITE_LAST_WRITE_DATA;
+
+//
+// This GUID will be used to install PPI to inform the check for FTW last write data has been done.
+// The related FAULT_TOLERANT_WRITE_LAST_WRITE_DATA GUID hob will be only built if
+// FTW last write was still in progress with SpareComplete set and DestinationComplete not set.
+// It means the target buffer has been backed up in spare block, then target block has been erased,
+// but the target buffer has not been writen in target block from spare block.
+//
+extern EFI_GUID gEdkiiFaultTolerantWriteGuid;
+
+#endif
diff --git a/MdeModulePkg/Include/Guid/SystemNvDataGuid.h b/MdeModulePkg/Include/Guid/SystemNvDataGuid.h
index 4e2188835..40446bcc1 100644
--- a/MdeModulePkg/Include/Guid/SystemNvDataGuid.h
+++ b/MdeModulePkg/Include/Guid/SystemNvDataGuid.h
@@ -1,10 +1,10 @@
/** @file
- This file defines NvDataFv GUID and FTW working block structure header.
- This guid can be used as FileSystemGuid in EFI_FIRMWARE_VOLUME_HEADER if
+ This file defines NvDataFv GUID and FTW working block structures.
+ The NvDataFv GUID can be used as FileSystemGuid in EFI_FIRMWARE_VOLUME_HEADER if
this FV image contains NV data, such as NV variable data.
- This guid can also be used as the signature of FTW working block header.
+ This file also defines WorkingBlockSignature GUID for FTW working block signature.
-Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials are licensed and made available under
the terms and conditions of the BSD License that accompanies this distribution.
The full text of the license may be found at
@@ -21,10 +21,11 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#define EFI_SYSTEM_NV_DATA_FV_GUID \
{0xfff12b8d, 0x7696, 0x4c8b, {0xa9, 0x85, 0x27, 0x47, 0x7, 0x5b, 0x4f, 0x50} }
-///
-/// An NvDataFv GUID used as the signature of FTW working block header.
-///
+#define EDKII_WORKING_BLOCK_SIGNATURE_GUID \
+ {0x9e58292b, 0x7c68, 0x497d, {0xa0, 0xce, 0x65, 0x0, 0xfd, 0x9f, 0x1b, 0x95} }
+
extern EFI_GUID gEfiSystemNvDataFvGuid;
+extern EFI_GUID gEdkiiWorkingBlockSignatureGuid;
#define WORKING_BLOCK_VALID 0x1
#define WORKING_BLOCK_INVALID 0x2
@@ -35,7 +36,9 @@ extern EFI_GUID gEfiSystemNvDataFvGuid;
///
typedef struct {
///
- /// System Non Volatile FV Guid.
+ /// FTW working block signature.
+ /// Its value has be updated from gEfiSystemNvDataFvGuid to gEdkiiWorkingBlockSignatureGuid,
+ /// because its write queue data format has been updated to support the crossing archs.
///
EFI_GUID Signature;
///
@@ -55,8 +58,60 @@ typedef struct {
UINT64 WriteQueueSize;
///
/// Write Queue data.
- /// UINT8 WriteQueue[WriteQueueSize];
+ ///
+ /// EFI_FAULT_TOLERANT_WRITE_HEADER FtwHeader;
+ /// EFI_FAULT_TOLERANT_WRITE_RECORD FtwRecord[FtwHeader.NumberOfWrites]
+ /// EFI_FAULT_TOLERANT_WRITE_HEADER FtwHeader2;
+ /// EFI_FAULT_TOLERANT_WRITE_RECORD FtwRecord2[FtwHeader2.NumberOfWrites]
+ /// ...
///
} EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER;
+#define FTW_VALID_STATE 0
+#define FTW_INVALID_STATE 1
+
+//
+// EFI Fault tolerant block update write queue entry.
+//
+typedef struct {
+ UINT8 HeaderAllocated : 1;
+ UINT8 WritesAllocated : 1;
+ UINT8 Complete : 1;
+ UINT8 Reserved : 5;
+ EFI_GUID CallerId;
+ UINT64 NumberOfWrites;
+ UINT64 PrivateDataSize;
+} EFI_FAULT_TOLERANT_WRITE_HEADER;
+
+//
+// EFI Fault tolerant block update write queue record.
+//
+typedef struct {
+ UINT8 BootBlockUpdate : 1;
+ UINT8 SpareComplete : 1;
+ UINT8 DestinationComplete : 1;
+ UINT8 Reserved : 5;
+ EFI_LBA Lba;
+ UINT64 Offset;
+ UINT64 Length;
+ //
+ // Relative offset to spare block.
+ //
+ INT64 RelativeOffset;
+ //
+ // UINT8 PrivateData[PrivateDataSize]
+ //
+} EFI_FAULT_TOLERANT_WRITE_RECORD;
+
+#define FTW_RECORD_SIZE(PrivateDataSize) (sizeof (EFI_FAULT_TOLERANT_WRITE_RECORD) + (UINTN) PrivateDataSize)
+
+#define FTW_RECORD_TOTAL_SIZE(NumberOfWrites, PrivateDataSize) \
+ ((UINTN) (NumberOfWrites) * (sizeof (EFI_FAULT_TOLERANT_WRITE_RECORD) + (UINTN) PrivateDataSize))
+
+#define FTW_WRITE_TOTAL_SIZE(NumberOfWrites, PrivateDataSize) \
+ ( \
+ sizeof (EFI_FAULT_TOLERANT_WRITE_HEADER) + (UINTN) (NumberOfWrites) * \
+ (sizeof (EFI_FAULT_TOLERANT_WRITE_RECORD) + (UINTN) PrivateDataSize) \
+ )
+
#endif
diff --git a/MdeModulePkg/Include/Library/CustomizedDisplayLib.h b/MdeModulePkg/Include/Library/CustomizedDisplayLib.h
new file mode 100644
index 000000000..31e1091e8
--- /dev/null
+++ b/MdeModulePkg/Include/Library/CustomizedDisplayLib.h
@@ -0,0 +1,356 @@
+/** @file
+ This library class defines a set of interfaces to customize Display module
+
+Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that 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 __CUSTOMIZED_DISPLAY_LIB_H__
+#define __CUSTOMIZED_DISPLAY_LIB_H__
+
+#include <Protocol/DisplayProtocol.h>
+
+/**
++------------------------------------------------------------------------------+
+| Setup Page |
++------------------------------------------------------------------------------+
+
+Statement
+Statement
+Statement
+
+
+
+
+
++------------------------------------------------------------------------------+
+| F9=Reset to Defaults F10=Save |
+| ^"=Move Highlight <Spacebar> Toggles Checkbox Esc=Exit |
++------------------------------------------------------------------------------+
+ StatusBar
+**/
+
+/**
+ This funtion defines Page Frame and Backgroud.
+
+ Based on the above layout, it will be responsible for HeaderHeight, FooterHeight,
+ StatusBarHeight and Backgroud. And, it will reserve Screen for Statement.
+
+ @param[in] FormData Form Data to be shown in Page.
+ @param[out] ScreenForStatement Screen to be used for Statement. (Prompt, Value and Help)
+
+ @return Status
+**/
+EFI_STATUS
+EFIAPI
+DisplayPageFrame (
+ IN FORM_DISPLAY_ENGINE_FORM *FormData,
+ OUT EFI_SCREEN_DESCRIPTOR *ScreenForStatement
+ );
+
+/**
+ Clear Screen to the initial state.
+**/
+VOID
+EFIAPI
+ClearDisplayPage (
+ VOID
+ );
+
+/**
+ This function updates customized key panel's help information.
+ The library will prepare those Strings for the basic key, ESC, Enter, Up/Down/Left/Right, +/-.
+ and arrange them in Footer panel.
+
+ @param[in] FormData Form Data to be shown in Page. FormData has the highlighted statement.
+ @param[in] Statement The statement current selected.
+ @param[in] Selected Whether or not a tag be selected. TRUE means Enter has hit this question.
+**/
+VOID
+EFIAPI
+RefreshKeyHelp (
+ IN FORM_DISPLAY_ENGINE_FORM *FormData,
+ IN FORM_DISPLAY_ENGINE_STATEMENT *Statement,
+ IN BOOLEAN Selected
+ );
+
+/**
+ Update status bar.
+
+ This function updates the status bar on the bottom of menu screen. It just shows StatusBar.
+ Original logic in this function should be splitted out.
+
+ @param[in] MessageType The type of message to be shown. InputError or Configuration Changed.
+ @param[in] State Show or Clear Message.
+**/
+VOID
+EFIAPI
+UpdateStatusBar (
+ IN UINTN MessageType,
+ IN BOOLEAN State
+ );
+
+/**
+ Create popup window.
+
+ This function draws OEM/Vendor specific pop up windows.
+
+ @param[out] Key User Input Key
+ @param ... String to be shown in Popup. The variable argument list is terminated by a NULL.
+
+**/
+VOID
+EFIAPI
+CreateDialog (
+ OUT EFI_INPUT_KEY *Key, OPTIONAL
+ ...
+ );
+
+/**
+ Confirm how to handle the changed data.
+
+ @return Action BROWSER_ACTION_SUBMIT, BROWSER_ACTION_DISCARD or other values.
+**/
+UINTN
+EFIAPI
+ConfirmDataChange (
+ VOID
+ );
+
+/**
+ OEM specifies whether Setup exits Page by ESC key.
+
+ This function customized the behavior that whether Setup exits Page so that
+ system able to boot when configuration is not changed.
+
+ @retval TRUE Exits FrontPage
+ @retval FALSE Don't exit FrontPage.
+**/
+BOOLEAN
+EFIAPI
+FormExitPolicy (
+ VOID
+ );
+
+/**
+ Set Timeout value for a ceratain Form to get user response.
+
+ This function allows to set timeout value on a ceratain form if necessary.
+ If timeout is not zero, the form will exit if user has no response in timeout.
+
+ @param[in] FormData Form Data to be shown in Page
+
+ @return 0 No timeout for this form.
+ @return > 0 Timeout value in 100 ns units.
+**/
+UINT64
+EFIAPI
+FormExitTimeout (
+ IN FORM_DISPLAY_ENGINE_FORM *FormData
+ );
+
+//
+// Print Functions
+//
+/**
+ Prints a unicode string to the default console, at
+ the supplied cursor position, using L"%s" format.
+
+ @param Column The cursor position to print the string at. When it is -1, use current Position.
+ @param Row The cursor position to print the string at. When it is -1, use current Position.
+ @param String String pointer.
+
+ @return Length of string printed to the console
+
+**/
+UINTN
+EFIAPI
+PrintStringAt (
+ IN UINTN Column,
+ IN UINTN Row,
+ IN CHAR16 *String
+ );
+
+
+/**
+ Prints a unicode string with the specified width to the default console, at
+ the supplied cursor position, using L"%s" format.
+
+ @param Column The cursor position to print the string at. When it is -1, use current Position.
+ @param Row The cursor position to print the string at. When it is -1, use current Position.
+ @param String String pointer.
+ @param Width Width for String to be printed. If the print length of String < Width,
+ Space char (L' ') will be used to append String.
+
+ @return Length of string printed to the console
+
+**/
+UINTN
+EFIAPI
+PrintStringAtWithWidth (
+ IN UINTN Column,
+ IN UINTN Row,
+ IN CHAR16 *String,
+ IN UINTN Width
+ );
+
+/**
+ Prints a chracter to the default console, at
+ the supplied cursor position, using L"%c" format.
+
+ @param Column The cursor position to print the string at. When it is -1, use current Position.
+ @param Row The cursor position to print the string at. When it is -1, use current Position.
+ @param Character Character to print.
+
+ @return Length of string printed to the console.
+
+**/
+UINTN
+EFIAPI
+PrintCharAt (
+ IN UINTN Column,
+ IN UINTN Row,
+ CHAR16 Character
+ );
+
+/**
+ Clear retangle with specified text attribute.
+
+ @param LeftColumn Left column of retangle.
+ @param RightColumn Right column of retangle.
+ @param TopRow Start row of retangle.
+ @param BottomRow End row of retangle.
+ @param TextAttribute The character foreground and background.
+
+**/
+VOID
+EFIAPI
+ClearLines (
+ IN UINTN LeftColumn,
+ IN UINTN RightColumn,
+ IN UINTN TopRow,
+ IN UINTN BottomRow,
+ IN UINTN TextAttribute
+ );
+
+//
+// Color Setting Functions
+//
+/**
+ Get OEM/Vendor specific popup attribute colors.
+
+ @retval Byte code color setting for popup color.
+**/
+UINT8
+EFIAPI
+GetPopupColor (
+ VOID
+ );
+
+/**
+ Get OEM/Vendor specific popup attribute colors.
+
+ @retval Byte code color setting for popup inverse color.
+**/
+UINT8
+EFIAPI
+GetPopupInverseColor (
+ VOID
+ );
+
+/**
+ Get OEM/Vendor specific PickList color attribute.
+
+ @retval Byte code color setting for pick list color.
+**/
+UINT8
+EFIAPI
+GetPickListColor (
+ VOID
+ );
+
+/**
+ Get OEM/Vendor specific arrow color attribute.
+
+ @retval Byte code color setting for arrow color.
+**/
+UINT8
+EFIAPI
+GetArrowColor (
+ VOID
+ );
+
+/**
+ Get OEM/Vendor specific info text color attribute.
+
+ @retval Byte code color setting for info text color.
+**/
+UINT8
+EFIAPI
+GetInfoTextColor (
+ VOID
+ );
+
+/**
+ Get OEM/Vendor specific help text color attribute.
+
+ @retval Byte code color setting for help text color.
+**/
+UINT8
+EFIAPI
+GetHelpTextColor (
+ VOID
+ );
+
+/**
+ Get OEM/Vendor specific grayed out text color attribute.
+
+ @retval Byte code color setting for grayed out text color.
+**/
+UINT8
+EFIAPI
+GetGrayedTextColor (
+ VOID
+ );
+
+/**
+ Get OEM/Vendor specific highlighted text color attribute.
+
+ @retval Byte code color setting for highlight text color.
+**/
+UINT8
+EFIAPI
+GetHighlightTextColor (
+ VOID
+ );
+
+/**
+ Get OEM/Vendor specific field text color attribute.
+
+ @retval Byte code color setting for field text color.
+**/
+UINT8
+EFIAPI
+GetFieldTextColor (
+ VOID
+ );
+
+/**
+ Get OEM/Vendor specific subtitle text color attribute.
+
+ @retval Byte code color setting for subtitle text color.
+**/
+UINT8
+EFIAPI
+GetSubTitleTextColor (
+ VOID
+ );
+
+#endif
diff --git a/MdeModulePkg/Include/Ppi/Usb2HostController.h b/MdeModulePkg/Include/Ppi/Usb2HostController.h
index e6d00ee92..7bcb341a9 100644
--- a/MdeModulePkg/Include/Ppi/Usb2HostController.h
+++ b/MdeModulePkg/Include/Ppi/Usb2HostController.h
@@ -5,7 +5,7 @@
Refer to section 16.1 of the UEFI 2.3 Specification for more information on
these interfaces.
-Copyright (c) 2010, Intel Corporation. All rights reserved. <BR>
+Copyright (c) 2010 - 2013, Intel Corporation. All rights reserved. <BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions
@@ -62,6 +62,9 @@ typedef struct _PEI_USB2_HOST_CONTROLLER_PPI PEI_USB2_HOST_CONTROLLER_PPI;
actually transferred.
@param[in] TimeOut Indicates the maximum time, in milliseconds,
that the transfer is allowed to complete.
+ If Timeout is 0, then the caller must wait for
+ the function to be completed until EFI_SUCCESS
+ or EFI_DEVICE_ERROR is returned.
@param[in] Translator A pointer to the transaction translator data.
@param[out] TransferResult A pointer to the detailed result information
generated by this control transfer.
@@ -114,6 +117,9 @@ EFI_STATUS
@param[in,out] DataToggle A pointer to the data toggle value.
@param[in] TimeOut Indicates the maximum time, in milliseconds,
in which the transfer is allowed to complete.
+ If Timeout is 0, then the caller must wait for
+ the function to be completed until EFI_SUCCESS
+ or EFI_DEVICE_ERROR is returned.
@param[in] Translator A pointer to the transaction translator data.
@param[out] TransferResult A pointer to the detailed result information
of the bulk transfer.
diff --git a/MdeModulePkg/Include/Ppi/UsbHostController.h b/MdeModulePkg/Include/Ppi/UsbHostController.h
index 107b7997d..232a66673 100644
--- a/MdeModulePkg/Include/Ppi/UsbHostController.h
+++ b/MdeModulePkg/Include/Ppi/UsbHostController.h
@@ -5,7 +5,7 @@
Refer to section 16.1 of the UEFI 2.3 Specification for more information on
these interfaces.
-Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions
@@ -61,7 +61,10 @@ typedef struct _PEI_USB_HOST_CONTROLLER_PPI PEI_USB_HOST_CONTROLLER_PPI;
On output, indicates the amount of data
actually transferred.
@param[in] TimeOut Indicates the maximum time, in milliseconds,
- that the transfer is allowed to complete.
+ that the transfer is allowed to complete.
+ If Timeout is 0, then the caller must wait for
+ the function to be completed until EFI_SUCCESS
+ or EFI_DEVICE_ERROR is returned.
@param[out] TransferResult A pointer to the detailed result information
generated by this control transfer.
@@ -107,6 +110,9 @@ EFI_STATUS
@param[in,out] DataToggle A pointer to the data toggle value.
@param[in] TimeOut Indicates the maximum time, in milliseconds,
in which the transfer is allowed to complete.
+ If Timeout is 0, then the caller must wait for
+ the function to be completed until EFI_SUCCESS
+ or EFI_DEVICE_ERROR is returned.
@param[out] TransferResult A pointer to the detailed result information
of the bulk transfer.
diff --git a/MdeModulePkg/Include/Ppi/UsbIo.h b/MdeModulePkg/Include/Ppi/UsbIo.h
index 16660f88a..b024d4640 100644
--- a/MdeModulePkg/Include/Ppi/UsbIo.h
+++ b/MdeModulePkg/Include/Ppi/UsbIo.h
@@ -6,7 +6,7 @@
Refer to section 16.2.4 of the UEFI 2.3 Specification for more information on
these interfaces.
-Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions
@@ -47,8 +47,11 @@ typedef struct _PEI_USB_IO_PPI PEI_USB_IO_PPI;
@param[in] Direction Specifies the data direction for the transfer. There
are three values available:
EfiUsbDataIn, EfiUsbDataOut and EfiUsbNoData.
- @param[in] TimeOut Indicates the maximum time, in milliseconds, that
+ @param[in] Timeout Indicates the maximum time, in milliseconds, that
the transfer is allowed to complete.
+ If Timeout is 0, then the caller must wait for the
+ function to be completed until EFI_SUCCESS or
+ EFI_DEVICE_ERROR is returned.
@param[in,out] Data A pointer to the buffer of data that will be
transmitted to or received from the USB device.
@param[in] DataLength On input, indicates the size, in bytes, of the data
@@ -82,10 +85,13 @@ EFI_STATUS
@param[in] PeiServices The pointer to the PEI Services Table.
@param[in] This The pointer to this instance of the PEI_USB_IO_PPI.
- @param[in] EndPointAddress The endpoint address.
+ @param[in] DeviceEndpoint The endpoint address.
@param[in] Data The data buffer to be transfered.
@param[in] DataLength The length of data buffer.
- @param[in] TimeOut The timeout for the transfer, in milliseconds.
+ @param[in] Timeout The timeout for the transfer, in milliseconds.
+ If Timeout is 0, then the caller must wait for the
+ function to be completed until EFI_SUCCESS or
+ EFI_DEVICE_ERROR is returned.
@retval EFI_SUCCESS The bulk transfer completed successfully.
@retval EFI_INVALID_PARAMETER Some parameters are invalid.
diff --git a/MdeModulePkg/Include/Protocol/DisplayProtocol.h b/MdeModulePkg/Include/Protocol/DisplayProtocol.h
new file mode 100644
index 000000000..d4f0debf9
--- /dev/null
+++ b/MdeModulePkg/Include/Protocol/DisplayProtocol.h
@@ -0,0 +1,350 @@
+/** @file
+ FormDiplay protocol to show Form
+
+Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that 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 __DISPLAY_PROTOCOL_H__
+#define __DISPLAY_PROTOCOL_H__
+
+#include <Protocol/FormBrowser2.h>
+
+#define EDKII_FORM_DISPLAY_ENGINE_PROTOCOL_GUID \
+ { 0x9bbe29e9, 0xfda1, 0x41ec, { 0xad, 0x52, 0x45, 0x22, 0x13, 0x74, 0x2d, 0x2e } }
+
+//
+// Do nothing.
+//
+#define BROWSER_ACTION_NONE BIT16
+//
+// ESC Exit
+//
+#define BROWSER_ACTION_FORM_EXIT BIT17
+
+#define BROWSER_SUCCESS 0x0
+#define BROWSER_ERROR BIT31
+#define BROWSER_SUBMIT_FAIL BROWSER_ERROR | 0x01
+#define BROWSER_NO_SUBMIT_IF BROWSER_ERROR | 0x02
+#define BROWSER_FORM_NOT_FOUND BROWSER_ERROR | 0x03
+#define BROWSER_FORM_SUPPRESS BROWSER_ERROR | 0x04
+#define BROWSER_PROTOCOL_NOT_FOUND BROWSER_ERROR | 0x05
+
+#define FORM_DISPLAY_ENGINE_STATEMENT_VERSION_1 0x10000
+#define FORM_DISPLAY_ENGINE_VERSION_1 0x10000
+
+typedef struct {
+ //
+ // HII Data Type
+ //
+ UINT8 Type;
+ //
+ // Buffer Data and Length if Type is EFI_IFR_TYPE_BUFFER or EFI_IFR_TYPE_STRING
+ //
+ UINT8 *Buffer;
+ UINT16 BufferLen;
+ EFI_IFR_TYPE_VALUE Value;
+} EFI_HII_VALUE;
+
+#define DISPLAY_QUESTION_OPTION_SIGNATURE SIGNATURE_32 ('Q', 'O', 'P', 'T')
+
+typedef struct {
+ UINTN Signature;
+ LIST_ENTRY Link;
+ //
+ // OneOfOption Data
+ //
+ EFI_IFR_ONE_OF_OPTION *OptionOpCode;
+ //
+ // Option ImageId and AnimationId
+ //
+ EFI_IMAGE_ID ImageId;
+ EFI_ANIMATION_ID AnimationId;
+} DISPLAY_QUESTION_OPTION;
+
+#define DISPLAY_QUESTION_OPTION_FROM_LINK(a) CR (a, DISPLAY_QUESTION_OPTION, Link, DISPLAY_QUESTION_OPTION_SIGNATURE)
+
+typedef struct _FORM_DISPLAY_ENGINE_STATEMENT FORM_DISPLAY_ENGINE_STATEMENT;
+typedef struct _FORM_DISPLAY_ENGINE_FORM FORM_DISPLAY_ENGINE_FORM;
+
+#define STATEMENT_VALID 0x0
+#define STATEMENT_INVALID BIT31
+
+#define INCOSISTENT_IF_TRUE STATEMENT_INVALID | 0x01
+#define WARNING_IF_TRUE STATEMENT_INVALID | 0x02
+#define STRING_TOO_LONG STATEMENT_INVALID | 0x03
+// ... to be extended.
+
+typedef struct {
+ //
+ // StringId for INCONSITENT_IF or WARNING_IF
+ //
+ EFI_STRING_ID StringId;
+ //
+ // TimeOut for WARNING_IF
+ //
+ UINT8 TimeOut;
+} STATEMENT_ERROR_INFO;
+
+/**
+ Perform value check for a question.
+
+ @param Form Form where Statement is in.
+ @param Statement Value will check for it.
+ @param Value New value will be checked.
+
+ @retval Status Value Status
+
+**/
+typedef
+UINT32
+(EFIAPI *VALIDATE_QUESTION) (
+ IN FORM_DISPLAY_ENGINE_FORM *Form,
+ IN FORM_DISPLAY_ENGINE_STATEMENT *Statement,
+ IN EFI_HII_VALUE *Value,
+ OUT STATEMENT_ERROR_INFO *ErrorInfo
+ );
+
+/**
+ Perform Password check.
+ Passwork may be encrypted by driver that requires the specific check.
+
+ @param Form Form where Password Statement is in.
+ @param Statement Password statement
+ @param PasswordString Password string to be checked. It may be NULL.
+ NULL means to restore password.
+ "" string can be used to checked whether old password does exist.
+
+ @return Status Status of Password check.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *PASSWORD_CHECK) (
+ IN FORM_DISPLAY_ENGINE_FORM *Form,
+ IN FORM_DISPLAY_ENGINE_STATEMENT *Statement,
+ IN EFI_STRING PasswordString OPTIONAL
+ );
+
+#define FORM_DISPLAY_ENGINE_STATEMENT_SIGNATURE SIGNATURE_32 ('F', 'S', 'T', 'A')
+
+//
+// Attribute for Statement and Form
+//
+#define HII_DISPLAY_GRAYOUT BIT0
+#define HII_DISPLAY_LOCK BIT1
+#define HII_DISPLAY_READONLY BIT2
+#define HII_DISPLAY_MODAL BIT3
+
+struct _FORM_DISPLAY_ENGINE_STATEMENT{
+ UINTN Signature;
+ //
+ // Version for future structure extension
+ //
+ UINTN Version;
+ //
+ // link to all the statement which will show in the display form.
+ //
+ LIST_ENTRY DisplayLink;
+ //
+ // Pointer to statement opcode.
+ // for Guided Opcode. All buffers will be here if GUIDED opcode scope is set.
+ //
+ EFI_IFR_OP_HEADER *OpCode;
+ //
+ // Question CurrentValue
+ //
+ EFI_HII_VALUE CurrentValue;
+ //
+ // Flag to describe whether setting is changed or not.
+ // Displayer may depend on it to show it with the different color.
+ //
+ BOOLEAN SettingChangedFlag;
+ //
+ // nested Statement list inside of EFI_IFR_SUBTITLE
+ //
+ LIST_ENTRY NestStatementList;
+ //
+ // nested EFI_IFR_ONE_OF_OPTION list (QUESTION_OPTION)
+ //
+ LIST_ENTRY OptionListHead;
+ //
+ // Statement attributes: GRAYOUT, LOCK and READONLY
+ //
+ UINT32 Attribute;
+
+ //
+ // ValidateQuestion to do InconsistIf check
+ // It may be NULL if any value is valid.
+ //
+ VALIDATE_QUESTION ValidateQuestion;
+
+ //
+ // Password additional check. It may be NULL when the additional check is not required.
+ //
+ PASSWORD_CHECK PasswordCheck;
+
+ //
+ // Statement ImageId and AnimationId
+ //
+ EFI_IMAGE_ID ImageId;
+ EFI_ANIMATION_ID AnimationId;
+};
+
+#define FORM_DISPLAY_ENGINE_STATEMENT_FROM_LINK(a) CR (a, FORM_DISPLAY_ENGINE_STATEMENT, DisplayLink, FORM_DISPLAY_ENGINE_STATEMENT_SIGNATURE)
+
+#define BROWSER_HOT_KEY_SIGNATURE SIGNATURE_32 ('B', 'H', 'K', 'S')
+
+typedef struct {
+ UINTN Signature;
+ LIST_ENTRY Link;
+
+ EFI_INPUT_KEY *KeyData;
+ //
+ // Action is Discard, Default, Submit, Reset and Exit.
+ //
+ UINT32 Action;
+ UINT16 DefaultId;
+ //
+ // HotKey Help String
+ //
+ EFI_STRING HelpString;
+} BROWSER_HOT_KEY;
+
+#define BROWSER_HOT_KEY_FROM_LINK(a) CR (a, BROWSER_HOT_KEY, Link, BROWSER_HOT_KEY_SIGNATURE)
+
+#define FORM_DISPLAY_ENGINE_FORM_SIGNATURE SIGNATURE_32 ('F', 'F', 'R', 'M')
+
+struct _FORM_DISPLAY_ENGINE_FORM {
+ UINTN Signature;
+ //
+ // Version for future structure extension
+ //
+ UINTN Version;
+ //
+ // Statement List inside of Form
+ //
+ LIST_ENTRY StatementListHead;
+ //
+ // Statement List outside of Form
+ //
+ LIST_ENTRY StatementListOSF;
+ //
+ // The input screen dimenstions info.
+ //
+ EFI_SCREEN_DESCRIPTOR *ScreenDimensions;
+ //
+ // FormSet information
+ //
+ EFI_GUID FormSetGuid;
+ //
+ // HiiHandle can be used to get String, Image or Animation
+ //
+ EFI_HII_HANDLE HiiHandle;
+
+ //
+ // Form ID and Title.
+ //
+ UINT16 FormId;
+ EFI_STRING_ID FormTitle;
+ //
+ // Form Attributes: Lock, Modal.
+ //
+ UINT32 Attribute;
+ //
+ // Flag to describe whether setting is changed or not.
+ // Displayer depends on it to show ChangedFlag.
+ //
+ BOOLEAN SettingChangedFlag;
+
+ //
+ // Statement to be HighLighted
+ //
+ FORM_DISPLAY_ENGINE_STATEMENT *HighLightedStatement;
+ //
+ // Event to notify Displayer that FormData is updated to be refreshed.
+ //
+ EFI_EVENT FormRefreshEvent;
+ //
+ // Additional Hotkey registered by BrowserEx protocol.
+ //
+ LIST_ENTRY HotKeyListHead;
+
+ //
+ // Form ImageId and AnimationId
+ //
+ EFI_IMAGE_ID ImageId;
+ EFI_ANIMATION_ID AnimationId;
+
+ //
+ // If Status is error, display needs to handle it.
+ //
+ UINT32 BrowserStatus;
+ //
+ // String for error status. It may be NULL.
+ //
+ EFI_STRING ErrorString;
+};
+
+#define FORM_DISPLAY_ENGINE_FORM_FROM_LINK(a) CR (a, FORM_DISPLAY_ENGINE_FORM, Link, FORM_DISPLAY_ENGINE_FORM_SIGNATURE)
+
+typedef struct {
+ FORM_DISPLAY_ENGINE_STATEMENT *SelectedStatement; // Selected Statement and InputValue
+
+ EFI_HII_VALUE InputValue;
+
+ UINT32 Action; // If SelectedStatement is NULL, Action will be used.
+ // Trig Action (Discard, Default, Submit, Reset and Exit)
+ UINT16 DefaultId;
+} USER_INPUT;
+
+/**
+ Display one form, and return user input.
+
+ @param FormData Form Data to be shown.
+ @param UserInputData User input data.
+
+ @retval EFI_SUCCESS Form Data is shown, and user input is got.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *FORM_DISPLAY) (
+ IN FORM_DISPLAY_ENGINE_FORM *FormData,
+ OUT USER_INPUT *UserInputData
+);
+
+/**
+ Exit Display and Clear Screen to the original state.
+
+**/
+typedef
+VOID
+(EFIAPI *EXIT_DISPLAY) (
+ VOID
+);
+
+/**
+ Confirm how to handle the changed data.
+
+ @return Action of Submit, Discard and None
+**/
+typedef
+UINTN
+(EFIAPI *CONFIRM_DATA_CHANGE) (
+ VOID
+);
+
+typedef struct {
+ FORM_DISPLAY FormDisplay;
+ EXIT_DISPLAY ExitDisplay;
+ CONFIRM_DATA_CHANGE ConfirmDataChange;
+} EDKII_FORM_DISPLAY_ENGINE_PROTOCOL;
+
+extern EFI_GUID gEdkiiFormDisplayEngineProtocolGuid;
+#endif
diff --git a/MdeModulePkg/Include/Protocol/FormBrowserEx2.h b/MdeModulePkg/Include/Protocol/FormBrowserEx2.h
new file mode 100644
index 000000000..105ac0308
--- /dev/null
+++ b/MdeModulePkg/Include/Protocol/FormBrowserEx2.h
@@ -0,0 +1,90 @@
+/** @file
+ Extension Form Browser Protocol provides the services that can be used to
+ register the different hot keys for the standard Browser actions described in UEFI specification.
+
+Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that 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 __FORM_BROWSER_EXTENSION2_H__
+#define __FORM_BROWSER_EXTENSION2_H__
+
+#include <Protocol/FormBrowserEx.h>
+
+#define EDKII_FORM_BROWSER_EXTENSION2_PROTOCOL_GUID \
+ { 0xa770c357, 0xb693, 0x4e6d, { 0xa6, 0xcf, 0xd2, 0x1c, 0x72, 0x8e, 0x55, 0xb }}
+
+typedef struct _EDKII_FORM_BROWSER_EXTENSION2_PROTOCOL EDKII_FORM_BROWSER_EXTENSION2_PROTOCOL;
+
+#define BROWSER_EXTENSION2_VERSION_1 0x10000
+
+/**
+ Check whether the browser data has been modified.
+
+ @retval TRUE Browser data is modified.
+ @retval FALSE No browser data is modified.
+
+**/
+typedef
+BOOLEAN
+(EFIAPI *IS_BROWSER_DATA_MODIFIED) (
+ VOID
+ );
+
+/**
+ Execute the action requested by the Action parameter.
+
+ @param[in] Action Execute the request action.
+ @param[in] DefaultId The default Id info when need to load default value.
+
+ @retval EFI_SUCCESS Execute the request action succss.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EXECUTE_ACTION) (
+ IN UINT32 Action,
+ IN UINT16 DefaultId
+ );
+
+#define FORM_ENTRY_INFO_SIGNATURE SIGNATURE_32 ('f', 'e', 'i', 's')
+
+typedef struct {
+ UINTN Signature;
+ LIST_ENTRY Link;
+
+ EFI_HII_HANDLE HiiHandle;
+ EFI_GUID FormSetGuid;
+ EFI_FORM_ID FormId;
+ EFI_QUESTION_ID QuestionId;
+} FORM_ENTRY_INFO;
+
+#define FORM_ENTRY_INFO_FROM_LINK(a) CR (a, FORM_ENTRY_INFO, Link, FORM_ENTRY_INFO_SIGNATURE)
+
+struct _EDKII_FORM_BROWSER_EXTENSION2_PROTOCOL {
+ ///
+ /// Version for protocol future extension.
+ ///
+ UINT32 Version;
+ SET_SCOPE SetScope;
+ REGISTER_HOT_KEY RegisterHotKey;
+ REGISTER_EXIT_HANDLER RegiserExitHandler;
+ IS_BROWSER_DATA_MODIFIED IsBrowserDataModified;
+ EXECUTE_ACTION ExecuteAction;
+ ///
+ /// A list of type FORMID_INFO is Browser View Form History List.
+ ///
+ LIST_ENTRY FormViewHistoryHead;
+};
+
+extern EFI_GUID gEdkiiFormBrowserEx2ProtocolGuid;
+
+#endif
+
diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/Colors.h b/MdeModulePkg/Library/CustomizedDisplayLib/Colors.h
index 2db8b9961..2db8b9961 100644
--- a/MdeModulePkg/Universal/SetupBrowserDxe/Colors.h
+++ b/MdeModulePkg/Library/CustomizedDisplayLib/Colors.h
diff --git a/MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.c b/MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.c
new file mode 100644
index 000000000..aa28146b0
--- /dev/null
+++ b/MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.c
@@ -0,0 +1,921 @@
+/** @file
+
+ This library class defines a set of interfaces to customize Display module
+
+Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that 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 "CustomizedDisplayLibInternal.h"
+
+EFI_GUID gCustomizedDisplayLibGuid = { 0x99fdc8fd, 0x849b, 0x4eba, { 0xad, 0x13, 0xfb, 0x96, 0x99, 0xc9, 0xa, 0x4d } };
+
+EFI_HII_HANDLE mCDLStringPackHandle;
+UINT16 gClassOfVfr; // Formset class information
+BOOLEAN gLibIsFirstForm = TRUE;
+BANNER_DATA *gBannerData;
+
+UINTN gFooterHeight;
+
+/**
++------------------------------------------------------------------------------+
+| Setup Page |
++------------------------------------------------------------------------------+
+
+Statement
+Statement
+Statement
+
+
+
+
+
++------------------------------------------------------------------------------+
+| F9=Reset to Defaults F10=Save |
+| ^"=Move Highlight <Spacebar> Toggles Checkbox Esc=Exit |
++------------------------------------------------------------------------------+
+ StatusBar
+**/
+
+/**
+ This funtion defines Page Frame and Backgroud.
+
+ Based on the above layout, it will be responsible for HeaderHeight, FooterHeight,
+ StatusBarHeight and Backgroud. And, it will reserve Screen for Statement.
+
+ @param[in] FormData Form Data to be shown in Page.
+ @param[out] ScreenForStatement Screen to be used for Statement. (Prompt, Value and Help)
+
+ @return Status
+**/
+EFI_STATUS
+EFIAPI
+DisplayPageFrame (
+ IN FORM_DISPLAY_ENGINE_FORM *FormData,
+ OUT EFI_SCREEN_DESCRIPTOR *ScreenForStatement
+ )
+{
+ EFI_STATUS Status;
+
+ ASSERT (FormData != NULL && ScreenForStatement != NULL);
+ if (FormData == NULL || ScreenForStatement == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = ScreenDiemensionInfoValidate (FormData);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ gClassOfVfr = FORMSET_CLASS_PLATFORM_SETUP;
+
+ ProcessExternedOpcode(FormData);
+
+ //
+ // Calculate the ScreenForStatement.
+ //
+ ScreenForStatement->BottomRow = gScreenDimensions.BottomRow - STATUS_BAR_HEIGHT - gFooterHeight;
+ if (gClassOfVfr == FORMSET_CLASS_FRONT_PAGE) {
+ ScreenForStatement->TopRow = gScreenDimensions.TopRow + FRONT_PAGE_HEADER_HEIGHT;
+ } else {
+ ScreenForStatement->TopRow = gScreenDimensions.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT;
+ }
+ ScreenForStatement->LeftColumn = gScreenDimensions.LeftColumn;
+ ScreenForStatement->RightColumn = gScreenDimensions.RightColumn;
+
+ if ((gLibIsFirstForm) || ((FormData->Attribute & HII_DISPLAY_MODAL) != 0)) {
+ //
+ // Ensure we are in Text mode
+ //
+ gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));
+ ClearLines (0, gScreenDimensions.RightColumn, 0, gScreenDimensions.BottomRow, KEYHELP_BACKGROUND);
+ gLibIsFirstForm = FALSE;
+ }
+
+ //
+ // Don't print frame for modal form.
+ //
+ if ((FormData->Attribute & HII_DISPLAY_MODAL) != 0) {
+ return EFI_SUCCESS;
+ }
+
+ if (gClassOfVfr == FORMSET_CLASS_FRONT_PAGE) {
+ PrintBannerInfo (FormData);
+ }
+
+ PrintFramework (FormData);
+
+ UpdateStatusBar(NV_UPDATE_REQUIRED, FormData->SettingChangedFlag);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function updates customized key panel's help information.
+ The library will prepare those Strings for the basic key, ESC, Enter, Up/Down/Left/Right, +/-.
+ and arrange them in Footer panel.
+
+ @param[in] FormData Form Data to be shown in Page. FormData has the highlighted statement.
+ @param[in] Statement The statement current selected.
+ @param[in] Selected Whether or not a tag be selected. TRUE means Enter has hit this question.
+**/
+VOID
+EFIAPI
+RefreshKeyHelp (
+ IN FORM_DISPLAY_ENGINE_FORM *FormData,
+ IN FORM_DISPLAY_ENGINE_STATEMENT *Statement,
+ IN BOOLEAN Selected
+ )
+{
+ UINTN SecCol;
+ UINTN ThdCol;
+ UINTN LeftColumnOfHelp;
+ UINTN RightColumnOfHelp;
+ UINTN TopRowOfHelp;
+ UINTN BottomRowOfHelp;
+ UINTN StartColumnOfHelp;
+ EFI_IFR_NUMERIC *NumericOp;
+ EFI_IFR_DATE *DateOp;
+ EFI_IFR_TIME *TimeOp;
+ BOOLEAN HexDisplay;
+
+ ASSERT (FormData != NULL);
+ if (FormData == NULL) {
+ return;
+ }
+
+ gST->ConOut->SetAttribute (gST->ConOut, KEYHELP_TEXT | KEYHELP_BACKGROUND);
+
+ if ((FormData->Attribute & HII_DISPLAY_MODAL) != 0) {
+ return;
+ }
+
+ SecCol = gScreenDimensions.LeftColumn + (gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn) / 3;
+ ThdCol = gScreenDimensions.LeftColumn + (gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn) / 3 * 2;
+
+ StartColumnOfHelp = gScreenDimensions.LeftColumn + 2;
+ LeftColumnOfHelp = gScreenDimensions.LeftColumn + 1;
+ RightColumnOfHelp = gScreenDimensions.RightColumn - 2;
+ TopRowOfHelp = gScreenDimensions.BottomRow - STATUS_BAR_HEIGHT - gFooterHeight + 1;
+ BottomRowOfHelp = gScreenDimensions.BottomRow - STATUS_BAR_HEIGHT - 2;
+
+ ClearLines (LeftColumnOfHelp, RightColumnOfHelp, TopRowOfHelp, BottomRowOfHelp, KEYHELP_TEXT | KEYHELP_BACKGROUND);
+ if (Statement == NULL) {
+ //
+ // Print Key for Form without showable statement.
+ //
+ PrintHotKeyHelpString (FormData);
+ PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString);
+ return;
+ }
+
+ HexDisplay = FALSE;
+ NumericOp = NULL;
+ DateOp = NULL;
+ TimeOp = NULL;
+ if (Statement->OpCode->OpCode == EFI_IFR_NUMERIC_OP) {
+ NumericOp = (EFI_IFR_NUMERIC *) Statement->OpCode;
+ HexDisplay = (NumericOp->Flags & EFI_IFR_DISPLAY_UINT_HEX) == EFI_IFR_DISPLAY_UINT_HEX;
+ } else if (Statement->OpCode->OpCode == EFI_IFR_DATE_OP) {
+ DateOp = (EFI_IFR_DATE *) Statement->OpCode;
+ HexDisplay = (DateOp->Flags & EFI_IFR_DISPLAY_UINT_HEX) == EFI_IFR_DISPLAY_UINT_HEX;
+ } else if (Statement->OpCode->OpCode == EFI_IFR_TIME_OP) {
+ TimeOp = (EFI_IFR_TIME *) Statement->OpCode;
+ HexDisplay = (TimeOp->Flags & EFI_IFR_DISPLAY_UINT_HEX) == EFI_IFR_DISPLAY_UINT_HEX;
+ }
+ switch (Statement->OpCode->OpCode) {
+ 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:
+ if (!Selected) {
+ PrintHotKeyHelpString (FormData);
+
+ if (gClassOfVfr == FORMSET_CLASS_PLATFORM_SETUP) {
+ PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString);
+ }
+
+ if ((Statement->OpCode->OpCode == EFI_IFR_DATE_OP) ||
+ (Statement->OpCode->OpCode == EFI_IFR_TIME_OP)) {
+ PrintAt (
+ 0,
+ StartColumnOfHelp,
+ BottomRowOfHelp,
+ L"%c%c%c%c%s",
+ ARROW_UP,
+ ARROW_DOWN,
+ ARROW_RIGHT,
+ ARROW_LEFT,
+ gMoveHighlight
+ );
+ PrintStringAt (SecCol, BottomRowOfHelp, gEnterString);
+ PrintStringAt (StartColumnOfHelp, TopRowOfHelp, gAdjustNumber);
+ } else {
+ PrintAt (0, StartColumnOfHelp, BottomRowOfHelp, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);
+ if (Statement->OpCode->OpCode == EFI_IFR_NUMERIC_OP && NumericOp != NULL && LibGetFieldFromNum(Statement->OpCode) != 0) {
+ PrintStringAt (StartColumnOfHelp, TopRowOfHelp, gAdjustNumber);
+ }
+ PrintStringAt (SecCol, BottomRowOfHelp, gEnterString);
+ }
+ } else {
+ PrintStringAt (SecCol, BottomRowOfHelp, gEnterCommitString);
+
+ //
+ // If it is a selected numeric with manual input, display different message
+ //
+ if ((Statement->OpCode->OpCode == EFI_IFR_NUMERIC_OP) ||
+ (Statement->OpCode->OpCode == EFI_IFR_DATE_OP) ||
+ (Statement->OpCode->OpCode == EFI_IFR_TIME_OP)) {
+ PrintStringAt (
+ SecCol,
+ TopRowOfHelp,
+ HexDisplay ? gHexNumericInput : gDecNumericInput
+ );
+ } else if (Statement->OpCode->OpCode != EFI_IFR_ORDERED_LIST_OP) {
+ PrintAt (0, StartColumnOfHelp, BottomRowOfHelp, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);
+ }
+
+ if (Statement->OpCode->OpCode == EFI_IFR_ORDERED_LIST_OP) {
+ PrintStringAt (StartColumnOfHelp, TopRowOfHelp, gPlusString);
+ PrintStringAt (ThdCol, TopRowOfHelp, gMinusString);
+ }
+
+ PrintStringAt (ThdCol, BottomRowOfHelp, gEnterEscapeString);
+ }
+ break;
+
+ case EFI_IFR_CHECKBOX_OP:
+ PrintHotKeyHelpString (FormData);
+
+ if (gClassOfVfr == FORMSET_CLASS_PLATFORM_SETUP) {
+ PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString);
+ }
+
+ PrintAt (0, StartColumnOfHelp, BottomRowOfHelp, 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:
+ case EFI_IFR_TEXT_OP:
+ case EFI_IFR_ACTION_OP:
+ case EFI_IFR_RESET_BUTTON_OP:
+ case EFI_IFR_SUBTITLE_OP:
+ if (!Selected) {
+ PrintHotKeyHelpString (FormData);
+
+ if (gClassOfVfr == FORMSET_CLASS_PLATFORM_SETUP) {
+ PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString);
+ }
+
+ PrintAt (0, StartColumnOfHelp, BottomRowOfHelp, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);
+ if (Statement->OpCode->OpCode != EFI_IFR_TEXT_OP && Statement->OpCode->OpCode != EFI_IFR_SUBTITLE_OP) {
+ PrintStringAt (SecCol, BottomRowOfHelp, gEnterString);
+ }
+ } else {
+ if (Statement->OpCode->OpCode != EFI_IFR_REF_OP) {
+ PrintStringAt (
+ (gScreenDimensions.RightColumn - LibGetStringWidth (gEnterCommitString) / 2) / 2,
+ BottomRowOfHelp,
+ gEnterCommitString
+ );
+ PrintStringAt (ThdCol, BottomRowOfHelp, gEnterEscapeString);
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+/**
+ Update status bar.
+
+ This function updates the status bar on the bottom of menu screen. It just shows StatusBar.
+ Original logic in this function should be splitted out.
+
+ @param[in] MessageType The type of message to be shown. InputError or Configuration Changed.
+ @param[in] State Show or Clear Message.
+**/
+VOID
+EFIAPI
+UpdateStatusBar (
+ IN UINTN MessageType,
+ IN BOOLEAN State
+ )
+{
+ UINTN Index;
+ CHAR16 OptionWidth;
+
+ OptionWidth = (CHAR16) ((gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn) / 3);
+
+ switch (MessageType) {
+ case INPUT_ERROR:
+ if (State) {
+ gST->ConOut->SetAttribute (gST->ConOut, ERROR_TEXT);
+ PrintStringAt (
+ gScreenDimensions.LeftColumn + OptionWidth,
+ gScreenDimensions.BottomRow - 1,
+ gInputErrorMessage
+ );
+ } else {
+ gST->ConOut->SetAttribute (gST->ConOut, KEYHELP_BACKGROUND);
+ for (Index = 0; Index < (LibGetStringWidth (gInputErrorMessage) - 2) / 2; Index++) {
+ PrintStringAt (gScreenDimensions.LeftColumn + OptionWidth + Index, gScreenDimensions.BottomRow - 1, L" ");
+ }
+ }
+ break;
+
+ case NV_UPDATE_REQUIRED:
+ //
+ // Global setting support. Show configuration change on every form.
+ //
+ if (State) {
+ gST->ConOut->SetAttribute (gST->ConOut, INFO_TEXT);
+ PrintStringAt (
+ gScreenDimensions.LeftColumn + OptionWidth * 2,
+ gScreenDimensions.BottomRow - 1,
+ gNvUpdateMessage
+ );
+ } else {
+ gST->ConOut->SetAttribute (gST->ConOut, KEYHELP_BACKGROUND);
+ for (Index = 0; Index < (LibGetStringWidth (gNvUpdateMessage) - 2) / 2; Index++) {
+ PrintStringAt (
+ (gScreenDimensions.LeftColumn + OptionWidth * 2 + Index),
+ gScreenDimensions.BottomRow - 1,
+ L" "
+ );
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+/**
+ Create popup window. It will replace CreateDialog().
+
+ This function draws OEM/Vendor specific pop up windows.
+
+ @param[out] Key User Input Key
+ @param ... String to be shown in Popup. The variable argument list is terminated by a NULL.
+
+**/
+VOID
+EFIAPI
+CreateDialog (
+ OUT EFI_INPUT_KEY *Key, OPTIONAL
+ ...
+ )
+{
+ VA_LIST Marker;
+ EFI_INPUT_KEY KeyValue;
+ EFI_STATUS Status;
+ UINTN LargestString;
+ UINTN LineNum;
+ UINTN Index;
+ UINTN Count;
+ CHAR16 Character;
+ UINTN Start;
+ UINTN End;
+ UINTN Top;
+ UINTN Bottom;
+ CHAR16 *String;
+ UINTN DimensionsWidth;
+ UINTN DimensionsHeight;
+ UINTN CurrentAttribute;
+
+ //
+ // If screen dimension info is not ready, get it from console.
+ //
+ if (gScreenDimensions.RightColumn == 0 || gScreenDimensions.BottomRow == 0) {
+ ZeroMem (&gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));
+ gST->ConOut->QueryMode (
+ gST->ConOut,
+ gST->ConOut->Mode->Mode,
+ &gScreenDimensions.RightColumn,
+ &gScreenDimensions.BottomRow
+ );
+ }
+
+ DimensionsWidth = gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn;
+ DimensionsHeight = gScreenDimensions.BottomRow - gScreenDimensions.TopRow;
+
+ LargestString = 0;
+ LineNum = 0;
+ VA_START (Marker, Key);
+ while ((String = VA_ARG (Marker, CHAR16 *)) != NULL) {
+ LineNum ++;
+
+ if ((LibGetStringWidth (String) / 2) > LargestString) {
+ LargestString = (LibGetStringWidth (String) / 2);
+ }
+ }
+ VA_END (Marker);
+
+ if ((LargestString + 2) > DimensionsWidth) {
+ LargestString = DimensionsWidth - 2;
+ }
+
+ CurrentAttribute = gST->ConOut->Mode->Attribute;
+ gST->ConOut->EnableCursor (gST->ConOut, FALSE);
+ gST->ConOut->SetAttribute (gST->ConOut, GetPopupColor ());
+
+ //
+ // Subtract the PopUp width from total Columns, allow for one space extra on
+ // each end plus a border.
+ //
+ Start = (DimensionsWidth - LargestString - 2) / 2 + gScreenDimensions.LeftColumn + 1;
+ End = Start + LargestString + 1;
+
+ Top = ((DimensionsHeight - LineNum - 2) / 2) + gScreenDimensions.TopRow - 1;
+ Bottom = Top + LineNum + 2;
+
+ Character = BOXDRAW_DOWN_RIGHT;
+ PrintCharAt (Start, Top, Character);
+ Character = BOXDRAW_HORIZONTAL;
+ for (Index = Start; Index + 2 < End; Index++) {
+ PrintCharAt ((UINTN)-1, (UINTN)-1, Character);
+ }
+
+ Character = BOXDRAW_DOWN_LEFT;
+ PrintCharAt ((UINTN)-1, (UINTN)-1, Character);
+ Character = BOXDRAW_VERTICAL;
+
+ Count = 0;
+ VA_START (Marker, Key);
+ for (Index = Top; Index + 2 < Bottom; Index++, Count++) {
+ String = VA_ARG (Marker, CHAR16*);
+
+ if (String[0] == CHAR_NULL) {
+ //
+ // Passing in a NULL results in a blank space
+ //
+ ClearLines (Start, End, Index + 1, Index + 1, GetPopupColor ());
+ } else if (String[0] == L' ') {
+ //
+ // Passing in a space results in the assumption that this is where typing will occur
+ //
+ ClearLines (Start + 1, End - 1, Index + 1, Index + 1, POPUP_INVERSE_TEXT | POPUP_INVERSE_BACKGROUND);
+ PrintStringAt (
+ ((DimensionsWidth - LibGetStringWidth (String) / 2) / 2) + gScreenDimensions.LeftColumn + 1,
+ Index + 1,
+ String + 1
+ );
+ } else {
+ //
+ // 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.
+ //
+ ClearLines (Start, End, Index + 1, Index + 1, GetPopupColor ());
+ PrintStringAt (
+ ((DimensionsWidth - LibGetStringWidth (String) / 2) / 2) + gScreenDimensions.LeftColumn + 1,
+ Index + 1,
+ String
+ );
+ }
+
+ gST->ConOut->SetAttribute (gST->ConOut, GetPopupColor ());
+ PrintCharAt (Start, Index + 1, Character);
+ PrintCharAt (End - 1, Index + 1, Character);
+ }
+ VA_END (Marker);
+
+ Character = BOXDRAW_UP_RIGHT;
+ PrintCharAt (Start, Bottom - 1, Character);
+ Character = BOXDRAW_HORIZONTAL;
+ for (Index = Start; Index + 2 < End; Index++) {
+ PrintCharAt ((UINTN)-1, (UINTN) -1, Character);
+ }
+
+ Character = BOXDRAW_UP_LEFT;
+ PrintCharAt ((UINTN)-1, (UINTN) -1, Character);
+
+ if (Key != NULL) {
+ Status = WaitForKeyStroke (&KeyValue);
+ ASSERT_EFI_ERROR (Status);
+ CopyMem (Key, &KeyValue, sizeof (EFI_INPUT_KEY));
+ }
+
+ gST->ConOut->SetAttribute (gST->ConOut, CurrentAttribute);
+ gST->ConOut->EnableCursor (gST->ConOut, TRUE);
+}
+
+/**
+ Confirm how to handle the changed data.
+
+ @return Action BROWSER_ACTION_SUBMIT, BROWSER_ACTION_DISCARD or other values.
+**/
+UINTN
+EFIAPI
+ConfirmDataChange (
+ VOID
+ )
+{
+ CHAR16 YesResponse;
+ CHAR16 NoResponse;
+ EFI_INPUT_KEY Key;
+
+ gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
+
+ YesResponse = gYesResponse[0];
+ NoResponse = gNoResponse[0];
+
+ //
+ // If NV flag is up, prompt user
+ //
+ do {
+ CreateDialog (&Key, gLibEmptyString, gSaveChanges, gAreYouSure, gLibEmptyString, NULL);
+ } 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 (Key.ScanCode == SCAN_ESC) {
+ return BROWSER_ACTION_NONE;
+ } else if ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) == (YesResponse | UPPER_LOWER_CASE_OFFSET)) {
+ return BROWSER_ACTION_SUBMIT;
+ } else {
+ return BROWSER_ACTION_DISCARD;
+ }
+}
+
+/**
+ OEM specifies whether Setup exits Page by ESC key.
+
+ This function customized the behavior that whether Setup exits Page so that
+ system able to boot when configuration is not changed.
+
+ @retval TRUE Exits FrontPage
+ @retval FALSE Don't exit FrontPage.
+**/
+BOOLEAN
+EFIAPI
+FormExitPolicy (
+ VOID
+ )
+{
+ return gClassOfVfr == FORMSET_CLASS_FRONT_PAGE ? FALSE : TRUE;
+}
+
+/**
+ Set Timeout value for a ceratain Form to get user response.
+
+ This function allows to set timeout value on a ceratain form if necessary.
+ If timeout is not zero, the form will exit if user has no response in timeout.
+
+ @param[in] FormData Form Data to be shown in Page
+
+ @return 0 No timeout for this form.
+ @return > 0 Timeout value in 100 ns units.
+**/
+UINT64
+EFIAPI
+FormExitTimeout (
+ IN FORM_DISPLAY_ENGINE_FORM *FormData
+ )
+{
+ return 0;
+}
+//
+// Print Functions
+//
+/**
+ Prints a unicode string to the default console, at
+ the supplied cursor position, using L"%s" format.
+
+ @param Column The cursor position to print the string at. When it is -1, use current Position.
+ @param Row The cursor position to print the string at. When it is -1, use current Position.
+ @param String String pointer.
+
+ @return Length of string printed to the console
+
+**/
+UINTN
+EFIAPI
+PrintStringAt (
+ IN UINTN Column,
+ IN UINTN Row,
+ IN CHAR16 *String
+ )
+{
+ return PrintAt (0, Column, Row, L"%s", String);
+}
+
+/**
+ Prints a unicode string to the default console, at
+ the supplied cursor position, using L"%s" format.
+
+ @param Column The cursor position to print the string at. When it is -1, use current Position.
+ @param Row The cursor position to print the string at. When it is -1, use current Position.
+ @param String String pointer.
+ @param Width Width for String.
+
+ @return Length of string printed to the console
+
+**/
+UINTN
+EFIAPI
+PrintStringAtWithWidth (
+ IN UINTN Column,
+ IN UINTN Row,
+ IN CHAR16 *String,
+ IN UINTN Width
+ )
+{
+ return PrintAt (Width, Column, Row, L"%s", String);
+}
+
+/**
+ Prints a chracter to the default console, at
+ the supplied cursor position, using L"%c" format.
+
+ @param Column The cursor position to print the string at. When it is -1, use current Position.
+ @param Row The cursor position to print the string at. When it is -1, use current Position.
+ @param Character Character to print.
+
+ @return Length of string printed to the console.
+
+**/
+UINTN
+EFIAPI
+PrintCharAt (
+ IN UINTN Column,
+ IN UINTN Row,
+ CHAR16 Character
+ )
+{
+ return PrintAt (0, Column, Row, L"%c", Character);
+}
+
+/**
+ Clear retangle with specified text attribute.
+
+ @param LeftColumn Left column of retangle.
+ @param RightColumn Right column of retangle.
+ @param TopRow Start row of retangle.
+ @param BottomRow End row of retangle.
+ @param TextAttribute The character foreground and background.
+
+**/
+VOID
+EFIAPI
+ClearLines (
+ IN UINTN LeftColumn,
+ IN UINTN RightColumn,
+ IN UINTN TopRow,
+ IN UINTN BottomRow,
+ IN 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
+ //
+ LibSetUnicodeMem (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);
+}
+
+//
+// Color Setting Functions
+//
+
+/**
+ Get OEM/Vendor specific popup attribute colors.
+
+ @retval Byte code color setting for popup color.
+**/
+UINT8
+EFIAPI
+GetPopupColor (
+ VOID
+ )
+{
+ return POPUP_TEXT | POPUP_BACKGROUND;
+}
+
+/**
+ Get OEM/Vendor specific popup attribute colors.
+
+ @retval Byte code color setting for popup inverse color.
+**/
+UINT8
+EFIAPI
+GetPopupInverseColor (
+ VOID
+ )
+{
+ return POPUP_INVERSE_TEXT | POPUP_INVERSE_BACKGROUND;
+}
+
+/**
+ Get OEM/Vendor specific PickList color attribute.
+
+ @retval Byte code color setting for pick list color.
+**/
+UINT8
+EFIAPI
+GetPickListColor (
+ VOID
+ )
+{
+ return PICKLIST_HIGHLIGHT_TEXT | PICKLIST_HIGHLIGHT_BACKGROUND;
+}
+
+/**
+ Get OEM/Vendor specific arrow color attribute.
+
+ @retval Byte code color setting for arrow color.
+**/
+UINT8
+EFIAPI
+GetArrowColor (
+ VOID
+ )
+{
+ return ARROW_TEXT | ARROW_BACKGROUND;
+}
+
+/**
+ Get OEM/Vendor specific info text color attribute.
+
+ @retval Byte code color setting for info text color.
+**/
+UINT8
+EFIAPI
+GetInfoTextColor (
+ VOID
+ )
+{
+ return INFO_TEXT | FIELD_BACKGROUND;
+}
+
+/**
+ Get OEM/Vendor specific help text color attribute.
+
+ @retval Byte code color setting for help text color.
+**/
+UINT8
+EFIAPI
+GetHelpTextColor (
+ VOID
+ )
+{
+ return HELP_TEXT | FIELD_BACKGROUND;
+}
+
+/**
+ Get OEM/Vendor specific grayed out text color attribute.
+
+ @retval Byte code color setting for grayed out text color.
+**/
+UINT8
+EFIAPI
+GetGrayedTextColor (
+ VOID
+ )
+{
+ return FIELD_TEXT_GRAYED | FIELD_BACKGROUND;
+}
+
+/**
+ Get OEM/Vendor specific highlighted text color attribute.
+
+ @retval Byte code color setting for highlight text color.
+**/
+UINT8
+EFIAPI
+GetHighlightTextColor (
+ VOID
+ )
+{
+ return PcdGet8 (PcdBrowserFieldTextHighlightColor) | PcdGet8 (PcdBrowserFieldBackgroundHighlightColor);
+}
+
+/**
+ Get OEM/Vendor specific field text color attribute.
+
+ @retval Byte code color setting for field text color.
+**/
+UINT8
+EFIAPI
+GetFieldTextColor (
+ VOID
+ )
+{
+ return PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND;
+}
+
+/**
+ Get OEM/Vendor specific subtitle text color attribute.
+
+ @retval Byte code color setting for subtitle text color.
+**/
+UINT8
+EFIAPI
+GetSubTitleTextColor (
+ VOID
+ )
+{
+ return PcdGet8 (PcdBrowserSubtitleTextColor) | FIELD_BACKGROUND;
+}
+
+/**
+ Clear Screen to the initial state.
+**/
+VOID
+EFIAPI
+ClearDisplayPage (
+ VOID
+ )
+{
+ gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));
+ gST->ConOut->ClearScreen (gST->ConOut);
+ gLibIsFirstForm = TRUE;
+}
+
+/**
+ Constructor of Customized Display Library Instance.
+
+ @param ImageHandle The firmware allocated handle for the EFI image.
+ @param SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS.
+
+**/
+EFI_STATUS
+EFIAPI
+CustomizedDisplayLibConstructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ mCDLStringPackHandle = HiiAddPackages (&gCustomizedDisplayLibGuid, ImageHandle, CustomizedDisplayLibStrings, NULL);
+ ASSERT (mCDLStringPackHandle != NULL);
+
+ InitializeLibStrings();
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Destructor of Customized Display Library Instance.
+
+ @param ImageHandle The firmware allocated handle for the EFI image.
+ @param SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The destructor completed successfully.
+ @retval Other value The destructor did not complete successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+CustomizedDisplayLibDestructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ HiiRemovePackages(mCDLStringPackHandle);
+
+ FreeLibStrings ();
+
+ return EFI_SUCCESS;
+}
+
diff --git a/MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.inf b/MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.inf
new file mode 100644
index 000000000..ade45b6a5
--- /dev/null
+++ b/MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.inf
@@ -0,0 +1,74 @@
+##
+# This file contains an 'Intel Peripheral Driver' and is
+# licensed for Intel CPUs and chipsets under the terms of your
+# license agreement with Intel or your vendor. This file may
+# be modified by the user, subject to additional terms of the
+# license agreement
+##
+## @file
+#
+# General BDS defines and produce general interfaces for platform BDS driver including:
+# 1) BDS boot policy interface;
+# 2) BDS boot device connect interface;
+# 3) BDS Misc interfaces for mainting boot variable, ouput string, etc.
+#
+# Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.<BR>
+# This software and associated documentation (if any) is furnished
+# under a license and may only be used or copied in accordance
+# with the terms of the license. Except as permitted by such
+# license, no part of this software or documentation may be
+# reproduced, stored in a retrieval system, or transmitted in any
+# form or by any means without the express written consent of
+# Intel Corporation.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = CustomizedDisplayLib
+ FILE_GUID = 80B92017-EC64-4923-938D-94FAEE85832E
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = CustomizedDisplayLib|DXE_DRIVER UEFI_APPLICATION
+ CONSTRUCTOR = CustomizedDisplayLibConstructor
+ DESTRUCTOR = CustomizedDisplayLibDestructor
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources]
+ CustomizedDisplayLib.c
+ Colors.h
+ CustomizedDisplayLibInternal.h
+ CustomizedDisplayLibInternal.c
+ CustomizedDisplayLib.uni
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ MemoryAllocationLib
+ BaseLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+ UefiRuntimeServicesTableLib
+ BaseMemoryLib
+ DebugLib
+ PrintLib
+ HiiLib
+ DevicePathLib
+ PcdLib
+
+[Guids]
+ gEfiIfrTianoGuid
+
+[Protocols]
+
+[Pcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdBrowserSubtitleTextColor ## CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdBrowserFieldTextColor ## CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdBrowserFieldTextHighlightColor ## CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdBrowserFieldBackgroundHighlightColor ## CONSUMES \ No newline at end of file
diff --git a/MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.uni b/MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.uni
new file mode 100644
index 000000000..18a5c3b56
--- /dev/null
+++ b/MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.uni
Binary files differ
diff --git a/MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLibInternal.c b/MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLibInternal.c
new file mode 100644
index 000000000..b6b4055b6
--- /dev/null
+++ b/MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLibInternal.c
@@ -0,0 +1,914 @@
+/** @file
+
+ This library class defines a set of interfaces to customize Display module
+
+Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that 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 "CustomizedDisplayLibInternal.h"
+
+EFI_SCREEN_DESCRIPTOR gScreenDimensions;
+CHAR16 *mLibUnknownString;
+extern EFI_HII_HANDLE mCDLStringPackHandle;
+CHAR16 *mSpaceBuffer;
+#define SPACE_BUFFER_SIZE 1000
+
+//
+// Browser Global Strings
+//
+CHAR16 *gEnterString;
+CHAR16 *gEnterCommitString;
+CHAR16 *gEnterEscapeString;
+CHAR16 *gEscapeString;
+CHAR16 *gMoveHighlight;
+CHAR16 *gDecNumericInput;
+CHAR16 *gHexNumericInput;
+CHAR16 *gToggleCheckBox;
+CHAR16 *gLibEmptyString;
+CHAR16 *gAreYouSure;
+CHAR16 *gYesResponse;
+CHAR16 *gNoResponse;
+CHAR16 *gPlusString;
+CHAR16 *gMinusString;
+CHAR16 *gAdjustNumber;
+CHAR16 *gSaveChanges;
+CHAR16 *gNvUpdateMessage;
+CHAR16 *gInputErrorMessage;
+
+/**
+
+ Print banner info for front page.
+
+ @param[in] FormData Form Data to be shown in Page
+
+**/
+VOID
+PrintBannerInfo (
+ IN FORM_DISPLAY_ENGINE_FORM *FormData
+ )
+{
+ UINT8 Line;
+ UINT8 Alignment;
+ CHAR16 *StrFrontPageBanner;
+ UINT8 RowIdx;
+ UINT8 ColumnIdx;
+
+ //
+ // ClearLines(0, LocalScreen.RightColumn, 0, BANNER_HEIGHT-1, BANNER_TEXT | BANNER_BACKGROUND);
+ //
+ ClearLines (
+ gScreenDimensions.LeftColumn,
+ gScreenDimensions.RightColumn,
+ gScreenDimensions.TopRow,
+ FRONT_PAGE_HEADER_HEIGHT - 1 + gScreenDimensions.TopRow,
+ BANNER_TEXT | BANNER_BACKGROUND
+ );
+
+ //
+ // for (Line = 0; Line < BANNER_HEIGHT; Line++) {
+ //
+ for (Line = (UINT8) gScreenDimensions.TopRow; Line < BANNER_HEIGHT + (UINT8) gScreenDimensions.TopRow; Line++) {
+ //
+ // for (Alignment = 0; Alignment < BANNER_COLUMNS; Alignment++) {
+ //
+ for (Alignment = (UINT8) gScreenDimensions.LeftColumn;
+ Alignment < BANNER_COLUMNS + (UINT8) gScreenDimensions.LeftColumn;
+ Alignment++
+ ) {
+ RowIdx = (UINT8) (Line - (UINT8) gScreenDimensions.TopRow);
+ ColumnIdx = (UINT8) (Alignment - (UINT8) gScreenDimensions.LeftColumn);
+
+ ASSERT (RowIdx < BANNER_HEIGHT && ColumnIdx < BANNER_COLUMNS);
+
+ if (gBannerData!= NULL && gBannerData->Banner[RowIdx][ColumnIdx] != 0x0000) {
+ StrFrontPageBanner = LibGetToken (gBannerData->Banner[RowIdx][ColumnIdx], FormData->HiiHandle);
+ } else {
+ continue;
+ }
+
+ switch (Alignment - gScreenDimensions.LeftColumn) {
+ case 0:
+ //
+ // Handle left column
+ //
+ PrintStringAt (gScreenDimensions.LeftColumn + BANNER_LEFT_COLUMN_INDENT, Line, StrFrontPageBanner);
+ break;
+
+ case 1:
+ //
+ // Handle center column
+ //
+ PrintStringAt (
+ gScreenDimensions.LeftColumn + (gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn) / 3,
+ Line,
+ StrFrontPageBanner
+ );
+ break;
+
+ case 2:
+ //
+ // Handle right column
+ //
+ PrintStringAt (
+ gScreenDimensions.LeftColumn + (gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn) * 2 / 3,
+ Line,
+ StrFrontPageBanner
+ );
+ break;
+ }
+
+ FreePool (StrFrontPageBanner);
+ }
+ }
+}
+
+/**
+ Print framework and form title for a page.
+
+ @param[in] FormData Form Data to be shown in Page
+**/
+VOID
+PrintFramework (
+ IN FORM_DISPLAY_ENGINE_FORM *FormData
+ )
+{
+ UINTN Index;
+ CHAR16 Character;
+ CHAR16 *Buffer;
+ UINTN Row;
+ CHAR16 *TitleStr;
+
+ if (gClassOfVfr != FORMSET_CLASS_PLATFORM_SETUP) {
+ //
+ // Only Setup page needs Framework
+ //
+ ClearLines (
+ gScreenDimensions.LeftColumn,
+ gScreenDimensions.RightColumn,
+ gScreenDimensions.BottomRow - STATUS_BAR_HEIGHT - gFooterHeight,
+ gScreenDimensions.BottomRow - STATUS_BAR_HEIGHT - 1,
+ KEYHELP_TEXT | KEYHELP_BACKGROUND
+ );
+ return;
+ }
+
+ Buffer = AllocateZeroPool (0x10000);
+ ASSERT (Buffer != NULL);
+ Character = BOXDRAW_HORIZONTAL;
+ for (Index = 0; Index + 2 < (gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn); Index++) {
+ Buffer[Index] = Character;
+ }
+
+ //
+ // Print Top border line
+ // +------------------------------------------------------------------------------+
+ // ? ?
+ // +------------------------------------------------------------------------------+
+ //
+ gST->ConOut->SetAttribute (gST->ConOut, TITLE_TEXT | TITLE_BACKGROUND);
+ Character = BOXDRAW_DOWN_RIGHT;
+
+ PrintCharAt (gScreenDimensions.LeftColumn, gScreenDimensions.TopRow, Character);
+ PrintStringAt ((UINTN) -1, (UINTN) -1, Buffer);
+
+ Character = BOXDRAW_DOWN_LEFT;
+ PrintCharAt ((UINTN) -1, (UINTN) -1, Character);
+
+ Character = BOXDRAW_VERTICAL;
+ for (Row = gScreenDimensions.TopRow + 1; Row <= gScreenDimensions.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT - 2; Row++) {
+ PrintCharAt (gScreenDimensions.LeftColumn, Row, Character);
+ PrintCharAt (gScreenDimensions.RightColumn - 1, Row, Character);
+ }
+
+ //
+ // Print Form Title
+ //
+ ClearLines (
+ gScreenDimensions.LeftColumn + 1,
+ gScreenDimensions.RightColumn - 1,
+ gScreenDimensions.TopRow + 1,
+ gScreenDimensions.TopRow + 1,
+ TITLE_TEXT | TITLE_BACKGROUND
+ );
+
+ TitleStr = LibGetToken (FormData->FormTitle, FormData->HiiHandle);
+ ASSERT (TitleStr != NULL);
+ PrintStringAt (
+ (gScreenDimensions.RightColumn + gScreenDimensions.LeftColumn - LibGetStringWidth (TitleStr) / 2) / 2,
+ gScreenDimensions.TopRow + 1,
+ TitleStr
+ );
+ FreePool (TitleStr);
+
+ Character = BOXDRAW_UP_RIGHT;
+ PrintCharAt (gScreenDimensions.LeftColumn, gScreenDimensions.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT - 1, Character);
+ PrintStringAt ((UINTN) -1, (UINTN) -1, Buffer);
+
+ Character = BOXDRAW_UP_LEFT;
+ PrintCharAt ((UINTN) -1, (UINTN) -1, Character);
+
+ //
+ // Print Bottom border line
+ // +------------------------------------------------------------------------------+
+ // ? ?
+ // +------------------------------------------------------------------------------+
+ //
+ Character = BOXDRAW_DOWN_RIGHT;
+ PrintCharAt (gScreenDimensions.LeftColumn, gScreenDimensions.BottomRow - STATUS_BAR_HEIGHT - gFooterHeight, Character);
+
+ PrintStringAt ((UINTN) -1, (UINTN) -1, Buffer);
+
+ Character = BOXDRAW_DOWN_LEFT;
+ PrintCharAt ((UINTN) -1, (UINTN) -1, Character);
+ Character = BOXDRAW_VERTICAL;
+ for (Row = gScreenDimensions.BottomRow - STATUS_BAR_HEIGHT - gFooterHeight + 1;
+ Row <= gScreenDimensions.BottomRow - STATUS_BAR_HEIGHT - 2;
+ Row++
+ ) {
+ PrintCharAt (gScreenDimensions.LeftColumn, Row, Character);
+ PrintCharAt (gScreenDimensions.RightColumn - 1, Row, Character);
+ }
+
+ Character = BOXDRAW_UP_RIGHT;
+ PrintCharAt (gScreenDimensions.LeftColumn, gScreenDimensions.BottomRow - STATUS_BAR_HEIGHT - 1, Character);
+
+ PrintStringAt ((UINTN) -1, (UINTN) -1, Buffer);
+
+ Character = BOXDRAW_UP_LEFT;
+ PrintCharAt ((UINTN) -1, (UINTN) -1, Character);
+
+ FreePool (Buffer);
+}
+
+/**
+ Process some op code which is not recognized by browser core.
+
+ @param OpCodeData The pointer to the op code buffer.
+
+ @return EFI_SUCCESS Pass the statement success.
+
+**/
+VOID
+ProcessUserOpcode(
+ IN EFI_IFR_OP_HEADER *OpCodeData
+ )
+{
+ switch (OpCodeData->OpCode) {
+ case EFI_IFR_GUID_OP:
+ if (CompareGuid (&gEfiIfrTianoGuid, (EFI_GUID *)((CHAR8*) OpCodeData + sizeof (EFI_IFR_OP_HEADER)))) {
+ //
+ // Tiano specific GUIDed opcodes
+ //
+ switch (((EFI_IFR_GUID_LABEL *) OpCodeData)->ExtendOpCode) {
+ case EFI_IFR_EXTEND_OP_LABEL:
+ //
+ // just ignore label
+ //
+ break;
+
+ case EFI_IFR_EXTEND_OP_BANNER:
+ //
+ // Only in front page form set, we care about the banner data.
+ //
+ if (gClassOfVfr == FORMSET_CLASS_FRONT_PAGE) {
+ //
+ // Initialize Driver private data
+ //
+ if (gBannerData == NULL) {
+ gBannerData = AllocateZeroPool (sizeof (BANNER_DATA));
+ ASSERT (gBannerData != NULL);
+ }
+
+ CopyMem (
+ &gBannerData->Banner[((EFI_IFR_GUID_BANNER *) OpCodeData)->LineNumber][
+ ((EFI_IFR_GUID_BANNER *) OpCodeData)->Alignment],
+ &((EFI_IFR_GUID_BANNER *) OpCodeData)->Title,
+ sizeof (EFI_STRING_ID)
+ );
+ }
+ break;
+
+ case EFI_IFR_EXTEND_OP_SUBCLASS:
+ if (((EFI_IFR_GUID_SUBCLASS *) OpCodeData)->SubClass == EFI_FRONT_PAGE_SUBCLASS) {
+ gClassOfVfr = FORMSET_CLASS_FRONT_PAGE;
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+/**
+ Process some op codes which is out side of current form.
+
+ @param FormData Pointer to the form data.
+
+ @return EFI_SUCCESS Pass the statement success.
+
+**/
+VOID
+ProcessExternedOpcode (
+ IN FORM_DISPLAY_ENGINE_FORM *FormData
+ )
+{
+ LIST_ENTRY *Link;
+ FORM_DISPLAY_ENGINE_STATEMENT *Statement;
+
+ Link = GetFirstNode (&FormData->StatementListOSF);
+ while (!IsNull (&FormData->StatementListOSF, Link)) {
+ Statement = FORM_DISPLAY_ENGINE_STATEMENT_FROM_LINK (Link);
+ Link = GetNextNode (&FormData->StatementListOSF, Link);
+
+ ProcessUserOpcode(Statement->OpCode);
+ }
+
+ Link = GetFirstNode (&FormData->StatementListHead);
+ while (!IsNull (&FormData->StatementListHead, Link)) {
+ Statement = FORM_DISPLAY_ENGINE_STATEMENT_FROM_LINK (Link);
+ Link = GetNextNode (&FormData->StatementListHead, Link);
+
+ ProcessUserOpcode(Statement->OpCode);
+ }
+}
+
+/**
+ Validate the input screen diemenstion info.
+
+ @param FormData The input form data info.
+
+ @return EFI_SUCCESS The input screen info is acceptable.
+ @return EFI_INVALID_PARAMETER The input screen info is not acceptable.
+
+**/
+EFI_STATUS
+ScreenDiemensionInfoValidate (
+ IN FORM_DISPLAY_ENGINE_FORM *FormData
+ )
+{
+ LIST_ENTRY *Link;
+ UINTN Index;
+
+ //
+ // Calculate total number of Register HotKeys.
+ //
+ Index = 0;
+ if (!IsListEmpty (&FormData->HotKeyListHead)){
+ Link = GetFirstNode (&FormData->HotKeyListHead);
+ while (!IsNull (&FormData->HotKeyListHead, Link)) {
+ Link = GetNextNode (&FormData->HotKeyListHead, Link);
+ Index ++;
+ }
+ }
+
+ //
+ // Show three HotKeys help information on one row.
+ //
+ gFooterHeight = FOOTER_HEIGHT + (Index / 3);
+
+
+ ZeroMem (&gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));
+ gST->ConOut->QueryMode (
+ gST->ConOut,
+ gST->ConOut->Mode->Mode,
+ &gScreenDimensions.RightColumn,
+ &gScreenDimensions.BottomRow
+ );
+
+ //
+ // Check local dimension vs. global dimension.
+ //
+ if (FormData->ScreenDimensions != NULL) {
+ if ((gScreenDimensions.RightColumn < FormData->ScreenDimensions->RightColumn) ||
+ (gScreenDimensions.BottomRow < FormData->ScreenDimensions->BottomRow)
+ ) {
+ return EFI_INVALID_PARAMETER;
+ } else {
+ //
+ // Local dimension validation.
+ //
+ if ((FormData->ScreenDimensions->RightColumn > FormData->ScreenDimensions->LeftColumn) &&
+ (FormData->ScreenDimensions->BottomRow > FormData->ScreenDimensions->TopRow) &&
+ ((FormData->ScreenDimensions->RightColumn - FormData->ScreenDimensions->LeftColumn) > 2) &&
+ ((FormData->ScreenDimensions->BottomRow - FormData->ScreenDimensions->TopRow) > STATUS_BAR_HEIGHT +
+ FRONT_PAGE_HEADER_HEIGHT + gFooterHeight + 3)) {
+ CopyMem (&gScreenDimensions, (VOID *) FormData->ScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));
+ } else {
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Get the string based on the StringId and HII Package List Handle.
+
+ @param Token The String's ID.
+ @param HiiHandle The package list in the HII database to search for
+ the specified string.
+
+ @return The output string.
+
+**/
+CHAR16 *
+LibGetToken (
+ IN EFI_STRING_ID Token,
+ IN EFI_HII_HANDLE HiiHandle
+ )
+{
+ EFI_STRING String;
+
+ String = HiiGetString (HiiHandle, Token, NULL);
+ if (String == NULL) {
+ String = AllocateCopyPool (StrSize (mLibUnknownString), mLibUnknownString);
+ ASSERT (String != NULL);
+ }
+
+ return (CHAR16 *) String;
+}
+
+
+/**
+ Count the storage space of a Unicode string.
+
+ This function handles the Unicode string with NARROW_CHAR
+ and WIDE_CHAR control characters. NARROW_HCAR and WIDE_CHAR
+ does not count in the resultant output. If a WIDE_CHAR is
+ hit, then 2 Unicode character will consume an output storage
+ space with size of CHAR16 till a NARROW_CHAR is hit.
+
+ If String is NULL, then ASSERT ().
+
+ @param String The input string to be counted.
+
+ @return Storage space for the input string.
+
+**/
+UINTN
+LibGetStringWidth (
+ IN CHAR16 *String
+ )
+{
+ UINTN Index;
+ UINTN Count;
+ UINTN IncrementValue;
+
+ ASSERT (String != NULL);
+ if (String == NULL) {
+ return 0;
+ }
+
+ 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);
+}
+
+/**
+ Show all registered HotKey help strings on bottom Rows.
+
+ @param FormData The curent input form data info.
+
+**/
+VOID
+PrintHotKeyHelpString (
+ IN FORM_DISPLAY_ENGINE_FORM *FormData
+ )
+{
+ UINTN CurrentCol;
+ UINTN CurrentRow;
+ UINTN BottomRowOfHotKeyHelp;
+ UINTN ColumnWidth;
+ UINTN Index;
+ EFI_SCREEN_DESCRIPTOR LocalScreen;
+ LIST_ENTRY *Link;
+ BROWSER_HOT_KEY *HotKey;
+
+ if (IsListEmpty (&FormData->HotKeyListHead)) {
+ return;
+ }
+
+ CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));
+ ColumnWidth = (LocalScreen.RightColumn - LocalScreen.LeftColumn) / 3;
+ BottomRowOfHotKeyHelp = LocalScreen.BottomRow - STATUS_BAR_HEIGHT - 3;
+
+ //
+ // Calculate total number of Register HotKeys.
+ //
+ Index = 0;
+ Link = GetFirstNode (&FormData->HotKeyListHead);
+ while (!IsNull (&FormData->HotKeyListHead, Link)) {
+ HotKey = BROWSER_HOT_KEY_FROM_LINK (Link);
+ //
+ // Help string can't exceed ColumnWidth. One Row will show three Help information.
+ //
+ if (StrLen (HotKey->HelpString) > ColumnWidth) {
+ HotKey->HelpString[ColumnWidth] = L'\0';
+ }
+ //
+ // Calculate help information Column and Row.
+ //
+ if ((Index % 3) != 2) {
+ CurrentCol = LocalScreen.LeftColumn + (2 - Index % 3) * ColumnWidth;
+ } else {
+ CurrentCol = LocalScreen.LeftColumn + 2;
+ }
+ CurrentRow = BottomRowOfHotKeyHelp - Index / 3;
+ //
+ // Print HotKey help string on bottom Row.
+ //
+ PrintStringAt (CurrentCol, CurrentRow, HotKey->HelpString);
+
+ //
+ // Get Next Hot Key.
+ //
+ Link = GetNextNode (&FormData->HotKeyListHead, Link);
+ Index ++;
+ }
+
+ return;
+}
+
+/**
+ Get step info from numeric opcode.
+
+ @param[in] OpCode The input numeric op code.
+
+ @return step info for this opcode.
+**/
+UINT64
+LibGetFieldFromNum (
+ IN EFI_IFR_OP_HEADER *OpCode
+ )
+{
+ EFI_IFR_NUMERIC *NumericOp;
+ UINT64 Step;
+
+ NumericOp = (EFI_IFR_NUMERIC *) OpCode;
+
+ switch (NumericOp->Flags & EFI_IFR_NUMERIC_SIZE) {
+ case EFI_IFR_NUMERIC_SIZE_1:
+ Step = NumericOp->data.u8.Step;
+ break;
+
+ case EFI_IFR_NUMERIC_SIZE_2:
+ Step = NumericOp->data.u16.Step;
+ break;
+
+ case EFI_IFR_NUMERIC_SIZE_4:
+ Step = NumericOp->data.u32.Step;
+ break;
+
+ case EFI_IFR_NUMERIC_SIZE_8:
+ Step = NumericOp->data.u64.Step;
+ break;
+
+ default:
+ Step = 0;
+ break;
+ }
+
+ return Step;
+}
+
+/**
+ Initialize the HII String Token to the correct values.
+
+**/
+VOID
+InitializeLibStrings (
+ VOID
+ )
+{
+ mLibUnknownString = L"!";
+
+ gEnterString = LibGetToken (STRING_TOKEN (ENTER_STRING), mCDLStringPackHandle);
+ gEnterCommitString = LibGetToken (STRING_TOKEN (ENTER_COMMIT_STRING), mCDLStringPackHandle);
+ gEnterEscapeString = LibGetToken (STRING_TOKEN (ENTER_ESCAPE_STRING), mCDLStringPackHandle);
+ gEscapeString = LibGetToken (STRING_TOKEN (ESCAPE_STRING), mCDLStringPackHandle);
+ gMoveHighlight = LibGetToken (STRING_TOKEN (MOVE_HIGHLIGHT), mCDLStringPackHandle);
+ gDecNumericInput = LibGetToken (STRING_TOKEN (DEC_NUMERIC_INPUT), mCDLStringPackHandle);
+ gHexNumericInput = LibGetToken (STRING_TOKEN (HEX_NUMERIC_INPUT), mCDLStringPackHandle);
+ gToggleCheckBox = LibGetToken (STRING_TOKEN (TOGGLE_CHECK_BOX), mCDLStringPackHandle);
+
+ gAreYouSure = LibGetToken (STRING_TOKEN (ARE_YOU_SURE), mCDLStringPackHandle);
+ gYesResponse = LibGetToken (STRING_TOKEN (ARE_YOU_SURE_YES), mCDLStringPackHandle);
+ gNoResponse = LibGetToken (STRING_TOKEN (ARE_YOU_SURE_NO), mCDLStringPackHandle);
+ gPlusString = LibGetToken (STRING_TOKEN (PLUS_STRING), mCDLStringPackHandle);
+ gMinusString = LibGetToken (STRING_TOKEN (MINUS_STRING), mCDLStringPackHandle);
+ gAdjustNumber = LibGetToken (STRING_TOKEN (ADJUST_NUMBER), mCDLStringPackHandle);
+ gSaveChanges = LibGetToken (STRING_TOKEN (SAVE_CHANGES), mCDLStringPackHandle);
+
+ gLibEmptyString = LibGetToken (STRING_TOKEN (EMPTY_STRING), mCDLStringPackHandle);
+
+ gNvUpdateMessage = LibGetToken (STRING_TOKEN (NV_UPDATE_MESSAGE), mCDLStringPackHandle);
+ gInputErrorMessage = LibGetToken (STRING_TOKEN (INPUT_ERROR_MESSAGE), mCDLStringPackHandle);
+
+ //
+ // SpaceBuffer;
+ //
+ mSpaceBuffer = AllocatePool ((SPACE_BUFFER_SIZE + 1) * sizeof (CHAR16));
+ ASSERT (mSpaceBuffer != NULL);
+ LibSetUnicodeMem (mSpaceBuffer, SPACE_BUFFER_SIZE, L' ');
+ mSpaceBuffer[SPACE_BUFFER_SIZE] = L'\0';
+}
+
+
+/**
+ Free the HII String.
+
+**/
+VOID
+FreeLibStrings (
+ VOID
+ )
+{
+ FreePool (gEnterString);
+ FreePool (gEnterCommitString);
+ FreePool (gEnterEscapeString);
+ FreePool (gEscapeString);
+ FreePool (gMoveHighlight);
+ FreePool (gDecNumericInput);
+ FreePool (gHexNumericInput);
+ FreePool (gToggleCheckBox);
+
+ FreePool (gAreYouSure);
+ FreePool (gYesResponse);
+ FreePool (gNoResponse);
+ FreePool (gPlusString);
+ FreePool (gMinusString);
+ FreePool (gAdjustNumber);
+ FreePool (gSaveChanges);
+
+ FreePool (gLibEmptyString);
+
+ FreePool (gNvUpdateMessage);
+ FreePool (gInputErrorMessage);
+
+ FreePool (mSpaceBuffer);
+}
+
+/**
+ Wait for a key to be pressed by user.
+
+ @param Key The key which is pressed by user.
+
+ @retval EFI_SUCCESS The function always completed successfully.
+
+**/
+EFI_STATUS
+WaitForKeyStroke (
+ OUT EFI_INPUT_KEY *Key
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+
+ while (TRUE) {
+ Status = gST->ConIn->ReadKeyStroke (gST->ConIn, Key);
+ if (!EFI_ERROR (Status)) {
+ break;
+ }
+
+ if (Status != EFI_NOT_READY) {
+ continue;
+ }
+
+ gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &Index);
+ }
+ return Status;
+}
+
+
+/**
+ Set Buffer to Value for Size bytes.
+
+ @param Buffer Memory to set.
+ @param Size Number of bytes to set
+ @param Value Value of the set operation.
+
+**/
+VOID
+LibSetUnicodeMem (
+ IN VOID *Buffer,
+ IN UINTN Size,
+ IN CHAR16 Value
+ )
+{
+ CHAR16 *Ptr;
+
+ Ptr = Buffer;
+ while ((Size--) != 0) {
+ *(Ptr++) = Value;
+ }
+}
+
+/**
+ The internal function prints to the EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
+ protocol instance.
+
+ @param Width Width of string to be print.
+ @param Column The position of the output string.
+ @param Row The position of the output string.
+ @param Out The EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL instance.
+ @param Fmt The format string.
+ @param Args The additional argument for the variables in the format string.
+
+ @return Number of Unicode character printed.
+
+**/
+UINTN
+PrintInternal (
+ IN UINTN Width,
+ IN UINTN Column,
+ IN UINTN Row,
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *Out,
+ IN CHAR16 *Fmt,
+ IN VA_LIST Args
+ )
+{
+ CHAR16 *Buffer;
+ CHAR16 *BackupBuffer;
+ UINTN Index;
+ UINTN PreviousIndex;
+ UINTN Count;
+ UINTN PrintWidth;
+ UINTN CharWidth;
+
+ //
+ // 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;
+ Count = 0;
+ PrintWidth = 0;
+ CharWidth = 1;
+
+ 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]);
+ Count += StrLen (&BackupBuffer[PreviousIndex]);
+ PrintWidth += Count * CharWidth;
+
+ //
+ // 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);
+ CharWidth = 1;
+ } else {
+ //
+ // Must be wide, set bit 7 ON
+ //
+ Out->Mode->Attribute = Out->Mode->Attribute | EFI_WIDE_ATTRIBUTE;
+ Out->SetAttribute (Out, Out->Mode->Attribute);
+ CharWidth = 2;
+ }
+
+ Index++;
+
+ } while (Buffer[Index] != 0);
+
+ //
+ // We hit the end of the string - print it
+ //
+ Out->OutputString (Out, &BackupBuffer[PreviousIndex]);
+ Count += StrLen (&BackupBuffer[PreviousIndex]);
+ PrintWidth += Count * CharWidth;
+ if (PrintWidth < Width) {
+ Out->Mode->Attribute = Out->Mode->Attribute & 0x7f;
+ Out->SetAttribute (Out, Out->Mode->Attribute);
+ Out->OutputString (Out, &mSpaceBuffer[SPACE_BUFFER_SIZE - Width + PrintWidth]);
+ }
+
+ FreePool (Buffer);
+ FreePool (BackupBuffer);
+ return Count;
+}
+
+/**
+ Prints a formatted unicode string to the default console, at
+ the supplied cursor position.
+
+ @param Width Width of String to be printed.
+ @param Column The cursor position to print the string at.
+ @param Row The cursor position to print the string at.
+ @param Fmt Format string.
+ @param ... Variable argument list for format string.
+
+ @return Length of string printed to the console
+
+**/
+UINTN
+EFIAPI
+PrintAt (
+ IN UINTN Width,
+ IN UINTN Column,
+ IN UINTN Row,
+ IN CHAR16 *Fmt,
+ ...
+ )
+{
+ VA_LIST Args;
+ UINTN LengthOfPrinted;
+
+ VA_START (Args, Fmt);
+ LengthOfPrinted = PrintInternal (Width, Column, Row, gST->ConOut, Fmt, Args);
+ VA_END (Args);
+ return LengthOfPrinted;
+}
+
diff --git a/MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLibInternal.h b/MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLibInternal.h
new file mode 100644
index 000000000..ccbd45f42
--- /dev/null
+++ b/MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLibInternal.h
@@ -0,0 +1,295 @@
+/** @file
+
+ This library class defines a set of interfaces to customize Display module
+
+Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that 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 __CUSTOMIZED_DISPLAY_LIB_INTERNAL_H__
+#define __CUSTOMIZED_DISPLAY_LIB_INTERNAL_H__
+
+
+
+#include <PiDxe.h>
+
+#include <Protocol/SimpleTextOut.h>
+#include <Protocol/SimpleTextIn.h>
+#include <Protocol/FormBrowser2.h>
+#include <Protocol/FormBrowserEx2.h>
+#include <Protocol/DisplayProtocol.h>
+#include <Protocol/DevicePath.h>
+#include <Protocol/UnicodeCollation.h>
+#include <Protocol/HiiConfigAccess.h>
+#include <Protocol/HiiConfigRouting.h>
+#include <Protocol/HiiDatabase.h>
+#include <Protocol/HiiString.h>
+#include <Protocol/UserManager.h>
+#include <Protocol/DevicePathFromText.h>
+
+#include <Guid/MdeModuleHii.h>
+#include <Guid/HiiPlatformSetupFormset.h>
+#include <Guid/HiiFormMapMethodGuid.h>
+
+#include <Library/PrintLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/BaseLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/HiiLib.h>
+#include <Library/PcdLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/CustomizedDisplayLib.h>
+
+#include "Colors.h"
+
+
+
+#define FORMSET_CLASS_PLATFORM_SETUP 0x0001
+#define FORMSET_CLASS_FRONT_PAGE 0x0002
+
+
+#define FRONT_PAGE_HEADER_HEIGHT 6
+#define NONE_FRONT_PAGE_HEADER_HEIGHT 3
+#define FOOTER_HEIGHT 4
+#define STATUS_BAR_HEIGHT 1
+
+//
+// Screen definitions
+//
+#define BANNER_HEIGHT 6
+#define BANNER_COLUMNS 3
+#define BANNER_LEFT_COLUMN_INDENT 1
+
+//
+// Character definitions
+//
+#define UPPER_LOWER_CASE_OFFSET 0x20
+
+//
+// This is the Input Error Message
+//
+#define INPUT_ERROR 1
+
+//
+// This is the NV RAM update required Message
+//
+#define NV_UPDATE_REQUIRED 2
+
+typedef struct {
+ EFI_STRING_ID Banner[BANNER_HEIGHT][BANNER_COLUMNS];
+} BANNER_DATA;
+
+extern UINT16 gClassOfVfr; // Formset class information
+extern BANNER_DATA *gBannerData;
+extern EFI_SCREEN_DESCRIPTOR gScreenDimensions;
+extern UINTN gFooterHeight;
+
+//
+// Browser Global Strings
+//
+extern CHAR16 *gEnterString;
+extern CHAR16 *gEnterCommitString;
+extern CHAR16 *gEnterEscapeString;
+extern CHAR16 *gEscapeString;
+extern CHAR16 *gMoveHighlight;
+extern CHAR16 *gDecNumericInput;
+extern CHAR16 *gHexNumericInput;
+extern CHAR16 *gToggleCheckBox;
+extern CHAR16 *gLibEmptyString;
+extern CHAR16 *gAreYouSure;
+extern CHAR16 *gYesResponse;
+extern CHAR16 *gNoResponse;
+extern CHAR16 *gPlusString;
+extern CHAR16 *gMinusString;
+extern CHAR16 *gAdjustNumber;
+extern CHAR16 *gSaveChanges;
+extern CHAR16 *gNvUpdateMessage;
+extern CHAR16 *gInputErrorMessage;
+/**
+
+ Print banner info for front page.
+
+ @param[in] FormData Form Data to be shown in Page
+
+**/
+VOID
+PrintBannerInfo (
+ IN FORM_DISPLAY_ENGINE_FORM *FormData
+ );
+
+/**
+ Print framework and form title for a page.
+
+ @param[in] FormData Form Data to be shown in Page
+**/
+VOID
+PrintFramework (
+ IN FORM_DISPLAY_ENGINE_FORM *FormData
+ );
+
+/**
+ Validate the input screen diemenstion info.
+
+ @param FormData The input form data info.
+
+ @return EFI_SUCCESS The input screen info is acceptable.
+ @return EFI_INVALID_PARAMETER The input screen info is not acceptable.
+
+**/
+EFI_STATUS
+ScreenDiemensionInfoValidate (
+ IN FORM_DISPLAY_ENGINE_FORM *FormData
+ );
+
+/**
+ Get the string based on the StringId and HII Package List Handle.
+
+ @param Token The String's ID.
+ @param HiiHandle The package list in the HII database to search for
+ the specified string.
+
+ @return The output string.
+
+**/
+CHAR16 *
+LibGetToken (
+ IN EFI_STRING_ID Token,
+ IN EFI_HII_HANDLE HiiHandle
+ );
+
+/**
+ Count the storage space of a Unicode string.
+
+ This function handles the Unicode string with NARROW_CHAR
+ and WIDE_CHAR control characters. NARROW_HCAR and WIDE_CHAR
+ does not count in the resultant output. If a WIDE_CHAR is
+ hit, then 2 Unicode character will consume an output storage
+ space with size of CHAR16 till a NARROW_CHAR is hit.
+
+ If String is NULL, then ASSERT ().
+
+ @param String The input string to be counted.
+
+ @return Storage space for the input string.
+
+**/
+UINTN
+LibGetStringWidth (
+ IN CHAR16 *String
+ );
+
+/**
+ Show all registered HotKey help strings on bottom Rows.
+
+ @param FormData The curent input form data info.
+
+**/
+VOID
+PrintHotKeyHelpString (
+ IN FORM_DISPLAY_ENGINE_FORM *FormData
+ );
+
+/**
+ Get step info from numeric opcode.
+
+ @param[in] OpCode The input numeric op code.
+
+ @return step info for this opcode.
+**/
+UINT64
+LibGetFieldFromNum (
+ IN EFI_IFR_OP_HEADER *OpCode
+ );
+
+/**
+ Initialize the HII String Token to the correct values.
+
+**/
+VOID
+InitializeLibStrings (
+ VOID
+ );
+
+/**
+ Free the HII String.
+
+**/
+VOID
+FreeLibStrings (
+ VOID
+ );
+
+/**
+ Wait for a key to be pressed by user.
+
+ @param Key The key which is pressed by user.
+
+ @retval EFI_SUCCESS The function always completed successfully.
+
+**/
+EFI_STATUS
+WaitForKeyStroke (
+ OUT EFI_INPUT_KEY *Key
+ );
+
+/**
+ Set Buffer to Value for Size bytes.
+
+ @param Buffer Memory to set.
+ @param Size Number of bytes to set
+ @param Value Value of the set operation.
+
+**/
+VOID
+LibSetUnicodeMem (
+ IN VOID *Buffer,
+ IN UINTN Size,
+ IN CHAR16 Value
+ );
+
+/**
+ Prints a formatted unicode string to the default console, at
+ the supplied cursor position.
+
+ @param Width Width of String to be printed.
+ @param Column The cursor position to print the string at.
+ @param Row The cursor position to print the string at.
+ @param Fmt Format string.
+ @param ... Variable argument list for format string.
+
+ @return Length of string printed to the console
+
+**/
+UINTN
+EFIAPI
+PrintAt (
+ IN UINTN Width,
+ IN UINTN Column,
+ IN UINTN Row,
+ IN CHAR16 *Fmt,
+ ...
+ );
+
+/**
+ Process some op codes which is out side of current form.
+
+ @param FormData Pointer to the form data.
+
+**/
+VOID
+ProcessExternedOpcode (
+ IN FORM_DISPLAY_ENGINE_FORM *FormData
+ );
+
+#endif
diff --git a/MdeModulePkg/Library/UefiHiiLib/HiiLib.c b/MdeModulePkg/Library/UefiHiiLib/HiiLib.c
index 9590f8f14..f48f42fcd 100644
--- a/MdeModulePkg/Library/UefiHiiLib/HiiLib.c
+++ b/MdeModulePkg/Library/UefiHiiLib/HiiLib.c
@@ -31,6 +31,11 @@ typedef struct {
UINT8 Scope;
} IFR_BLOCK_DATA;
+typedef struct {
+ EFI_VARSTORE_ID VarStoreId;
+ UINT16 Size;
+} IFR_VARSTORAGE_DATA;
+
//
// <ConfigHdr> Template
//
@@ -914,42 +919,92 @@ InternalHiiGetValueOfNumber (
}
/**
+ Get value from config request resp string.
+
+ @param ConfigElement ConfigResp string contains the current setting.
+ @param VarName The variable name which need to get value.
+ @param VarValue The return value.
+
+ @retval EFI_SUCCESS Get the value for the VarName
+ @retval EFI_OUT_OF_RESOURCES The memory is not enough.
+**/
+EFI_STATUS
+GetValueFromRequest (
+ IN CHAR16 *ConfigElement,
+ IN CHAR16 *VarName,
+ OUT UINT64 *VarValue
+ )
+{
+ UINT8 *TmpBuffer;
+ CHAR16 *StringPtr;
+ UINTN Length;
+ EFI_STATUS Status;
+
+ //
+ // Find VarName related string.
+ //
+ StringPtr = StrStr (ConfigElement, VarName);
+ ASSERT (StringPtr != NULL);
+
+ //
+ // Skip the "VarName=" string
+ //
+ StringPtr += StrLen (VarName) + 1;
+
+ //
+ // Get Offset
+ //
+ Status = InternalHiiGetValueOfNumber (StringPtr, &TmpBuffer, &Length);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ *VarValue = 0;
+ CopyMem (VarValue, TmpBuffer, (((Length + 1) / 2) < sizeof (UINT64)) ? ((Length + 1) / 2) : sizeof (UINT64));
+
+ FreePool (TmpBuffer);
+
+ return EFI_SUCCESS;
+}
+
+/**
This internal function parses IFR data to validate current setting.
- @param ConfigResp ConfigResp string contains the current setting.
+ Base on the NameValueType, if it is TRUE, RequestElement and HiiHandle is valid;
+ else the VarBuffer and CurrentBlockArray is valid.
+
@param HiiPackageList Point to Hii package list.
@param PackageListLength The length of the pacakge.
@param VarGuid Guid of the buffer storage.
@param VarName Name of the buffer storage.
+ @param VarBuffer The data buffer for the storage.
+ @param CurrentBlockArray The block array from the config Requst string.
+ @param RequestElement The config string for this storage.
+ @param HiiHandle The HiiHandle for this formset.
+ @param NameValueType Whether current storage is name/value varstore or not.
@retval EFI_SUCCESS The current setting is valid.
@retval EFI_OUT_OF_RESOURCES The memory is not enough.
@retval EFI_INVALID_PARAMETER The config string or the Hii package is invalid.
**/
EFI_STATUS
-EFIAPI
-InternalHiiValidateCurrentSetting (
- IN EFI_STRING ConfigResp,
+ValidateQuestionFromVfr (
IN EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList,
IN UINTN PackageListLength,
IN EFI_GUID *VarGuid,
- IN CHAR16 *VarName
+ IN CHAR16 *VarName,
+ IN UINT8 *VarBuffer,
+ IN IFR_BLOCK_DATA *CurrentBlockArray,
+ IN CHAR16 *RequestElement,
+ IN EFI_HII_HANDLE HiiHandle,
+ IN BOOLEAN NameValueType
)
-{
- IFR_BLOCK_DATA *CurrentBlockArray;
- IFR_BLOCK_DATA *BlockData;
- IFR_BLOCK_DATA *NewBlockData;
+{
IFR_BLOCK_DATA VarBlockData;
- EFI_STRING StringPtr;
- UINTN Length;
- UINT8 *TmpBuffer;
UINT16 Offset;
UINT16 Width;
UINT64 VarValue;
EFI_IFR_TYPE_VALUE TmpValue;
- LIST_ENTRY *Link;
- UINT8 *VarBuffer;
- UINTN MaxBufferSize;
EFI_STATUS Status;
EFI_HII_PACKAGE_HEADER PacakgeHeader;
UINT32 PackageOffset;
@@ -957,6 +1012,9 @@ InternalHiiValidateCurrentSetting (
UINTN IfrOffset;
EFI_IFR_OP_HEADER *IfrOpHdr;
EFI_IFR_VARSTORE *IfrVarStore;
+ EFI_IFR_VARSTORE_NAME_VALUE *IfrNameValueStore;
+ EFI_IFR_VARSTORE_EFI *IfrEfiVarStore;
+ IFR_VARSTORAGE_DATA VarStoreData;
EFI_IFR_ONE_OF *IfrOneOf;
EFI_IFR_NUMERIC *IfrNumeric;
EFI_IFR_ONE_OF_OPTION *IfrOneOfOption;
@@ -964,230 +1022,29 @@ InternalHiiValidateCurrentSetting (
EFI_IFR_STRING *IfrString;
CHAR8 *VarStoreName;
UINTN Index;
-
- //
- // 1. Get the current setting to current block data array and Convert them into VarBuffer
- //
+ CHAR16 *QuestionName;
+ CHAR16 *StringPtr;
//
- // Skip ConfigHdr string
- //
- StringPtr = ConfigResp;
- StringPtr = StrStr (ConfigResp, L"&OFFSET");
- if (StringPtr == NULL) {
- //
- // No ConfigBlock value is required to be validated.
- // EFI_SUCCESS directly return.
- //
- return EFI_SUCCESS;
- }
-
- //
// Initialize the local variables.
//
- Index = 0;
- VarStoreName = NULL;
- Status = EFI_SUCCESS;
- BlockData = NULL;
- NewBlockData = NULL;
- TmpBuffer = NULL;
- MaxBufferSize = HII_LIB_DEFAULT_VARSTORE_SIZE;
- VarBuffer = AllocateZeroPool (MaxBufferSize);
- if (VarBuffer == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- //
- // Init CurrentBlockArray
- //
- CurrentBlockArray = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
- if (CurrentBlockArray == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto Done;
- }
- InitializeListHead (&CurrentBlockArray->Entry);
-
- //
- // Parse each <RequestElement> if exists
- // Only <BlockName> format is supported by this help function.
- // <BlockName> ::= &'OFFSET='<Number>&'WIDTH='<Number>
- //
- while (*StringPtr != 0 && StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) == 0) {
- //
- // Skip the &OFFSET= string
- //
- StringPtr += StrLen (L"&OFFSET=");
-
- //
- // Get Offset
- //
- Status = InternalHiiGetValueOfNumber (StringPtr, &TmpBuffer, &Length);
- if (EFI_ERROR (Status)) {
- goto Done;
- }
- Offset = 0;
- CopyMem (
- &Offset,
- TmpBuffer,
- (((Length + 1) / 2) < sizeof (UINT16)) ? ((Length + 1) / 2) : sizeof (UINT16)
- );
- FreePool (TmpBuffer);
- TmpBuffer = NULL;
-
- StringPtr += Length;
- if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {
- Status = EFI_INVALID_PARAMETER;
- goto Done;
- }
- StringPtr += StrLen (L"&WIDTH=");
-
- //
- // Get Width
- //
- Status = InternalHiiGetValueOfNumber (StringPtr, &TmpBuffer, &Length);
- if (EFI_ERROR (Status)) {
- goto Done;
- }
- Width = 0;
- CopyMem (
- &Width,
- TmpBuffer,
- (((Length + 1) / 2) < sizeof (UINT16)) ? ((Length + 1) / 2) : sizeof (UINT16)
- );
- FreePool (TmpBuffer);
- TmpBuffer = NULL;
-
- StringPtr += Length;
- if (*StringPtr != 0 && *StringPtr != L'&') {
- Status = EFI_INVALID_PARAMETER;
- goto Done;
- }
-
- if (StrnCmp (StringPtr, L"&VALUE=", StrLen (L"&VALUE=")) != 0) {
- Status = EFI_INVALID_PARAMETER;
- goto Done;
- }
- StringPtr += StrLen (L"&VALUE=");
-
- //
- // Get Value
- //
- Status = InternalHiiGetValueOfNumber (StringPtr, &TmpBuffer, &Length);
- if (EFI_ERROR (Status)) {
- goto Done;
- }
-
- StringPtr += Length;
- if (*StringPtr != 0 && *StringPtr != L'&') {
- Status = EFI_INVALID_PARAMETER;
- goto Done;
- }
-
- //
- // Check whether VarBuffer is enough
- //
- if ((UINTN) (Offset + Width) > MaxBufferSize) {
- VarBuffer = ReallocatePool (
- MaxBufferSize,
- Offset + Width + HII_LIB_DEFAULT_VARSTORE_SIZE,
- VarBuffer
- );
- if (VarBuffer == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto Done;
- }
- MaxBufferSize = Offset + Width + HII_LIB_DEFAULT_VARSTORE_SIZE;
- }
-
- //
- // Update the Block with configuration info
- //
- CopyMem (VarBuffer + Offset, TmpBuffer, Width);
- FreePool (TmpBuffer);
- TmpBuffer = NULL;
-
- //
- // Set new Block Data
- //
- NewBlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
- if (NewBlockData == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto Done;
- }
- NewBlockData->Offset = Offset;
- NewBlockData->Width = Width;
-
- //
- // Insert the new block data into the block data array.
- //
- for (Link = CurrentBlockArray->Entry.ForwardLink; Link != &CurrentBlockArray->Entry; Link = Link->ForwardLink) {
- BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);
- if (NewBlockData->Offset == BlockData->Offset) {
- if (NewBlockData->Width > BlockData->Width) {
- BlockData->Width = NewBlockData->Width;
- }
- FreePool (NewBlockData);
- break;
- } else if (NewBlockData->Offset < BlockData->Offset) {
- //
- // Insert new block data as the previous one of this link.
- //
- InsertTailList (Link, &NewBlockData->Entry);
- break;
- }
- }
-
- //
- // Insert new block data into the array tail.
- //
- if (Link == &CurrentBlockArray->Entry) {
- InsertTailList (Link, &NewBlockData->Entry);
- }
-
- //
- // If '\0', parsing is finished.
- //
- if (*StringPtr == 0) {
- break;
- }
- //
- // Go to next ConfigBlock
- //
- }
-
- //
- // Merge the aligned block data into the single block data.
- //
- Link = CurrentBlockArray->Entry.ForwardLink;
- while ((Link != &CurrentBlockArray->Entry) && (Link->ForwardLink != &CurrentBlockArray->Entry)) {
- BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);
- NewBlockData = BASE_CR (Link->ForwardLink, IFR_BLOCK_DATA, Entry);
- if ((NewBlockData->Offset >= BlockData->Offset) && (NewBlockData->Offset <= (BlockData->Offset + BlockData->Width))) {
- if ((NewBlockData->Offset + NewBlockData->Width) > (BlockData->Offset + BlockData->Width)) {
- BlockData->Width = (UINT16) (NewBlockData->Offset + NewBlockData->Width - BlockData->Offset);
- }
- RemoveEntryList (Link->ForwardLink);
- FreePool (NewBlockData);
- continue;
- }
- Link = Link->ForwardLink;
- }
-
- if (IsListEmpty (&CurrentBlockArray->Entry)) {
- Status = EFI_SUCCESS;
- goto Done;
- }
+ Index = 0;
+ VarStoreName = NULL;
+ Status = EFI_SUCCESS;
+ VarValue = 0;
+ IfrVarStore = NULL;
+ IfrNameValueStore = NULL;
+ IfrEfiVarStore = NULL;
+ ZeroMem (&VarStoreData, sizeof (IFR_VARSTORAGE_DATA));
+ ZeroMem (&VarBlockData, sizeof (VarBlockData));
//
- // 2. Check IFR value is in block data, then Validate Value
+ // Check IFR value is in block data, then Validate Value
//
- ZeroMem (&VarBlockData, sizeof (VarBlockData));
- VarValue = 0;
- IfrVarStore = NULL;
PackageOffset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);
while (PackageOffset < PackageListLength) {
CopyMem (&PacakgeHeader, (UINT8 *) HiiPackageList + PackageOffset, sizeof (PacakgeHeader));
-
+
//
// Parse IFR opcode from the form package.
//
@@ -1200,11 +1057,11 @@ InternalHiiValidateCurrentSetting (
// Validate current setting to the value built in IFR opcode
//
switch (IfrOpHdr->OpCode) {
- case EFI_IFR_VARSTORE_OP:
+ case EFI_IFR_VARSTORE_OP:
//
// VarStoreId has been found. No further found.
//
- if (IfrVarStore != NULL) {
+ if (VarStoreData.VarStoreId != 0) {
break;
}
//
@@ -1227,15 +1084,82 @@ InternalHiiValidateCurrentSetting (
} else {
IfrVarStore = NULL;
}
+
+ if (IfrVarStore != NULL) {
+ VarStoreData.VarStoreId = IfrVarStore->VarStoreId;
+ VarStoreData.Size = IfrVarStore->Size;
+ }
+ break;
+ case EFI_IFR_VARSTORE_NAME_VALUE_OP:
+ //
+ // VarStoreId has been found. No further found.
+ //
+ if (VarStoreData.VarStoreId != 0) {
+ break;
+ }
+ //
+ // Find the matched VarStoreId to the input VarGuid
+ //
+ IfrNameValueStore = (EFI_IFR_VARSTORE_NAME_VALUE *) IfrOpHdr;
+ if (!CompareGuid ((EFI_GUID *) (VOID *) &IfrNameValueStore->Guid, VarGuid)) {
+ IfrNameValueStore = NULL;
+ }
+
+ if (IfrNameValueStore != NULL) {
+ VarStoreData.VarStoreId = IfrNameValueStore->VarStoreId;
+ }
+ break;
+ case EFI_IFR_VARSTORE_EFI_OP:
+ //
+ // VarStore is found. Don't need to search any more.
+ //
+ if (VarStoreData.VarStoreId != 0) {
+ break;
+ }
+
+ IfrEfiVarStore = (EFI_IFR_VARSTORE_EFI *) IfrOpHdr;
+
+ //
+ // If the length is small than the structure, this is from old efi
+ // varstore definition. Old efi varstore get config directly from
+ // GetVariable function.
+ //
+ if (IfrOpHdr->Length < sizeof (EFI_IFR_VARSTORE_EFI)) {
+ break;
+ }
+
+ if (CompareGuid ((EFI_GUID *) (VOID *) &IfrEfiVarStore->Guid, VarGuid)) {
+ VarStoreName = (CHAR8 *) IfrEfiVarStore->Name;
+ for (Index = 0; VarStoreName[Index] != 0; Index ++) {
+ if ((CHAR16) VarStoreName[Index] != VarName[Index]) {
+ break;
+ }
+ }
+ //
+ // The matched VarStore is found.
+ //
+ if ((VarStoreName[Index] != 0) || (VarName[Index] != 0)) {
+ IfrEfiVarStore = NULL;
+ }
+ } else {
+ IfrEfiVarStore = NULL;
+ }
+
+ if (IfrEfiVarStore != NULL) {
+ //
+ // Find the matched VarStore
+ //
+ VarStoreData.VarStoreId = IfrEfiVarStore->VarStoreId;
+ VarStoreData.Size = IfrEfiVarStore->Size;
+ }
break;
case EFI_IFR_FORM_OP:
case EFI_IFR_FORM_MAP_OP:
//
// Check the matched VarStoreId is found.
//
- if (IfrVarStore == NULL) {
- Status = EFI_SUCCESS;
- goto Done;
+ if (VarStoreData.VarStoreId == 0) {
+ return EFI_SUCCESS;
}
break;
case EFI_IFR_ONE_OF_OP:
@@ -1246,53 +1170,66 @@ InternalHiiValidateCurrentSetting (
//
// OneOf question is not in IFR Form. This IFR form is not valid.
//
- if (IfrVarStore == NULL) {
- Status = EFI_INVALID_PARAMETER;
- goto Done;
+ if (VarStoreData.VarStoreId == 0) {
+ return EFI_INVALID_PARAMETER;
}
//
// Check whether this question is for the requested varstore.
//
IfrOneOf = (EFI_IFR_ONE_OF *) IfrOpHdr;
- if (IfrOneOf->Question.VarStoreId != IfrVarStore->VarStoreId) {
+ if (IfrOneOf->Question.VarStoreId != VarStoreData.VarStoreId) {
break;
}
-
- //
- // Get Offset by Question header and Width by DataType Flags
- //
- Offset = IfrOneOf->Question.VarStoreInfo.VarOffset;
- Width = (UINT16) (1 << (IfrOneOf->Flags & EFI_IFR_NUMERIC_SIZE));
- //
- // Check whether this question is in current block array.
- //
- if (!BlockArrayCheck (CurrentBlockArray, Offset, Width)) {
+
+ if (NameValueType) {
+ QuestionName = HiiGetString (HiiHandle, IfrOneOf->Question.VarStoreInfo.VarName, NULL);
+ ASSERT (QuestionName != NULL);
+
+ if (StrStr (RequestElement, QuestionName) == NULL) {
+ //
+ // This question is not in the current configuration string. Skip it.
+ //
+ break;
+ }
+
+ Status = GetValueFromRequest (RequestElement, QuestionName, &VarValue);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ } else {
//
- // This question is not in the current configuration string. Skip it.
+ // Get Offset by Question header and Width by DataType Flags
//
- break;
- }
- //
- // Check this var question is in the var storage
- //
- if ((Offset + Width) > IfrVarStore->Size) {
+ Offset = IfrOneOf->Question.VarStoreInfo.VarOffset;
+ Width = (UINT16) (1 << (IfrOneOf->Flags & EFI_IFR_NUMERIC_SIZE));
//
- // This question exceeds the var store size.
+ // Check whether this question is in current block array.
//
- Status = EFI_INVALID_PARAMETER;
- goto Done;
- }
+ if (!BlockArrayCheck (CurrentBlockArray, Offset, Width)) {
+ //
+ // This question is not in the current configuration string. Skip it.
+ //
+ break;
+ }
+ //
+ // Check this var question is in the var storage
+ //
+ if ((Offset + Width) > VarStoreData.Size) {
+ //
+ // This question exceeds the var store size.
+ //
+ return EFI_INVALID_PARAMETER;
+ }
- //
- // Get the current value for oneof opcode
- //
- VarValue = 0;
- CopyMem (&VarValue, VarBuffer + Offset, Width);
+ //
+ // Get the current value for oneof opcode
+ //
+ VarValue = 0;
+ CopyMem (&VarValue, VarBuffer + Offset, Width);
+ }
//
// Set Block Data, to be checked in the following Oneof option opcode.
//
- VarBlockData.Offset = Offset;
- VarBlockData.Width = Width;
VarBlockData.OpCode = IfrOpHdr->OpCode;
VarBlockData.Scope = IfrOpHdr->Scope;
break;
@@ -1304,56 +1241,70 @@ InternalHiiValidateCurrentSetting (
//
// Numeric question is not in IFR Form. This IFR form is not valid.
//
- if (IfrVarStore == NULL) {
- Status = EFI_INVALID_PARAMETER;
- goto Done;
+ if (VarStoreData.VarStoreId == 0) {
+ return EFI_INVALID_PARAMETER;
}
//
// Check whether this question is for the requested varstore.
//
IfrNumeric = (EFI_IFR_NUMERIC *) IfrOpHdr;
- if (IfrNumeric->Question.VarStoreId != IfrVarStore->VarStoreId) {
+ if (IfrNumeric->Question.VarStoreId != VarStoreData.VarStoreId) {
break;
}
-
- //
- // Get Offset by Question header and Width by DataType Flags
- //
- Offset = IfrNumeric->Question.VarStoreInfo.VarOffset;
- Width = (UINT16) (1 << (IfrNumeric->Flags & EFI_IFR_NUMERIC_SIZE));
- //
- // Check whether this question is in current block array.
- //
- if (!BlockArrayCheck (CurrentBlockArray, Offset, Width)) {
+
+ if (NameValueType) {
+ QuestionName = HiiGetString (HiiHandle, IfrNumeric->Question.VarStoreInfo.VarName, NULL);
+ ASSERT (QuestionName != NULL);
+
+ if (StrStr (RequestElement, QuestionName) == NULL) {
+ //
+ // This question is not in the current configuration string. Skip it.
+ //
+ break;
+ }
+
+ Status = GetValueFromRequest (RequestElement, QuestionName, &VarValue);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ } else {
//
- // This question is not in the current configuration string. Skip it.
+ // Get Offset by Question header and Width by DataType Flags
//
- break;
- }
- //
- // Check this var question is in the var storage
- //
- if ((Offset + Width) > IfrVarStore->Size) {
+ Offset = IfrNumeric->Question.VarStoreInfo.VarOffset;
+ Width = (UINT16) (1 << (IfrNumeric->Flags & EFI_IFR_NUMERIC_SIZE));
//
- // This question exceeds the var store size.
+ // Check whether this question is in current block array.
//
- Status = EFI_INVALID_PARAMETER;
- goto Done;
- }
+ if (!BlockArrayCheck (CurrentBlockArray, Offset, Width)) {
+ //
+ // This question is not in the current configuration string. Skip it.
+ //
+ break;
+ }
+ //
+ // Check this var question is in the var storage
+ //
+ if ((Offset + Width) > VarStoreData.Size) {
+ //
+ // This question exceeds the var store size.
+ //
+ return EFI_INVALID_PARAMETER;
+ }
- //
- // Check the current value is in the numeric range.
- //
- VarValue = 0;
- CopyMem (&VarValue, VarBuffer + Offset, Width);
+ //
+ // Check the current value is in the numeric range.
+ //
+ VarValue = 0;
+ CopyMem (&VarValue, VarBuffer + Offset, Width);
+ }
switch (IfrNumeric->Flags & EFI_IFR_NUMERIC_SIZE) {
case EFI_IFR_NUMERIC_SIZE_1:
if ((UINT8) VarValue < IfrNumeric->data.u8.MinValue || (UINT8) VarValue > IfrNumeric->data.u8.MaxValue) {
//
// Not in the valid range.
//
- Status = EFI_INVALID_PARAMETER;
- goto Done;
+ return EFI_INVALID_PARAMETER;
}
break;
case EFI_IFR_NUMERIC_SIZE_2:
@@ -1361,8 +1312,7 @@ InternalHiiValidateCurrentSetting (
//
// Not in the valid range.
//
- Status = EFI_INVALID_PARAMETER;
- goto Done;
+ return EFI_INVALID_PARAMETER;
}
break;
case EFI_IFR_NUMERIC_SIZE_4:
@@ -1370,8 +1320,7 @@ InternalHiiValidateCurrentSetting (
//
// Not in the valid range.
//
- Status = EFI_INVALID_PARAMETER;
- goto Done;
+ return EFI_INVALID_PARAMETER;
}
break;
case EFI_IFR_NUMERIC_SIZE_8:
@@ -1379,8 +1328,7 @@ InternalHiiValidateCurrentSetting (
//
// Not in the valid range.
//
- Status = EFI_INVALID_PARAMETER;
- goto Done;
+ return EFI_INVALID_PARAMETER;
}
break;
}
@@ -1394,52 +1342,69 @@ InternalHiiValidateCurrentSetting (
//
// CheckBox question is not in IFR Form. This IFR form is not valid.
//
- if (IfrVarStore == NULL) {
- Status = EFI_INVALID_PARAMETER;
- goto Done;
+ if (VarStoreData.VarStoreId == 0) {
+ return EFI_INVALID_PARAMETER;
}
//
// Check whether this question is for the requested varstore.
//
IfrCheckBox = (EFI_IFR_CHECKBOX *) IfrOpHdr;
- if (IfrCheckBox->Question.VarStoreId != IfrVarStore->VarStoreId) {
+ if (IfrCheckBox->Question.VarStoreId != VarStoreData.VarStoreId) {
break;
}
-
- //
- // Get Offset by Question header
- //
- Offset = IfrCheckBox->Question.VarStoreInfo.VarOffset;
- Width = (UINT16) sizeof (BOOLEAN);
- //
- // Check whether this question is in current block array.
- //
- if (!BlockArrayCheck (CurrentBlockArray, Offset, Width)) {
+
+ if (NameValueType) {
+ QuestionName = HiiGetString (HiiHandle, IfrCheckBox->Question.VarStoreInfo.VarName, NULL);
+ ASSERT (QuestionName != NULL);
+
+ if (StrStr (RequestElement, QuestionName) == NULL) {
+ //
+ // This question is not in the current configuration string. Skip it.
+ //
+ break;
+ }
+
+ Status = GetValueFromRequest (RequestElement, QuestionName, &VarValue);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ } else {
//
- // This question is not in the current configuration string. Skip it.
+ // Get Offset by Question header
//
- break;
- }
- //
- // Check this var question is in the var storage
- //
- if ((Offset + Width) > IfrVarStore->Size) {
+ Offset = IfrCheckBox->Question.VarStoreInfo.VarOffset;
+ Width = (UINT16) sizeof (BOOLEAN);
//
- // This question exceeds the var store size.
+ // Check whether this question is in current block array.
//
- Status = EFI_INVALID_PARAMETER;
- goto Done;
+ if (!BlockArrayCheck (CurrentBlockArray, Offset, Width)) {
+ //
+ // This question is not in the current configuration string. Skip it.
+ //
+ break;
+ }
+ //
+ // Check this var question is in the var storage
+ //
+ if ((Offset + Width) > VarStoreData.Size) {
+ //
+ // This question exceeds the var store size.
+ //
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Check the current value is in the numeric range.
+ //
+ VarValue = 0;
+ CopyMem (&VarValue, VarBuffer + Offset, Width);
}
-
//
// Boolean type, only 1 and 0 is valid.
//
- if (*(VarBuffer + Offset) > 1) {
- Status = EFI_INVALID_PARAMETER;
- goto Done;
+ if (VarValue > 1) {
+ return EFI_INVALID_PARAMETER;
}
-
break;
case EFI_IFR_STRING_OP:
//
@@ -1449,50 +1414,74 @@ InternalHiiValidateCurrentSetting (
//
// CheckBox question is not in IFR Form. This IFR form is not valid.
//
- if (IfrVarStore == NULL) {
- Status = EFI_INVALID_PARAMETER;
- goto Done;
+ if (VarStoreData.VarStoreId == 0) {
+ return EFI_INVALID_PARAMETER;
}
//
// Check whether this question is for the requested varstore.
//
IfrString = (EFI_IFR_STRING *) IfrOpHdr;
- if (IfrString->Question.VarStoreId != IfrVarStore->VarStoreId) {
+ if (IfrString->Question.VarStoreId != VarStoreData.VarStoreId) {
break;
}
-
//
- // Get Offset/Width by Question header and OneOf Flags
+ // Get Width by OneOf Flags
//
- Offset = IfrString->Question.VarStoreInfo.VarOffset;
Width = (UINT16) (IfrString->MaxSize * sizeof (UINT16));
- //
- // Check whether this question is in current block array.
- //
- if (!BlockArrayCheck (CurrentBlockArray, Offset, Width)) {
+ if (NameValueType) {
+ QuestionName = HiiGetString (HiiHandle, IfrString->Question.VarStoreInfo.VarName, NULL);
+ ASSERT (QuestionName != NULL);
+
+ StringPtr = StrStr (RequestElement, QuestionName);
+ if (StringPtr == NULL) {
+ //
+ // This question is not in the current configuration string. Skip it.
+ //
+ break;
+ }
+
//
- // This question is not in the current configuration string. Skip it.
+ // Skip the "=".
+ //
+ StringPtr += 1;
+
//
- break;
- }
- //
- // Check this var question is in the var storage
- //
- if ((Offset + Width) > IfrVarStore->Size) {
+ // Check current string length is less than maxsize
//
- // This question exceeds the var store size.
+ if (StrSize (StringPtr) > Width) {
+ return EFI_INVALID_PARAMETER;
+ }
+ } else {
//
- Status = EFI_INVALID_PARAMETER;
- goto Done;
- }
-
- //
- // Check current string length is less than maxsize
- //
- if (StrSize ((CHAR16 *) (VarBuffer + Offset)) > Width) {
- Status = EFI_INVALID_PARAMETER;
- goto Done;
+ // Get Offset/Width by Question header and OneOf Flags
+ //
+ Offset = IfrString->Question.VarStoreInfo.VarOffset;
+ //
+ // Check whether this question is in current block array.
+ //
+ if (!BlockArrayCheck (CurrentBlockArray, Offset, Width)) {
+ //
+ // This question is not in the current configuration string. Skip it.
+ //
+ break;
+ }
+ //
+ // Check this var question is in the var storage
+ //
+ if ((Offset + Width) > VarStoreData.Size) {
+ //
+ // This question exceeds the var store size.
+ //
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Check current string length is less than maxsize
+ //
+ if (StrSize ((CHAR16 *) (VarBuffer + Offset)) > Width) {
+ return EFI_INVALID_PARAMETER;
+ }
}
break;
case EFI_IFR_ONE_OF_OPTION_OP:
@@ -1522,7 +1511,6 @@ InternalHiiValidateCurrentSetting (
VarBlockData.OpCode = 0;
}
}
-
break;
case EFI_IFR_END_OP:
//
@@ -1536,8 +1524,7 @@ InternalHiiValidateCurrentSetting (
// OneOf value doesn't belong to one of option value.
//
if ((VarBlockData.Scope == 0) && (VarBlockData.OpCode == EFI_IFR_ONE_OF_OP)) {
- Status = EFI_INVALID_PARAMETER;
- goto Done;
+ return EFI_INVALID_PARAMETER;
}
break;
default:
@@ -1559,14 +1546,339 @@ InternalHiiValidateCurrentSetting (
//
break;
}
-
+
//
// Go to next package.
//
- PackageOffset += PacakgeHeader.Length;
+ PackageOffset += PacakgeHeader.Length;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This internal function parses IFR data to validate current setting.
+
+ @param ConfigElement ConfigResp element string contains the current setting.
+ @param CurrentBlockArray Current block array.
+ @param VarBuffer Data buffer for this varstore.
+
+ @retval EFI_SUCCESS The current setting is valid.
+ @retval EFI_OUT_OF_RESOURCES The memory is not enough.
+ @retval EFI_INVALID_PARAMETER The config string or the Hii package is invalid.
+**/
+EFI_STATUS
+GetBlockDataInfo (
+ IN CHAR16 *ConfigElement,
+ OUT IFR_BLOCK_DATA **CurrentBlockArray,
+ OUT UINT8 **VarBuffer
+ )
+{
+ IFR_BLOCK_DATA *BlockData;
+ IFR_BLOCK_DATA *NewBlockData;
+ EFI_STRING StringPtr;
+ UINTN Length;
+ UINT8 *TmpBuffer;
+ UINT16 Offset;
+ UINT16 Width;
+ LIST_ENTRY *Link;
+ UINTN MaxBufferSize;
+ EFI_STATUS Status;
+ IFR_BLOCK_DATA *BlockArray;
+ UINT8 *DataBuffer;
+
+ //
+ // Initialize the local variables.
+ //
+ Status = EFI_SUCCESS;
+ BlockData = NULL;
+ NewBlockData = NULL;
+ TmpBuffer = NULL;
+ BlockArray = NULL;
+ MaxBufferSize = HII_LIB_DEFAULT_VARSTORE_SIZE;
+ DataBuffer = AllocateZeroPool (MaxBufferSize);
+ if (DataBuffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Init BlockArray
+ //
+ BlockArray = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
+ if (BlockArray == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+ InitializeListHead (&BlockArray->Entry);
+
+ StringPtr = StrStr (ConfigElement, L"&OFFSET=");
+ ASSERT (StringPtr != NULL);
+
+ //
+ // Parse each <RequestElement> if exists
+ // Only <BlockName> format is supported by this help function.
+ // <BlockName> ::= &'OFFSET='<Number>&'WIDTH='<Number>
+ //
+ while (*StringPtr != 0 && StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) == 0) {
+ //
+ // Skip the &OFFSET= string
+ //
+ StringPtr += StrLen (L"&OFFSET=");
+
+ //
+ // Get Offset
+ //
+ Status = InternalHiiGetValueOfNumber (StringPtr, &TmpBuffer, &Length);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+ Offset = 0;
+ CopyMem (
+ &Offset,
+ TmpBuffer,
+ (((Length + 1) / 2) < sizeof (UINT16)) ? ((Length + 1) / 2) : sizeof (UINT16)
+ );
+ FreePool (TmpBuffer);
+ TmpBuffer = NULL;
+
+ StringPtr += Length;
+ if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+ StringPtr += StrLen (L"&WIDTH=");
+
+ //
+ // Get Width
+ //
+ Status = InternalHiiGetValueOfNumber (StringPtr, &TmpBuffer, &Length);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+ Width = 0;
+ CopyMem (
+ &Width,
+ TmpBuffer,
+ (((Length + 1) / 2) < sizeof (UINT16)) ? ((Length + 1) / 2) : sizeof (UINT16)
+ );
+ FreePool (TmpBuffer);
+ TmpBuffer = NULL;
+
+ StringPtr += Length;
+ if (*StringPtr != 0 && *StringPtr != L'&') {
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ if (StrnCmp (StringPtr, L"&VALUE=", StrLen (L"&VALUE=")) != 0) {
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+ StringPtr += StrLen (L"&VALUE=");
+
+ //
+ // Get Value
+ //
+ Status = InternalHiiGetValueOfNumber (StringPtr, &TmpBuffer, &Length);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ StringPtr += Length;
+ if (*StringPtr != 0 && *StringPtr != L'&') {
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ //
+ // Check whether VarBuffer is enough
+ //
+ if ((UINTN) (Offset + Width) > MaxBufferSize) {
+ DataBuffer = ReallocatePool (
+ MaxBufferSize,
+ Offset + Width + HII_LIB_DEFAULT_VARSTORE_SIZE,
+ DataBuffer
+ );
+ if (DataBuffer == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+ MaxBufferSize = Offset + Width + HII_LIB_DEFAULT_VARSTORE_SIZE;
+ }
+
+ //
+ // Update the Block with configuration info
+ //
+ CopyMem (DataBuffer + Offset, TmpBuffer, Width);
+ FreePool (TmpBuffer);
+ TmpBuffer = NULL;
+
+ //
+ // Set new Block Data
+ //
+ NewBlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
+ if (NewBlockData == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+ NewBlockData->Offset = Offset;
+ NewBlockData->Width = Width;
+
+ //
+ // Insert the new block data into the block data array.
+ //
+ for (Link = BlockArray->Entry.ForwardLink; Link != &BlockArray->Entry; Link = Link->ForwardLink) {
+ BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);
+ if (NewBlockData->Offset == BlockData->Offset) {
+ if (NewBlockData->Width > BlockData->Width) {
+ BlockData->Width = NewBlockData->Width;
+ }
+ FreePool (NewBlockData);
+ break;
+ } else if (NewBlockData->Offset < BlockData->Offset) {
+ //
+ // Insert new block data as the previous one of this link.
+ //
+ InsertTailList (Link, &NewBlockData->Entry);
+ break;
+ }
+ }
+
+ //
+ // Insert new block data into the array tail.
+ //
+ if (Link == &BlockArray->Entry) {
+ InsertTailList (Link, &NewBlockData->Entry);
+ }
+
+ //
+ // If '\0', parsing is finished.
+ //
+ if (*StringPtr == 0) {
+ break;
+ }
+ //
+ // Go to next ConfigBlock
+ //
+ }
+
+ //
+ // Merge the aligned block data into the single block data.
+ //
+ Link = BlockArray->Entry.ForwardLink;
+ while ((Link != &BlockArray->Entry) && (Link->ForwardLink != &BlockArray->Entry)) {
+ BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);
+ NewBlockData = BASE_CR (Link->ForwardLink, IFR_BLOCK_DATA, Entry);
+ if ((NewBlockData->Offset >= BlockData->Offset) && (NewBlockData->Offset <= (BlockData->Offset + BlockData->Width))) {
+ if ((NewBlockData->Offset + NewBlockData->Width) > (BlockData->Offset + BlockData->Width)) {
+ BlockData->Width = (UINT16) (NewBlockData->Offset + NewBlockData->Width - BlockData->Offset);
+ }
+ RemoveEntryList (Link->ForwardLink);
+ FreePool (NewBlockData);
+ continue;
+ }
+ Link = Link->ForwardLink;
}
+ *VarBuffer = DataBuffer;
+ *CurrentBlockArray = BlockArray;
+ return EFI_SUCCESS;
+
Done:
+ if (DataBuffer != NULL) {
+ FreePool (DataBuffer);
+ }
+
+ if (BlockArray != NULL) {
+ //
+ // Free Link Array CurrentBlockArray
+ //
+ while (!IsListEmpty (&BlockArray->Entry)) {
+ BlockData = BASE_CR (BlockArray->Entry.ForwardLink, IFR_BLOCK_DATA, Entry);
+ RemoveEntryList (&BlockData->Entry);
+ FreePool (BlockData);
+ }
+ FreePool (BlockArray);
+ }
+
+ return Status;
+}
+
+/**
+ This internal function parses IFR data to validate current setting.
+
+ @param ConfigResp ConfigResp string contains the current setting.
+ @param HiiPackageList Point to Hii package list.
+ @param PackageListLength The length of the pacakge.
+ @param VarGuid Guid of the buffer storage.
+ @param VarName Name of the buffer storage.
+ @param HiiHandle The HiiHandle for this package.
+
+ @retval EFI_SUCCESS The current setting is valid.
+ @retval EFI_OUT_OF_RESOURCES The memory is not enough.
+ @retval EFI_INVALID_PARAMETER The config string or the Hii package is invalid.
+**/
+EFI_STATUS
+EFIAPI
+InternalHiiValidateCurrentSetting (
+ IN EFI_STRING ConfigResp,
+ IN EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList,
+ IN UINTN PackageListLength,
+ IN EFI_GUID *VarGuid,
+ IN CHAR16 *VarName,
+ IN EFI_HII_HANDLE HiiHandle
+ )
+{
+ CHAR16 *StringPtr;
+ EFI_STATUS Status;
+ IFR_BLOCK_DATA *CurrentBlockArray;
+ IFR_BLOCK_DATA *BlockData;
+ UINT8 *VarBuffer;
+ BOOLEAN NameValueType;
+
+ CurrentBlockArray = NULL;
+ VarBuffer = NULL;
+ StringPtr = NULL;
+ Status = EFI_SUCCESS;
+
+ //
+ // If StringPtr != NULL, get the request elements.
+ //
+ if (StrStr (ConfigResp, L"&OFFSET=") != NULL) {
+ Status = GetBlockDataInfo(ConfigResp, &CurrentBlockArray, &VarBuffer);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ NameValueType = FALSE;
+ } else {
+ //
+ // Skip header part.
+ //
+ StringPtr = StrStr (ConfigResp, L"PATH=");
+ ASSERT (StringPtr != NULL);
+
+ if (StrStr (StringPtr, L"&") != NULL) {
+ NameValueType = TRUE;
+ } else {
+ //
+ // Not found Request element, return success.
+ //
+ return EFI_SUCCESS;
+ }
+ }
+
+ Status = ValidateQuestionFromVfr(
+ HiiPackageList,
+ PackageListLength,
+ VarGuid,
+ VarName,
+ VarBuffer,
+ CurrentBlockArray,
+ ConfigResp,
+ HiiHandle,
+ NameValueType
+ );
+
if (VarBuffer != NULL) {
FreePool (VarBuffer);
}
@@ -1580,13 +1892,41 @@ Done:
RemoveEntryList (&BlockData->Entry);
FreePool (BlockData);
}
- FreePool (CurrentBlockArray);
+ FreePool (CurrentBlockArray);
}
return Status;
}
/**
+ Check whether the ConfigRequest string has the request elements.
+ For EFI_HII_VARSTORE_BUFFER type, the request has "&OFFSET=****&WIDTH=****..." format.
+ For EFI_HII_VARSTORE_NAME_VALUE type, the request has "&NAME1**&NAME2..." format.
+
+ @param ConfigRequest The input config request string.
+
+ @retval TRUE The input include config request elements.
+ @retval FALSE The input string not includes.
+
+**/
+BOOLEAN
+GetElementsFromRequest (
+ IN EFI_STRING ConfigRequest
+ )
+{
+ EFI_STRING TmpRequest;
+
+ TmpRequest = StrStr (ConfigRequest, L"PATH=");
+ ASSERT (TmpRequest != NULL);
+
+ if ((StrStr (TmpRequest, L"&OFFSET=") != NULL) || (StrStr (TmpRequest, L"&") != NULL)) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
This function parses the input ConfigRequest string and its matched IFR code
string for setting default value and validating current setting.
@@ -1765,7 +2105,7 @@ InternalHiiIfrValueAction (
// Its default value and validating can't execute by parsing IFR data.
// Directly jump into the next ConfigAltResp string for another pair Guid, Name, and Path.
//
- Status = EFI_SUCCESS;
+ Status = EFI_SUCCESS;
goto NextConfigAltResp;
}
@@ -1822,7 +2162,7 @@ InternalHiiIfrValueAction (
//
// Only the ConfigHdr is found. Not any block data is found. No data is required to be validated and set.
//
- if (StrStr (ConfigResp, L"&OFFSET=") == NULL) {
+ if (!GetElementsFromRequest (ConfigResp)) {
goto NextConfigAltResp;
}
@@ -1839,7 +2179,7 @@ InternalHiiIfrValueAction (
//
// Current Setting is in ConfigResp, will be set into buffer, then check it again.
//
- Status = InternalHiiValidateCurrentSetting (ConfigResp, HiiPackageList, PackageListLength, VarGuid, VarName);
+ Status = InternalHiiValidateCurrentSetting (ConfigResp, HiiPackageList, PackageListLength, VarGuid, VarName, HiiHandle);
}
if (EFI_ERROR (Status)) {
@@ -1855,10 +2195,10 @@ NextConfigAltResp:
HiiPackageList = NULL;
}
- if (ConfigResp != NULL) {
- FreePool (ConfigResp);
- ConfigResp = NULL;
- }
+ if (ConfigResp != NULL) {
+ FreePool (ConfigResp);
+ ConfigResp = NULL;
+ }
//
// Free the allocated buffer.
diff --git a/MdeModulePkg/MdeModulePkg.dec b/MdeModulePkg/MdeModulePkg.dec
index 3c07c69a9..895c0497f 100644
--- a/MdeModulePkg/MdeModulePkg.dec
+++ b/MdeModulePkg/MdeModulePkg.dec
@@ -98,6 +98,10 @@
#
CpuExceptionHandlerLib|Include/Library/CpuExceptionHandlerLib.h
+ ## @libraryclass Provides platform specific display interface.
+ #
+ CustomizedDisplayLib|Include/Library/CustomizedDisplayLib.h
+
[Guids]
## MdeModule package token space guid
# Include/Guid/MdeModulePkgTokenSpace.h
@@ -119,6 +123,14 @@
# Include/Guid/SystemNvDataGuid.h
gEfiSystemNvDataFvGuid = { 0xFFF12B8D, 0x7696, 0x4C8B, { 0xA9, 0x85, 0x27, 0x47, 0x07, 0x5B, 0x4F, 0x50 }}
+ ## GUID used as the signature of FTW working block header.
+ # Include/Guid/SystemNvDataGuid.h
+ gEdkiiWorkingBlockSignatureGuid = { 0x9e58292b, 0x7c68, 0x497d, { 0xa0, 0xce, 0x65, 0x0, 0xfd, 0x9f, 0x1b, 0x95 }}
+
+ ## GUID used to build FTW last write data hob and install PPI to inform the check for FTW last write data has been done.
+ # Include/Guid/FaultTolerantWrite.h
+ gEdkiiFaultTolerantWriteGuid = { 0x1d3e9cb8, 0x43af, 0x490b, { 0x83, 0xa, 0x35, 0x16, 0xaa, 0x53, 0x20, 0x47 }}
+
## Guid specify the device is the console out device.
# Include/Guid/ConsoleOutDevice.h
gEfiConsoleOutDeviceGuid = { 0xD3B36F2C, 0xD551, 0x11D4, { 0x9A, 0x46, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D }}
@@ -353,6 +365,12 @@
## Include/Protocol/BootLogo.h
gEfiBootLogoProtocolGuid = { 0xcdea2bd3, 0xfc25, 0x4c1c, { 0xb9, 0x7c, 0xb3, 0x11, 0x86, 0x6, 0x49, 0x90 } }
+ ## Include/Protocol/DisplayProtocol.h
+ gEdkiiFormDisplayEngineProtocolGuid = { 0x9bbe29e9, 0xfda1, 0x41ec, { 0xad, 0x52, 0x45, 0x22, 0x13, 0x74, 0x2d, 0x2e } }
+
+ ## Include/Protocol/FormBrowserEx2.h
+ gEdkiiFormBrowserEx2ProtocolGuid = { 0xa770c357, 0xb693, 0x4e6d, { 0xa6, 0xcf, 0xd2, 0x1c, 0x72, 0x8e, 0x55, 0xb } }
+
[PcdsFeatureFlag]
## Indicate whether platform can support update capsule across a system reset
gEfiMdeModulePkgTokenSpaceGuid.PcdSupportUpdateCapsuleReset|FALSE|BOOLEAN|0x0001001d
@@ -540,7 +558,7 @@
## The size of volatile buffer. This buffer is used to store VOLATILE attribute variable.
gEfiMdeModulePkgTokenSpaceGuid.PcdVariableStoreSize|0x10000|UINT32|0x30000005
- ## Size of the FTW spare block range. Note that this value should larger than PcdFlashNvStorageVariableSize
+ ## Size of the FTW spare block range. Note that this value should larger than PcdFlashNvStorageVariableSize and block size aligned.
# The root cause is that variable driver will use FTW protocol to reclaim variable region.
# If the length of variable region is larger than FTW spare size, it means the whole variable region can not
# be reflushed through the manner of fault tolerant write.
@@ -555,18 +573,12 @@
## FFS filename to find the capsule coalesce image.
gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleCoalesceFile|{ 0xA6, 0xE4, 0xFD, 0xF7, 0x4C, 0x29, 0x3c, 0x49, 0xB5, 0x0F, 0x97, 0x34, 0x55, 0x3B, 0xB7, 0x57 }|VOID*|0x30000017
- ## Single root I/O virtualization virtual function memory BAR alignment
- # BITN set indicates 2 of n+12 power
- # BIT0 set indicates 4KB alignment
- # BIT1 set indicates 8KB alignment
- gEfiMdeModulePkgTokenSpaceGuid.PcdSrIovSystemPageSize|0x1|UINT32|0x10000047
-
## Flag of enabling/disabling the feature of Loading Module at Fixed Address
- # -1: Enable the feature as fixed offset to TOLM
- # 0: Disable the feature.
- # Positive Value: Enable the feature as fixed absolute address, and the value is the top memory address
+ # 0xFFFFFFFFFFFFFFFF: Enable the feature as fixed offset to TOLM
+ # 0: Disable the feature
+ # Other Value: Enable the feature as fixed absolute address, and the value is the top memory address
gEfiMdeModulePkgTokenSpaceGuid.PcdLoadModuleAtFixAddressEnable|0|UINT64|0x30001015
-
+
## Smbios version
gEfiMdeModulePkgTokenSpaceGuid.PcdSmbiosVersion|0x0207|UINT16|0x00010055
@@ -671,7 +683,7 @@
## Base address of the NV variable range in flash device
gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase|0x0|UINT32|0x30000001
- ## Base address of the FTW spare block range in flash device.
+ ## Base address of the FTW spare block range in flash device. Note that this value should be block size aligned.
gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase|0x0|UINT32|0x30000013
## Base address of the FTW working block range in flash device.
@@ -680,7 +692,7 @@
## 64-bit Base address of the NV variable range in flash device
gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64|0x0|UINT64|0x80000001
- ## 64-bit Base address of the FTW spare block range in flash device.
+ ## 64-bit Base address of the FTW spare block range in flash device. Note that this value should be block size aligned.
gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase64|0x0|UINT64|0x80000013
## 64-bit Base address of the FTW working block range in flash device.
@@ -704,6 +716,12 @@
gEfiMdeModulePkgTokenSpaceGuid.PcdMrIovSupport|FALSE|BOOLEAN|0x10000046
[PcdsFixedAtBuild, PcdsPatchableInModule, PcdsDynamic, PcdsDynamicEx]
+ ## Single root I/O virtualization virtual function memory BAR alignment
+ # BITN set indicates 2 of n+12 power
+ # BIT0 set indicates 4KB alignment
+ # BIT1 set indicates 8KB alignment
+ gEfiMdeModulePkgTokenSpaceGuid.PcdSrIovSystemPageSize|0x1|UINT32|0x10000047
+
## This PCD defines the times to print hello world string.
# This PCD is a sample to explain FixedAtBuild UINT32 PCD usage.
gEfiMdeModulePkgTokenSpaceGuid.PcdHelloWorldPrintTimes|1|UINT32|0x40000005
diff --git a/MdeModulePkg/MdeModulePkg.dsc b/MdeModulePkg/MdeModulePkg.dsc
index 444cd8358..a2248697d 100644
--- a/MdeModulePkg/MdeModulePkg.dsc
+++ b/MdeModulePkg/MdeModulePkg.dsc
@@ -19,7 +19,7 @@
PLATFORM_VERSION = 0.92
DSC_SPECIFICATION = 0x00010005
OUTPUT_DIRECTORY = Build/MdeModule
- SUPPORTED_ARCHITECTURES = IA32|IPF|X64|EBC|ARM
+ SUPPORTED_ARCHITECTURES = IA32|IPF|X64|EBC|ARM|AARCH64
BUILD_TARGETS = DEBUG|RELEASE
SKUID_IDENTIFIER = DEFAULT
@@ -76,6 +76,7 @@
CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf
PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
PalLib|MdePkg/Library/BasePalLibNull/BasePalLibNull.inf
+ CustomizedDisplayLib|MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.inf
#
# Misc
#
@@ -195,6 +196,7 @@
MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
MdeModulePkg/Bus/Pci/IncompatiblePciDeviceSupportDxe/IncompatiblePciDeviceSupportDxe.inf
+ MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressDxe.inf
MdeModulePkg/Bus/Pci/XhciDxe/XhciDxe.inf
MdeModulePkg/Bus/Pci/EhciDxe/EhciDxe.inf
MdeModulePkg/Bus/Pci/UhciDxe/UhciDxe.inf
@@ -212,6 +214,9 @@
MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassStorageDxe.inf
MdeModulePkg/Bus/Usb/UsbMouseAbsolutePointerDxe/UsbMouseAbsolutePointerDxe.inf
MdeModulePkg/Bus/Usb/UsbMouseDxe/UsbMouseDxe.inf
+ MdeModulePkg/Bus/I2c/I2cDxe/I2cBusDxe.inf
+ MdeModulePkg/Bus/I2c/I2cDxe/I2cHostDxe.inf
+ MdeModulePkg/Bus/I2c/I2cDxe/I2cDxe.inf
MdeModulePkg/Core/Dxe/DxeMain.inf {
<LibraryClasses>
@@ -293,7 +298,9 @@
MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf
MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf
+ MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf
MdeModulePkg/Application/VariableInfo/VariableInfo.inf
+ MdeModulePkg/Universal/FaultTolerantWritePei/FaultTolerantWritePei.inf
MdeModulePkg/Universal/Variable/Pei/VariablePei.inf
MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf
MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf
diff --git a/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf b/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
index e52b6a5f2..3354fb7fc 100644
--- a/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
+++ b/MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
@@ -33,7 +33,7 @@
[Sources]
CapsuleService.c
-[Sources.Ia32, Sources.IPF, Sources.EBC, Sources.ARM]
+[Sources.Ia32, Sources.IPF, Sources.EBC, Sources.ARM, Sources.AARCH64]
SaveLongModeContext.c
[Sources.X64]
diff --git a/MdeModulePkg/Universal/Console/TerminalDxe/TerminalConIn.c b/MdeModulePkg/Universal/Console/TerminalDxe/TerminalConIn.c
index 1a88a746c..d95b1237a 100644
--- a/MdeModulePkg/Universal/Console/TerminalDxe/TerminalConIn.c
+++ b/MdeModulePkg/Universal/Console/TerminalDxe/TerminalConIn.c
@@ -1,7 +1,7 @@
/** @file
Implementation for EFI_SIMPLE_TEXT_INPUT_PROTOCOL protocol.
-Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
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
@@ -295,6 +295,10 @@ TerminalConInSetState (
return EFI_INVALID_PARAMETER;
}
+ if ((*KeyToggleState & EFI_TOGGLE_STATE_VALID) != EFI_TOGGLE_STATE_VALID) {
+ return EFI_UNSUPPORTED;
+ }
+
return EFI_SUCCESS;
}
diff --git a/MdeModulePkg/Universal/DevicePathDxe/DevicePath.c b/MdeModulePkg/Universal/DevicePathDxe/DevicePath.c
index 716aa605c..70f03bd27 100644
--- a/MdeModulePkg/Universal/DevicePathDxe/DevicePath.c
+++ b/MdeModulePkg/Universal/DevicePathDxe/DevicePath.c
@@ -2,7 +2,7 @@
Device Path Driver to produce DevPathUtilities Protocol, DevPathFromText Protocol
and DevPathToText Protocol.
-Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
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
@@ -13,19 +13,24 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
-#include "DevicePath.h"
-
-EFI_HANDLE mDevicePathHandle = NULL;
+#include <Uefi.h>
+#include <Protocol/DevicePathUtilities.h>
+#include <Protocol/DevicePathToText.h>
+#include <Protocol/DevicePathFromText.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/PcdLib.h>
GLOBAL_REMOVE_IF_UNREFERENCED CONST EFI_DEVICE_PATH_UTILITIES_PROTOCOL mDevicePathUtilities = {
- GetDevicePathSizeProtocolInterface,
- DuplicateDevicePathProtocolInterface,
- AppendDevicePathProtocolInterface,
- AppendDeviceNodeProtocolInterface,
- AppendDevicePathInstanceProtocolInterface,
- GetNextDevicePathInstanceProtocolInterface,
- IsDevicePathMultiInstanceProtocolInterface,
- CreateDeviceNodeProtocolInterface
+ GetDevicePathSize,
+ DuplicateDevicePath,
+ AppendDevicePath,
+ AppendDevicePathNode,
+ AppendDevicePathInstance,
+ GetNextDevicePathInstance,
+ IsDevicePathMultiInstance,
+ CreateDeviceNode
};
GLOBAL_REMOVE_IF_UNREFERENCED CONST EFI_DEVICE_PATH_TO_TEXT_PROTOCOL mDevicePathToText = {
@@ -38,11 +43,6 @@ GLOBAL_REMOVE_IF_UNREFERENCED CONST EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL mDevicePa
ConvertTextToDevicePath
};
-GLOBAL_REMOVE_IF_UNREFERENCED CONST EFI_GUID mEfiDevicePathMessagingUartFlowControlGuid = DEVICE_PATH_MESSAGING_UART_FLOW_CONTROL;
-GLOBAL_REMOVE_IF_UNREFERENCED CONST EFI_GUID mEfiDevicePathMessagingSASGuid = DEVICE_PATH_MESSAGING_SAS;
-
-
-
/**
The user Entry Point for DevicePath module.
@@ -64,12 +64,14 @@ DevicePathEntryPoint (
)
{
EFI_STATUS Status;
+ EFI_HANDLE Handle;
+ Handle = NULL;
Status = EFI_UNSUPPORTED;
if (FeaturePcdGet (PcdDevicePathSupportDevicePathToText)) {
if (FeaturePcdGet (PcdDevicePathSupportDevicePathFromText)) {
Status = gBS->InstallMultipleProtocolInterfaces (
- &mDevicePathHandle,
+ &Handle,
&gEfiDevicePathUtilitiesProtocolGuid, &mDevicePathUtilities,
&gEfiDevicePathToTextProtocolGuid, &mDevicePathToText,
&gEfiDevicePathFromTextProtocolGuid, &mDevicePathFromText,
@@ -77,7 +79,7 @@ DevicePathEntryPoint (
);
} else {
Status = gBS->InstallMultipleProtocolInterfaces (
- &mDevicePathHandle,
+ &Handle,
&gEfiDevicePathUtilitiesProtocolGuid, &mDevicePathUtilities,
&gEfiDevicePathToTextProtocolGuid, &mDevicePathToText,
NULL
@@ -86,14 +88,14 @@ DevicePathEntryPoint (
} else {
if (FeaturePcdGet (PcdDevicePathSupportDevicePathFromText)) {
Status = gBS->InstallMultipleProtocolInterfaces (
- &mDevicePathHandle,
+ &Handle,
&gEfiDevicePathUtilitiesProtocolGuid, &mDevicePathUtilities,
&gEfiDevicePathFromTextProtocolGuid, &mDevicePathFromText,
NULL
);
} else {
Status = gBS->InstallMultipleProtocolInterfaces (
- &mDevicePathHandle,
+ &Handle,
&gEfiDevicePathUtilitiesProtocolGuid, &mDevicePathUtilities,
NULL
);
diff --git a/MdeModulePkg/Universal/DevicePathDxe/DevicePath.h b/MdeModulePkg/Universal/DevicePathDxe/DevicePath.h
deleted file mode 100644
index 8beb68c7a..000000000
--- a/MdeModulePkg/Universal/DevicePathDxe/DevicePath.h
+++ /dev/null
@@ -1,433 +0,0 @@
-/** @file
- Definition for Device Path Utilities driver
-
-Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
-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 _DEVICE_PATH_DRIVER_H_
-#define _DEVICE_PATH_DRIVER_H_
-
-#include <Uefi.h>
-#include <Protocol/DevicePathUtilities.h>
-#include <Protocol/DebugPort.h>
-#include <Protocol/DevicePathToText.h>
-#include <Protocol/DevicePathFromText.h>
-#include <Guid/PcAnsi.h>
-#include <Library/DebugLib.h>
-#include <Library/PrintLib.h>
-#include <Library/UefiDriverEntryPoint.h>
-#include <Library/BaseLib.h>
-#include <Library/BaseMemoryLib.h>
-#include <Library/MemoryAllocationLib.h>
-#include <Library/UefiBootServicesTableLib.h>
-#include <Library/DevicePathLib.h>
-#include <Library/PcdLib.h>
-
-#define IS_COMMA(a) ((a) == L',')
-#define IS_HYPHEN(a) ((a) == L'-')
-#define IS_DOT(a) ((a) == L'.')
-#define IS_LEFT_PARENTH(a) ((a) == L'(')
-#define IS_RIGHT_PARENTH(a) ((a) == L')')
-#define IS_SLASH(a) ((a) == L'/')
-#define IS_NULL(a) ((a) == L'\0')
-
-
-#define SET_DEVICE_PATH_INSTANCE_END_NODE(a) { \
- (a)->Type = END_DEVICE_PATH_TYPE; \
- (a)->SubType = END_INSTANCE_DEVICE_PATH_SUBTYPE; \
- (a)->Length[0] = (UINT8) sizeof (EFI_DEVICE_PATH_PROTOCOL); \
- (a)->Length[1] = 0; \
- }
-
-//
-// Private Data structure
-//
-typedef struct {
- CHAR16 *Str;
- UINTN Length;
- UINTN Capacity;
-} POOL_PRINT;
-
-typedef
-EFI_DEVICE_PATH_PROTOCOL *
-(*DUMP_NODE) (
- IN CHAR16 *DeviceNodeStr
- );
-
-typedef
-VOID
-(*DEVICE_PATH_TO_TEXT_FUNC) (
- IN OUT POOL_PRINT *Str,
- IN VOID *DevPath,
- IN BOOLEAN DisplayOnly,
- IN BOOLEAN AllowShortcuts
- );
-
-typedef struct {
- UINT8 Type;
- UINT8 SubType;
- DEVICE_PATH_TO_TEXT_FUNC Function;
-} DEVICE_PATH_TO_TEXT_TABLE;
-
-typedef struct {
- CHAR16 *DevicePathNodeText;
- DUMP_NODE Function;
-} DEVICE_PATH_FROM_TEXT_TABLE;
-
-typedef struct {
- BOOLEAN ClassExist;
- UINT8 Class;
- BOOLEAN SubClassExist;
- UINT8 SubClass;
-} USB_CLASS_TEXT;
-
-#define USB_CLASS_AUDIO 1
-#define USB_CLASS_CDCCONTROL 2
-#define USB_CLASS_HID 3
-#define USB_CLASS_IMAGE 6
-#define USB_CLASS_PRINTER 7
-#define USB_CLASS_MASS_STORAGE 8
-#define USB_CLASS_HUB 9
-#define USB_CLASS_CDCDATA 10
-#define USB_CLASS_SMART_CARD 11
-#define USB_CLASS_VIDEO 14
-#define USB_CLASS_DIAGNOSTIC 220
-#define USB_CLASS_WIRELESS 224
-
-#define USB_CLASS_RESERVE 254
-#define USB_SUBCLASS_FW_UPDATE 1
-#define USB_SUBCLASS_IRDA_BRIDGE 2
-#define USB_SUBCLASS_TEST 3
-
-#define RFC_1700_UDP_PROTOCOL 17
-#define RFC_1700_TCP_PROTOCOL 6
-
-#pragma pack(1)
-
-typedef struct {
- EFI_DEVICE_PATH_PROTOCOL Header;
- EFI_GUID Guid;
- UINT8 VendorDefinedData[1];
-} VENDOR_DEFINED_HARDWARE_DEVICE_PATH;
-
-typedef struct {
- EFI_DEVICE_PATH_PROTOCOL Header;
- EFI_GUID Guid;
- UINT8 VendorDefinedData[1];
-} VENDOR_DEFINED_MESSAGING_DEVICE_PATH;
-
-typedef struct {
- EFI_DEVICE_PATH_PROTOCOL Header;
- EFI_GUID Guid;
- UINT8 VendorDefinedData[1];
-} VENDOR_DEFINED_MEDIA_DEVICE_PATH;
-
-typedef struct {
- EFI_DEVICE_PATH_PROTOCOL Header;
- UINT32 Hid;
- UINT32 Uid;
- UINT32 Cid;
- CHAR8 HidUidCidStr[3];
-} ACPI_EXTENDED_HID_DEVICE_PATH_WITH_STR;
-
-typedef struct {
- EFI_DEVICE_PATH_PROTOCOL Header;
- UINT16 NetworkProtocol;
- UINT16 LoginOption;
- UINT64 Lun;
- UINT16 TargetPortalGroupTag;
- CHAR8 TargetName[1];
-} ISCSI_DEVICE_PATH_WITH_NAME;
-
-typedef struct {
- EFI_DEVICE_PATH_PROTOCOL Header;
- EFI_GUID Guid;
- UINT8 VendorDefinedData[1];
-} VENDOR_DEVICE_PATH_WITH_DATA;
-
-#pragma pack()
-
-/**
- Converts a device node to its string representation.
-
- @param DeviceNode A Pointer to the device node to be converted.
- @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation
- of the display node is used, where applicable. If DisplayOnly
- is FALSE, then the longer text representation of the display node
- is used.
- @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text
- representation for a device node can be used, where applicable.
-
- @return A pointer to the allocated text representation of the device node or NULL if DeviceNode
- is NULL or there was insufficient memory.
-
-**/
-CHAR16 *
-EFIAPI
-ConvertDeviceNodeToText (
- IN CONST EFI_DEVICE_PATH_PROTOCOL *DeviceNode,
- IN BOOLEAN DisplayOnly,
- IN BOOLEAN AllowShortcuts
- );
-
-/**
- Converts a device path to its text representation.
-
- @param DevicePath A Pointer to the device to be converted.
- @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation
- of the display node is used, where applicable. If DisplayOnly
- is FALSE, then the longer text representation of the display node
- is used.
- @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text
- representation for a device node can be used, where applicable.
-
- @return A pointer to the allocated text representation of the device path or
- NULL if DeviceNode is NULL or there was insufficient memory.
-
-**/
-CHAR16 *
-EFIAPI
-ConvertDevicePathToText (
- IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,
- IN BOOLEAN DisplayOnly,
- IN BOOLEAN AllowShortcuts
- );
-
-/**
- Convert text to the binary representation of a device node.
-
- @param TextDeviceNode TextDeviceNode points to the text representation of a device
- node. Conversion starts with the first character and continues
- until the first non-device node character.
-
- @return A pointer to the EFI device node or NULL if TextDeviceNode is NULL or there was
- insufficient memory or text unsupported.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-EFIAPI
-ConvertTextToDeviceNode (
- IN CONST CHAR16 *TextDeviceNode
- );
-
-/**
- Convert text to the binary representation of a device path.
-
-
- @param TextDevicePath TextDevicePath points to the text representation of a device
- path. Conversion starts with the first character and continues
- until the first non-device node character.
-
- @return A pointer to the allocated device path or NULL if TextDeviceNode is NULL or
- there was insufficient memory.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-EFIAPI
-ConvertTextToDevicePath (
- IN CONST CHAR16 *TextDevicePath
- );
-
-/**
- Returns the size of a device path in bytes.
-
- This function returns the size, in bytes, of the device path data structure specified by
- DevicePath including the end of device path node. If DevicePath is NULL, then 0 is returned.
-
- @param DevicePath A pointer to a device path data structure.
-
- @return The size of a device path in bytes.
-
-**/
-UINTN
-EFIAPI
-GetDevicePathSizeProtocolInterface (
- IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath
- );
-
-/**
- Creates a new device path by appending a second device path to a first device path.
-
- This function allocates space for a new copy of the device path specified by DevicePath. If
- DevicePath is NULL, then NULL is returned. If the memory is successfully allocated, then the
- contents of DevicePath are copied to the newly allocated buffer, and a pointer to that buffer
- is returned. Otherwise, NULL is returned.
-
- @param DevicePath A pointer to a device path data structure.
-
- @return A pointer to the duplicated device path.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-EFIAPI
-DuplicateDevicePathProtocolInterface (
- IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath
- );
-
-/**
- Creates a new device path by appending a second device path to a first device path.
-
- This function creates a new device path by appending a copy of SecondDevicePath to a copy of
- FirstDevicePath in a newly allocated buffer. Only the end-of-device-path device node from
- SecondDevicePath is retained. The newly created device path is returned.
- If FirstDevicePath is NULL, then it is ignored, and a duplicate of SecondDevicePath is returned.
- If SecondDevicePath is NULL, then it is ignored, and a duplicate of FirstDevicePath is returned.
- If both FirstDevicePath and SecondDevicePath are NULL, then a copy of an end-of-device-path is
- returned.
- If there is not enough memory for the newly allocated buffer, then NULL is returned.
- The memory for the new device path is allocated from EFI boot services memory. It is the
- responsibility of the caller to free the memory allocated.
-
- @param FirstDevicePath A pointer to a device path data structure.
- @param SecondDevicePath A pointer to a device path data structure.
-
- @return A pointer to the new device path.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-EFIAPI
-AppendDevicePathProtocolInterface (
- IN CONST EFI_DEVICE_PATH_PROTOCOL *FirstDevicePath,
- IN CONST EFI_DEVICE_PATH_PROTOCOL *SecondDevicePath
- );
-
-/**
- Creates a new path by appending the device node to the device path.
-
- This function creates a new device path by appending a copy of the device node specified by
- DevicePathNode to a copy of the device path specified by DevicePath in an allocated buffer.
- The end-of-device-path device node is moved after the end of the appended device node.
- If DevicePathNode is NULL then a copy of DevicePath is returned.
- If DevicePath is NULL then a copy of DevicePathNode, followed by an end-of-device path device
- node is returned.
- If both DevicePathNode and DevicePath are NULL then a copy of an end-of-device-path device node
- is returned.
- If there is not enough memory to allocate space for the new device path, then NULL is returned.
- The memory is allocated from EFI boot services memory. It is the responsibility of the caller to
- free the memory allocated.
-
- @param DevicePath A pointer to a device path data structure.
- @param DevicePathNode A pointer to a single device path node.
-
- @return A pointer to the new device path.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-EFIAPI
-AppendDeviceNodeProtocolInterface (
- IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,
- IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePathNode
- );
-
-/**
- Creates a new device path by appending the specified device path instance to the specified device
- path.
-
- This function creates a new device path by appending a copy of the device path instance specified
- by DevicePathInstance to a copy of the device path specified by DevicePath in a allocated buffer.
- The end-of-device-path device node is moved after the end of the appended device path instance
- and a new end-of-device-path-instance node is inserted between.
- If DevicePath is NULL, then a copy if DevicePathInstance is returned.
- If DevicePathInstance is NULL, then NULL is returned.
- If there is not enough memory to allocate space for the new device path, then NULL is returned.
- The memory is allocated from EFI boot services memory. It is the responsibility of the caller to
- free the memory allocated.
-
- @param DevicePath A pointer to a device path data structure.
- @param DevicePathInstance A pointer to a device path instance.
-
- @return A pointer to the new device path.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-EFIAPI
-AppendDevicePathInstanceProtocolInterface (
- IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,
- IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePathInstance
- );
-
-/**
- Creates a copy of the current device path instance and returns a pointer to the next device path
- instance.
-
- This function creates a copy of the current device path instance. It also updates DevicePath to
- point to the next device path instance in the device path (or NULL if no more) and updates Size
- to hold the size of the device path instance copy.
- If DevicePath is NULL, then NULL is returned.
- If there is not enough memory to allocate space for the new device path, then NULL is returned.
- The memory is allocated from EFI boot services memory. It is the responsibility of the caller to
- free the memory allocated.
- If Size is NULL, then ASSERT().
-
- @param DevicePath On input, this holds the pointer to the current device path
- instance. On output, this holds the pointer to the next device
- path instance or NULL if there are no more device path
- instances in the device path pointer to a device path data
- structure.
- @param Size On output, this holds the size of the device path instance, in
- bytes or zero, if DevicePath is NULL.
-
- @return A pointer to the current device path instance.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-EFIAPI
-GetNextDevicePathInstanceProtocolInterface (
- IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath,
- OUT UINTN *Size
- );
-
-/**
- Determines if a device path is single or multi-instance.
-
- This function returns TRUE if the device path specified by DevicePath is multi-instance.
- Otherwise, FALSE is returned. If DevicePath is NULL, then FALSE is returned.
-
- @param DevicePath A pointer to a device path data structure.
-
- @retval TRUE DevicePath is multi-instance.
- @retval FALSE DevicePath is not multi-instance or DevicePath is NULL.
-
-**/
-BOOLEAN
-EFIAPI
-IsDevicePathMultiInstanceProtocolInterface (
- IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath
- );
-
-/**
- Creates a copy of the current device path instance and returns a pointer to the next device path
- instance.
-
- This function creates a new device node in a newly allocated buffer of size NodeLength and
- initializes the device path node header with NodeType and NodeSubType. The new device path node
- is returned.
- If NodeLength is smaller than a device path header, then NULL is returned.
- If there is not enough memory to allocate space for the new device path, then NULL is returned.
- The memory is allocated from EFI boot services memory. It is the responsibility of the caller to
- free the memory allocated.
-
- @param NodeType The device node type for the new device node.
- @param NodeSubType The device node sub-type for the new device node.
- @param NodeLength The length of the new device node.
-
- @return The new device path.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-EFIAPI
-CreateDeviceNodeProtocolInterface (
- IN UINT8 NodeType,
- IN UINT8 NodeSubType,
- IN UINT16 NodeLength
- );
-
-#endif
diff --git a/MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf b/MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf
index d315fe6f5..29017bad0 100644
--- a/MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf
+++ b/MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf
@@ -6,7 +6,7 @@
# PcdDevicePathSupportDevicePathToText & PcdDevicePathSupportDevicePathFromText
# respectively.
#
-# Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
# 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
@@ -32,40 +32,21 @@
#
[Sources]
- DevicePathUtilities.c
- DevicePathToText.c ||||gEfiMdeModulePkgTokenSpaceGuid.PcdDevicePathSupportDevicePathToText
- DevicePathFromText.c ||||gEfiMdeModulePkgTokenSpaceGuid.PcdDevicePathSupportDevicePathFromText
- DevicePath.h
DevicePath.c
[Packages]
- MdeModulePkg/MdeModulePkg.dec
MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
[LibraryClasses]
- PcdLib
DevicePathLib
UefiBootServicesTableLib
- MemoryAllocationLib
- BaseMemoryLib
- BaseLib
UefiDriverEntryPoint
- PrintLib
- DebugLib
-
-[Guids]
- gEfiVTUTF8Guid | gEfiMdeModulePkgTokenSpaceGuid.PcdDevicePathSupportDevicePathFromText OR gEfiMdeModulePkgTokenSpaceGuid.PcdDevicePathSupportDevicePathToText ## SOMETIMES_CONSUMES ## GUID
- gEfiVT100Guid | gEfiMdeModulePkgTokenSpaceGuid.PcdDevicePathSupportDevicePathFromText OR gEfiMdeModulePkgTokenSpaceGuid.PcdDevicePathSupportDevicePathToText ## SOMETIMES_CONSUMES ## GUID
- gEfiVT100PlusGuid | gEfiMdeModulePkgTokenSpaceGuid.PcdDevicePathSupportDevicePathFromText OR gEfiMdeModulePkgTokenSpaceGuid.PcdDevicePathSupportDevicePathToText ## SOMETIMES_CONSUMES ## GUID
- gEfiPcAnsiGuid | gEfiMdeModulePkgTokenSpaceGuid.PcdDevicePathSupportDevicePathFromText OR gEfiMdeModulePkgTokenSpaceGuid.PcdDevicePathSupportDevicePathToText ## SOMETIMES_CONSUMES ## GUID
- gEfiUartDevicePathGuid | gEfiMdeModulePkgTokenSpaceGuid.PcdDevicePathSupportDevicePathFromText OR gEfiMdeModulePkgTokenSpaceGuid.PcdDevicePathSupportDevicePathToText ## SOMETIMES_CONSUMES ## GUID
- gEfiSasDevicePathGuid | gEfiMdeModulePkgTokenSpaceGuid.PcdDevicePathSupportDevicePathFromText OR gEfiMdeModulePkgTokenSpaceGuid.PcdDevicePathSupportDevicePathToText ## SOMETIMES_CONSUMES ## GUID
[Protocols]
gEfiDevicePathToTextProtocolGuid | gEfiMdeModulePkgTokenSpaceGuid.PcdDevicePathSupportDevicePathFromText ## PRODUCES
gEfiDevicePathFromTextProtocolGuid | gEfiMdeModulePkgTokenSpaceGuid.PcdDevicePathSupportDevicePathToText ## PRODUCES
gEfiDevicePathUtilitiesProtocolGuid ## PRODUCES
- gEfiDebugPortProtocolGuid | gEfiMdeModulePkgTokenSpaceGuid.PcdDevicePathSupportDevicePathFromText OR gEfiMdeModulePkgTokenSpaceGuid.PcdDevicePathSupportDevicePathToText ## SOMETIMES_CONSUMES ## GUID
[FeaturePcd]
gEfiMdeModulePkgTokenSpaceGuid.PcdDevicePathSupportDevicePathFromText
diff --git a/MdeModulePkg/Universal/DevicePathDxe/DevicePathFromText.c b/MdeModulePkg/Universal/DevicePathDxe/DevicePathFromText.c
deleted file mode 100644
index f96bea147..000000000
--- a/MdeModulePkg/Universal/DevicePathDxe/DevicePathFromText.c
+++ /dev/null
@@ -1,3210 +0,0 @@
-/** @file
- DevicePathFromText protocol as defined in the UEFI 2.0 specification.
-
-Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
-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 "DevicePath.h"
-
-
-/**
-
- Duplicates a string.
-
- @param Src Source string.
-
- @return The duplicated string.
-
-**/
-CHAR16 *
-StrDuplicate (
- IN CONST CHAR16 *Src
- )
-{
- return AllocateCopyPool (StrSize (Src), Src);
-}
-
-/**
-
- Get parameter in a pair of parentheses follow the given node name.
- For example, given the "Pci(0,1)" and NodeName "Pci", it returns "0,1".
-
- @param Str Device Path Text.
- @param NodeName Name of the node.
-
- @return Parameter text for the node.
-
-**/
-CHAR16 *
-GetParamByNodeName (
- IN CHAR16 *Str,
- IN CHAR16 *NodeName
- )
-{
- CHAR16 *ParamStr;
- CHAR16 *StrPointer;
- UINTN NodeNameLength;
- UINTN ParameterLength;
-
- //
- // Check whether the node name matchs
- //
- NodeNameLength = StrLen (NodeName);
- if (CompareMem (Str, NodeName, NodeNameLength * sizeof (CHAR16)) != 0) {
- return NULL;
- }
-
- ParamStr = Str + NodeNameLength;
- if (!IS_LEFT_PARENTH (*ParamStr)) {
- return NULL;
- }
-
- //
- // Skip the found '(' and find first occurrence of ')'
- //
- ParamStr++;
- ParameterLength = 0;
- StrPointer = ParamStr;
- while (!IS_NULL (*StrPointer)) {
- if (IS_RIGHT_PARENTH (*StrPointer)) {
- break;
- }
- StrPointer++;
- ParameterLength++;
- }
- if (IS_NULL (*StrPointer)) {
- //
- // ')' not found
- //
- return NULL;
- }
-
- ParamStr = AllocateCopyPool ((ParameterLength + 1) * sizeof (CHAR16), ParamStr);
- if (ParamStr == NULL) {
- return NULL;
- }
- //
- // Terminate the parameter string
- //
- ParamStr[ParameterLength] = L'\0';
-
- return ParamStr;
-}
-
-/**
- Gets current sub-string from a string list, before return
- the list header is moved to next sub-string. The sub-string is separated
- by the specified character. For example, the separator is ',', the string
- list is "2,0,3", it returns "2", the remain list move to "0,3"
-
- @param List A string list separated by the specified separator
- @param Separator The separator character
-
- @return A pointer to the current sub-string
-
-**/
-CHAR16 *
-SplitStr (
- IN OUT CHAR16 **List,
- IN CHAR16 Separator
- )
-{
- CHAR16 *Str;
- CHAR16 *ReturnStr;
-
- Str = *List;
- ReturnStr = Str;
-
- if (IS_NULL (*Str)) {
- return ReturnStr;
- }
-
- //
- // Find first occurrence of the separator
- //
- while (!IS_NULL (*Str)) {
- if (*Str == Separator) {
- break;
- }
- Str++;
- }
-
- if (*Str == Separator) {
- //
- // Find a sub-string, terminate it
- //
- *Str = L'\0';
- Str++;
- }
-
- //
- // Move to next sub-string
- //
- *List = Str;
-
- return ReturnStr;
-}
-
-/**
- Gets the next parameter string from the list.
-
- @param List A string list separated by the specified separator
-
- @return A pointer to the current sub-string
-
-**/
-CHAR16 *
-GetNextParamStr (
- IN OUT CHAR16 **List
- )
-{
- //
- // The separator is comma
- //
- return SplitStr (List, L',');
-}
-
-/**
- Get one device node from entire device path text.
-
- @param DevicePath On input, the current Device Path node; on output, the next device path node
- @param IsInstanceEnd This node is the end of a device path instance
-
- @return A device node text or NULL if no more device node available
-
-**/
-CHAR16 *
-GetNextDeviceNodeStr (
- IN OUT CHAR16 **DevicePath,
- OUT BOOLEAN *IsInstanceEnd
- )
-{
- CHAR16 *Str;
- CHAR16 *ReturnStr;
- UINTN ParenthesesStack;
-
- Str = *DevicePath;
- if (IS_NULL (*Str)) {
- return NULL;
- }
-
- //
- // Skip the leading '/', '(', ')' and ','
- //
- while (!IS_NULL (*Str)) {
- if (!IS_SLASH (*Str) &&
- !IS_COMMA (*Str) &&
- !IS_LEFT_PARENTH (*Str) &&
- !IS_RIGHT_PARENTH (*Str)) {
- break;
- }
- Str++;
- }
-
- ReturnStr = Str;
-
- //
- // Scan for the separator of this device node, '/' or ','
- //
- ParenthesesStack = 0;
- while (!IS_NULL (*Str)) {
- if ((IS_COMMA (*Str) || IS_SLASH (*Str)) && (ParenthesesStack == 0)) {
- break;
- }
-
- if (IS_LEFT_PARENTH (*Str)) {
- ParenthesesStack++;
- } else if (IS_RIGHT_PARENTH (*Str)) {
- ParenthesesStack--;
- }
-
- Str++;
- }
-
- if (ParenthesesStack != 0) {
- //
- // The '(' doesn't pair with ')', invalid device path text
- //
- return NULL;
- }
-
- if (IS_COMMA (*Str)) {
- *IsInstanceEnd = TRUE;
- *Str = L'\0';
- Str++;
- } else {
- *IsInstanceEnd = FALSE;
- if (!IS_NULL (*Str)) {
- *Str = L'\0';
- Str++;
- }
- }
-
- *DevicePath = Str;
-
- return ReturnStr;
-}
-
-
-/**
- Skip the leading white space and '0x' or '0X' of a integer string
-
- @param Str The integer string
- @param IsHex TRUE: Hex string, FALSE: Decimal string
-
- @return The trimmed Hex string.
-
-**/
-CHAR16 *
-TrimHexStr (
- IN CHAR16 *Str,
- OUT BOOLEAN *IsHex
- )
-{
- *IsHex = FALSE;
-
- //
- // skip preceeding white space
- //
- while ((*Str != 0) && *Str == ' ') {
- Str += 1;
- }
- //
- // skip preceeding zeros
- //
- while ((*Str != 0) && *Str == '0') {
- Str += 1;
- }
- //
- // skip preceeding character 'x' or 'X'
- //
- if ((*Str != 0) && (*Str == 'x' || *Str == 'X')) {
- Str += 1;
- *IsHex = TRUE;
- }
-
- return Str;
-}
-
-/**
-
- Convert hex string to uint.
-
- @param Str The hex string
-
- @return A UINTN value represented by Str
-
-**/
-UINTN
-Xtoi (
- IN CHAR16 *Str
- )
-{
- return StrHexToUintn (Str);
-}
-
-/**
-
- Convert hex string to 64 bit data.
-
- @param Str The hex string
- @param Data A pointer to the UINT64 value represented by Str
-
-**/
-VOID
-Xtoi64 (
- IN CHAR16 *Str,
- OUT UINT64 *Data
- )
-{
- *Data = StrHexToUint64 (Str);
-}
-
-/**
-
- Convert decimal string to uint.
-
- @param Str The decimal string
-
- @return A UINTN value represented by Str
-
-**/
-UINTN
-Dtoi (
- IN CHAR16 *Str
- )
-{
- UINTN Rvalue;
- CHAR16 Char;
- UINTN High;
- UINTN Low;
-
- ASSERT (Str != NULL);
-
- High = (UINTN) -1 / 10;
- Low = (UINTN) -1 % 10;
- //
- // skip preceeding white space
- //
- while ((*Str != 0) && *Str == ' ') {
- Str += 1;
- }
- //
- // convert digits
- //
- Rvalue = 0;
- Char = *(Str++);
- while (Char != 0) {
- if (Char >= '0' && Char <= '9') {
- if ((Rvalue > High || Rvalue == High) && (Char - '0' > (INTN) Low)) {
- return (UINTN) -1;
- }
-
- Rvalue = (Rvalue * 10) + Char - '0';
- } else {
- break;
- }
-
- Char = *(Str++);
- }
-
- return Rvalue;
-}
-
-/**
-
- Convert decimal string to uint.
-
- @param Str The decimal string
- @param Data A pointer to the UINT64 value represented by Str
-
-**/
-VOID
-Dtoi64 (
- IN CHAR16 *Str,
- OUT UINT64 *Data
- )
-{
- UINT64 Rvalue;
- CHAR16 Char;
- UINT64 High;
- UINT64 Low;
-
- ASSERT (Str != NULL);
- ASSERT (Data != NULL);
-
- //
- // skip preceeding white space
- //
- while ((*Str != 0) && *Str == ' ') {
- Str += 1;
- }
- //
- // convert digits
- //
- Rvalue = 0;
- Char = *(Str++);
- while (Char != 0) {
- if (Char >= '0' && Char <= '9') {
- High = LShiftU64 (Rvalue, 3);
- Low = LShiftU64 (Rvalue, 1);
- Rvalue = High + Low + Char - '0';
- } else {
- break;
- }
-
- Char = *(Str++);
- }
-
- *Data = Rvalue;
-}
-
-/**
-
- Convert integer string to uint.
-
- @param Str The integer string. If leading with "0x" or "0X", it's hexadecimal.
-
- @return A UINTN value represented by Str
-
-**/
-UINTN
-Strtoi (
- IN CHAR16 *Str
- )
-{
- BOOLEAN IsHex;
-
- Str = TrimHexStr (Str, &IsHex);
-
- if (IsHex) {
- return Xtoi (Str);
- } else {
- return Dtoi (Str);
- }
-}
-
-/**
-
- Convert integer string to 64 bit data.
-
- @param Str The integer string. If leading with "0x" or "0X", it's hexadecimal.
- @param Data A pointer to the UINT64 value represented by Str
-
-**/
-VOID
-Strtoi64 (
- IN CHAR16 *Str,
- OUT UINT64 *Data
- )
-{
- BOOLEAN IsHex;
-
- Str = TrimHexStr (Str, &IsHex);
-
- if (IsHex) {
- Xtoi64 (Str, Data);
- } else {
- Dtoi64 (Str, Data);
- }
-}
-
-/**
- Converts a list of string to a specified buffer.
-
- @param Buf The output buffer that contains the string.
- @param BufferLength The length of the buffer
- @param Str The input string that contains the hex number
-
- @retval EFI_SUCCESS The string was successfully converted to the buffer.
-
-**/
-EFI_STATUS
-StrToBuf (
- OUT UINT8 *Buf,
- IN UINTN BufferLength,
- IN CHAR16 *Str
- )
-{
- UINTN Index;
- UINTN StrLength;
- UINT8 Digit;
- UINT8 Byte;
-
- Digit = 0;
-
- //
- // Two hex char make up one byte
- //
- StrLength = BufferLength * sizeof (CHAR16);
-
- for(Index = 0; Index < StrLength; Index++, Str++) {
-
- if ((*Str >= L'a') && (*Str <= L'f')) {
- Digit = (UINT8) (*Str - L'a' + 0x0A);
- } else if ((*Str >= L'A') && (*Str <= L'F')) {
- Digit = (UINT8) (*Str - L'A' + 0x0A);
- } else if ((*Str >= L'0') && (*Str <= L'9')) {
- Digit = (UINT8) (*Str - L'0');
- } else {
- return EFI_INVALID_PARAMETER;
- }
-
- //
- // For odd characters, write the upper nibble for each buffer byte,
- // and for even characters, the lower nibble.
- //
- if ((Index & 1) == 0) {
- Byte = (UINT8) (Digit << 4);
- } else {
- Byte = Buf[Index / 2];
- Byte &= 0xF0;
- Byte = (UINT8) (Byte | Digit);
- }
-
- Buf[Index / 2] = Byte;
- }
-
- return EFI_SUCCESS;
-}
-
-/**
- Converts a string to GUID value.
- Guid Format is xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
-
- @param Str The registry format GUID string that contains the GUID value.
- @param Guid A pointer to the converted GUID value.
-
- @retval EFI_SUCCESS The GUID string was successfully converted to the GUID value.
- @retval EFI_UNSUPPORTED The input string is not in registry format.
- @return others Some error occurred when converting part of GUID value.
-
-**/
-EFI_STATUS
-StrToGuid (
- IN CHAR16 *Str,
- OUT EFI_GUID *Guid
- )
-{
- //
- // Get the first UINT32 data
- //
- Guid->Data1 = (UINT32) StrHexToUint64 (Str);
- while (!IS_HYPHEN (*Str) && !IS_NULL (*Str)) {
- Str ++;
- }
-
- if (IS_HYPHEN (*Str)) {
- Str++;
- } else {
- return EFI_UNSUPPORTED;
- }
-
- //
- // Get the second UINT16 data
- //
- Guid->Data2 = (UINT16) StrHexToUint64 (Str);
- while (!IS_HYPHEN (*Str) && !IS_NULL (*Str)) {
- Str ++;
- }
-
- if (IS_HYPHEN (*Str)) {
- Str++;
- } else {
- return EFI_UNSUPPORTED;
- }
-
- //
- // Get the third UINT16 data
- //
- Guid->Data3 = (UINT16) StrHexToUint64 (Str);
- while (!IS_HYPHEN (*Str) && !IS_NULL (*Str)) {
- Str ++;
- }
-
- if (IS_HYPHEN (*Str)) {
- Str++;
- } else {
- return EFI_UNSUPPORTED;
- }
-
- //
- // Get the following 8 bytes data
- //
- StrToBuf (&Guid->Data4[0], 2, Str);
- //
- // Skip 2 byte hex chars
- //
- Str += 2 * 2;
-
- if (IS_HYPHEN (*Str)) {
- Str++;
- } else {
- return EFI_UNSUPPORTED;
- }
- StrToBuf (&Guid->Data4[2], 6, Str);
-
- return EFI_SUCCESS;
-}
-
-/**
- Converts a string to IPv4 address
-
- @param Str A string representation of IPv4 address.
- @param IPv4Addr A pointer to the converted IPv4 address.
-
-**/
-VOID
-StrToIPv4Addr (
- IN OUT CHAR16 **Str,
- OUT EFI_IPv4_ADDRESS *IPv4Addr
- )
-{
- UINTN Index;
-
- for (Index = 0; Index < 4; Index++) {
- IPv4Addr->Addr[Index] = (UINT8) Dtoi (SplitStr (Str, L'.'));
- }
-}
-
-/**
- Converts a string to IPv4 address
-
- @param Str A string representation of IPv6 address.
- @param IPv6Addr A pointer to the converted IPv6 address.
-
-**/
-VOID
-StrToIPv6Addr (
- IN OUT CHAR16 **Str,
- OUT EFI_IPv6_ADDRESS *IPv6Addr
- )
-{
- UINTN Index;
- UINT16 Data;
-
- for (Index = 0; Index < 8; Index++) {
- Data = (UINT16) Xtoi (SplitStr (Str, L':'));
- IPv6Addr->Addr[Index * 2] = (UINT8) (Data >> 8);
- IPv6Addr->Addr[Index * 2 + 1] = (UINT8) (Data & 0xff);
- }
-}
-
-/**
- Converts a Unicode string to ASCII string.
-
- @param Str The equivalent Unicode string
- @param AsciiStr On input, it points to destination ASCII string buffer; on output, it points
- to the next ASCII string next to it
-
-**/
-VOID
-StrToAscii (
- IN CHAR16 *Str,
- IN OUT CHAR8 **AsciiStr
- )
-{
- CHAR8 *Dest;
-
- Dest = *AsciiStr;
- while (!IS_NULL (*Str)) {
- *(Dest++) = (CHAR8) *(Str++);
- }
- *Dest = 0;
-
- //
- // Return the string next to it
- //
- *AsciiStr = Dest + 1;
-}
-
-/**
- Converts a text device path node to Hardware PCI device path structure.
-
- @param TextDeviceNode The input Text device path node.
-
- @return A pointer to Hardware PCI device path structure.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-DevPathFromTextPci (
- IN CHAR16 *TextDeviceNode
- )
-{
- CHAR16 *FunctionStr;
- CHAR16 *DeviceStr;
- PCI_DEVICE_PATH *Pci;
-
- DeviceStr = GetNextParamStr (&TextDeviceNode);
- FunctionStr = GetNextParamStr (&TextDeviceNode);
- Pci = (PCI_DEVICE_PATH *) CreateDeviceNode (
- HARDWARE_DEVICE_PATH,
- HW_PCI_DP,
- (UINT16) sizeof (PCI_DEVICE_PATH)
- );
-
- Pci->Function = (UINT8) Strtoi (FunctionStr);
- Pci->Device = (UINT8) Strtoi (DeviceStr);
-
- return (EFI_DEVICE_PATH_PROTOCOL *) Pci;
-}
-
-/**
- Converts a text device path node to Hardware PC card device path structure.
-
- @param TextDeviceNode The input Text device path node.
-
- @return A pointer to Hardware PC card device path structure.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-DevPathFromTextPcCard (
- IN CHAR16 *TextDeviceNode
- )
-{
- CHAR16 *FunctionNumberStr;
- PCCARD_DEVICE_PATH *Pccard;
-
- FunctionNumberStr = GetNextParamStr (&TextDeviceNode);
- Pccard = (PCCARD_DEVICE_PATH *) CreateDeviceNode (
- HARDWARE_DEVICE_PATH,
- HW_PCCARD_DP,
- (UINT16) sizeof (PCCARD_DEVICE_PATH)
- );
-
- Pccard->FunctionNumber = (UINT8) Strtoi (FunctionNumberStr);
-
- return (EFI_DEVICE_PATH_PROTOCOL *) Pccard;
-}
-
-/**
- Converts a text device path node to Hardware memory map device path structure.
-
- @param TextDeviceNode The input Text device path node.
-
- @return A pointer to Hardware memory map device path structure.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-DevPathFromTextMemoryMapped (
- IN CHAR16 *TextDeviceNode
- )
-{
- CHAR16 *MemoryTypeStr;
- CHAR16 *StartingAddressStr;
- CHAR16 *EndingAddressStr;
- MEMMAP_DEVICE_PATH *MemMap;
-
- MemoryTypeStr = GetNextParamStr (&TextDeviceNode);
- StartingAddressStr = GetNextParamStr (&TextDeviceNode);
- EndingAddressStr = GetNextParamStr (&TextDeviceNode);
- MemMap = (MEMMAP_DEVICE_PATH *) CreateDeviceNode (
- HARDWARE_DEVICE_PATH,
- HW_MEMMAP_DP,
- (UINT16) sizeof (MEMMAP_DEVICE_PATH)
- );
-
- MemMap->MemoryType = (UINT32) Strtoi (MemoryTypeStr);
- Strtoi64 (StartingAddressStr, &MemMap->StartingAddress);
- Strtoi64 (EndingAddressStr, &MemMap->EndingAddress);
-
- return (EFI_DEVICE_PATH_PROTOCOL *) MemMap;
-}
-
-/**
- Converts a text device path node to Vendor device path structure based on the input Type
- and SubType.
-
- @param TextDeviceNode The input Text device path node.
- @param Type The type of device path node.
- @param SubType The subtype of device path node.
-
- @return A pointer to the newly-created Vendor device path structure.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-ConvertFromTextVendor (
- IN CHAR16 *TextDeviceNode,
- IN UINT8 Type,
- IN UINT8 SubType
- )
-{
- CHAR16 *GuidStr;
- CHAR16 *DataStr;
- UINTN Length;
- VENDOR_DEVICE_PATH *Vendor;
-
- GuidStr = GetNextParamStr (&TextDeviceNode);
-
- DataStr = GetNextParamStr (&TextDeviceNode);
- Length = StrLen (DataStr);
- //
- // Two hex characters make up 1 buffer byte
- //
- Length = (Length + 1) / 2;
-
- Vendor = (VENDOR_DEVICE_PATH *) CreateDeviceNode (
- Type,
- SubType,
- (UINT16) (sizeof (VENDOR_DEVICE_PATH) + Length)
- );
-
- StrToGuid (GuidStr, &Vendor->Guid);
- StrToBuf (((UINT8 *) Vendor) + sizeof (VENDOR_DEVICE_PATH), Length, DataStr);
-
- return (EFI_DEVICE_PATH_PROTOCOL *) Vendor;
-}
-
-/**
- Converts a text device path node to Vendor Hardware device path structure.
-
- @param TextDeviceNode The input Text device path node.
-
- @return A pointer to the newly-created Vendor Hardware device path structure.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-DevPathFromTextVenHw (
- IN CHAR16 *TextDeviceNode
- )
-{
- return ConvertFromTextVendor (
- TextDeviceNode,
- HARDWARE_DEVICE_PATH,
- HW_VENDOR_DP
- );
-}
-
-/**
- Converts a text device path node to Hardware Controller device path structure.
-
- @param TextDeviceNode The input Text device path node.
-
- @return A pointer to the newly-created Hardware Controller device path structure.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-DevPathFromTextCtrl (
- IN CHAR16 *TextDeviceNode
- )
-{
- CHAR16 *ControllerStr;
- CONTROLLER_DEVICE_PATH *Controller;
-
- ControllerStr = GetNextParamStr (&TextDeviceNode);
- Controller = (CONTROLLER_DEVICE_PATH *) CreateDeviceNode (
- HARDWARE_DEVICE_PATH,
- HW_CONTROLLER_DP,
- (UINT16) sizeof (CONTROLLER_DEVICE_PATH)
- );
- Controller->ControllerNumber = (UINT32) Strtoi (ControllerStr);
-
- return (EFI_DEVICE_PATH_PROTOCOL *) Controller;
-}
-
-/**
- Converts a string to EisaId.
-
- @param Text The input string.
- @param EisaId A pointer to the output EisaId.
-
-**/
-VOID
-EisaIdFromText (
- IN CHAR16 *Text,
- OUT UINT32 *EisaId
- )
-{
- UINTN PnpId;
-
- PnpId = Xtoi (Text + 3);
- *EisaId = (((Text[0] - '@') & 0x1f) << 10) +
- (((Text[1] - '@') & 0x1f) << 5) +
- ((Text[2] - '@') & 0x1f) +
- (UINT32) (PnpId << 16);
-}
-
-/**
- Converts a text device path node to ACPI HID device path structure.
-
- @param TextDeviceNode The input Text device path node.
-
- @return A pointer to the newly-created ACPI HID device path structure.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-DevPathFromTextAcpi (
- IN CHAR16 *TextDeviceNode
- )
-{
- CHAR16 *HIDStr;
- CHAR16 *UIDStr;
- ACPI_HID_DEVICE_PATH *Acpi;
-
- HIDStr = GetNextParamStr (&TextDeviceNode);
- UIDStr = GetNextParamStr (&TextDeviceNode);
- Acpi = (ACPI_HID_DEVICE_PATH *) CreateDeviceNode (
- ACPI_DEVICE_PATH,
- ACPI_DP,
- (UINT16) sizeof (ACPI_HID_DEVICE_PATH)
- );
-
- EisaIdFromText (HIDStr, &Acpi->HID);
- Acpi->UID = (UINT32) Strtoi (UIDStr);
-
- return (EFI_DEVICE_PATH_PROTOCOL *) Acpi;
-}
-
-/**
- Converts a text device path node to ACPI HID device path structure.
-
- @param TextDeviceNode The input Text device path node.
- @param PnPId The input plug and play identification.
-
- @return A pointer to the newly-created ACPI HID device path structure.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-ConvertFromTextAcpi (
- IN CHAR16 *TextDeviceNode,
- IN UINT32 PnPId
- )
-{
- CHAR16 *UIDStr;
- ACPI_HID_DEVICE_PATH *Acpi;
-
- UIDStr = GetNextParamStr (&TextDeviceNode);
- Acpi = (ACPI_HID_DEVICE_PATH *) CreateDeviceNode (
- ACPI_DEVICE_PATH,
- ACPI_DP,
- (UINT16) sizeof (ACPI_HID_DEVICE_PATH)
- );
-
- Acpi->HID = EFI_PNP_ID (PnPId);
- Acpi->UID = (UINT32) Strtoi (UIDStr);
-
- return (EFI_DEVICE_PATH_PROTOCOL *) Acpi;
-}
-
-/**
- Converts a text device path node to PCI root device path structure.
-
- @param TextDeviceNode The input Text device path node.
-
- @return A pointer to the newly-created PCI root device path structure.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-DevPathFromTextPciRoot (
- IN CHAR16 *TextDeviceNode
- )
-{
- return ConvertFromTextAcpi (TextDeviceNode, 0x0a03);
-}
-
-/**
- Converts a text device path node to PCIE root device path structure.
-
- @param TextDeviceNode The input Text device path node.
-
- @return A pointer to the newly-created PCIE root device path structure.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-DevPathFromTextPcieRoot (
- IN CHAR16 *TextDeviceNode
- )
-{
- return ConvertFromTextAcpi (TextDeviceNode, 0x0a08);
-}
-
-/**
- Converts a text device path node to Floppy device path structure.
-
- @param TextDeviceNode The input Text device path node.
-
- @return A pointer to the newly-created Floppy device path structure.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-DevPathFromTextFloppy (
- IN CHAR16 *TextDeviceNode
- )
-{
- return ConvertFromTextAcpi (TextDeviceNode, 0x0604);
-}
-
-/**
- Converts a text device path node to Keyboard device path structure.
-
- @param TextDeviceNode The input Text device path node.
-
- @return A pointer to the newly-created Keyboard device path structure.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-DevPathFromTextKeyboard (
- IN CHAR16 *TextDeviceNode
- )
-{
- return ConvertFromTextAcpi (TextDeviceNode, 0x0301);
-}
-
-/**
- Converts a text device path node to Serial device path structure.
-
- @param TextDeviceNode The input Text device path node.
-
- @return A pointer to the newly-created Serial device path structure.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-DevPathFromTextSerial (
- IN CHAR16 *TextDeviceNode
- )
-{
- return ConvertFromTextAcpi (TextDeviceNode, 0x0501);
-}
-
-/**
- Converts a text device path node to Parallel Port device path structure.
-
- @param TextDeviceNode The input Text device path node.
-
- @return A pointer to the newly-created Parallel Port device path structure.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-DevPathFromTextParallelPort (
- IN CHAR16 *TextDeviceNode
- )
-{
- return ConvertFromTextAcpi (TextDeviceNode, 0x0401);
-}
-
-/**
- Converts a text device path node to ACPI extension device path structure.
-
- @param TextDeviceNode The input Text device path node.
-
- @return A pointer to the newly-created ACPI extension device path structure.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-DevPathFromTextAcpiEx (
- IN CHAR16 *TextDeviceNode
- )
-{
- CHAR16 *HIDStr;
- CHAR16 *CIDStr;
- CHAR16 *UIDStr;
- CHAR16 *HIDSTRStr;
- CHAR16 *CIDSTRStr;
- CHAR16 *UIDSTRStr;
- CHAR8 *AsciiStr;
- UINT16 Length;
- ACPI_EXTENDED_HID_DEVICE_PATH *AcpiEx;
-
- HIDStr = GetNextParamStr (&TextDeviceNode);
- CIDStr = GetNextParamStr (&TextDeviceNode);
- UIDStr = GetNextParamStr (&TextDeviceNode);
- HIDSTRStr = GetNextParamStr (&TextDeviceNode);
- CIDSTRStr = GetNextParamStr (&TextDeviceNode);
- UIDSTRStr = GetNextParamStr (&TextDeviceNode);
-
- Length = (UINT16) (sizeof (ACPI_EXTENDED_HID_DEVICE_PATH) + StrLen (HIDSTRStr) + 1);
- Length = (UINT16) (Length + StrLen (UIDSTRStr) + 1);
- Length = (UINT16) (Length + StrLen (CIDSTRStr) + 1);
- AcpiEx = (ACPI_EXTENDED_HID_DEVICE_PATH *) CreateDeviceNode (
- ACPI_DEVICE_PATH,
- ACPI_EXTENDED_DP,
- Length
- );
-
- EisaIdFromText (HIDStr, &AcpiEx->HID);
- EisaIdFromText (CIDStr, &AcpiEx->CID);
- AcpiEx->UID = (UINT32) Strtoi (UIDStr);
-
- AsciiStr = (CHAR8 *) ((UINT8 *)AcpiEx + sizeof (ACPI_EXTENDED_HID_DEVICE_PATH));
- StrToAscii (HIDSTRStr, &AsciiStr);
- StrToAscii (UIDSTRStr, &AsciiStr);
- StrToAscii (CIDSTRStr, &AsciiStr);
-
- return (EFI_DEVICE_PATH_PROTOCOL *) AcpiEx;
-}
-
-/**
- Converts a text device path node to ACPI extension device path structure.
-
- @param TextDeviceNode The input Text device path node.
-
- @return A pointer to the newly-created ACPI extension device path structure.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-DevPathFromTextAcpiExp (
- IN CHAR16 *TextDeviceNode
- )
-{
- CHAR16 *HIDStr;
- CHAR16 *CIDStr;
- CHAR16 *UIDSTRStr;
- CHAR8 *AsciiStr;
- UINT16 Length;
- ACPI_EXTENDED_HID_DEVICE_PATH *AcpiEx;
-
- HIDStr = GetNextParamStr (&TextDeviceNode);
- CIDStr = GetNextParamStr (&TextDeviceNode);
- UIDSTRStr = GetNextParamStr (&TextDeviceNode);
- Length = (UINT16) (sizeof (ACPI_EXTENDED_HID_DEVICE_PATH) + StrLen (UIDSTRStr) + 3);
- AcpiEx = (ACPI_EXTENDED_HID_DEVICE_PATH *) CreateDeviceNode (
- ACPI_DEVICE_PATH,
- ACPI_EXTENDED_DP,
- Length
- );
-
- EisaIdFromText (HIDStr, &AcpiEx->HID);
- EisaIdFromText (CIDStr, &AcpiEx->CID);
- AcpiEx->UID = 0;
-
- AsciiStr = (CHAR8 *) ((UINT8 *)AcpiEx + sizeof (ACPI_EXTENDED_HID_DEVICE_PATH));
- //
- // HID string is NULL
- //
- *AsciiStr = '\0';
- //
- // Convert UID string
- //
- AsciiStr++;
- StrToAscii (UIDSTRStr, &AsciiStr);
- //
- // CID string is NULL
- //
- *AsciiStr = '\0';
-
- return (EFI_DEVICE_PATH_PROTOCOL *) AcpiEx;
-}
-
-/**
- Converts a text device path node to ACPI _ADR device path structure.
-
- @param TextDeviceNode The input Text device path node.
-
- @return A pointer to the newly-created ACPI _ADR device path structure.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-DevPathFromTextAcpiAdr (
- IN CHAR16 *TextDeviceNode
- )
-{
- CHAR16 *DisplayDeviceStr;
- ACPI_ADR_DEVICE_PATH *AcpiAdr;
- UINTN Index;
- UINTN Length;
-
- AcpiAdr = (ACPI_ADR_DEVICE_PATH *) CreateDeviceNode (
- ACPI_DEVICE_PATH,
- ACPI_ADR_DP,
- (UINT16) sizeof (ACPI_ADR_DEVICE_PATH)
- );
- ASSERT (AcpiAdr != NULL);
-
- for (Index = 0; ; Index++) {
- DisplayDeviceStr = GetNextParamStr (&TextDeviceNode);
- if (IS_NULL (*DisplayDeviceStr)) {
- break;
- }
- if (Index > 0) {
- Length = DevicePathNodeLength (AcpiAdr);
- AcpiAdr = ReallocatePool (
- Length,
- Length + sizeof (UINT32),
- AcpiAdr
- );
- ASSERT (AcpiAdr != NULL);
- SetDevicePathNodeLength (AcpiAdr, Length + sizeof (UINT32));
- }
-
- (&AcpiAdr->ADR)[Index] = (UINT32) Strtoi (DisplayDeviceStr);
- }
-
- return (EFI_DEVICE_PATH_PROTOCOL *) AcpiAdr;
-}
-
-/**
- Converts a text device path node to Parallel Port device path structure.
-
- @param TextDeviceNode The input Text device path node.
-
- @return A pointer to the newly-created Parallel Port device path structure.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-DevPathFromTextAta (
- IN CHAR16 *TextDeviceNode
- )
-{
- CHAR16 *PrimarySecondaryStr;
- CHAR16 *SlaveMasterStr;
- CHAR16 *LunStr;
- ATAPI_DEVICE_PATH *Atapi;
-
- Atapi = (ATAPI_DEVICE_PATH *) CreateDeviceNode (
- MESSAGING_DEVICE_PATH,
- MSG_ATAPI_DP,
- (UINT16) sizeof (ATAPI_DEVICE_PATH)
- );
-
- PrimarySecondaryStr = GetNextParamStr (&TextDeviceNode);
- SlaveMasterStr = GetNextParamStr (&TextDeviceNode);
- LunStr = GetNextParamStr (&TextDeviceNode);
-
- Atapi->PrimarySecondary = (UINT8) ((StrCmp (PrimarySecondaryStr, L"Primary") == 0) ? 0 : 1);
- Atapi->SlaveMaster = (UINT8) ((StrCmp (SlaveMasterStr, L"Master") == 0) ? 0 : 1);
- Atapi->Lun = (UINT16) Strtoi (LunStr);
-
- return (EFI_DEVICE_PATH_PROTOCOL *) Atapi;
-}
-
-/**
- Converts a text device path node to SCSI device path structure.
-
- @param TextDeviceNode The input Text device path node.
-
- @return A pointer to the newly-created SCSI device path structure.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-DevPathFromTextScsi (
- IN CHAR16 *TextDeviceNode
- )
-{
- CHAR16 *PunStr;
- CHAR16 *LunStr;
- SCSI_DEVICE_PATH *Scsi;
-
- PunStr = GetNextParamStr (&TextDeviceNode);
- LunStr = GetNextParamStr (&TextDeviceNode);
- Scsi = (SCSI_DEVICE_PATH *) CreateDeviceNode (
- MESSAGING_DEVICE_PATH,
- MSG_SCSI_DP,
- (UINT16) sizeof (SCSI_DEVICE_PATH)
- );
-
- Scsi->Pun = (UINT16) Strtoi (PunStr);
- Scsi->Lun = (UINT16) Strtoi (LunStr);
-
- return (EFI_DEVICE_PATH_PROTOCOL *) Scsi;
-}
-
-/**
- Converts a text device path node to Fibre device path structure.
-
- @param TextDeviceNode The input Text device path node.
-
- @return A pointer to the newly-created Fibre device path structure.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-DevPathFromTextFibre (
- IN CHAR16 *TextDeviceNode
- )
-{
- CHAR16 *WWNStr;
- CHAR16 *LunStr;
- FIBRECHANNEL_DEVICE_PATH *Fibre;
-
- WWNStr = GetNextParamStr (&TextDeviceNode);
- LunStr = GetNextParamStr (&TextDeviceNode);
- Fibre = (FIBRECHANNEL_DEVICE_PATH *) CreateDeviceNode (
- MESSAGING_DEVICE_PATH,
- MSG_FIBRECHANNEL_DP,
- (UINT16) sizeof (FIBRECHANNEL_DEVICE_PATH)
- );
-
- Fibre->Reserved = 0;
- Strtoi64 (WWNStr, &Fibre->WWN);
- Strtoi64 (LunStr, &Fibre->Lun);
-
- return (EFI_DEVICE_PATH_PROTOCOL *) Fibre;
-}
-
-/**
- Converts a text device path node to FibreEx device path structure.
-
- @param TextDeviceNode The input Text device path node.
-
- @return A pointer to the newly-created FibreEx device path structure.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-DevPathFromTextFibreEx (
- IN CHAR16 *TextDeviceNode
- )
-{
- CHAR16 *WWNStr;
- CHAR16 *LunStr;
- FIBRECHANNELEX_DEVICE_PATH *FibreEx;
-
- WWNStr = GetNextParamStr (&TextDeviceNode);
- LunStr = GetNextParamStr (&TextDeviceNode);
- FibreEx = (FIBRECHANNELEX_DEVICE_PATH *) CreateDeviceNode (
- MESSAGING_DEVICE_PATH,
- MSG_FIBRECHANNELEX_DP,
- (UINT16) sizeof (FIBRECHANNELEX_DEVICE_PATH)
- );
-
- FibreEx->Reserved = 0;
- Strtoi64 (WWNStr, (UINT64 *) (&FibreEx->WWN));
- Strtoi64 (LunStr, (UINT64 *) (&FibreEx->Lun));
-
- *(UINT64 *) (&FibreEx->WWN) = SwapBytes64 (*(UINT64 *) (&FibreEx->WWN));
- *(UINT64 *) (&FibreEx->Lun) = SwapBytes64 (*(UINT64 *) (&FibreEx->Lun));
-
- return (EFI_DEVICE_PATH_PROTOCOL *) FibreEx;
-}
-
-/**
- Converts a text device path node to 1394 device path structure.
-
- @param TextDeviceNode The input Text device path node.
-
- @return A pointer to the newly-created 1394 device path structure.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-DevPathFromText1394 (
- IN CHAR16 *TextDeviceNode
- )
-{
- CHAR16 *GuidStr;
- F1394_DEVICE_PATH *F1394DevPath;
-
- GuidStr = GetNextParamStr (&TextDeviceNode);
- F1394DevPath = (F1394_DEVICE_PATH *) CreateDeviceNode (
- MESSAGING_DEVICE_PATH,
- MSG_1394_DP,
- (UINT16) sizeof (F1394_DEVICE_PATH)
- );
-
- F1394DevPath->Reserved = 0;
- Xtoi64 (GuidStr, &F1394DevPath->Guid);
-
- return (EFI_DEVICE_PATH_PROTOCOL *) F1394DevPath;
-}
-
-/**
- Converts a text device path node to USB device path structure.
-
- @param TextDeviceNode The input Text device path node.
-
- @return A pointer to the newly-created USB device path structure.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-DevPathFromTextUsb (
- IN CHAR16 *TextDeviceNode
- )
-{
- CHAR16 *PortStr;
- CHAR16 *InterfaceStr;
- USB_DEVICE_PATH *Usb;
-
- PortStr = GetNextParamStr (&TextDeviceNode);
- InterfaceStr = GetNextParamStr (&TextDeviceNode);
- Usb = (USB_DEVICE_PATH *) CreateDeviceNode (
- MESSAGING_DEVICE_PATH,
- MSG_USB_DP,
- (UINT16) sizeof (USB_DEVICE_PATH)
- );
-
- Usb->ParentPortNumber = (UINT8) Strtoi (PortStr);
- Usb->InterfaceNumber = (UINT8) Strtoi (InterfaceStr);
-
- return (EFI_DEVICE_PATH_PROTOCOL *) Usb;
-}
-
-/**
- Converts a text device path node to I20 device path structure.
-
- @param TextDeviceNode The input Text device path node.
-
- @return A pointer to the newly-created I20 device path structure.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-DevPathFromTextI2O (
- IN CHAR16 *TextDeviceNode
- )
-{
- CHAR16 *TIDStr;
- I2O_DEVICE_PATH *I2ODevPath;
-
- TIDStr = GetNextParamStr (&TextDeviceNode);
- I2ODevPath = (I2O_DEVICE_PATH *) CreateDeviceNode (
- MESSAGING_DEVICE_PATH,
- MSG_I2O_DP,
- (UINT16) sizeof (I2O_DEVICE_PATH)
- );
-
- I2ODevPath->Tid = (UINT32) Strtoi (TIDStr);
-
- return (EFI_DEVICE_PATH_PROTOCOL *) I2ODevPath;
-}
-
-/**
- Converts a text device path node to Infini Band device path structure.
-
- @param TextDeviceNode The input Text device path node.
-
- @return A pointer to the newly-created Infini Band device path structure.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-DevPathFromTextInfiniband (
- IN CHAR16 *TextDeviceNode
- )
-{
- CHAR16 *FlagsStr;
- CHAR16 *GuidStr;
- CHAR16 *SidStr;
- CHAR16 *TidStr;
- CHAR16 *DidStr;
- EFI_GUID PortGid;
- INFINIBAND_DEVICE_PATH *InfiniBand;
-
- FlagsStr = GetNextParamStr (&TextDeviceNode);
- GuidStr = GetNextParamStr (&TextDeviceNode);
- SidStr = GetNextParamStr (&TextDeviceNode);
- TidStr = GetNextParamStr (&TextDeviceNode);
- DidStr = GetNextParamStr (&TextDeviceNode);
- InfiniBand = (INFINIBAND_DEVICE_PATH *) CreateDeviceNode (
- MESSAGING_DEVICE_PATH,
- MSG_INFINIBAND_DP,
- (UINT16) sizeof (INFINIBAND_DEVICE_PATH)
- );
-
- InfiniBand->ResourceFlags = (UINT32) Strtoi (FlagsStr);
- StrToGuid (GuidStr, &PortGid);
- CopyMem (InfiniBand->PortGid, &PortGid, sizeof (EFI_GUID));
- Strtoi64 (SidStr, &InfiniBand->ServiceId);
- Strtoi64 (TidStr, &InfiniBand->TargetPortId);
- Strtoi64 (DidStr, &InfiniBand->DeviceId);
-
- return (EFI_DEVICE_PATH_PROTOCOL *) InfiniBand;
-}
-
-/**
- Converts a text device path node to Vendor-Defined Messaging device path structure.
-
- @param TextDeviceNode The input Text device path node.
-
- @return A pointer to the newly-created Vendor-Defined Messaging device path structure.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-DevPathFromTextVenMsg (
- IN CHAR16 *TextDeviceNode
- )
-{
- return ConvertFromTextVendor (
- TextDeviceNode,
- MESSAGING_DEVICE_PATH,
- MSG_VENDOR_DP
- );
-}
-
-/**
- Converts a text device path node to Vendor defined PC-ANSI device path structure.
-
- @param TextDeviceNode The input Text device path node.
-
- @return A pointer to the newly-created Vendor defined PC-ANSI device path structure.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-DevPathFromTextVenPcAnsi (
- IN CHAR16 *TextDeviceNode
- )
-{
- VENDOR_DEVICE_PATH *Vendor;
-
- Vendor = (VENDOR_DEVICE_PATH *) CreateDeviceNode (
- MESSAGING_DEVICE_PATH,
- MSG_VENDOR_DP,
- (UINT16) sizeof (VENDOR_DEVICE_PATH));
- CopyGuid (&Vendor->Guid, &gEfiPcAnsiGuid);
-
- return (EFI_DEVICE_PATH_PROTOCOL *) Vendor;
-}
-
-/**
- Converts a text device path node to Vendor defined VT100 device path structure.
-
- @param TextDeviceNode The input Text device path node.
-
- @return A pointer to the newly-created Vendor defined VT100 device path structure.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-DevPathFromTextVenVt100 (
- IN CHAR16 *TextDeviceNode
- )
-{
- VENDOR_DEVICE_PATH *Vendor;
-
- Vendor = (VENDOR_DEVICE_PATH *) CreateDeviceNode (
- MESSAGING_DEVICE_PATH,
- MSG_VENDOR_DP,
- (UINT16) sizeof (VENDOR_DEVICE_PATH));
- CopyGuid (&Vendor->Guid, &gEfiVT100Guid);
-
- return (EFI_DEVICE_PATH_PROTOCOL *) Vendor;
-}
-
-/**
- Converts a text device path node to Vendor defined VT100 Plus device path structure.
-
- @param TextDeviceNode The input Text device path node.
-
- @return A pointer to the newly-created Vendor defined VT100 Plus device path structure.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-DevPathFromTextVenVt100Plus (
- IN CHAR16 *TextDeviceNode
- )
-{
- VENDOR_DEVICE_PATH *Vendor;
-
- Vendor = (VENDOR_DEVICE_PATH *) CreateDeviceNode (
- MESSAGING_DEVICE_PATH,
- MSG_VENDOR_DP,
- (UINT16) sizeof (VENDOR_DEVICE_PATH));
- CopyGuid (&Vendor->Guid, &gEfiVT100PlusGuid);
-
- return (EFI_DEVICE_PATH_PROTOCOL *) Vendor;
-}
-
-/**
- Converts a text device path node to Vendor defined UTF8 device path structure.
-
- @param TextDeviceNode The input Text device path node.
-
- @return A pointer to the newly-created Vendor defined UTF8 device path structure.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-DevPathFromTextVenUtf8 (
- IN CHAR16 *TextDeviceNode
- )
-{
- VENDOR_DEVICE_PATH *Vendor;
-
- Vendor = (VENDOR_DEVICE_PATH *) CreateDeviceNode (
- MESSAGING_DEVICE_PATH,
- MSG_VENDOR_DP,
- (UINT16) sizeof (VENDOR_DEVICE_PATH));
- CopyGuid (&Vendor->Guid, &gEfiVTUTF8Guid);
-
- return (EFI_DEVICE_PATH_PROTOCOL *) Vendor;
-}
-
-/**
- Converts a text device path node to UART Flow Control device path structure.
-
- @param TextDeviceNode The input Text device path node.
-
- @return A pointer to the newly-created UART Flow Control device path structure.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-DevPathFromTextUartFlowCtrl (
- IN CHAR16 *TextDeviceNode
- )
-{
- CHAR16 *ValueStr;
- UART_FLOW_CONTROL_DEVICE_PATH *UartFlowControl;
-
- ValueStr = GetNextParamStr (&TextDeviceNode);
- UartFlowControl = (UART_FLOW_CONTROL_DEVICE_PATH *) CreateDeviceNode (
- MESSAGING_DEVICE_PATH,
- MSG_VENDOR_DP,
- (UINT16) sizeof (UART_FLOW_CONTROL_DEVICE_PATH)
- );
-
- CopyGuid (&UartFlowControl->Guid, &gEfiUartDevicePathGuid);
- if (StrCmp (ValueStr, L"XonXoff") == 0) {
- UartFlowControl->FlowControlMap = 2;
- } else if (StrCmp (ValueStr, L"Hardware") == 0) {
- UartFlowControl->FlowControlMap = 1;
- } else {
- UartFlowControl->FlowControlMap = 0;
- }
-
- return (EFI_DEVICE_PATH_PROTOCOL *) UartFlowControl;
-}
-
-/**
- Converts a text device path node to Serial Attached SCSI device path structure.
-
- @param TextDeviceNode The input Text device path node.
-
- @return A pointer to the newly-created Serial Attached SCSI device path structure.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-DevPathFromTextSAS (
- IN CHAR16 *TextDeviceNode
- )
-{
- CHAR16 *AddressStr;
- CHAR16 *LunStr;
- CHAR16 *RTPStr;
- CHAR16 *SASSATAStr;
- CHAR16 *LocationStr;
- CHAR16 *ConnectStr;
- CHAR16 *DriveBayStr;
- CHAR16 *ReservedStr;
- UINT16 Info;
- UINT16 Uint16;
- SAS_DEVICE_PATH *Sas;
-
- AddressStr = GetNextParamStr (&TextDeviceNode);
- LunStr = GetNextParamStr (&TextDeviceNode);
- RTPStr = GetNextParamStr (&TextDeviceNode);
- SASSATAStr = GetNextParamStr (&TextDeviceNode);
- LocationStr = GetNextParamStr (&TextDeviceNode);
- ConnectStr = GetNextParamStr (&TextDeviceNode);
- DriveBayStr = GetNextParamStr (&TextDeviceNode);
- ReservedStr = GetNextParamStr (&TextDeviceNode);
- Sas = (SAS_DEVICE_PATH *) CreateDeviceNode (
- MESSAGING_DEVICE_PATH,
- MSG_VENDOR_DP,
- (UINT16) sizeof (SAS_DEVICE_PATH)
- );
-
- CopyGuid (&Sas->Guid, &gEfiSasDevicePathGuid);
- Strtoi64 (AddressStr, &Sas->SasAddress);
- Strtoi64 (LunStr, &Sas->Lun);
- Sas->RelativeTargetPort = (UINT16) Strtoi (RTPStr);
-
- if (StrCmp (SASSATAStr, L"NoTopology") == 0) {
- Info = 0x0;
-
- } else if ((StrCmp (SASSATAStr, L"SATA") == 0) || (StrCmp (SASSATAStr, L"SAS") == 0)) {
-
- Uint16 = (UINT16) Strtoi (DriveBayStr);
- if (Uint16 == 0) {
- Info = 0x1;
- } else {
- Info = (UINT16) (0x2 | ((Uint16 - 1) << 8));
- }
-
- if (StrCmp (SASSATAStr, L"SATA") == 0) {
- Info |= BIT4;
- }
-
- //
- // Location is an integer between 0 and 1 or else
- // the keyword Internal (0) or External (1).
- //
- if (StrCmp (LocationStr, L"External") == 0) {
- Uint16 = 1;
- } else if (StrCmp (LocationStr, L"Internal") == 0) {
- Uint16 = 0;
- } else {
- Uint16 = ((UINT16) Strtoi (LocationStr) & BIT0);
- }
- Info |= (Uint16 << 5);
-
- //
- // Connect is an integer between 0 and 3 or else
- // the keyword Direct (0) or Expanded (1).
- //
- if (StrCmp (ConnectStr, L"Expanded") == 0) {
- Uint16 = 1;
- } else if (StrCmp (ConnectStr, L"Direct") == 0) {
- Uint16 = 0;
- } else {
- Uint16 = ((UINT16) Strtoi (ConnectStr) & (BIT0 | BIT1));
- }
- Info |= (Uint16 << 6);
-
- } else {
- Info = (UINT16) Strtoi (SASSATAStr);
- }
-
- Sas->DeviceTopology = Info;
- Sas->Reserved = (UINT32) Strtoi (ReservedStr);
-
- return (EFI_DEVICE_PATH_PROTOCOL *) Sas;
-}
-
-/**
- Converts a text device path node to Serial Attached SCSI Ex device path structure.
-
- @param TextDeviceNode The input Text device path node.
-
- @return A pointer to the newly-created Serial Attached SCSI Ex device path structure.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-DevPathFromTextSasEx (
- IN CHAR16 *TextDeviceNode
- )
-{
- CHAR16 *AddressStr;
- CHAR16 *LunStr;
- CHAR16 *RTPStr;
- CHAR16 *SASSATAStr;
- CHAR16 *LocationStr;
- CHAR16 *ConnectStr;
- CHAR16 *DriveBayStr;
- UINT16 Info;
- UINT16 Uint16;
- UINT64 SasAddress;
- UINT64 Lun;
- SASEX_DEVICE_PATH *SasEx;
-
- AddressStr = GetNextParamStr (&TextDeviceNode);
- LunStr = GetNextParamStr (&TextDeviceNode);
- RTPStr = GetNextParamStr (&TextDeviceNode);
- SASSATAStr = GetNextParamStr (&TextDeviceNode);
- LocationStr = GetNextParamStr (&TextDeviceNode);
- ConnectStr = GetNextParamStr (&TextDeviceNode);
- DriveBayStr = GetNextParamStr (&TextDeviceNode);
- SasEx = (SASEX_DEVICE_PATH *) CreateDeviceNode (
- MESSAGING_DEVICE_PATH,
- MSG_SASEX_DP,
- (UINT16) sizeof (SASEX_DEVICE_PATH)
- );
-
- Strtoi64 (AddressStr, &SasAddress);
- Strtoi64 (LunStr, &Lun);
- WriteUnaligned64 ((UINT64 *) &SasEx->SasAddress, SwapBytes64 (SasAddress));
- WriteUnaligned64 ((UINT64 *) &SasEx->Lun, SwapBytes64 (Lun));
- SasEx->RelativeTargetPort = (UINT16) Strtoi (RTPStr);
-
- if (StrCmp (SASSATAStr, L"NoTopology") == 0) {
- Info = 0x0;
-
- } else if ((StrCmp (SASSATAStr, L"SATA") == 0) || (StrCmp (SASSATAStr, L"SAS") == 0)) {
-
- Uint16 = (UINT16) Strtoi (DriveBayStr);
- if (Uint16 == 0) {
- Info = 0x1;
- } else {
- Info = (UINT16) (0x2 | ((Uint16 - 1) << 8));
- }
-
- if (StrCmp (SASSATAStr, L"SATA") == 0) {
- Info |= BIT4;
- }
-
- //
- // Location is an integer between 0 and 1 or else
- // the keyword Internal (0) or External (1).
- //
- if (StrCmp (LocationStr, L"External") == 0) {
- Uint16 = 1;
- } else if (StrCmp (LocationStr, L"Internal") == 0) {
- Uint16 = 0;
- } else {
- Uint16 = ((UINT16) Strtoi (LocationStr) & BIT0);
- }
- Info |= (Uint16 << 5);
-
- //
- // Connect is an integer between 0 and 3 or else
- // the keyword Direct (0) or Expanded (1).
- //
- if (StrCmp (ConnectStr, L"Expanded") == 0) {
- Uint16 = 1;
- } else if (StrCmp (ConnectStr, L"Direct") == 0) {
- Uint16 = 0;
- } else {
- Uint16 = ((UINT16) Strtoi (ConnectStr) & (BIT0 | BIT1));
- }
- Info |= (Uint16 << 6);
-
- } else {
- Info = (UINT16) Strtoi (SASSATAStr);
- }
-
- SasEx->DeviceTopology = Info;
-
- return (EFI_DEVICE_PATH_PROTOCOL *) SasEx;
-}
-
-/**
- Converts a text device path node to Debug Port device path structure.
-
- @param TextDeviceNode The input Text device path node.
-
- @return A pointer to the newly-created Debug Port device path structure.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-DevPathFromTextDebugPort (
- IN CHAR16 *TextDeviceNode
- )
-{
- VENDOR_DEFINED_MESSAGING_DEVICE_PATH *Vend;
-
- Vend = (VENDOR_DEFINED_MESSAGING_DEVICE_PATH *) CreateDeviceNode (
- MESSAGING_DEVICE_PATH,
- MSG_VENDOR_DP,
- (UINT16) sizeof (VENDOR_DEFINED_MESSAGING_DEVICE_PATH)
- );
-
- CopyGuid (&Vend->Guid, &gEfiDebugPortProtocolGuid);
-
- return (EFI_DEVICE_PATH_PROTOCOL *) Vend;
-}
-
-/**
- Converts a text device path node to MAC device path structure.
-
- @param TextDeviceNode The input Text device path node.
-
- @return A pointer to the newly-created MAC device path structure.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-DevPathFromTextMAC (
- IN CHAR16 *TextDeviceNode
- )
-{
- CHAR16 *AddressStr;
- CHAR16 *IfTypeStr;
- UINTN Length;
- MAC_ADDR_DEVICE_PATH *MACDevPath;
-
- AddressStr = GetNextParamStr (&TextDeviceNode);
- IfTypeStr = GetNextParamStr (&TextDeviceNode);
- MACDevPath = (MAC_ADDR_DEVICE_PATH *) CreateDeviceNode (
- MESSAGING_DEVICE_PATH,
- MSG_MAC_ADDR_DP,
- (UINT16) sizeof (MAC_ADDR_DEVICE_PATH)
- );
-
- MACDevPath->IfType = (UINT8) Strtoi (IfTypeStr);
-
- Length = sizeof (EFI_MAC_ADDRESS);
- StrToBuf (&MACDevPath->MacAddress.Addr[0], Length, AddressStr);
-
- return (EFI_DEVICE_PATH_PROTOCOL *) MACDevPath;
-}
-
-
-/**
- Converts a text format to the network protocol ID.
-
- @param Text String of protocol field.
-
- @return Network protocol ID .
-
-**/
-UINTN
-NetworkProtocolFromText (
- IN CHAR16 *Text
- )
-{
- if (StrCmp (Text, L"UDP") == 0) {
- return RFC_1700_UDP_PROTOCOL;
- }
-
- if (StrCmp (Text, L"TCP") == 0) {
- return RFC_1700_TCP_PROTOCOL;
- }
-
- return Strtoi (Text);
-}
-
-
-/**
- Converts a text device path node to IPV4 device path structure.
-
- @param TextDeviceNode The input Text device path node.
-
- @return A pointer to the newly-created IPV4 device path structure.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-DevPathFromTextIPv4 (
- IN CHAR16 *TextDeviceNode
- )
-{
- CHAR16 *RemoteIPStr;
- CHAR16 *ProtocolStr;
- CHAR16 *TypeStr;
- CHAR16 *LocalIPStr;
- CHAR16 *GatewayIPStr;
- CHAR16 *SubnetMaskStr;
- IPv4_DEVICE_PATH *IPv4;
-
- RemoteIPStr = GetNextParamStr (&TextDeviceNode);
- ProtocolStr = GetNextParamStr (&TextDeviceNode);
- TypeStr = GetNextParamStr (&TextDeviceNode);
- LocalIPStr = GetNextParamStr (&TextDeviceNode);
- GatewayIPStr = GetNextParamStr (&TextDeviceNode);
- SubnetMaskStr = GetNextParamStr (&TextDeviceNode);
- IPv4 = (IPv4_DEVICE_PATH *) CreateDeviceNode (
- MESSAGING_DEVICE_PATH,
- MSG_IPv4_DP,
- (UINT16) sizeof (IPv4_DEVICE_PATH)
- );
-
- StrToIPv4Addr (&RemoteIPStr, &IPv4->RemoteIpAddress);
- IPv4->Protocol = (UINT16) NetworkProtocolFromText (ProtocolStr);
- if (StrCmp (TypeStr, L"Static") == 0) {
- IPv4->StaticIpAddress = TRUE;
- } else {
- IPv4->StaticIpAddress = FALSE;
- }
-
- StrToIPv4Addr (&LocalIPStr, &IPv4->LocalIpAddress);
- if (!IS_NULL (*GatewayIPStr) && !IS_NULL (*SubnetMaskStr)) {
- StrToIPv4Addr (&GatewayIPStr, &IPv4->GatewayIpAddress);
- StrToIPv4Addr (&SubnetMaskStr, &IPv4->SubnetMask);
- } else {
- ZeroMem (&IPv4->GatewayIpAddress, sizeof (IPv4->GatewayIpAddress));
- ZeroMem (&IPv4->SubnetMask, sizeof (IPv4->SubnetMask));
- }
-
- IPv4->LocalPort = 0;
- IPv4->RemotePort = 0;
-
- return (EFI_DEVICE_PATH_PROTOCOL *) IPv4;
-}
-
-/**
- Converts a text device path node to IPV6 device path structure.
-
- @param TextDeviceNode The input Text device path node.
-
- @return A pointer to the newly-created IPV6 device path structure.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-DevPathFromTextIPv6 (
- IN CHAR16 *TextDeviceNode
- )
-{
- CHAR16 *RemoteIPStr;
- CHAR16 *ProtocolStr;
- CHAR16 *TypeStr;
- CHAR16 *LocalIPStr;
- CHAR16 *GatewayIPStr;
- CHAR16 *PrefixLengthStr;
- IPv6_DEVICE_PATH *IPv6;
-
- RemoteIPStr = GetNextParamStr (&TextDeviceNode);
- ProtocolStr = GetNextParamStr (&TextDeviceNode);
- TypeStr = GetNextParamStr (&TextDeviceNode);
- LocalIPStr = GetNextParamStr (&TextDeviceNode);
- PrefixLengthStr = GetNextParamStr (&TextDeviceNode);
- GatewayIPStr = GetNextParamStr (&TextDeviceNode);
- IPv6 = (IPv6_DEVICE_PATH *) CreateDeviceNode (
- MESSAGING_DEVICE_PATH,
- MSG_IPv6_DP,
- (UINT16) sizeof (IPv6_DEVICE_PATH)
- );
-
- StrToIPv6Addr (&RemoteIPStr, &IPv6->RemoteIpAddress);
- IPv6->Protocol = (UINT16) NetworkProtocolFromText (ProtocolStr);
- if (StrCmp (TypeStr, L"Static") == 0) {
- IPv6->IpAddressOrigin = 0;
- } else if (StrCmp (TypeStr, L"StatelessAutoConfigure") == 0) {
- IPv6->IpAddressOrigin = 1;
- } else {
- IPv6->IpAddressOrigin = 2;
- }
-
- StrToIPv6Addr (&LocalIPStr, &IPv6->LocalIpAddress);
- if (!IS_NULL (*GatewayIPStr) && !IS_NULL (*PrefixLengthStr)) {
- StrToIPv6Addr (&GatewayIPStr, &IPv6->GatewayIpAddress);
- IPv6->PrefixLength = (UINT8) Strtoi (PrefixLengthStr);
- } else {
- ZeroMem (&IPv6->GatewayIpAddress, sizeof (IPv6->GatewayIpAddress));
- IPv6->PrefixLength = 0;
- }
-
- IPv6->LocalPort = 0;
- IPv6->RemotePort = 0;
-
- return (EFI_DEVICE_PATH_PROTOCOL *) IPv6;
-}
-
-/**
- Converts a text device path node to UART device path structure.
-
- @param TextDeviceNode The input Text device path node.
-
- @return A pointer to the newly-created UART device path structure.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-DevPathFromTextUart (
- IN CHAR16 *TextDeviceNode
- )
-{
- CHAR16 *BaudStr;
- CHAR16 *DataBitsStr;
- CHAR16 *ParityStr;
- CHAR16 *StopBitsStr;
- UART_DEVICE_PATH *Uart;
-
- BaudStr = GetNextParamStr (&TextDeviceNode);
- DataBitsStr = GetNextParamStr (&TextDeviceNode);
- ParityStr = GetNextParamStr (&TextDeviceNode);
- StopBitsStr = GetNextParamStr (&TextDeviceNode);
- Uart = (UART_DEVICE_PATH *) CreateDeviceNode (
- MESSAGING_DEVICE_PATH,
- MSG_UART_DP,
- (UINT16) sizeof (UART_DEVICE_PATH)
- );
-
- Uart->BaudRate = (StrCmp (BaudStr, L"DEFAULT") == 0) ? 115200 : Dtoi (BaudStr);
- Uart->DataBits = (UINT8) ((StrCmp (DataBitsStr, L"DEFAULT") == 0) ? 8 : Dtoi (DataBitsStr));
- switch (*ParityStr) {
- case L'D':
- Uart->Parity = 0;
- break;
-
- case L'N':
- Uart->Parity = 1;
- break;
-
- case L'E':
- Uart->Parity = 2;
- break;
-
- case L'O':
- Uart->Parity = 3;
- break;
-
- case L'M':
- Uart->Parity = 4;
- break;
-
- case L'S':
- Uart->Parity = 5;
- break;
-
- default:
- Uart->Parity = 0xff;
- }
-
- if (StrCmp (StopBitsStr, L"D") == 0) {
- Uart->StopBits = (UINT8) 0;
- } else if (StrCmp (StopBitsStr, L"1") == 0) {
- Uart->StopBits = (UINT8) 1;
- } else if (StrCmp (StopBitsStr, L"1.5") == 0) {
- Uart->StopBits = (UINT8) 2;
- } else if (StrCmp (StopBitsStr, L"2") == 0) {
- Uart->StopBits = (UINT8) 3;
- } else {
- Uart->StopBits = 0xff;
- }
-
- return (EFI_DEVICE_PATH_PROTOCOL *) Uart;
-}
-
-/**
- Converts a text device path node to USB class device path structure.
-
- @param TextDeviceNode The input Text device path node.
- @param UsbClassText A pointer to USB_CLASS_TEXT structure to be integrated to USB Class Text.
-
- @return A pointer to the newly-created USB class device path structure.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-ConvertFromTextUsbClass (
- IN CHAR16 *TextDeviceNode,
- IN USB_CLASS_TEXT *UsbClassText
- )
-{
- CHAR16 *VIDStr;
- CHAR16 *PIDStr;
- CHAR16 *ClassStr;
- CHAR16 *SubClassStr;
- CHAR16 *ProtocolStr;
- USB_CLASS_DEVICE_PATH *UsbClass;
-
- UsbClass = (USB_CLASS_DEVICE_PATH *) CreateDeviceNode (
- MESSAGING_DEVICE_PATH,
- MSG_USB_CLASS_DP,
- (UINT16) sizeof (USB_CLASS_DEVICE_PATH)
- );
-
- VIDStr = GetNextParamStr (&TextDeviceNode);
- PIDStr = GetNextParamStr (&TextDeviceNode);
- if (UsbClassText->ClassExist) {
- ClassStr = GetNextParamStr (&TextDeviceNode);
- UsbClass->DeviceClass = (UINT8) Strtoi (ClassStr);
- } else {
- UsbClass->DeviceClass = UsbClassText->Class;
- }
- if (UsbClassText->SubClassExist) {
- SubClassStr = GetNextParamStr (&TextDeviceNode);
- UsbClass->DeviceSubClass = (UINT8) Strtoi (SubClassStr);
- } else {
- UsbClass->DeviceSubClass = UsbClassText->SubClass;
- }
-
- ProtocolStr = GetNextParamStr (&TextDeviceNode);
-
- UsbClass->VendorId = (UINT16) Strtoi (VIDStr);
- UsbClass->ProductId = (UINT16) Strtoi (PIDStr);
- UsbClass->DeviceProtocol = (UINT8) Strtoi (ProtocolStr);
-
- return (EFI_DEVICE_PATH_PROTOCOL *) UsbClass;
-}
-
-
-/**
- Converts a text device path node to USB class device path structure.
-
- @param TextDeviceNode The input Text device path node.
-
- @return A pointer to the newly-created USB class device path structure.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-DevPathFromTextUsbClass (
- IN CHAR16 *TextDeviceNode
- )
-{
- USB_CLASS_TEXT UsbClassText;
-
- UsbClassText.ClassExist = TRUE;
- UsbClassText.SubClassExist = TRUE;
-
- return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText);
-}
-
-/**
- Converts a text device path node to USB audio device path structure.
-
- @param TextDeviceNode The input Text device path node.
-
- @return A pointer to the newly-created USB audio device path structure.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-DevPathFromTextUsbAudio (
- IN CHAR16 *TextDeviceNode
- )
-{
- USB_CLASS_TEXT UsbClassText;
-
- UsbClassText.ClassExist = FALSE;
- UsbClassText.Class = USB_CLASS_AUDIO;
- UsbClassText.SubClassExist = TRUE;
-
- return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText);
-}
-
-/**
- Converts a text device path node to USB CDC Control device path structure.
-
- @param TextDeviceNode The input Text device path node.
-
- @return A pointer to the newly-created USB CDC Control device path structure.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-DevPathFromTextUsbCDCControl (
- IN CHAR16 *TextDeviceNode
- )
-{
- USB_CLASS_TEXT UsbClassText;
-
- UsbClassText.ClassExist = FALSE;
- UsbClassText.Class = USB_CLASS_CDCCONTROL;
- UsbClassText.SubClassExist = TRUE;
-
- return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText);
-}
-
-/**
- Converts a text device path node to USB HID device path structure.
-
- @param TextDeviceNode The input Text device path node.
-
- @return A pointer to the newly-created USB HID device path structure.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-DevPathFromTextUsbHID (
- IN CHAR16 *TextDeviceNode
- )
-{
- USB_CLASS_TEXT UsbClassText;
-
- UsbClassText.ClassExist = FALSE;
- UsbClassText.Class = USB_CLASS_HID;
- UsbClassText.SubClassExist = TRUE;
-
- return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText);
-}
-
-/**
- Converts a text device path node to USB Image device path structure.
-
- @param TextDeviceNode The input Text device path node.
-
- @return A pointer to the newly-created USB Image device path structure.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-DevPathFromTextUsbImage (
- IN CHAR16 *TextDeviceNode
- )
-{
- USB_CLASS_TEXT UsbClassText;
-
- UsbClassText.ClassExist = FALSE;
- UsbClassText.Class = USB_CLASS_IMAGE;
- UsbClassText.SubClassExist = TRUE;
-
- return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText);
-}
-
-/**
- Converts a text device path node to USB Print device path structure.
-
- @param TextDeviceNode The input Text device path node.
-
- @return A pointer to the newly-created USB Print device path structure.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-DevPathFromTextUsbPrinter (
- IN CHAR16 *TextDeviceNode
- )
-{
- USB_CLASS_TEXT UsbClassText;
-
- UsbClassText.ClassExist = FALSE;
- UsbClassText.Class = USB_CLASS_PRINTER;
- UsbClassText.SubClassExist = TRUE;
-
- return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText);
-}
-
-/**
- Converts a text device path node to USB mass storage device path structure.
-
- @param TextDeviceNode The input Text device path node.
-
- @return A pointer to the newly-created USB mass storage device path structure.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-DevPathFromTextUsbMassStorage (
- IN CHAR16 *TextDeviceNode
- )
-{
- USB_CLASS_TEXT UsbClassText;
-
- UsbClassText.ClassExist = FALSE;
- UsbClassText.Class = USB_CLASS_MASS_STORAGE;
- UsbClassText.SubClassExist = TRUE;
-
- return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText);
-}
-
-/**
- Converts a text device path node to USB HUB device path structure.
-
- @param TextDeviceNode The input Text device path node.
-
- @return A pointer to the newly-created USB HUB device path structure.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-DevPathFromTextUsbHub (
- IN CHAR16 *TextDeviceNode
- )
-{
- USB_CLASS_TEXT UsbClassText;
-
- UsbClassText.ClassExist = FALSE;
- UsbClassText.Class = USB_CLASS_HUB;
- UsbClassText.SubClassExist = TRUE;
-
- return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText);
-}
-
-/**
- Converts a text device path node to USB CDC data device path structure.
-
- @param TextDeviceNode The input Text device path node.
-
- @return A pointer to the newly-created USB CDC data device path structure.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-DevPathFromTextUsbCDCData (
- IN CHAR16 *TextDeviceNode
- )
-{
- USB_CLASS_TEXT UsbClassText;
-
- UsbClassText.ClassExist = FALSE;
- UsbClassText.Class = USB_CLASS_CDCDATA;
- UsbClassText.SubClassExist = TRUE;
-
- return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText);
-}
-
-/**
- Converts a text device path node to USB smart card device path structure.
-
- @param TextDeviceNode The input Text device path node.
-
- @return A pointer to the newly-created USB smart card device path structure.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-DevPathFromTextUsbSmartCard (
- IN CHAR16 *TextDeviceNode
- )
-{
- USB_CLASS_TEXT UsbClassText;
-
- UsbClassText.ClassExist = FALSE;
- UsbClassText.Class = USB_CLASS_SMART_CARD;
- UsbClassText.SubClassExist = TRUE;
-
- return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText);
-}
-
-/**
- Converts a text device path node to USB video device path structure.
-
- @param TextDeviceNode The input Text device path node.
-
- @return A pointer to the newly-created USB video device path structure.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-DevPathFromTextUsbVideo (
- IN CHAR16 *TextDeviceNode
- )
-{
- USB_CLASS_TEXT UsbClassText;
-
- UsbClassText.ClassExist = FALSE;
- UsbClassText.Class = USB_CLASS_VIDEO;
- UsbClassText.SubClassExist = TRUE;
-
- return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText);
-}
-
-/**
- Converts a text device path node to USB diagnostic device path structure.
-
- @param TextDeviceNode The input Text device path node.
-
- @return A pointer to the newly-created USB diagnostic device path structure.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-DevPathFromTextUsbDiagnostic (
- IN CHAR16 *TextDeviceNode
- )
-{
- USB_CLASS_TEXT UsbClassText;
-
- UsbClassText.ClassExist = FALSE;
- UsbClassText.Class = USB_CLASS_DIAGNOSTIC;
- UsbClassText.SubClassExist = TRUE;
-
- return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText);
-}
-
-/**
- Converts a text device path node to USB wireless device path structure.
-
- @param TextDeviceNode The input Text device path node.
-
- @return A pointer to the newly-created USB wireless device path structure.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-DevPathFromTextUsbWireless (
- IN CHAR16 *TextDeviceNode
- )
-{
- USB_CLASS_TEXT UsbClassText;
-
- UsbClassText.ClassExist = FALSE;
- UsbClassText.Class = USB_CLASS_WIRELESS;
- UsbClassText.SubClassExist = TRUE;
-
- return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText);
-}
-
-/**
- Converts a text device path node to USB device firmware update device path structure.
-
- @param TextDeviceNode The input Text device path node.
-
- @return A pointer to the newly-created USB device firmware update device path structure.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-DevPathFromTextUsbDeviceFirmwareUpdate (
- IN CHAR16 *TextDeviceNode
- )
-{
- USB_CLASS_TEXT UsbClassText;
-
- UsbClassText.ClassExist = FALSE;
- UsbClassText.Class = USB_CLASS_RESERVE;
- UsbClassText.SubClassExist = FALSE;
- UsbClassText.SubClass = USB_SUBCLASS_FW_UPDATE;
-
- return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText);
-}
-
-/**
- Converts a text device path node to USB IRDA bridge device path structure.
-
- @param TextDeviceNode The input Text device path node.
-
- @return A pointer to the newly-created USB IRDA bridge device path structure.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-DevPathFromTextUsbIrdaBridge (
- IN CHAR16 *TextDeviceNode
- )
-{
- USB_CLASS_TEXT UsbClassText;
-
- UsbClassText.ClassExist = FALSE;
- UsbClassText.Class = USB_CLASS_RESERVE;
- UsbClassText.SubClassExist = FALSE;
- UsbClassText.SubClass = USB_SUBCLASS_IRDA_BRIDGE;
-
- return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText);
-}
-
-/**
- Converts a text device path node to USB text and measurement device path structure.
-
- @param TextDeviceNode The input Text device path node.
-
- @return A pointer to the newly-created USB text and measurement device path structure.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-DevPathFromTextUsbTestAndMeasurement (
- IN CHAR16 *TextDeviceNode
- )
-{
- USB_CLASS_TEXT UsbClassText;
-
- UsbClassText.ClassExist = FALSE;
- UsbClassText.Class = USB_CLASS_RESERVE;
- UsbClassText.SubClassExist = FALSE;
- UsbClassText.SubClass = USB_SUBCLASS_TEST;
-
- return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText);
-}
-
-/**
- Converts a text device path node to USB WWID device path structure.
-
- @param TextDeviceNode The input Text device path node.
-
- @return A pointer to the newly-created USB WWID device path structure.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-DevPathFromTextUsbWwid (
- IN CHAR16 *TextDeviceNode
- )
-{
- CHAR16 *VIDStr;
- CHAR16 *PIDStr;
- CHAR16 *InterfaceNumStr;
- CHAR16 *SerialNumberStr;
- USB_WWID_DEVICE_PATH *UsbWwid;
-
- VIDStr = GetNextParamStr (&TextDeviceNode);
- PIDStr = GetNextParamStr (&TextDeviceNode);
- InterfaceNumStr = GetNextParamStr (&TextDeviceNode);
- SerialNumberStr = GetNextParamStr (&TextDeviceNode);
- UsbWwid = (USB_WWID_DEVICE_PATH *) CreateDeviceNode (
- MESSAGING_DEVICE_PATH,
- MSG_USB_WWID_DP,
- (UINT16) (sizeof (USB_WWID_DEVICE_PATH) + StrSize (SerialNumberStr))
- );
-
- UsbWwid->VendorId = (UINT16) Strtoi (VIDStr);
- UsbWwid->ProductId = (UINT16) Strtoi (PIDStr);
- UsbWwid->InterfaceNumber = (UINT16) Strtoi (InterfaceNumStr);
- StrCpy ((CHAR16 *) ((UINT8 *) UsbWwid + sizeof (USB_WWID_DEVICE_PATH)), SerialNumberStr);
-
- return (EFI_DEVICE_PATH_PROTOCOL *) UsbWwid;
-}
-
-/**
- Converts a text device path node to Logic Unit device path structure.
-
- @param TextDeviceNode The input Text device path node.
-
- @return A pointer to the newly-created Logic Unit device path structure.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-DevPathFromTextUnit (
- IN CHAR16 *TextDeviceNode
- )
-{
- CHAR16 *LunStr;
- DEVICE_LOGICAL_UNIT_DEVICE_PATH *LogicalUnit;
-
- LunStr = GetNextParamStr (&TextDeviceNode);
- LogicalUnit = (DEVICE_LOGICAL_UNIT_DEVICE_PATH *) CreateDeviceNode (
- MESSAGING_DEVICE_PATH,
- MSG_DEVICE_LOGICAL_UNIT_DP,
- (UINT16) sizeof (DEVICE_LOGICAL_UNIT_DEVICE_PATH)
- );
-
- LogicalUnit->Lun = (UINT8) Strtoi (LunStr);
-
- return (EFI_DEVICE_PATH_PROTOCOL *) LogicalUnit;
-}
-
-/**
- Converts a text device path node to iSCSI device path structure.
-
- @param TextDeviceNode The input Text device path node.
-
- @return A pointer to the newly-created iSCSI device path structure.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-DevPathFromTextiSCSI (
- IN CHAR16 *TextDeviceNode
- )
-{
- UINT16 Options;
- CHAR16 *NameStr;
- CHAR16 *PortalGroupStr;
- CHAR16 *LunStr;
- CHAR16 *HeaderDigestStr;
- CHAR16 *DataDigestStr;
- CHAR16 *AuthenticationStr;
- CHAR16 *ProtocolStr;
- CHAR8 *AsciiStr;
- ISCSI_DEVICE_PATH_WITH_NAME *ISCSIDevPath;
-
- NameStr = GetNextParamStr (&TextDeviceNode);
- PortalGroupStr = GetNextParamStr (&TextDeviceNode);
- LunStr = GetNextParamStr (&TextDeviceNode);
- HeaderDigestStr = GetNextParamStr (&TextDeviceNode);
- DataDigestStr = GetNextParamStr (&TextDeviceNode);
- AuthenticationStr = GetNextParamStr (&TextDeviceNode);
- ProtocolStr = GetNextParamStr (&TextDeviceNode);
- ISCSIDevPath = (ISCSI_DEVICE_PATH_WITH_NAME *) CreateDeviceNode (
- MESSAGING_DEVICE_PATH,
- MSG_ISCSI_DP,
- (UINT16) (sizeof (ISCSI_DEVICE_PATH_WITH_NAME) + StrLen (NameStr))
- );
-
- AsciiStr = ISCSIDevPath->TargetName;
- StrToAscii (NameStr, &AsciiStr);
-
- ISCSIDevPath->TargetPortalGroupTag = (UINT16) Strtoi (PortalGroupStr);
- Strtoi64 (LunStr, &ISCSIDevPath->Lun);
-
- Options = 0x0000;
- if (StrCmp (HeaderDigestStr, L"CRC32C") == 0) {
- Options |= 0x0002;
- }
-
- if (StrCmp (DataDigestStr, L"CRC32C") == 0) {
- Options |= 0x0008;
- }
-
- if (StrCmp (AuthenticationStr, L"None") == 0) {
- Options |= 0x0800;
- }
-
- if (StrCmp (AuthenticationStr, L"CHAP_UNI") == 0) {
- Options |= 0x1000;
- }
-
- ISCSIDevPath->LoginOption = (UINT16) Options;
-
- ISCSIDevPath->NetworkProtocol = (UINT16) StrCmp (ProtocolStr, L"TCP");
-
- return (EFI_DEVICE_PATH_PROTOCOL *) ISCSIDevPath;
-}
-
-/**
- Converts a text device path node to VLAN device path structure.
-
- @param TextDeviceNode The input Text device path node.
-
- @return A pointer to the newly-created VLAN device path structure.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-DevPathFromTextVlan (
- IN CHAR16 *TextDeviceNode
- )
-{
- CHAR16 *VlanStr;
- VLAN_DEVICE_PATH *Vlan;
-
- VlanStr = GetNextParamStr (&TextDeviceNode);
- Vlan = (VLAN_DEVICE_PATH *) CreateDeviceNode (
- MESSAGING_DEVICE_PATH,
- MSG_VLAN_DP,
- (UINT16) sizeof (VLAN_DEVICE_PATH)
- );
-
- Vlan->VlanId = (UINT16) Strtoi (VlanStr);
-
- return (EFI_DEVICE_PATH_PROTOCOL *) Vlan;
-}
-
-/**
- Converts a text device path node to HD device path structure.
-
- @param TextDeviceNode The input Text device path node.
-
- @return A pointer to the newly-created HD device path structure.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-DevPathFromTextHD (
- IN CHAR16 *TextDeviceNode
- )
-{
- CHAR16 *PartitionStr;
- CHAR16 *TypeStr;
- CHAR16 *SignatureStr;
- CHAR16 *StartStr;
- CHAR16 *SizeStr;
- UINT32 Signature32;
- EFI_GUID SignatureGuid;
- HARDDRIVE_DEVICE_PATH *Hd;
-
- PartitionStr = GetNextParamStr (&TextDeviceNode);
- TypeStr = GetNextParamStr (&TextDeviceNode);
- SignatureStr = GetNextParamStr (&TextDeviceNode);
- StartStr = GetNextParamStr (&TextDeviceNode);
- SizeStr = GetNextParamStr (&TextDeviceNode);
- Hd = (HARDDRIVE_DEVICE_PATH *) CreateDeviceNode (
- MEDIA_DEVICE_PATH,
- MEDIA_HARDDRIVE_DP,
- (UINT16) sizeof (HARDDRIVE_DEVICE_PATH)
- );
-
- Hd->PartitionNumber = (UINT32) Dtoi (PartitionStr);
-
- ZeroMem (Hd->Signature, 16);
- Hd->MBRType = (UINT8) 0;
-
- if (StrCmp (TypeStr, L"MBR") == 0) {
- Hd->SignatureType = SIGNATURE_TYPE_MBR;
- Hd->MBRType = 0x01;
-
- Signature32 = (UINT32) Strtoi (SignatureStr);
- CopyMem (Hd->Signature, &Signature32, sizeof (UINT32));
- } else if (StrCmp (TypeStr, L"GPT") == 0) {
- Hd->SignatureType = SIGNATURE_TYPE_GUID;
- Hd->MBRType = 0x02;
-
- StrToGuid (SignatureStr, &SignatureGuid);
- CopyMem (Hd->Signature, &SignatureGuid, sizeof (EFI_GUID));
- } else {
- Hd->SignatureType = (UINT8) Strtoi (TypeStr);
- }
-
- Strtoi64 (StartStr, &Hd->PartitionStart);
- Strtoi64 (SizeStr, &Hd->PartitionSize);
-
- return (EFI_DEVICE_PATH_PROTOCOL *) Hd;
-}
-
-/**
- Converts a text device path node to CDROM device path structure.
-
- @param TextDeviceNode The input Text device path node.
-
- @return A pointer to the newly-created CDROM device path structure.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-DevPathFromTextCDROM (
- IN CHAR16 *TextDeviceNode
- )
-{
- CHAR16 *EntryStr;
- CHAR16 *StartStr;
- CHAR16 *SizeStr;
- CDROM_DEVICE_PATH *CDROMDevPath;
-
- EntryStr = GetNextParamStr (&TextDeviceNode);
- StartStr = GetNextParamStr (&TextDeviceNode);
- SizeStr = GetNextParamStr (&TextDeviceNode);
- CDROMDevPath = (CDROM_DEVICE_PATH *) CreateDeviceNode (
- MEDIA_DEVICE_PATH,
- MEDIA_CDROM_DP,
- (UINT16) sizeof (CDROM_DEVICE_PATH)
- );
-
- CDROMDevPath->BootEntry = (UINT32) Strtoi (EntryStr);
- Strtoi64 (StartStr, &CDROMDevPath->PartitionStart);
- Strtoi64 (SizeStr, &CDROMDevPath->PartitionSize);
-
- return (EFI_DEVICE_PATH_PROTOCOL *) CDROMDevPath;
-}
-
-/**
- Converts a text device path node to Vendor-defined media device path structure.
-
- @param TextDeviceNode The input Text device path node.
-
- @return A pointer to the newly-created Vendor-defined media device path structure.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-DevPathFromTextVenMEDIA (
- IN CHAR16 *TextDeviceNode
- )
-{
- return ConvertFromTextVendor (
- TextDeviceNode,
- MEDIA_DEVICE_PATH,
- MEDIA_VENDOR_DP
- );
-}
-
-/**
- Converts a text device path node to File device path structure.
-
- @param TextDeviceNode The input Text device path node.
-
- @return A pointer to the newly-created File device path structure.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-DevPathFromTextFilePath (
- IN CHAR16 *TextDeviceNode
- )
-{
- FILEPATH_DEVICE_PATH *File;
-
- File = (FILEPATH_DEVICE_PATH *) CreateDeviceNode (
- MEDIA_DEVICE_PATH,
- MEDIA_FILEPATH_DP,
- (UINT16) (sizeof (FILEPATH_DEVICE_PATH) + StrLen (TextDeviceNode) * 2)
- );
-
- StrCpy (File->PathName, TextDeviceNode);
-
- return (EFI_DEVICE_PATH_PROTOCOL *) File;
-}
-
-/**
- Converts a text device path node to Media protocol device path structure.
-
- @param TextDeviceNode The input Text device path node.
-
- @return A pointer to the newly-created Media protocol device path structure.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-DevPathFromTextMedia (
- IN CHAR16 *TextDeviceNode
- )
-{
- CHAR16 *GuidStr;
- MEDIA_PROTOCOL_DEVICE_PATH *Media;
-
- GuidStr = GetNextParamStr (&TextDeviceNode);
- Media = (MEDIA_PROTOCOL_DEVICE_PATH *) CreateDeviceNode (
- MEDIA_DEVICE_PATH,
- MEDIA_PROTOCOL_DP,
- (UINT16) sizeof (MEDIA_PROTOCOL_DEVICE_PATH)
- );
-
- StrToGuid (GuidStr, &Media->Protocol);
-
- return (EFI_DEVICE_PATH_PROTOCOL *) Media;
-}
-
-/**
- Converts a text device path node to firmware volume device path structure.
-
- @param TextDeviceNode The input Text device path node.
-
- @return A pointer to the newly-created firmware volume device path structure.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-DevPathFromTextFv (
- IN CHAR16 *TextDeviceNode
- )
-{
- CHAR16 *GuidStr;
- MEDIA_FW_VOL_DEVICE_PATH *Fv;
-
- GuidStr = GetNextParamStr (&TextDeviceNode);
- Fv = (MEDIA_FW_VOL_DEVICE_PATH *) CreateDeviceNode (
- MEDIA_DEVICE_PATH,
- MEDIA_PIWG_FW_VOL_DP,
- (UINT16) sizeof (MEDIA_FW_VOL_DEVICE_PATH)
- );
-
- StrToGuid (GuidStr, &Fv->FvName);
-
- return (EFI_DEVICE_PATH_PROTOCOL *) Fv;
-}
-
-/**
- Converts a text device path node to firmware file device path structure.
-
- @param TextDeviceNode The input Text device path node.
-
- @return A pointer to the newly-created firmware file device path structure.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-DevPathFromTextFvFile (
- IN CHAR16 *TextDeviceNode
- )
-{
- CHAR16 *GuidStr;
- MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FvFile;
-
- GuidStr = GetNextParamStr (&TextDeviceNode);
- FvFile = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) CreateDeviceNode (
- MEDIA_DEVICE_PATH,
- MEDIA_PIWG_FW_FILE_DP,
- (UINT16) sizeof (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH)
- );
-
- StrToGuid (GuidStr, &FvFile->FvFileName);
-
- return (EFI_DEVICE_PATH_PROTOCOL *) FvFile;
-}
-
-/**
- Converts a text device path node to text relative offset device path structure.
-
- @param TextDeviceNode The input Text device path node.
-
- @return A pointer to the newly-created Text device path structure.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-DevPathFromTextRelativeOffsetRange (
- IN CHAR16 *TextDeviceNode
- )
-{
- CHAR16 *StartingOffsetStr;
- CHAR16 *EndingOffsetStr;
- MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH *Offset;
-
- StartingOffsetStr = GetNextParamStr (&TextDeviceNode);
- EndingOffsetStr = GetNextParamStr (&TextDeviceNode);
- Offset = (MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH *) CreateDeviceNode (
- MEDIA_DEVICE_PATH,
- MEDIA_RELATIVE_OFFSET_RANGE_DP,
- (UINT16) sizeof (MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH)
- );
-
- Strtoi64 (StartingOffsetStr, &Offset->StartingOffset);
- Strtoi64 (EndingOffsetStr, &Offset->EndingOffset);
-
- return (EFI_DEVICE_PATH_PROTOCOL *) Offset;
-}
-
-/**
- Converts a text device path node to BIOS Boot Specification device path structure.
-
- @param TextDeviceNode The input Text device path node.
-
- @return A pointer to the newly-created BIOS Boot Specification device path structure.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-DevPathFromTextBBS (
- IN CHAR16 *TextDeviceNode
- )
-{
- CHAR16 *TypeStr;
- CHAR16 *IdStr;
- CHAR16 *FlagsStr;
- CHAR8 *AsciiStr;
- BBS_BBS_DEVICE_PATH *Bbs;
-
- TypeStr = GetNextParamStr (&TextDeviceNode);
- IdStr = GetNextParamStr (&TextDeviceNode);
- FlagsStr = GetNextParamStr (&TextDeviceNode);
- Bbs = (BBS_BBS_DEVICE_PATH *) CreateDeviceNode (
- BBS_DEVICE_PATH,
- BBS_BBS_DP,
- (UINT16) (sizeof (BBS_BBS_DEVICE_PATH) + StrLen (IdStr))
- );
-
- if (StrCmp (TypeStr, L"Floppy") == 0) {
- Bbs->DeviceType = BBS_TYPE_FLOPPY;
- } else if (StrCmp (TypeStr, L"HD") == 0) {
- Bbs->DeviceType = BBS_TYPE_HARDDRIVE;
- } else if (StrCmp (TypeStr, L"CDROM") == 0) {
- Bbs->DeviceType = BBS_TYPE_CDROM;
- } else if (StrCmp (TypeStr, L"PCMCIA") == 0) {
- Bbs->DeviceType = BBS_TYPE_PCMCIA;
- } else if (StrCmp (TypeStr, L"USB") == 0) {
- Bbs->DeviceType = BBS_TYPE_USB;
- } else if (StrCmp (TypeStr, L"Network") == 0) {
- Bbs->DeviceType = BBS_TYPE_EMBEDDED_NETWORK;
- } else {
- Bbs->DeviceType = (UINT16) Strtoi (TypeStr);
- }
-
- AsciiStr = Bbs->String;
- StrToAscii (IdStr, &AsciiStr);
-
- Bbs->StatusFlag = (UINT16) Strtoi (FlagsStr);
-
- return (EFI_DEVICE_PATH_PROTOCOL *) Bbs;
-}
-
-/**
- Converts a text device path node to SATA device path structure.
-
- @param TextDeviceNode The input Text device path node.
-
- @return A pointer to the newly-created SATA device path structure.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-DevPathFromTextSata (
- IN CHAR16 *TextDeviceNode
- )
-{
- SATA_DEVICE_PATH *Sata;
- CHAR16 *Param1;
- CHAR16 *Param2;
- CHAR16 *Param3;
-
- //
- // The PMPN is optional.
- //
- Param1 = GetNextParamStr (&TextDeviceNode);
- Param2 = GetNextParamStr (&TextDeviceNode);
- Param3 = NULL;
- if (!IS_NULL (TextDeviceNode)) {
- Param3 = GetNextParamStr (&TextDeviceNode);
- }
-
- Sata = (SATA_DEVICE_PATH *) CreateDeviceNode (
- MESSAGING_DEVICE_PATH,
- MSG_SATA_DP,
- (UINT16) sizeof (SATA_DEVICE_PATH)
- );
- Sata->HBAPortNumber = (UINT16) Xtoi (Param1);
- if (Param3 != NULL) {
- Sata->PortMultiplierPortNumber = (UINT16) Xtoi (Param2);
- Param2 = Param3;
- } else {
- Sata->PortMultiplierPortNumber = SATA_HBA_DIRECT_CONNECT_FLAG;
- }
- Sata->Lun = (UINT16) Xtoi (Param2);
-
- return (EFI_DEVICE_PATH_PROTOCOL *) Sata;
-}
-
-GLOBAL_REMOVE_IF_UNREFERENCED DEVICE_PATH_FROM_TEXT_TABLE DevPathFromTextTable[] = {
- {L"Pci", DevPathFromTextPci},
- {L"PcCard", DevPathFromTextPcCard},
- {L"MemoryMapped", DevPathFromTextMemoryMapped},
- {L"VenHw", DevPathFromTextVenHw},
- {L"Ctrl", DevPathFromTextCtrl},
- {L"Acpi", DevPathFromTextAcpi},
- {L"PciRoot", DevPathFromTextPciRoot},
- {L"PcieRoot", DevPathFromTextPcieRoot},
- {L"Floppy", DevPathFromTextFloppy},
- {L"Keyboard", DevPathFromTextKeyboard},
- {L"Serial", DevPathFromTextSerial},
- {L"ParallelPort", DevPathFromTextParallelPort},
- {L"AcpiEx", DevPathFromTextAcpiEx},
- {L"AcpiExp", DevPathFromTextAcpiExp},
- {L"AcpiAdr", DevPathFromTextAcpiAdr},
- {L"Ata", DevPathFromTextAta},
- {L"Scsi", DevPathFromTextScsi},
- {L"Fibre", DevPathFromTextFibre},
- {L"FibreEx", DevPathFromTextFibreEx},
- {L"I1394", DevPathFromText1394},
- {L"USB", DevPathFromTextUsb},
- {L"I2O", DevPathFromTextI2O},
- {L"Infiniband", DevPathFromTextInfiniband},
- {L"VenMsg", DevPathFromTextVenMsg},
- {L"VenPcAnsi", DevPathFromTextVenPcAnsi},
- {L"VenVt100", DevPathFromTextVenVt100},
- {L"VenVt100Plus", DevPathFromTextVenVt100Plus},
- {L"VenUtf8", DevPathFromTextVenUtf8},
- {L"UartFlowCtrl", DevPathFromTextUartFlowCtrl},
- {L"SAS", DevPathFromTextSAS},
- {L"SasEx", DevPathFromTextSasEx},
- {L"DebugPort", DevPathFromTextDebugPort},
- {L"MAC", DevPathFromTextMAC},
- {L"IPv4", DevPathFromTextIPv4},
- {L"IPv6", DevPathFromTextIPv6},
- {L"Uart", DevPathFromTextUart},
- {L"UsbClass", DevPathFromTextUsbClass},
- {L"UsbAudio", DevPathFromTextUsbAudio},
- {L"UsbCDCControl", DevPathFromTextUsbCDCControl},
- {L"UsbHID", DevPathFromTextUsbHID},
- {L"UsbImage", DevPathFromTextUsbImage},
- {L"UsbPrinter", DevPathFromTextUsbPrinter},
- {L"UsbMassStorage", DevPathFromTextUsbMassStorage},
- {L"UsbHub", DevPathFromTextUsbHub},
- {L"UsbCDCData", DevPathFromTextUsbCDCData},
- {L"UsbSmartCard", DevPathFromTextUsbSmartCard},
- {L"UsbVideo", DevPathFromTextUsbVideo},
- {L"UsbDiagnostic", DevPathFromTextUsbDiagnostic},
- {L"UsbWireless", DevPathFromTextUsbWireless},
- {L"UsbDeviceFirmwareUpdate", DevPathFromTextUsbDeviceFirmwareUpdate},
- {L"UsbIrdaBridge", DevPathFromTextUsbIrdaBridge},
- {L"UsbTestAndMeasurement", DevPathFromTextUsbTestAndMeasurement},
- {L"UsbWwid", DevPathFromTextUsbWwid},
- {L"Unit", DevPathFromTextUnit},
- {L"iSCSI", DevPathFromTextiSCSI},
- {L"Vlan", DevPathFromTextVlan},
- {L"HD", DevPathFromTextHD},
- {L"CDROM", DevPathFromTextCDROM},
- {L"VenMEDIA", DevPathFromTextVenMEDIA},
- {L"Media", DevPathFromTextMedia},
- {L"Fv", DevPathFromTextFv},
- {L"FvFile", DevPathFromTextFvFile},
- {L"Offset", DevPathFromTextRelativeOffsetRange},
- {L"BBS", DevPathFromTextBBS},
- {L"Sata", DevPathFromTextSata},
- {NULL, NULL}
-};
-
-/**
- Convert text to the binary representation of a device node.
-
- @param TextDeviceNode TextDeviceNode points to the text representation of a device
- node. Conversion starts with the first character and continues
- until the first non-device node character.
-
- @return A pointer to the EFI device node or NULL if TextDeviceNode is NULL or there was
- insufficient memory or text unsupported.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-EFIAPI
-ConvertTextToDeviceNode (
- IN CONST CHAR16 *TextDeviceNode
- )
-{
- DUMP_NODE DumpNode;
- CHAR16 *ParamStr;
- EFI_DEVICE_PATH_PROTOCOL *DeviceNode;
- CHAR16 *DeviceNodeStr;
- UINTN Index;
-
- if ((TextDeviceNode == NULL) || (IS_NULL (*TextDeviceNode))) {
- return NULL;
- }
-
- ParamStr = NULL;
- DumpNode = NULL;
- DeviceNodeStr = StrDuplicate (TextDeviceNode);
- ASSERT (DeviceNodeStr != NULL);
-
- for (Index = 0; DevPathFromTextTable[Index].Function != NULL; Index++) {
- ParamStr = GetParamByNodeName (DeviceNodeStr, DevPathFromTextTable[Index].DevicePathNodeText);
- if (ParamStr != NULL) {
- DumpNode = DevPathFromTextTable[Index].Function;
- break;
- }
- }
-
- if (DumpNode == NULL) {
- //
- // A file path
- //
- DumpNode = DevPathFromTextFilePath;
- DeviceNode = DumpNode (DeviceNodeStr);
- } else {
- DeviceNode = DumpNode (ParamStr);
- FreePool (ParamStr);
- }
-
- FreePool (DeviceNodeStr);
-
- return DeviceNode;
-}
-
-/**
- Convert text to the binary representation of a device path.
-
-
- @param TextDevicePath TextDevicePath points to the text representation of a device
- path. Conversion starts with the first character and continues
- until the first non-device node character.
-
- @return A pointer to the allocated device path or NULL if TextDeviceNode is NULL or
- there was insufficient memory.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-EFIAPI
-ConvertTextToDevicePath (
- IN CONST CHAR16 *TextDevicePath
- )
-{
- DUMP_NODE DumpNode;
- CHAR16 *ParamStr;
- EFI_DEVICE_PATH_PROTOCOL *DeviceNode;
- UINTN Index;
- EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;
- CHAR16 *DevicePathStr;
- CHAR16 *Str;
- CHAR16 *DeviceNodeStr;
- UINT8 IsInstanceEnd;
- EFI_DEVICE_PATH_PROTOCOL *DevicePath;
-
- if ((TextDevicePath == NULL) || (IS_NULL (*TextDevicePath))) {
- return NULL;
- }
-
- DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) AllocatePool (END_DEVICE_PATH_LENGTH);
- ASSERT (DevicePath != NULL);
- SetDevicePathEndNode (DevicePath);
-
- ParamStr = NULL;
- DeviceNodeStr = NULL;
- DevicePathStr = StrDuplicate (TextDevicePath);
-
- Str = DevicePathStr;
- while ((DeviceNodeStr = GetNextDeviceNodeStr (&Str, &IsInstanceEnd)) != NULL) {
- DumpNode = NULL;
- for (Index = 0; DevPathFromTextTable[Index].Function != NULL; Index++) {
- ParamStr = GetParamByNodeName (DeviceNodeStr, DevPathFromTextTable[Index].DevicePathNodeText);
- if (ParamStr != NULL) {
- DumpNode = DevPathFromTextTable[Index].Function;
- break;
- }
- }
-
- if (DumpNode == NULL) {
- //
- // A file path
- //
- DumpNode = DevPathFromTextFilePath;
- DeviceNode = DumpNode (DeviceNodeStr);
- } else {
- DeviceNode = DumpNode (ParamStr);
- FreePool (ParamStr);
- }
-
- NewDevicePath = AppendDeviceNodeProtocolInterface (DevicePath, DeviceNode);
- FreePool (DevicePath);
- FreePool (DeviceNode);
- DevicePath = NewDevicePath;
-
- if (IsInstanceEnd != 0) {
- DeviceNode = (EFI_DEVICE_PATH_PROTOCOL *) AllocatePool (END_DEVICE_PATH_LENGTH);
- ASSERT (DeviceNode != NULL);
- SET_DEVICE_PATH_INSTANCE_END_NODE (DeviceNode);
-
- NewDevicePath = AppendDeviceNodeProtocolInterface (DevicePath, DeviceNode);
- FreePool (DevicePath);
- FreePool (DeviceNode);
- DevicePath = NewDevicePath;
- }
- }
-
- FreePool (DevicePathStr);
- return DevicePath;
-}
diff --git a/MdeModulePkg/Universal/DevicePathDxe/DevicePathToText.c b/MdeModulePkg/Universal/DevicePathDxe/DevicePathToText.c
deleted file mode 100644
index 3d9d7c7a7..000000000
--- a/MdeModulePkg/Universal/DevicePathDxe/DevicePathToText.c
+++ /dev/null
@@ -1,2071 +0,0 @@
-/** @file
- DevicePathToText protocol as defined in the UEFI 2.0 specification.
-
-Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
-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 "DevicePath.h"
-
-/**
- Concatenates a formatted unicode string to allocated pool. The caller must
- free the resulting buffer.
-
- @param Str Tracks the allocated pool, size in use, and
- amount of pool allocated.
- @param Fmt The format string
- @param ... Variable arguments based on the format string.
-
- @return Allocated buffer with the formatted string printed in it.
- The caller must free the allocated buffer. The buffer
- allocation is not packed.
-
-**/
-CHAR16 *
-EFIAPI
-CatPrint (
- IN OUT POOL_PRINT *Str,
- IN CHAR16 *Fmt,
- ...
- )
-{
- UINT16 *AppendStr;
- UINTN AppendCount;
- VA_LIST Args;
-
- AppendStr = AllocateZeroPool (0x1000);
- ASSERT (AppendStr != NULL);
-
- VA_START (Args, Fmt);
- AppendCount = UnicodeVSPrint (AppendStr, 0x1000, Fmt, Args);
- VA_END (Args);
-
- if (Str->Length + AppendCount * sizeof (CHAR16) > Str->Capacity) {
- Str->Capacity = Str->Length + (AppendCount + 1) * sizeof (CHAR16) * 2;
- Str->Str = ReallocatePool (
- Str->Length,
- Str->Capacity,
- Str->Str
- );
- ASSERT (Str->Str != NULL);
- }
-
- if (Str->Length == 0) {
- StrCpy (Str->Str, AppendStr);
- Str->Length = (AppendCount + 1) * sizeof (CHAR16);
- } else {
- StrCat (Str->Str, AppendStr);
- Str->Length += AppendCount * sizeof (CHAR16);
- }
-
- FreePool (AppendStr);
- return Str->Str;
-}
-
-/**
- Converts a PCI device path structure to its string representative.
-
- @param Str The string representative of input device.
- @param DevPath The input device path structure.
- @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation
- of the display node is used, where applicable. If DisplayOnly
- is FALSE, then the longer text representation of the display node
- is used.
- @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text
- representation for a device node can be used, where applicable.
-
-**/
-VOID
-DevPathToTextPci (
- IN OUT POOL_PRINT *Str,
- IN VOID *DevPath,
- IN BOOLEAN DisplayOnly,
- IN BOOLEAN AllowShortcuts
- )
-{
- PCI_DEVICE_PATH *Pci;
-
- Pci = DevPath;
- CatPrint (Str, L"Pci(0x%x,0x%x)", Pci->Device, Pci->Function);
-}
-
-/**
- Converts a PC Card device path structure to its string representative.
-
- @param Str The string representative of input device.
- @param DevPath The input device path structure.
- @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation
- of the display node is used, where applicable. If DisplayOnly
- is FALSE, then the longer text representation of the display node
- is used.
- @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text
- representation for a device node can be used, where applicable.
-
-**/
-VOID
-DevPathToTextPccard (
- IN OUT POOL_PRINT *Str,
- IN VOID *DevPath,
- IN BOOLEAN DisplayOnly,
- IN BOOLEAN AllowShortcuts
- )
-{
- PCCARD_DEVICE_PATH *Pccard;
-
- Pccard = DevPath;
- CatPrint (Str, L"PcCard(0x%x)", Pccard->FunctionNumber);
-}
-
-/**
- Converts a Memory Map device path structure to its string representative.
-
- @param Str The string representative of input device.
- @param DevPath The input device path structure.
- @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation
- of the display node is used, where applicable. If DisplayOnly
- is FALSE, then the longer text representation of the display node
- is used.
- @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text
- representation for a device node can be used, where applicable.
-
-**/
-VOID
-DevPathToTextMemMap (
- IN OUT POOL_PRINT *Str,
- IN VOID *DevPath,
- IN BOOLEAN DisplayOnly,
- IN BOOLEAN AllowShortcuts
- )
-{
- MEMMAP_DEVICE_PATH *MemMap;
-
- MemMap = DevPath;
- CatPrint (
- Str,
- L"MemoryMapped(0x%x,0x%lx,0x%lx)",
- MemMap->MemoryType,
- MemMap->StartingAddress,
- MemMap->EndingAddress
- );
-}
-
-/**
- Converts a Vendor device path structure to its string representative.
-
- @param Str The string representative of input device.
- @param DevPath The input device path structure.
- @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation
- of the display node is used, where applicable. If DisplayOnly
- is FALSE, then the longer text representation of the display node
- is used.
- @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text
- representation for a device node can be used, where applicable.
-
-**/
-VOID
-DevPathToTextVendor (
- IN OUT POOL_PRINT *Str,
- IN VOID *DevPath,
- IN BOOLEAN DisplayOnly,
- IN BOOLEAN AllowShortcuts
- )
-{
- VENDOR_DEVICE_PATH *Vendor;
- CHAR16 *Type;
- UINTN Index;
- UINTN DataLength;
- UINT32 FlowControlMap;
- UINT16 Info;
-
- Vendor = (VENDOR_DEVICE_PATH *) DevPath;
- switch (DevicePathType (&Vendor->Header)) {
- case HARDWARE_DEVICE_PATH:
- Type = L"Hw";
- break;
-
- case MESSAGING_DEVICE_PATH:
- Type = L"Msg";
- if (AllowShortcuts) {
- if (CompareGuid (&Vendor->Guid, &gEfiPcAnsiGuid)) {
- CatPrint (Str, L"VenPcAnsi()");
- return ;
- } else if (CompareGuid (&Vendor->Guid, &gEfiVT100Guid)) {
- CatPrint (Str, L"VenVt100()");
- return ;
- } else if (CompareGuid (&Vendor->Guid, &gEfiVT100PlusGuid)) {
- CatPrint (Str, L"VenVt100Plus()");
- return ;
- } else if (CompareGuid (&Vendor->Guid, &gEfiVTUTF8Guid)) {
- CatPrint (Str, L"VenUft8()");
- return ;
- } else if (CompareGuid (&Vendor->Guid, &gEfiUartDevicePathGuid)) {
- FlowControlMap = (((UART_FLOW_CONTROL_DEVICE_PATH *) Vendor)->FlowControlMap);
- switch (FlowControlMap & 0x00000003) {
- case 0:
- CatPrint (Str, L"UartFlowCtrl(%s)", L"None");
- break;
-
- case 1:
- CatPrint (Str, L"UartFlowCtrl(%s)", L"Hardware");
- break;
-
- case 2:
- CatPrint (Str, L"UartFlowCtrl(%s)", L"XonXoff");
- break;
-
- default:
- break;
- }
-
- return ;
- } else if (CompareGuid (&Vendor->Guid, &gEfiSasDevicePathGuid)) {
- CatPrint (
- Str,
- L"SAS(0x%lx,0x%lx,0x%x,",
- ((SAS_DEVICE_PATH *) Vendor)->SasAddress,
- ((SAS_DEVICE_PATH *) Vendor)->Lun,
- ((SAS_DEVICE_PATH *) Vendor)->RelativeTargetPort
- );
- Info = (((SAS_DEVICE_PATH *) Vendor)->DeviceTopology);
- if (((Info & 0x0f) == 0) && ((Info & BIT7) == 0)) {
- CatPrint (Str, L"NoTopology,0,0,0,");
- } else if (((Info & 0x0f) <= 2) && ((Info & BIT7) == 0)) {
- CatPrint (
- Str,
- L"%s,%s,%s,",
- ((Info & BIT4) != 0) ? L"SATA" : L"SAS",
- ((Info & BIT5) != 0) ? L"External" : L"Internal",
- ((Info & BIT6) != 0) ? L"Expanded" : L"Direct"
- );
- if ((Info & 0x0f) == 1) {
- CatPrint (Str, L"0,");
- } else {
- //
- // Value 0x0 thru 0xFF -> Drive 1 thru Drive 256
- //
- CatPrint (Str, L"0x%x,", ((Info >> 8) & 0xff) + 1);
- }
- } else {
- CatPrint (Str, L"0x%x,0,0,0,", Info);
- }
-
- CatPrint (Str, L"0x%x)", ((SAS_DEVICE_PATH *) Vendor)->Reserved);
- return ;
- } else if (CompareGuid (&Vendor->Guid, &gEfiDebugPortProtocolGuid)) {
- CatPrint (Str, L"DebugPort()");
- return ;
- }
- }
- break;
-
- case MEDIA_DEVICE_PATH:
- Type = L"Media";
- break;
-
- default:
- Type = L"?";
- break;
- }
-
- DataLength = DevicePathNodeLength (&Vendor->Header) - sizeof (VENDOR_DEVICE_PATH);
- CatPrint (Str, L"Ven%s(%g", Type, &Vendor->Guid);
- if (DataLength != 0) {
- CatPrint (Str, L",");
- for (Index = 0; Index < DataLength; Index++) {
- CatPrint (Str, L"%02x", ((VENDOR_DEVICE_PATH_WITH_DATA *) Vendor)->VendorDefinedData[Index]);
- }
- }
-
- CatPrint (Str, L")");
-}
-
-/**
- Converts a Controller device path structure to its string representative.
-
- @param Str The string representative of input device.
- @param DevPath The input device path structure.
- @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation
- of the display node is used, where applicable. If DisplayOnly
- is FALSE, then the longer text representation of the display node
- is used.
- @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text
- representation for a device node can be used, where applicable.
-
-**/
-VOID
-DevPathToTextController (
- IN OUT POOL_PRINT *Str,
- IN VOID *DevPath,
- IN BOOLEAN DisplayOnly,
- IN BOOLEAN AllowShortcuts
- )
-{
- CONTROLLER_DEVICE_PATH *Controller;
-
- Controller = DevPath;
- CatPrint (
- Str,
- L"Ctrl(0x%x)",
- Controller->ControllerNumber
- );
-}
-
-/**
- Converts a ACPI device path structure to its string representative.
-
- @param Str The string representative of input device.
- @param DevPath The input device path structure.
- @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation
- of the display node is used, where applicable. If DisplayOnly
- is FALSE, then the longer text representation of the display node
- is used.
- @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text
- representation for a device node can be used, where applicable.
-
-**/
-VOID
-DevPathToTextAcpi (
- IN OUT POOL_PRINT *Str,
- IN VOID *DevPath,
- IN BOOLEAN DisplayOnly,
- IN BOOLEAN AllowShortcuts
- )
-{
- ACPI_HID_DEVICE_PATH *Acpi;
-
- Acpi = DevPath;
- if ((Acpi->HID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) {
- switch (EISA_ID_TO_NUM (Acpi->HID)) {
- case 0x0a03:
- CatPrint (Str, L"PciRoot(0x%x)", Acpi->UID);
- break;
-
- case 0x0a08:
- CatPrint (Str, L"PcieRoot(0x%x)", Acpi->UID);
- break;
-
- case 0x0604:
- CatPrint (Str, L"Floppy(0x%x)", Acpi->UID);
- break;
-
- case 0x0301:
- CatPrint (Str, L"Keyboard(0x%x)", Acpi->UID);
- break;
-
- case 0x0501:
- CatPrint (Str, L"Serial(0x%x)", Acpi->UID);
- break;
-
- case 0x0401:
- CatPrint (Str, L"ParallelPort(0x%x)", Acpi->UID);
- break;
-
- default:
- CatPrint (Str, L"Acpi(PNP%04x,0x%x)", EISA_ID_TO_NUM (Acpi->HID), Acpi->UID);
- break;
- }
- } else {
- CatPrint (Str, L"Acpi(0x%08x,0x%x)", Acpi->HID, Acpi->UID);
- }
-}
-
-/**
- Converts EISA identification to string.
-
- @param EisaId The input EISA identification.
- @param Text A pointer to the output string.
-
-**/
-VOID
-EisaIdToText (
- IN UINT32 EisaId,
- IN OUT CHAR16 *Text
- )
-{
- CHAR16 PnpIdStr[17];
-
- //
- //UnicodeSPrint ("%X", 0x0a03) => "0000000000000A03"
- //
- UnicodeSPrint (PnpIdStr, 17 * 2, L"%16X", EisaId >> 16);
-
- UnicodeSPrint (
- Text,
- sizeof (CHAR16) + sizeof (CHAR16) + sizeof (CHAR16) + sizeof (PnpIdStr),
- L"%c%c%c%s",
- '@' + ((EisaId >> 10) & 0x1f),
- '@' + ((EisaId >> 5) & 0x1f),
- '@' + ((EisaId >> 0) & 0x1f),
- PnpIdStr + (16 - 4)
- );
-}
-
-/**
- Converts a ACPI extended HID device path structure to its string representative.
-
- @param Str The string representative of input device.
- @param DevPath The input device path structure.
- @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation
- of the display node is used, where applicable. If DisplayOnly
- is FALSE, then the longer text representation of the display node
- is used.
- @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text
- representation for a device node can be used, where applicable.
-
-**/
-VOID
-DevPathToTextAcpiEx (
- IN OUT POOL_PRINT *Str,
- IN VOID *DevPath,
- IN BOOLEAN DisplayOnly,
- IN BOOLEAN AllowShortcuts
- )
-{
- ACPI_EXTENDED_HID_DEVICE_PATH *AcpiEx;
- CHAR8 *HIDStr;
- CHAR8 *UIDStr;
- CHAR8 *CIDStr;
- CHAR16 HIDText[11];
- CHAR16 CIDText[11];
-
- AcpiEx = DevPath;
- HIDStr = (CHAR8 *) (((UINT8 *) AcpiEx) + sizeof (ACPI_EXTENDED_HID_DEVICE_PATH));
- UIDStr = HIDStr + AsciiStrLen (HIDStr) + 1;
- CIDStr = UIDStr + AsciiStrLen (UIDStr) + 1;
-
- EisaIdToText (AcpiEx->HID, HIDText);
- EisaIdToText (AcpiEx->CID, CIDText);
-
- if ((*HIDStr == '\0') && (*CIDStr == '\0') && (AcpiEx->UID == 0)) {
- //
- // use AcpiExp()
- //
- CatPrint (
- Str,
- L"AcpiExp(%s,%s,%a)",
- HIDText,
- CIDText,
- UIDStr
- );
- } else {
- if (AllowShortcuts) {
- //
- // display only
- //
- if (AcpiEx->HID == 0) {
- CatPrint (Str, L"AcpiEx(%a,", HIDStr);
- } else {
- CatPrint (Str, L"AcpiEx(%s,", HIDText);
- }
-
- if (AcpiEx->UID == 0) {
- CatPrint (Str, L"%a,", UIDStr);
- } else {
- CatPrint (Str, L"0x%x,", AcpiEx->UID);
- }
-
- if (AcpiEx->CID == 0) {
- CatPrint (Str, L"%a)", CIDStr);
- } else {
- CatPrint (Str, L"%s)", CIDText);
- }
- } else {
- CatPrint (
- Str,
- L"AcpiEx(%s,%s,0x%x,%a,%a,%a)",
- HIDText,
- CIDText,
- AcpiEx->UID,
- HIDStr,
- CIDStr,
- UIDStr
- );
- }
- }
-}
-
-/**
- Converts a ACPI address device path structure to its string representative.
-
- @param Str The string representative of input device.
- @param DevPath The input device path structure.
- @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation
- of the display node is used, where applicable. If DisplayOnly
- is FALSE, then the longer text representation of the display node
- is used.
- @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text
- representation for a device node can be used, where applicable.
-
-**/
-VOID
-DevPathToTextAcpiAdr (
- IN OUT POOL_PRINT *Str,
- IN VOID *DevPath,
- IN BOOLEAN DisplayOnly,
- IN BOOLEAN AllowShortcuts
- )
-{
- ACPI_ADR_DEVICE_PATH *AcpiAdr;
- UINT16 Index;
- UINT16 Length;
- UINT16 AdditionalAdrCount;
-
- AcpiAdr = DevPath;
- Length = (UINT16) DevicePathNodeLength ((EFI_DEVICE_PATH_PROTOCOL *) AcpiAdr);
- AdditionalAdrCount = (UINT16) ((Length - 8) / 4);
-
- CatPrint (Str, L"AcpiAdr(0x%x", AcpiAdr->ADR);
- for (Index = 0; Index < AdditionalAdrCount; Index++) {
- CatPrint (Str, L",0x%x", *(UINT32 *) ((UINT8 *) AcpiAdr + 8 + Index * 4));
- }
- CatPrint (Str, L")");
-}
-
-/**
- Converts a ATAPI device path structure to its string representative.
-
- @param Str The string representative of input device.
- @param DevPath The input device path structure.
- @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation
- of the display node is used, where applicable. If DisplayOnly
- is FALSE, then the longer text representation of the display node
- is used.
- @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text
- representation for a device node can be used, where applicable.
-
-**/
-VOID
-DevPathToTextAtapi (
- IN OUT POOL_PRINT *Str,
- IN VOID *DevPath,
- IN BOOLEAN DisplayOnly,
- IN BOOLEAN AllowShortcuts
- )
-{
- ATAPI_DEVICE_PATH *Atapi;
-
- Atapi = DevPath;
-
- if (DisplayOnly) {
- CatPrint (Str, L"Ata(0x%x)", Atapi->Lun);
- } else {
- CatPrint (
- Str,
- L"Ata(%s,%s,0x%x)",
- (Atapi->PrimarySecondary == 1) ? L"Secondary" : L"Primary",
- (Atapi->SlaveMaster == 1) ? L"Slave" : L"Master",
- Atapi->Lun
- );
- }
-}
-
-/**
- Converts a SCSI device path structure to its string representative.
-
- @param Str The string representative of input device.
- @param DevPath The input device path structure.
- @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation
- of the display node is used, where applicable. If DisplayOnly
- is FALSE, then the longer text representation of the display node
- is used.
- @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text
- representation for a device node can be used, where applicable.
-
-**/
-VOID
-DevPathToTextScsi (
- IN OUT POOL_PRINT *Str,
- IN VOID *DevPath,
- IN BOOLEAN DisplayOnly,
- IN BOOLEAN AllowShortcuts
- )
-{
- SCSI_DEVICE_PATH *Scsi;
-
- Scsi = DevPath;
- CatPrint (Str, L"Scsi(0x%x,0x%x)", Scsi->Pun, Scsi->Lun);
-}
-
-/**
- Converts a Fibre device path structure to its string representative.
-
- @param Str The string representative of input device.
- @param DevPath The input device path structure.
- @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation
- of the display node is used, where applicable. If DisplayOnly
- is FALSE, then the longer text representation of the display node
- is used.
- @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text
- representation for a device node can be used, where applicable.
-
-**/
-VOID
-DevPathToTextFibre (
- IN OUT POOL_PRINT *Str,
- IN VOID *DevPath,
- IN BOOLEAN DisplayOnly,
- IN BOOLEAN AllowShortcuts
- )
-{
- FIBRECHANNEL_DEVICE_PATH *Fibre;
-
- Fibre = DevPath;
- CatPrint (Str, L"Fibre(0x%lx,0x%lx)", Fibre->WWN, Fibre->Lun);
-}
-
-/**
- Converts a FibreEx device path structure to its string representative.
-
- @param Str The string representative of input device.
- @param DevPath The input device path structure.
- @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation
- of the display node is used, where applicable. If DisplayOnly
- is FALSE, then the longer text representation of the display node
- is used.
- @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text
- representation for a device node can be used, where applicable.
-
-**/
-VOID
-DevPathToTextFibreEx (
- IN OUT POOL_PRINT *Str,
- IN VOID *DevPath,
- IN BOOLEAN DisplayOnly,
- IN BOOLEAN AllowShortcuts
- )
-{
- FIBRECHANNELEX_DEVICE_PATH *FibreEx;
- UINTN Index;
-
- FibreEx = DevPath;
- CatPrint (Str, L"FibreEx(0x");
- for (Index = 0; Index < sizeof (FibreEx->WWN) / sizeof (FibreEx->WWN[0]); Index++) {
- CatPrint (Str, L"%02x", FibreEx->WWN[Index]);
- }
- CatPrint (Str, L",0x");
- for (Index = 0; Index < sizeof (FibreEx->Lun) / sizeof (FibreEx->Lun[0]); Index++) {
- CatPrint (Str, L"%02x", FibreEx->Lun[Index]);
- }
- CatPrint (Str, L")");
-}
-
-/**
- Converts a Sas Ex device path structure to its string representative.
-
- @param Str The string representative of input device.
- @param DevPath The input device path structure.
- @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation
- of the display node is used, where applicable. If DisplayOnly
- is FALSE, then the longer text representation of the display node
- is used.
- @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text
- representation for a device node can be used, where applicable.
-
-**/
-VOID
-DevPathToTextSasEx (
- IN OUT POOL_PRINT *Str,
- IN VOID *DevPath,
- IN BOOLEAN DisplayOnly,
- IN BOOLEAN AllowShortcuts
- )
-{
- SASEX_DEVICE_PATH *SasEx;
- UINTN Index;
-
- SasEx = DevPath;
- CatPrint (Str, L"SasEx(0x");
-
- for (Index = 0; Index < sizeof (SasEx->SasAddress) / sizeof (SasEx->SasAddress[0]); Index++) {
- CatPrint (Str, L"%02x", SasEx->SasAddress[Index]);
- }
- CatPrint (Str, L",0x");
- for (Index = 0; Index < sizeof (SasEx->Lun) / sizeof (SasEx->Lun[0]); Index++) {
- CatPrint (Str, L"%02x", SasEx->Lun[Index]);
- }
- CatPrint (Str, L",0x%x,", SasEx->RelativeTargetPort);
-
- if (((SasEx->DeviceTopology & 0x0f) == 0) && ((SasEx->DeviceTopology & BIT7) == 0)) {
- CatPrint (Str, L"NoTopology,0,0,0");
- } else if (((SasEx->DeviceTopology & 0x0f) <= 2) && ((SasEx->DeviceTopology & BIT7) == 0)) {
- CatPrint (
- Str,
- L"%s,%s,%s,",
- ((SasEx->DeviceTopology & BIT4) != 0) ? L"SATA" : L"SAS",
- ((SasEx->DeviceTopology & BIT5) != 0) ? L"External" : L"Internal",
- ((SasEx->DeviceTopology & BIT6) != 0) ? L"Expanded" : L"Direct"
- );
- if ((SasEx->DeviceTopology & 0x0f) == 1) {
- CatPrint (Str, L"0");
- } else {
- //
- // Value 0x0 thru 0xFF -> Drive 1 thru Drive 256
- //
- CatPrint (Str, L"0x%x", ((SasEx->DeviceTopology >> 8) & 0xff) + 1);
- }
- } else {
- CatPrint (Str, L"0x%x,0,0,0", SasEx->DeviceTopology);
- }
-
- CatPrint (Str, L")");
- return ;
-
-}
-
-/**
- Converts a 1394 device path structure to its string representative.
-
- @param Str The string representative of input device.
- @param DevPath The input device path structure.
- @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation
- of the display node is used, where applicable. If DisplayOnly
- is FALSE, then the longer text representation of the display node
- is used.
- @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text
- representation for a device node can be used, where applicable.
-
-**/
-VOID
-DevPathToText1394 (
- IN OUT POOL_PRINT *Str,
- IN VOID *DevPath,
- IN BOOLEAN DisplayOnly,
- IN BOOLEAN AllowShortcuts
- )
-{
- F1394_DEVICE_PATH *F1394DevPath;
-
- F1394DevPath = DevPath;
- //
- // Guid has format of IEEE-EUI64
- //
- CatPrint (Str, L"I1394(%016lx)", F1394DevPath->Guid);
-}
-
-/**
- Converts a USB device path structure to its string representative.
-
- @param Str The string representative of input device.
- @param DevPath The input device path structure.
- @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation
- of the display node is used, where applicable. If DisplayOnly
- is FALSE, then the longer text representation of the display node
- is used.
- @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text
- representation for a device node can be used, where applicable.
-
-**/
-VOID
-DevPathToTextUsb (
- IN OUT POOL_PRINT *Str,
- IN VOID *DevPath,
- IN BOOLEAN DisplayOnly,
- IN BOOLEAN AllowShortcuts
- )
-{
- USB_DEVICE_PATH *Usb;
-
- Usb = DevPath;
- CatPrint (Str, L"USB(0x%x,0x%x)", Usb->ParentPortNumber, Usb->InterfaceNumber);
-}
-
-/**
- Converts a USB WWID device path structure to its string representative.
-
- @param Str The string representative of input device.
- @param DevPath The input device path structure.
- @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation
- of the display node is used, where applicable. If DisplayOnly
- is FALSE, then the longer text representation of the display node
- is used.
- @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text
- representation for a device node can be used, where applicable.
-
-**/
-VOID
-DevPathToTextUsbWWID (
- IN OUT POOL_PRINT *Str,
- IN VOID *DevPath,
- IN BOOLEAN DisplayOnly,
- IN BOOLEAN AllowShortcuts
- )
-{
- USB_WWID_DEVICE_PATH *UsbWWId;
- CHAR16 *SerialNumberStr;
- CHAR16 *NewStr;
- UINT16 Length;
-
- UsbWWId = DevPath;
-
- SerialNumberStr = (CHAR16 *) ((UINT8 *) UsbWWId + sizeof (USB_WWID_DEVICE_PATH));
- Length = (UINT16) ((DevicePathNodeLength ((EFI_DEVICE_PATH_PROTOCOL *) UsbWWId) - sizeof (USB_WWID_DEVICE_PATH)) / sizeof (CHAR16));
- if (SerialNumberStr [Length - 1] != 0) {
- //
- // In case no NULL terminator in SerialNumber, create a new one with NULL terminator
- //
- NewStr = AllocateCopyPool ((Length + 1) * sizeof (CHAR16), SerialNumberStr);
- ASSERT (NewStr != NULL);
- NewStr [Length] = 0;
- SerialNumberStr = NewStr;
- }
-
- CatPrint (
- Str,
- L"UsbWwid(0x%x,0x%x,0x%x,\"%s\")",
- UsbWWId->VendorId,
- UsbWWId->ProductId,
- UsbWWId->InterfaceNumber,
- SerialNumberStr
- );
-}
-
-/**
- Converts a Logic Unit device path structure to its string representative.
-
- @param Str The string representative of input device.
- @param DevPath The input device path structure.
- @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation
- of the display node is used, where applicable. If DisplayOnly
- is FALSE, then the longer text representation of the display node
- is used.
- @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text
- representation for a device node can be used, where applicable.
-
-**/
-VOID
-DevPathToTextLogicalUnit (
- IN OUT POOL_PRINT *Str,
- IN VOID *DevPath,
- IN BOOLEAN DisplayOnly,
- IN BOOLEAN AllowShortcuts
- )
-{
- DEVICE_LOGICAL_UNIT_DEVICE_PATH *LogicalUnit;
-
- LogicalUnit = DevPath;
- CatPrint (Str, L"Unit(0x%x)", LogicalUnit->Lun);
-}
-
-/**
- Converts a USB class device path structure to its string representative.
-
- @param Str The string representative of input device.
- @param DevPath The input device path structure.
- @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation
- of the display node is used, where applicable. If DisplayOnly
- is FALSE, then the longer text representation of the display node
- is used.
- @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text
- representation for a device node can be used, where applicable.
-
-**/
-VOID
-DevPathToTextUsbClass (
- IN OUT POOL_PRINT *Str,
- IN VOID *DevPath,
- IN BOOLEAN DisplayOnly,
- IN BOOLEAN AllowShortcuts
- )
-{
- USB_CLASS_DEVICE_PATH *UsbClass;
- BOOLEAN IsKnownSubClass;
-
-
- UsbClass = DevPath;
-
- IsKnownSubClass = TRUE;
- switch (UsbClass->DeviceClass) {
- case USB_CLASS_AUDIO:
- CatPrint (Str, L"UsbAudio");
- break;
-
- case USB_CLASS_CDCCONTROL:
- CatPrint (Str, L"UsbCDCControl");
- break;
-
- case USB_CLASS_HID:
- CatPrint (Str, L"UsbHID");
- break;
-
- case USB_CLASS_IMAGE:
- CatPrint (Str, L"UsbImage");
- break;
-
- case USB_CLASS_PRINTER:
- CatPrint (Str, L"UsbPrinter");
- break;
-
- case USB_CLASS_MASS_STORAGE:
- CatPrint (Str, L"UsbMassStorage");
- break;
-
- case USB_CLASS_HUB:
- CatPrint (Str, L"UsbHub");
- break;
-
- case USB_CLASS_CDCDATA:
- CatPrint (Str, L"UsbCDCData");
- break;
-
- case USB_CLASS_SMART_CARD:
- CatPrint (Str, L"UsbSmartCard");
- break;
-
- case USB_CLASS_VIDEO:
- CatPrint (Str, L"UsbVideo");
- break;
-
- case USB_CLASS_DIAGNOSTIC:
- CatPrint (Str, L"UsbDiagnostic");
- break;
-
- case USB_CLASS_WIRELESS:
- CatPrint (Str, L"UsbWireless");
- break;
-
- default:
- IsKnownSubClass = FALSE;
- break;
- }
-
- if (IsKnownSubClass) {
- CatPrint (
- Str,
- L"(0x%x,0x%x,0x%x,0x%x)",
- UsbClass->VendorId,
- UsbClass->ProductId,
- UsbClass->DeviceSubClass,
- UsbClass->DeviceProtocol
- );
- return;
- }
-
- if (UsbClass->DeviceClass == USB_CLASS_RESERVE) {
- if (UsbClass->DeviceSubClass == USB_SUBCLASS_FW_UPDATE) {
- CatPrint (
- Str,
- L"UsbDeviceFirmwareUpdate(0x%x,0x%x,0x%x)",
- UsbClass->VendorId,
- UsbClass->ProductId,
- UsbClass->DeviceProtocol
- );
- return;
- } else if (UsbClass->DeviceSubClass == USB_SUBCLASS_IRDA_BRIDGE) {
- CatPrint (
- Str,
- L"UsbIrdaBridge(0x%x,0x%x,0x%x)",
- UsbClass->VendorId,
- UsbClass->ProductId,
- UsbClass->DeviceProtocol
- );
- return;
- } else if (UsbClass->DeviceSubClass == USB_SUBCLASS_TEST) {
- CatPrint (
- Str,
- L"UsbTestAndMeasurement(0x%x,0x%x,0x%x)",
- UsbClass->VendorId,
- UsbClass->ProductId,
- UsbClass->DeviceProtocol
- );
- return;
- }
- }
-
- CatPrint (
- Str,
- L"UsbClass(0x%x,0x%x,0x%x,0x%x,0x%x)",
- UsbClass->VendorId,
- UsbClass->ProductId,
- UsbClass->DeviceClass,
- UsbClass->DeviceSubClass,
- UsbClass->DeviceProtocol
- );
-}
-
-/**
- Converts a SATA device path structure to its string representative.
-
- @param Str The string representative of input device.
- @param DevPath The input device path structure.
- @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation
- of the display node is used, where applicable. If DisplayOnly
- is FALSE, then the longer text representation of the display node
- is used.
- @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text
- representation for a device node can be used, where applicable.
-
-**/
-VOID
-DevPathToTextSata (
- IN OUT POOL_PRINT *Str,
- IN VOID *DevPath,
- IN BOOLEAN DisplayOnly,
- IN BOOLEAN AllowShortcuts
- )
-{
- SATA_DEVICE_PATH *Sata;
-
- Sata = DevPath;
- if ((Sata->PortMultiplierPortNumber & SATA_HBA_DIRECT_CONNECT_FLAG) != 0) {
- CatPrint (
- Str,
- L"Sata(0x%x,0x%x)",
- Sata->HBAPortNumber,
- Sata->Lun
- );
- } else {
- CatPrint (
- Str,
- L"Sata(0x%x,0x%x,0x%x)",
- Sata->HBAPortNumber,
- Sata->PortMultiplierPortNumber,
- Sata->Lun
- );
- }
-}
-
-/**
- Converts a I20 device path structure to its string representative.
-
- @param Str The string representative of input device.
- @param DevPath The input device path structure.
- @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation
- of the display node is used, where applicable. If DisplayOnly
- is FALSE, then the longer text representation of the display node
- is used.
- @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text
- representation for a device node can be used, where applicable.
-
-**/
-VOID
-DevPathToTextI2O (
- IN OUT POOL_PRINT *Str,
- IN VOID *DevPath,
- IN BOOLEAN DisplayOnly,
- IN BOOLEAN AllowShortcuts
- )
-{
- I2O_DEVICE_PATH *I2ODevPath;
-
- I2ODevPath = DevPath;
- CatPrint (Str, L"I2O(0x%x)", I2ODevPath->Tid);
-}
-
-/**
- Converts a MAC address device path structure to its string representative.
-
- @param Str The string representative of input device.
- @param DevPath The input device path structure.
- @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation
- of the display node is used, where applicable. If DisplayOnly
- is FALSE, then the longer text representation of the display node
- is used.
- @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text
- representation for a device node can be used, where applicable.
-
-**/
-VOID
-DevPathToTextMacAddr (
- IN OUT POOL_PRINT *Str,
- IN VOID *DevPath,
- IN BOOLEAN DisplayOnly,
- IN BOOLEAN AllowShortcuts
- )
-{
- MAC_ADDR_DEVICE_PATH *MacDevPath;
- UINTN HwAddressSize;
- UINTN Index;
-
- MacDevPath = DevPath;
-
- HwAddressSize = sizeof (EFI_MAC_ADDRESS);
- if (MacDevPath->IfType == 0x01 || MacDevPath->IfType == 0x00) {
- HwAddressSize = 6;
- }
-
- CatPrint (Str, L"MAC(");
-
- for (Index = 0; Index < HwAddressSize; Index++) {
- CatPrint (Str, L"%02x", MacDevPath->MacAddress.Addr[Index]);
- }
-
- CatPrint (Str, L",0x%x)", MacDevPath->IfType);
-}
-
-/**
- Converts network protocol string to its text representation.
-
- @param Str The string representative of input device.
- @param Protocol The network protocol ID.
-
-**/
-VOID
-CatNetworkProtocol (
- IN OUT POOL_PRINT *Str,
- IN UINT16 Protocol
- )
-{
- if (Protocol == RFC_1700_TCP_PROTOCOL) {
- CatPrint (Str, L"TCP");
- } else if (Protocol == RFC_1700_UDP_PROTOCOL) {
- CatPrint (Str, L"UDP");
- } else {
- CatPrint (Str, L"0x%x", Protocol);
- }
-}
-
-/**
- Converts a IPv4 device path structure to its string representative.
-
- @param Str The string representative of input device.
- @param DevPath The input device path structure.
- @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation
- of the display node is used, where applicable. If DisplayOnly
- is FALSE, then the longer text representation of the display node
- is used.
- @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text
- representation for a device node can be used, where applicable.
-
-**/
-VOID
-DevPathToTextIPv4 (
- IN OUT POOL_PRINT *Str,
- IN VOID *DevPath,
- IN BOOLEAN DisplayOnly,
- IN BOOLEAN AllowShortcuts
- )
-{
- IPv4_DEVICE_PATH *IPDevPath;
-
- IPDevPath = DevPath;
- if (DisplayOnly) {
- CatPrint (
- Str,
- L"IPv4(%d.%d.%d.%d)",
- IPDevPath->RemoteIpAddress.Addr[0],
- IPDevPath->RemoteIpAddress.Addr[1],
- IPDevPath->RemoteIpAddress.Addr[2],
- IPDevPath->RemoteIpAddress.Addr[3]
- );
- return ;
- }
-
- CatPrint (
- Str,
- L"IPv4(%d.%d.%d.%d,",
- IPDevPath->RemoteIpAddress.Addr[0],
- IPDevPath->RemoteIpAddress.Addr[1],
- IPDevPath->RemoteIpAddress.Addr[2],
- IPDevPath->RemoteIpAddress.Addr[3]
- );
-
- CatNetworkProtocol (
- Str,
- IPDevPath->Protocol
- );
-
- CatPrint (
- Str,
- L",%s,%d.%d.%d.%d",
- IPDevPath->StaticIpAddress ? L"Static" : L"DHCP",
- IPDevPath->LocalIpAddress.Addr[0],
- IPDevPath->LocalIpAddress.Addr[1],
- IPDevPath->LocalIpAddress.Addr[2],
- IPDevPath->LocalIpAddress.Addr[3]
- );
- if (DevicePathNodeLength (IPDevPath) == sizeof (IPv4_DEVICE_PATH)) {
- CatPrint (
- Str,
- L",%d.%d.%d.%d,%d.%d.%d.%d",
- IPDevPath->GatewayIpAddress.Addr[0],
- IPDevPath->GatewayIpAddress.Addr[1],
- IPDevPath->GatewayIpAddress.Addr[2],
- IPDevPath->GatewayIpAddress.Addr[3],
- IPDevPath->SubnetMask.Addr[0],
- IPDevPath->SubnetMask.Addr[1],
- IPDevPath->SubnetMask.Addr[2],
- IPDevPath->SubnetMask.Addr[3]
- );
- }
- CatPrint (Str, L")");
-}
-
-/**
- Converts a IPv6 device path structure to its string representative.
-
- @param Str The string representative of input device.
- @param DevPath The input device path structure.
- @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation
- of the display node is used, where applicable. If DisplayOnly
- is FALSE, then the longer text representation of the display node
- is used.
- @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text
- representation for a device node can be used, where applicable.
-
-**/
-VOID
-DevPathToTextIPv6 (
- IN OUT POOL_PRINT *Str,
- IN VOID *DevPath,
- IN BOOLEAN DisplayOnly,
- IN BOOLEAN AllowShortcuts
- )
-{
- IPv6_DEVICE_PATH *IPDevPath;
-
- IPDevPath = DevPath;
- if (DisplayOnly) {
- CatPrint (
- Str,
- L"IPv6(%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x)",
- IPDevPath->RemoteIpAddress.Addr[0],
- IPDevPath->RemoteIpAddress.Addr[1],
- IPDevPath->RemoteIpAddress.Addr[2],
- IPDevPath->RemoteIpAddress.Addr[3],
- IPDevPath->RemoteIpAddress.Addr[4],
- IPDevPath->RemoteIpAddress.Addr[5],
- IPDevPath->RemoteIpAddress.Addr[6],
- IPDevPath->RemoteIpAddress.Addr[7],
- IPDevPath->RemoteIpAddress.Addr[8],
- IPDevPath->RemoteIpAddress.Addr[9],
- IPDevPath->RemoteIpAddress.Addr[10],
- IPDevPath->RemoteIpAddress.Addr[11],
- IPDevPath->RemoteIpAddress.Addr[12],
- IPDevPath->RemoteIpAddress.Addr[13],
- IPDevPath->RemoteIpAddress.Addr[14],
- IPDevPath->RemoteIpAddress.Addr[15]
- );
- return ;
- }
-
- CatPrint (
- Str,
- L"IPv6(%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x,",
- IPDevPath->RemoteIpAddress.Addr[0],
- IPDevPath->RemoteIpAddress.Addr[1],
- IPDevPath->RemoteIpAddress.Addr[2],
- IPDevPath->RemoteIpAddress.Addr[3],
- IPDevPath->RemoteIpAddress.Addr[4],
- IPDevPath->RemoteIpAddress.Addr[5],
- IPDevPath->RemoteIpAddress.Addr[6],
- IPDevPath->RemoteIpAddress.Addr[7],
- IPDevPath->RemoteIpAddress.Addr[8],
- IPDevPath->RemoteIpAddress.Addr[9],
- IPDevPath->RemoteIpAddress.Addr[10],
- IPDevPath->RemoteIpAddress.Addr[11],
- IPDevPath->RemoteIpAddress.Addr[12],
- IPDevPath->RemoteIpAddress.Addr[13],
- IPDevPath->RemoteIpAddress.Addr[14],
- IPDevPath->RemoteIpAddress.Addr[15]
- );
-
- CatNetworkProtocol (
- Str,
- IPDevPath->Protocol
- );
-
- switch (IPDevPath->IpAddressOrigin) {
- case 0:
- CatPrint (Str, L",Static");
- break;
- case 1:
- CatPrint (Str, L",StatelessAutoConfigure");
- break;
- default:
- CatPrint (Str, L",StatefulAutoConfigure");
- break;
- }
-
- CatPrint (
- Str,
- L",%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x",
- IPDevPath->LocalIpAddress.Addr[0],
- IPDevPath->LocalIpAddress.Addr[1],
- IPDevPath->LocalIpAddress.Addr[2],
- IPDevPath->LocalIpAddress.Addr[3],
- IPDevPath->LocalIpAddress.Addr[4],
- IPDevPath->LocalIpAddress.Addr[5],
- IPDevPath->LocalIpAddress.Addr[6],
- IPDevPath->LocalIpAddress.Addr[7],
- IPDevPath->LocalIpAddress.Addr[8],
- IPDevPath->LocalIpAddress.Addr[9],
- IPDevPath->LocalIpAddress.Addr[10],
- IPDevPath->LocalIpAddress.Addr[11],
- IPDevPath->LocalIpAddress.Addr[12],
- IPDevPath->LocalIpAddress.Addr[13],
- IPDevPath->LocalIpAddress.Addr[14],
- IPDevPath->LocalIpAddress.Addr[15]
- );
-
- if (DevicePathNodeLength (IPDevPath) == sizeof (IPv6_DEVICE_PATH)) {
- CatPrint (
- Str,
- L",0x%x,%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x",
- IPDevPath->PrefixLength,
- IPDevPath->GatewayIpAddress.Addr[0],
- IPDevPath->GatewayIpAddress.Addr[1],
- IPDevPath->GatewayIpAddress.Addr[2],
- IPDevPath->GatewayIpAddress.Addr[3],
- IPDevPath->GatewayIpAddress.Addr[4],
- IPDevPath->GatewayIpAddress.Addr[5],
- IPDevPath->GatewayIpAddress.Addr[6],
- IPDevPath->GatewayIpAddress.Addr[7],
- IPDevPath->GatewayIpAddress.Addr[8],
- IPDevPath->GatewayIpAddress.Addr[9],
- IPDevPath->GatewayIpAddress.Addr[10],
- IPDevPath->GatewayIpAddress.Addr[11],
- IPDevPath->GatewayIpAddress.Addr[12],
- IPDevPath->GatewayIpAddress.Addr[13],
- IPDevPath->GatewayIpAddress.Addr[14],
- IPDevPath->GatewayIpAddress.Addr[15]
- );
- }
- CatPrint (Str, L")");
-}
-
-/**
- Converts an Infini Band device path structure to its string representative.
-
- @param Str The string representative of input device.
- @param DevPath The input device path structure.
- @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation
- of the display node is used, where applicable. If DisplayOnly
- is FALSE, then the longer text representation of the display node
- is used.
- @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text
- representation for a device node can be used, where applicable.
-
-**/
-VOID
-DevPathToTextInfiniBand (
- IN OUT POOL_PRINT *Str,
- IN VOID *DevPath,
- IN BOOLEAN DisplayOnly,
- IN BOOLEAN AllowShortcuts
- )
-{
- INFINIBAND_DEVICE_PATH *InfiniBand;
-
- InfiniBand = DevPath;
- CatPrint (
- Str,
- L"Infiniband(0x%x,%g,0x%lx,0x%lx,0x%lx)",
- InfiniBand->ResourceFlags,
- InfiniBand->PortGid,
- InfiniBand->ServiceId,
- InfiniBand->TargetPortId,
- InfiniBand->DeviceId
- );
-}
-
-/**
- Converts a UART device path structure to its string representative.
-
- @param Str The string representative of input device.
- @param DevPath The input device path structure.
- @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation
- of the display node is used, where applicable. If DisplayOnly
- is FALSE, then the longer text representation of the display node
- is used.
- @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text
- representation for a device node can be used, where applicable.
-
-**/
-VOID
-DevPathToTextUart (
- IN OUT POOL_PRINT *Str,
- IN VOID *DevPath,
- IN BOOLEAN DisplayOnly,
- IN BOOLEAN AllowShortcuts
- )
-{
- UART_DEVICE_PATH *Uart;
- CHAR8 Parity;
-
- Uart = DevPath;
- switch (Uart->Parity) {
- case 0:
- Parity = 'D';
- break;
-
- case 1:
- Parity = 'N';
- break;
-
- case 2:
- Parity = 'E';
- break;
-
- case 3:
- Parity = 'O';
- break;
-
- case 4:
- Parity = 'M';
- break;
-
- case 5:
- Parity = 'S';
- break;
-
- default:
- Parity = 'x';
- break;
- }
-
- if (Uart->BaudRate == 0) {
- CatPrint (Str, L"Uart(DEFAULT,");
- } else {
- CatPrint (Str, L"Uart(%ld,", Uart->BaudRate);
- }
-
- if (Uart->DataBits == 0) {
- CatPrint (Str, L"DEFAULT,");
- } else {
- CatPrint (Str, L"%d,", Uart->DataBits);
- }
-
- CatPrint (Str, L"%c,", Parity);
-
- switch (Uart->StopBits) {
- case 0:
- CatPrint (Str, L"D)");
- break;
-
- case 1:
- CatPrint (Str, L"1)");
- break;
-
- case 2:
- CatPrint (Str, L"1.5)");
- break;
-
- case 3:
- CatPrint (Str, L"2)");
- break;
-
- default:
- CatPrint (Str, L"x)");
- break;
- }
-}
-
-/**
- Converts an iSCSI device path structure to its string representative.
-
- @param Str The string representative of input device.
- @param DevPath The input device path structure.
- @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation
- of the display node is used, where applicable. If DisplayOnly
- is FALSE, then the longer text representation of the display node
- is used.
- @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text
- representation for a device node can be used, where applicable.
-
-**/
-VOID
-DevPathToTextiSCSI (
- IN OUT POOL_PRINT *Str,
- IN VOID *DevPath,
- IN BOOLEAN DisplayOnly,
- IN BOOLEAN AllowShortcuts
- )
-{
- ISCSI_DEVICE_PATH_WITH_NAME *ISCSIDevPath;
- UINT16 Options;
-
- ISCSIDevPath = DevPath;
- CatPrint (
- Str,
- L"iSCSI(%a,0x%x,0x%lx,",
- ISCSIDevPath->TargetName,
- ISCSIDevPath->TargetPortalGroupTag,
- ISCSIDevPath->Lun
- );
-
- Options = ISCSIDevPath->LoginOption;
- CatPrint (Str, L"%s,", (((Options >> 1) & 0x0001) != 0) ? L"CRC32C" : L"None");
- CatPrint (Str, L"%s,", (((Options >> 3) & 0x0001) != 0) ? L"CRC32C" : L"None");
- if (((Options >> 11) & 0x0001) != 0) {
- CatPrint (Str, L"%s,", L"None");
- } else if (((Options >> 12) & 0x0001) != 0) {
- CatPrint (Str, L"%s,", L"CHAP_UNI");
- } else {
- CatPrint (Str, L"%s,", L"CHAP_BI");
-
- }
-
- CatPrint (Str, L"%s)", (ISCSIDevPath->NetworkProtocol == 0) ? L"TCP" : L"reserved");
-}
-
-/**
- Converts a VLAN device path structure to its string representative.
-
- @param Str The string representative of input device.
- @param DevPath The input device path structure.
- @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation
- of the display node is used, where applicable. If DisplayOnly
- is FALSE, then the longer text representation of the display node
- is used.
- @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text
- representation for a device node can be used, where applicable.
-
-**/
-VOID
-DevPathToTextVlan (
- IN OUT POOL_PRINT *Str,
- IN VOID *DevPath,
- IN BOOLEAN DisplayOnly,
- IN BOOLEAN AllowShortcuts
- )
-{
- VLAN_DEVICE_PATH *Vlan;
-
- Vlan = DevPath;
- CatPrint (Str, L"Vlan(%d)", Vlan->VlanId);
-}
-
-/**
- Converts a Hard drive device path structure to its string representative.
-
- @param Str The string representative of input device.
- @param DevPath The input device path structure.
- @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation
- of the display node is used, where applicable. If DisplayOnly
- is FALSE, then the longer text representation of the display node
- is used.
- @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text
- representation for a device node can be used, where applicable.
-
-**/
-VOID
-DevPathToTextHardDrive (
- IN OUT POOL_PRINT *Str,
- IN VOID *DevPath,
- IN BOOLEAN DisplayOnly,
- IN BOOLEAN AllowShortcuts
- )
-{
- HARDDRIVE_DEVICE_PATH *Hd;
-
- Hd = DevPath;
- switch (Hd->SignatureType) {
- case SIGNATURE_TYPE_MBR:
- CatPrint (
- Str,
- L"HD(%d,%s,0x%08x,",
- Hd->PartitionNumber,
- L"MBR",
- *((UINT32 *) (&(Hd->Signature[0])))
- );
- break;
-
- case SIGNATURE_TYPE_GUID:
- CatPrint (
- Str,
- L"HD(%d,%s,%g,",
- Hd->PartitionNumber,
- L"GPT",
- (EFI_GUID *) &(Hd->Signature[0])
- );
- break;
-
- default:
- CatPrint (
- Str,
- L"HD(%d,%d,0,",
- Hd->PartitionNumber,
- Hd->SignatureType
- );
- break;
- }
-
- CatPrint (Str, L"0x%lx,0x%lx)", Hd->PartitionStart, Hd->PartitionSize);
-}
-
-/**
- Converts a CDROM device path structure to its string representative.
-
- @param Str The string representative of input device.
- @param DevPath The input device path structure.
- @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation
- of the display node is used, where applicable. If DisplayOnly
- is FALSE, then the longer text representation of the display node
- is used.
- @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text
- representation for a device node can be used, where applicable.
-
-**/
-VOID
-DevPathToTextCDROM (
- IN OUT POOL_PRINT *Str,
- IN VOID *DevPath,
- IN BOOLEAN DisplayOnly,
- IN BOOLEAN AllowShortcuts
- )
-{
- CDROM_DEVICE_PATH *Cd;
-
- Cd = DevPath;
- if (DisplayOnly) {
- CatPrint (Str, L"CDROM(0x%x)", Cd->BootEntry);
- return ;
- }
-
- CatPrint (Str, L"CDROM(0x%x,0x%lx,0x%lx)", Cd->BootEntry, Cd->PartitionStart, Cd->PartitionSize);
-}
-
-/**
- Converts a File device path structure to its string representative.
-
- @param Str The string representative of input device.
- @param DevPath The input device path structure.
- @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation
- of the display node is used, where applicable. If DisplayOnly
- is FALSE, then the longer text representation of the display node
- is used.
- @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text
- representation for a device node can be used, where applicable.
-
-**/
-VOID
-DevPathToTextFilePath (
- IN OUT POOL_PRINT *Str,
- IN VOID *DevPath,
- IN BOOLEAN DisplayOnly,
- IN BOOLEAN AllowShortcuts
- )
-{
- FILEPATH_DEVICE_PATH *Fp;
-
- Fp = DevPath;
- CatPrint (Str, L"%s", Fp->PathName);
-}
-
-/**
- Converts a Media protocol device path structure to its string representative.
-
- @param Str The string representative of input device.
- @param DevPath The input device path structure.
- @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation
- of the display node is used, where applicable. If DisplayOnly
- is FALSE, then the longer text representation of the display node
- is used.
- @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text
- representation for a device node can be used, where applicable.
-
-**/
-VOID
-DevPathToTextMediaProtocol (
- IN OUT POOL_PRINT *Str,
- IN VOID *DevPath,
- IN BOOLEAN DisplayOnly,
- IN BOOLEAN AllowShortcuts
- )
-{
- MEDIA_PROTOCOL_DEVICE_PATH *MediaProt;
-
- MediaProt = DevPath;
- CatPrint (Str, L"Media(%g)", &MediaProt->Protocol);
-}
-
-/**
- Converts a Firmware Volume device path structure to its string representative.
-
- @param Str The string representative of input device.
- @param DevPath The input device path structure.
- @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation
- of the display node is used, where applicable. If DisplayOnly
- is FALSE, then the longer text representation of the display node
- is used.
- @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text
- representation for a device node can be used, where applicable.
-
-**/
-VOID
-DevPathToTextFv (
- IN OUT POOL_PRINT *Str,
- IN VOID *DevPath,
- IN BOOLEAN DisplayOnly,
- IN BOOLEAN AllowShortcuts
- )
-{
- MEDIA_FW_VOL_DEVICE_PATH *Fv;
-
- Fv = DevPath;
- CatPrint (Str, L"Fv(%g)", &Fv->FvName);
-}
-
-/**
- Converts a Firmware Volume File device path structure to its string representative.
-
- @param Str The string representative of input device.
- @param DevPath The input device path structure.
- @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation
- of the display node is used, where applicable. If DisplayOnly
- is FALSE, then the longer text representation of the display node
- is used.
- @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text
- representation for a device node can be used, where applicable.
-
-**/
-VOID
-DevPathToTextFvFile (
- IN OUT POOL_PRINT *Str,
- IN VOID *DevPath,
- IN BOOLEAN DisplayOnly,
- IN BOOLEAN AllowShortcuts
- )
-{
- MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FvFile;
-
- FvFile = DevPath;
- CatPrint (Str, L"FvFile(%g)", &FvFile->FvFileName);
-}
-
-/**
- Converts a Relative Offset device path structure to its string representative.
-
- @param Str The string representative of input device.
- @param DevPath The input device path structure.
- @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation
- of the display node is used, where applicable. If DisplayOnly
- is FALSE, then the longer text representation of the display node
- is used.
- @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text
- representation for a device node can be used, where applicable.
-
-**/
-VOID
-DevPathRelativeOffsetRange (
- IN OUT POOL_PRINT *Str,
- IN VOID *DevPath,
- IN BOOLEAN DisplayOnly,
- IN BOOLEAN AllowShortcuts
- )
-{
- MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH *Offset;
-
- Offset = DevPath;
- CatPrint (
- Str,
- L"Offset(0x%lx,0x%lx)",
- Offset->StartingOffset,
- Offset->EndingOffset
- );
-}
-
-/**
- Converts a BIOS Boot Specification device path structure to its string representative.
-
- @param Str The string representative of input device.
- @param DevPath The input device path structure.
- @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation
- of the display node is used, where applicable. If DisplayOnly
- is FALSE, then the longer text representation of the display node
- is used.
- @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text
- representation for a device node can be used, where applicable.
-
-**/
-VOID
-DevPathToTextBBS (
- IN OUT POOL_PRINT *Str,
- IN VOID *DevPath,
- IN BOOLEAN DisplayOnly,
- IN BOOLEAN AllowShortcuts
- )
-{
- BBS_BBS_DEVICE_PATH *Bbs;
- CHAR16 *Type;
-
- Bbs = DevPath;
- switch (Bbs->DeviceType) {
- case BBS_TYPE_FLOPPY:
- Type = L"Floppy";
- break;
-
- case BBS_TYPE_HARDDRIVE:
- Type = L"HD";
- break;
-
- case BBS_TYPE_CDROM:
- Type = L"CDROM";
- break;
-
- case BBS_TYPE_PCMCIA:
- Type = L"PCMCIA";
- break;
-
- case BBS_TYPE_USB:
- Type = L"USB";
- break;
-
- case BBS_TYPE_EMBEDDED_NETWORK:
- Type = L"Network";
- break;
-
- default:
- Type = NULL;
- break;
- }
-
- if (Type != NULL) {
- CatPrint (Str, L"BBS(%s,%a", Type, Bbs->String);
- } else {
- CatPrint (Str, L"BBS(0x%x,%a", Bbs->DeviceType, Bbs->String);
- }
-
- if (DisplayOnly) {
- CatPrint (Str, L")");
- return ;
- }
-
- CatPrint (Str, L",0x%x)", Bbs->StatusFlag);
-}
-
-/**
- Converts an End-of-Device-Path structure to its string representative.
-
- @param Str The string representative of input device.
- @param DevPath The input device path structure.
- @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation
- of the display node is used, where applicable. If DisplayOnly
- is FALSE, then the longer text representation of the display node
- is used.
- @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text
- representation for a device node can be used, where applicable.
-
-**/
-VOID
-DevPathToTextEndInstance (
- IN OUT POOL_PRINT *Str,
- IN VOID *DevPath,
- IN BOOLEAN DisplayOnly,
- IN BOOLEAN AllowShortcuts
- )
-{
- CatPrint (Str, L",");
-}
-
-/**
- Converts an unknown device path structure to its string representative.
-
- @param Str The string representative of input device.
- @param DevPath The input device path structure.
- @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation
- of the display node is used, where applicable. If DisplayOnly
- is FALSE, then the longer text representation of the display node
- is used.
- @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text
- representation for a device node can be used, where applicable.
-
-**/
-VOID
-DevPathToTextNodeUnknown (
- IN OUT POOL_PRINT *Str,
- IN VOID *DevPath,
- IN BOOLEAN DisplayOnly,
- IN BOOLEAN AllowShortcuts
- )
-{
- CatPrint (Str, L"?");
-}
-
-GLOBAL_REMOVE_IF_UNREFERENCED const DEVICE_PATH_TO_TEXT_TABLE DevPathToTextTable[] = {
- {HARDWARE_DEVICE_PATH, HW_PCI_DP, DevPathToTextPci},
- {HARDWARE_DEVICE_PATH, HW_PCCARD_DP, DevPathToTextPccard},
- {HARDWARE_DEVICE_PATH, HW_MEMMAP_DP, DevPathToTextMemMap},
- {HARDWARE_DEVICE_PATH, HW_VENDOR_DP, DevPathToTextVendor},
- {HARDWARE_DEVICE_PATH, HW_CONTROLLER_DP, DevPathToTextController},
- {ACPI_DEVICE_PATH, ACPI_DP, DevPathToTextAcpi},
- {ACPI_DEVICE_PATH, ACPI_EXTENDED_DP, DevPathToTextAcpiEx},
- {ACPI_DEVICE_PATH, ACPI_ADR_DP, DevPathToTextAcpiAdr},
- {MESSAGING_DEVICE_PATH, MSG_ATAPI_DP, DevPathToTextAtapi},
- {MESSAGING_DEVICE_PATH, MSG_SCSI_DP, DevPathToTextScsi},
- {MESSAGING_DEVICE_PATH, MSG_FIBRECHANNEL_DP, DevPathToTextFibre},
- {MESSAGING_DEVICE_PATH, MSG_FIBRECHANNELEX_DP, DevPathToTextFibreEx},
- {MESSAGING_DEVICE_PATH, MSG_SASEX_DP, DevPathToTextSasEx},
- {MESSAGING_DEVICE_PATH, MSG_1394_DP, DevPathToText1394},
- {MESSAGING_DEVICE_PATH, MSG_USB_DP, DevPathToTextUsb},
- {MESSAGING_DEVICE_PATH, MSG_USB_WWID_DP, DevPathToTextUsbWWID},
- {MESSAGING_DEVICE_PATH, MSG_DEVICE_LOGICAL_UNIT_DP, DevPathToTextLogicalUnit},
- {MESSAGING_DEVICE_PATH, MSG_USB_CLASS_DP, DevPathToTextUsbClass},
- {MESSAGING_DEVICE_PATH, MSG_SATA_DP, DevPathToTextSata},
- {MESSAGING_DEVICE_PATH, MSG_I2O_DP, DevPathToTextI2O},
- {MESSAGING_DEVICE_PATH, MSG_MAC_ADDR_DP, DevPathToTextMacAddr},
- {MESSAGING_DEVICE_PATH, MSG_IPv4_DP, DevPathToTextIPv4},
- {MESSAGING_DEVICE_PATH, MSG_IPv6_DP, DevPathToTextIPv6},
- {MESSAGING_DEVICE_PATH, MSG_INFINIBAND_DP, DevPathToTextInfiniBand},
- {MESSAGING_DEVICE_PATH, MSG_UART_DP, DevPathToTextUart},
- {MESSAGING_DEVICE_PATH, MSG_VENDOR_DP, DevPathToTextVendor},
- {MESSAGING_DEVICE_PATH, MSG_ISCSI_DP, DevPathToTextiSCSI},
- {MESSAGING_DEVICE_PATH, MSG_VLAN_DP, DevPathToTextVlan},
- {MEDIA_DEVICE_PATH, MEDIA_HARDDRIVE_DP, DevPathToTextHardDrive},
- {MEDIA_DEVICE_PATH, MEDIA_CDROM_DP, DevPathToTextCDROM},
- {MEDIA_DEVICE_PATH, MEDIA_VENDOR_DP, DevPathToTextVendor},
- {MEDIA_DEVICE_PATH, MEDIA_PROTOCOL_DP, DevPathToTextMediaProtocol},
- {MEDIA_DEVICE_PATH, MEDIA_FILEPATH_DP, DevPathToTextFilePath},
- {MEDIA_DEVICE_PATH, MEDIA_PIWG_FW_VOL_DP, DevPathToTextFv},
- {MEDIA_DEVICE_PATH, MEDIA_PIWG_FW_FILE_DP, DevPathToTextFvFile},
- {MEDIA_DEVICE_PATH, MEDIA_RELATIVE_OFFSET_RANGE_DP, DevPathRelativeOffsetRange},
- {BBS_DEVICE_PATH, BBS_BBS_DP, DevPathToTextBBS},
- {END_DEVICE_PATH_TYPE, END_INSTANCE_DEVICE_PATH_SUBTYPE, DevPathToTextEndInstance},
- {0, 0, NULL}
-};
-
-/**
- Converts a device node to its string representation.
-
- @param DeviceNode A Pointer to the device node to be converted.
- @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation
- of the display node is used, where applicable. If DisplayOnly
- is FALSE, then the longer text representation of the display node
- is used.
- @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text
- representation for a device node can be used, where applicable.
-
- @return A pointer to the allocated text representation of the device node or NULL if DeviceNode
- is NULL or there was insufficient memory.
-
-**/
-CHAR16 *
-EFIAPI
-ConvertDeviceNodeToText (
- IN CONST EFI_DEVICE_PATH_PROTOCOL *DeviceNode,
- IN BOOLEAN DisplayOnly,
- IN BOOLEAN AllowShortcuts
- )
-{
- POOL_PRINT Str;
- UINTN Index;
- VOID (*DumpNode)(POOL_PRINT *, VOID *, BOOLEAN, BOOLEAN);
-
- if (DeviceNode == NULL) {
- return NULL;
- }
-
- ZeroMem (&Str, sizeof (Str));
-
- //
- // Process the device path node
- //
- DumpNode = NULL;
- for (Index = 0; DevPathToTextTable[Index].Function != NULL; Index++) {
- if (DevicePathType (DeviceNode) == DevPathToTextTable[Index].Type &&
- DevicePathSubType (DeviceNode) == DevPathToTextTable[Index].SubType
- ) {
- DumpNode = DevPathToTextTable[Index].Function;
- break;
- }
- }
- //
- // If not found, use a generic function
- //
- if (DumpNode == NULL) {
- DumpNode = DevPathToTextNodeUnknown;
- }
-
- //
- // Print this node
- //
- DumpNode (&Str, (VOID *) DeviceNode, DisplayOnly, AllowShortcuts);
-
- ASSERT (Str.Str != NULL);
- return Str.Str;
-}
-
-/**
- Converts a device path to its text representation.
-
- @param DevicePath A Pointer to the device to be converted.
- @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation
- of the display node is used, where applicable. If DisplayOnly
- is FALSE, then the longer text representation of the display node
- is used.
- @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text
- representation for a device node can be used, where applicable.
-
- @return A pointer to the allocated text representation of the device path or
- NULL if DeviceNode is NULL or there was insufficient memory.
-
-**/
-CHAR16 *
-EFIAPI
-ConvertDevicePathToText (
- IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,
- IN BOOLEAN DisplayOnly,
- IN BOOLEAN AllowShortcuts
- )
-{
- POOL_PRINT Str;
- EFI_DEVICE_PATH_PROTOCOL *DevPathNode;
- EFI_DEVICE_PATH_PROTOCOL *AlignedDevPathNode;
- UINTN Index;
- VOID (*DumpNode) (POOL_PRINT *, VOID *, BOOLEAN, BOOLEAN);
-
- if (DevicePath == NULL) {
- return NULL;
- }
-
- ZeroMem (&Str, sizeof (Str));
-
- //
- // Process each device path node
- //
- DevPathNode = (EFI_DEVICE_PATH_PROTOCOL *) DevicePath;
- while (!IsDevicePathEnd (DevPathNode)) {
- //
- // Find the handler to dump this device path node
- //
- DumpNode = NULL;
- for (Index = 0; DevPathToTextTable[Index].Function != NULL; Index += 1) {
-
- if (DevicePathType (DevPathNode) == DevPathToTextTable[Index].Type &&
- DevicePathSubType (DevPathNode) == DevPathToTextTable[Index].SubType
- ) {
- DumpNode = DevPathToTextTable[Index].Function;
- break;
- }
- }
- //
- // If not found, use a generic function
- //
- if (!DumpNode) {
- DumpNode = DevPathToTextNodeUnknown;
- }
- //
- // Put a path separator in if needed
- //
- if ((Str.Length != 0) && (DumpNode != DevPathToTextEndInstance)) {
- if (*(Str.Str + Str.Length / sizeof (CHAR16) - 1) != L',') {
- CatPrint (&Str, L"/");
- }
- }
-
- AlignedDevPathNode = AllocateCopyPool (DevicePathNodeLength (DevPathNode), DevPathNode);
- //
- // Print this node of the device path
- //
- DumpNode (&Str, AlignedDevPathNode, DisplayOnly, AllowShortcuts);
- FreePool (AlignedDevPathNode);
-
- //
- // Next device path node
- //
- DevPathNode = NextDevicePathNode (DevPathNode);
- }
-
- if (Str.Str == NULL) {
- return AllocateZeroPool (sizeof (CHAR16));
- } else {
- return Str.Str;
- }
-}
diff --git a/MdeModulePkg/Universal/DevicePathDxe/DevicePathUtilities.c b/MdeModulePkg/Universal/DevicePathDxe/DevicePathUtilities.c
deleted file mode 100644
index 78b267011..000000000
--- a/MdeModulePkg/Universal/DevicePathDxe/DevicePathUtilities.c
+++ /dev/null
@@ -1,234 +0,0 @@
-/** @file
- Implementation file for Device Path Utilities Protocol
-
-Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.<BR>
-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 "DevicePath.h"
-
-/**
- Returns the size of a device path in bytes.
-
- This function returns the size, in bytes, of the device path data structure specified by
- DevicePath including the end of device path node. If DevicePath is NULL, then 0 is returned.
-
- @param DevicePath A pointer to a device path data structure.
-
- @return The size of a device path in bytes.
-
-**/
-UINTN
-EFIAPI
-GetDevicePathSizeProtocolInterface (
- IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath
- )
-{
- return GetDevicePathSize (DevicePath);
-}
-
-
-/**
- Creates a new device path by appending a second device path to a first device path.
-
- This function allocates space for a new copy of the device path specified by DevicePath. If
- DevicePath is NULL, then NULL is returned. If the memory is successfully allocated, then the
- contents of DevicePath are copied to the newly allocated buffer, and a pointer to that buffer
- is returned. Otherwise, NULL is returned.
-
- @param DevicePath A pointer to a device path data structure.
-
- @return A pointer to the duplicated device path.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-EFIAPI
-DuplicateDevicePathProtocolInterface (
- IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath
- )
-{
- return DuplicateDevicePath (DevicePath);
-}
-
-/**
- Creates a new device path by appending a second device path to a first device path.
-
- This function creates a new device path by appending a copy of SecondDevicePath to a copy of
- FirstDevicePath in a newly allocated buffer. Only the end-of-device-path device node from
- SecondDevicePath is retained. The newly created device path is returned.
- If FirstDevicePath is NULL, then it is ignored, and a duplicate of SecondDevicePath is returned.
- If SecondDevicePath is NULL, then it is ignored, and a duplicate of FirstDevicePath is returned.
- If both FirstDevicePath and SecondDevicePath are NULL, then a copy of an end-of-device-path is
- returned.
- If there is not enough memory for the newly allocated buffer, then NULL is returned.
- The memory for the new device path is allocated from EFI boot services memory. It is the
- responsibility of the caller to free the memory allocated.
-
- @param FirstDevicePath A pointer to a device path data structure.
- @param SecondDevicePath A pointer to a device path data structure.
-
- @return A pointer to the new device path.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-EFIAPI
-AppendDevicePathProtocolInterface (
- IN CONST EFI_DEVICE_PATH_PROTOCOL *FirstDevicePath,
- IN CONST EFI_DEVICE_PATH_PROTOCOL *SecondDevicePath
- )
-{
- return AppendDevicePath (FirstDevicePath, SecondDevicePath);
-}
-
-/**
- Creates a new path by appending the device node to the device path.
-
- This function creates a new device path by appending a copy of the device node specified by
- DevicePathNode to a copy of the device path specified by DevicePath in an allocated buffer.
- The end-of-device-path device node is moved after the end of the appended device node.
- If DevicePathNode is NULL then a copy of DevicePath is returned.
- If DevicePath is NULL then a copy of DevicePathNode, followed by an end-of-device path device
- node is returned.
- If both DevicePathNode and DevicePath are NULL then a copy of an end-of-device-path device node
- is returned.
- If there is not enough memory to allocate space for the new device path, then NULL is returned.
- The memory is allocated from EFI boot services memory. It is the responsibility of the caller to
- free the memory allocated.
-
- @param DevicePath A pointer to a device path data structure.
- @param DevicePathNode A pointer to a single device path node.
-
- @return A pointer to the new device path.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-EFIAPI
-AppendDeviceNodeProtocolInterface (
- IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,
- IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePathNode
- )
-{
- return AppendDevicePathNode (DevicePath, DevicePathNode);
-}
-
-/**
- Creates a new device path by appending the specified device path instance to the specified device
- path.
-
- This function creates a new device path by appending a copy of the device path instance specified
- by DevicePathInstance to a copy of the device path specified by DevicePath in a allocated buffer.
- The end-of-device-path device node is moved after the end of the appended device path instance
- and a new end-of-device-path-instance node is inserted between.
- If DevicePath is NULL, then a copy if DevicePathInstance is returned.
- If DevicePathInstance is NULL, then NULL is returned.
- If there is not enough memory to allocate space for the new device path, then NULL is returned.
- The memory is allocated from EFI boot services memory. It is the responsibility of the caller to
- free the memory allocated.
-
- @param DevicePath A pointer to a device path data structure.
- @param DevicePathInstance A pointer to a device path instance.
-
- @return A pointer to the new device path.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-EFIAPI
-AppendDevicePathInstanceProtocolInterface (
- IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,
- IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePathInstance
- )
-{
- return AppendDevicePathInstance (DevicePath, DevicePathInstance);
-}
-
-/**
- Creates a copy of the current device path instance and returns a pointer to the next device path
- instance.
-
- This function creates a copy of the current device path instance. It also updates DevicePath to
- point to the next device path instance in the device path (or NULL if no more) and updates Size
- to hold the size of the device path instance copy.
- If DevicePath is NULL, then NULL is returned.
- If there is not enough memory to allocate space for the new device path, then NULL is returned.
- The memory is allocated from EFI boot services memory. It is the responsibility of the caller to
- free the memory allocated.
- If Size is NULL, then ASSERT().
-
- @param DevicePath On input, this holds the pointer to the current device path
- instance. On output, this holds the pointer to the next device
- path instance or NULL if there are no more device path
- instances in the device path pointer to a device path data
- structure.
- @param Size On output, this holds the size of the device path instance, in
- bytes or zero, if DevicePath is NULL.
-
- @return A pointer to the current device path instance.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-EFIAPI
-GetNextDevicePathInstanceProtocolInterface (
- IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath,
- OUT UINTN *Size
- )
-{
- return GetNextDevicePathInstance (DevicePath, Size);
-}
-
-/**
- Determines if a device path is single or multi-instance.
-
- This function returns TRUE if the device path specified by DevicePath is multi-instance.
- Otherwise, FALSE is returned. If DevicePath is NULL, then FALSE is returned.
-
- @param DevicePath A pointer to a device path data structure.
-
- @retval TRUE DevicePath is multi-instance.
- @retval FALSE DevicePath is not multi-instance or DevicePath is NULL.
-
-**/
-BOOLEAN
-EFIAPI
-IsDevicePathMultiInstanceProtocolInterface (
- IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath
- )
-{
- return IsDevicePathMultiInstance (DevicePath);
-}
-
-/**
- Creates a copy of the current device path instance and returns a pointer to the next device path
- instance.
-
- This function creates a new device node in a newly allocated buffer of size NodeLength and
- initializes the device path node header with NodeType and NodeSubType. The new device path node
- is returned.
- If NodeLength is smaller than a device path header, then NULL is returned.
- If there is not enough memory to allocate space for the new device path, then NULL is returned.
- The memory is allocated from EFI boot services memory. It is the responsibility of the caller to
- free the memory allocated.
-
- @param NodeType The device node type for the new device node.
- @param NodeSubType The device node sub-type for the new device node.
- @param NodeLength The length of the new device node.
-
- @return The new device path.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-EFIAPI
-CreateDeviceNodeProtocolInterface (
- IN UINT8 NodeType,
- IN UINT8 NodeSubType,
- IN UINT16 NodeLength
- )
-{
- return CreateDeviceNode (NodeType, NodeSubType, NodeLength);
-}
diff --git a/MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIo.c b/MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIo.c
index 0175465ad..ba6130091 100644
--- a/MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIo.c
+++ b/MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIo.c
@@ -9,7 +9,7 @@
Aligned - A read of N contiguous sectors.
OverRun - The last byte is not on a sector boundary.
-Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
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
@@ -45,10 +45,15 @@ DISK_IO_PRIVATE_DATA gDiskIoPrivateDataTemplate = {
DiskIoReadDisk,
DiskIoWriteDisk
},
- NULL
+ {
+ EFI_DISK_IO2_PROTOCOL_REVISION,
+ DiskIo2Cancel,
+ DiskIo2ReadDiskEx,
+ DiskIo2WriteDiskEx,
+ DiskIo2FlushDiskEx
+ }
};
-
/**
Test to see if this driver supports ControllerHandle.
@@ -92,11 +97,11 @@ DiskIoDriverBindingSupported (
// Close the I/O Abstraction(s) used to perform the supported test.
//
gBS->CloseProtocol (
- ControllerHandle,
- &gEfiBlockIoProtocolGuid,
- This->DriverBindingHandle,
- ControllerHandle
- );
+ ControllerHandle,
+ &gEfiBlockIoProtocolGuid,
+ This->DriverBindingHandle,
+ ControllerHandle
+ );
return EFI_SUCCESS;
}
@@ -124,14 +129,15 @@ DiskIoDriverBindingStart (
)
{
EFI_STATUS Status;
- DISK_IO_PRIVATE_DATA *Private;
+ DISK_IO_PRIVATE_DATA *Instance;
EFI_TPL OldTpl;
+ Instance = NULL;
+
OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
- Private = NULL;
//
- // Connect to the Block IO interface on ControllerHandle.
+ // Connect to the Block IO and Block IO2 interface on ControllerHandle.
//
Status = gBS->OpenProtocol (
ControllerHandle,
@@ -144,39 +150,84 @@ DiskIoDriverBindingStart (
if (EFI_ERROR (Status)) {
goto ErrorExit1;
}
+
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiBlockIo2ProtocolGuid,
+ (VOID **) &gDiskIoPrivateDataTemplate.BlockIo2,
+ This->DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status)) {
+ gDiskIoPrivateDataTemplate.BlockIo2 = NULL;
+ }
//
// Initialize the Disk IO device instance.
//
- Private = AllocateCopyPool (sizeof (DISK_IO_PRIVATE_DATA), &gDiskIoPrivateDataTemplate);
- if (Private == NULL) {
+ Instance = AllocateCopyPool (sizeof (DISK_IO_PRIVATE_DATA), &gDiskIoPrivateDataTemplate);
+ if (Instance == NULL) {
Status = EFI_OUT_OF_RESOURCES;
goto ErrorExit;
}
//
+ // The BlockSize and IoAlign of BlockIo and BlockIo2 should equal.
+ //
+ ASSERT ((Instance->BlockIo2 == NULL) ||
+ ((Instance->BlockIo->Media->IoAlign == Instance->BlockIo2->Media->IoAlign) &&
+ (Instance->BlockIo->Media->BlockSize == Instance->BlockIo2->Media->BlockSize)
+ ));
+
+ InitializeListHead (&Instance->TaskQueue);
+ EfiInitializeLock (&Instance->TaskQueueLock, TPL_NOTIFY);
+ Instance->SharedWorkingBuffer = AllocateAlignedPages (
+ EFI_SIZE_TO_PAGES (DATA_BUFFER_BLOCK_NUM * Instance->BlockIo->Media->BlockSize),
+ Instance->BlockIo->Media->IoAlign
+ );
+ if (Instance->SharedWorkingBuffer == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ErrorExit;
+ }
+
+ //
// Install protocol interfaces for the Disk IO device.
//
- Status = gBS->InstallProtocolInterface (
- &ControllerHandle,
- &gEfiDiskIoProtocolGuid,
- EFI_NATIVE_INTERFACE,
- &Private->DiskIo
- );
+ if (Instance->BlockIo2 != NULL) {
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &ControllerHandle,
+ &gEfiDiskIoProtocolGuid, &Instance->DiskIo,
+ &gEfiDiskIo2ProtocolGuid, &Instance->DiskIo2,
+ NULL
+ );
+ } else {
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &ControllerHandle,
+ &gEfiDiskIoProtocolGuid, &Instance->DiskIo,
+ NULL
+ );
+ }
ErrorExit:
if (EFI_ERROR (Status)) {
+ if (Instance != NULL && Instance->SharedWorkingBuffer != NULL) {
+ FreeAlignedPages (
+ Instance->SharedWorkingBuffer,
+ EFI_SIZE_TO_PAGES (DATA_BUFFER_BLOCK_NUM * Instance->BlockIo->Media->BlockSize)
+ );
+ }
- if (Private != NULL) {
- FreePool (Private);
+ if (Instance != NULL) {
+ FreePool (Instance);
}
gBS->CloseProtocol (
- ControllerHandle,
- &gEfiBlockIoProtocolGuid,
- This->DriverBindingHandle,
- ControllerHandle
- );
+ ControllerHandle,
+ &gEfiBlockIoProtocolGuid,
+ This->DriverBindingHandle,
+ ControllerHandle
+ );
}
ErrorExit1:
@@ -184,7 +235,6 @@ ErrorExit1:
return Status;
}
-
/**
Stop this driver on ControllerHandle by removing Disk IO protocol and closing
the Block IO protocol on ControllerHandle.
@@ -210,7 +260,9 @@ DiskIoDriverBindingStop (
{
EFI_STATUS Status;
EFI_DISK_IO_PROTOCOL *DiskIo;
- DISK_IO_PRIVATE_DATA *Private;
+ EFI_DISK_IO2_PROTOCOL *DiskIo2;
+ DISK_IO_PRIVATE_DATA *Instance;
+ BOOLEAN AllTaskDone;
//
// Get our context back.
@@ -224,489 +276,948 @@ DiskIoDriverBindingStop (
EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
if (EFI_ERROR (Status)) {
- return EFI_UNSUPPORTED;
+ return Status;
}
-
- Private = DISK_IO_PRIVATE_DATA_FROM_THIS (DiskIo);
-
- Status = gBS->UninstallProtocolInterface (
+ Status = gBS->OpenProtocol (
ControllerHandle,
- &gEfiDiskIoProtocolGuid,
- &Private->DiskIo
+ &gEfiDiskIo2ProtocolGuid,
+ (VOID **) &DiskIo2,
+ This->DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
+ if (EFI_ERROR (Status)) {
+ DiskIo2 = NULL;
+ }
+
+ Instance = DISK_IO_PRIVATE_DATA_FROM_DISK_IO (DiskIo);
+
+ if (DiskIo2 != NULL) {
+ //
+ // Call BlockIo2::Reset() to terminate any in-flight non-blocking I/O requests
+ //
+ ASSERT (Instance->BlockIo2 != NULL);
+ Status = Instance->BlockIo2->Reset (Instance->BlockIo2, FALSE);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ Status = gBS->UninstallMultipleProtocolInterfaces (
+ ControllerHandle,
+ &gEfiDiskIoProtocolGuid, &Instance->DiskIo,
+ &gEfiDiskIo2ProtocolGuid, &Instance->DiskIo2,
+ NULL
+ );
+ } else {
+ Status = gBS->UninstallMultipleProtocolInterfaces (
+ ControllerHandle,
+ &gEfiDiskIoProtocolGuid, &Instance->DiskIo,
+ NULL
+ );
+ }
if (!EFI_ERROR (Status)) {
+
+ do {
+ EfiAcquireLock (&Instance->TaskQueueLock);
+ AllTaskDone = IsListEmpty (&Instance->TaskQueue);
+ EfiReleaseLock (&Instance->TaskQueueLock);
+ } while (!AllTaskDone);
+
+ FreeAlignedPages (
+ Instance->SharedWorkingBuffer,
+ EFI_SIZE_TO_PAGES (DATA_BUFFER_BLOCK_NUM * Instance->BlockIo->Media->BlockSize)
+ );
+
Status = gBS->CloseProtocol (
ControllerHandle,
&gEfiBlockIoProtocolGuid,
This->DriverBindingHandle,
ControllerHandle
);
+ ASSERT_EFI_ERROR (Status);
+ if (DiskIo2 != NULL) {
+ Status = gBS->CloseProtocol (
+ ControllerHandle,
+ &gEfiBlockIo2ProtocolGuid,
+ This->DriverBindingHandle,
+ ControllerHandle
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ FreePool (Instance);
}
- if (!EFI_ERROR (Status)) {
- FreePool (Private);
+ return Status;
+}
+
+
+/**
+ Destroy the sub task.
+
+ @param Instance Pointer to the DISK_IO_PRIVATE_DATA.
+ @param Subtask Subtask.
+
+ @return LIST_ENTRY * Pointer to the next link of subtask.
+**/
+LIST_ENTRY *
+DiskIoDestroySubtask (
+ IN DISK_IO_PRIVATE_DATA *Instance,
+ IN DISK_IO_SUBTASK *Subtask
+ )
+{
+ LIST_ENTRY *Link;
+ Link = RemoveEntryList (&Subtask->Link);
+ if (!Subtask->Blocking) {
+ if (Subtask->WorkingBuffer != NULL) {
+ FreeAlignedPages (
+ Subtask->WorkingBuffer,
+ Subtask->Length < Instance->BlockIo->Media->BlockSize
+ ? EFI_SIZE_TO_PAGES (Instance->BlockIo->Media->BlockSize)
+ : EFI_SIZE_TO_PAGES (Subtask->Length)
+ );
+ }
+ if (Subtask->BlockIo2Token.Event != NULL) {
+ gBS->CloseEvent (Subtask->BlockIo2Token.Event);
+ }
}
+ FreePool (Subtask);
- return Status;
+ return Link;
}
+/**
+ The callback for the BlockIo2 ReadBlocksEx/WriteBlocksEx.
+ @param Event Event whose notification function is being invoked.
+ @param Context The pointer to the notification function's context,
+ which points to the DISK_IO_SUBTASK instance.
+**/
+VOID
+EFIAPI
+DiskIo2OnReadWriteComplete (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ DISK_IO_SUBTASK *Subtask;
+ DISK_IO2_TASK *Task;
+ EFI_STATUS TransactionStatus;
+ DISK_IO_PRIVATE_DATA *Instance;
+
+ gBS->CloseEvent (Event);
+
+ Subtask = (DISK_IO_SUBTASK *) Context;
+ TransactionStatus = Subtask->BlockIo2Token.TransactionStatus;
+ Task = Subtask->Task;
+ Instance = Task->Instance;
+
+ ASSERT (Subtask->Signature == DISK_IO_SUBTASK_SIGNATURE);
+ ASSERT (Instance->Signature == DISK_IO_PRIVATE_DATA_SIGNATURE);
+ ASSERT (Task->Signature == DISK_IO2_TASK_SIGNATURE);
+
+ if (Subtask->WorkingBuffer != NULL) {
+ if (!EFI_ERROR (TransactionStatus) && (Task->Token != NULL) && !Subtask->Write) {
+ CopyMem (Subtask->Buffer, Subtask->WorkingBuffer + Subtask->Offset, Subtask->Length);
+ }
+ //
+ // The WorkingBuffer of blocking subtask either points to SharedWorkingBuffer
+ // or will be used by non-blocking subtask which will be freed below.
+ //
+ if (!Subtask->Blocking) {
+ FreeAlignedPages (
+ Subtask->WorkingBuffer,
+ Subtask->Length < Instance->BlockIo->Media->BlockSize
+ ? EFI_SIZE_TO_PAGES (Instance->BlockIo->Media->BlockSize)
+ : EFI_SIZE_TO_PAGES (Subtask->Length)
+ );
+ }
+ }
+ RemoveEntryList (&Subtask->Link);
+ FreePool (Subtask);
+
+ if (EFI_ERROR (TransactionStatus) || IsListEmpty (&Task->Subtasks)) {
+ if (Task->Token != NULL) {
+ //
+ // Signal error status once the subtask is failed.
+ // Or signal the last status once the last subtask is finished.
+ //
+ Task->Token->TransactionStatus = TransactionStatus;
+ gBS->SignalEvent (Task->Token->Event);
+
+ //
+ // Mark token to NULL
+ //
+ Task->Token = NULL;
+ }
+ }
+
+ if (IsListEmpty (&Task->Subtasks)) {
+ EfiAcquireLock (&Instance->TaskQueueLock);
+ RemoveEntryList (&Task->Link);
+ EfiReleaseLock (&Instance->TaskQueueLock);
+
+ FreePool (Task);
+ }
+}
/**
- Read BufferSize bytes from Offset into Buffer.
- Reads may support reads that are not aligned on
- sector boundaries. There are three cases:
- UnderRun - The first byte is not on a sector boundary or the read request is
- less than a sector in length.
- Aligned - A read of N contiguous sectors.
- OverRun - The last byte is not on a sector boundary.
+ Create the subtask.
- @param This Protocol instance pointer.
- @param MediaId Id of the media, changes every time the media is replaced.
- @param Offset The starting byte offset to read from
- @param BufferSize Size of Buffer
- @param Buffer Buffer containing read data
+ @param Write TRUE: Write request; FALSE: Read request.
+ @param Lba The starting logical block address to read from on the device.
+ @param Offset The starting byte offset to read from the LBA.
+ @param Length The number of bytes to read from the device.
+ @param WorkingBuffer The aligned buffer to hold the data for reading or writing.
+ @param Buffer The buffer to hold the data for reading or writing.
+ @param Blocking TRUE: Blocking request; FALSE: Non-blocking request.
- @retval EFI_SUCCESS The data was read correctly from the device.
- @retval EFI_DEVICE_ERROR The device reported an error while performing the read.
- @retval EFI_NO_MEDIA There is no media in the device.
- @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device.
- @retval EFI_INVALID_PARAMETER The read request contains device addresses that are not
- valid for the device.
+ @return A pointer to the created subtask.
+**/
+DISK_IO_SUBTASK *
+DiskIoCreateSubtask (
+ IN BOOLEAN Write,
+ IN UINT64 Lba,
+ IN UINT32 Offset,
+ IN UINTN Length,
+ IN VOID *WorkingBuffer, OPTIONAL
+ IN VOID *Buffer,
+ IN BOOLEAN Blocking
+ )
+{
+ DISK_IO_SUBTASK *Subtask;
+ EFI_STATUS Status;
+ Subtask = AllocateZeroPool (sizeof (DISK_IO_SUBTASK));
+ if (Subtask == NULL) {
+ return NULL;
+ }
+ Subtask->Signature = DISK_IO_SUBTASK_SIGNATURE;
+ Subtask->Write = Write;
+ Subtask->Lba = Lba;
+ Subtask->Offset = Offset;
+ Subtask->Length = Length;
+ Subtask->WorkingBuffer = WorkingBuffer;
+ Subtask->Buffer = Buffer;
+ Subtask->Blocking = Blocking;
+ if (!Blocking) {
+ Status = gBS->CreateEvent (
+ EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ DiskIo2OnReadWriteComplete,
+ Subtask,
+ &Subtask->BlockIo2Token.Event
+ );
+ if (EFI_ERROR (Status)) {
+ FreePool (Subtask);
+ return NULL;
+ }
+ }
+ DEBUG ((
+ EFI_D_BLKIO,
+ " %c:Lba/Offset/Length/WorkingBuffer/Buffer = %016lx/%08x/%08x/%08x/%08x\n",
+ Write ? 'W': 'R', Lba, Offset, Length, WorkingBuffer, Buffer
+ ));
+
+ return Subtask;
+}
+
+/**
+ Create the subtask list.
+
+ @param Instance Pointer to the DISK_IO_PRIVATE_DATA.
+ @param Write TRUE: Write request; FALSE: Read request.
+ @param Offset The starting byte offset to read from the device.
+ @param BufferSize The size in bytes of Buffer. The number of bytes to read from the device.
+ @param Buffer A pointer to the buffer for the data.
+ @param Blocking TRUE: Blocking request; FALSE: Non-blocking request.
+ @param SharedWorkingBuffer The aligned buffer to hold the data for reading or writing.
+ @param Subtasks The subtask list header.
+
+ @retval TRUE The subtask list is created successfully.
+ @retval FALSE The subtask list is not created.
**/
-EFI_STATUS
-EFIAPI
-DiskIoReadDisk (
- IN EFI_DISK_IO_PROTOCOL *This,
- IN UINT32 MediaId,
+BOOLEAN
+DiskIoCreateSubtaskList (
+ IN DISK_IO_PRIVATE_DATA *Instance,
+ IN BOOLEAN Write,
IN UINT64 Offset,
IN UINTN BufferSize,
- OUT VOID *Buffer
+ IN VOID *Buffer,
+ IN BOOLEAN Blocking,
+ IN VOID *SharedWorkingBuffer,
+ IN OUT LIST_ENTRY *Subtasks
)
{
- EFI_STATUS Status;
- DISK_IO_PRIVATE_DATA *Private;
- EFI_BLOCK_IO_PROTOCOL *BlockIo;
- EFI_BLOCK_IO_MEDIA *Media;
UINT32 BlockSize;
+ UINT32 IoAlign;
UINT64 Lba;
UINT64 OverRunLba;
UINT32 UnderRun;
UINT32 OverRun;
- BOOLEAN TransactionComplete;
- UINTN WorkingBufferSize;
- UINT8 *WorkingBuffer;
+ UINT8 *BufferPtr;
UINTN Length;
- UINT8 *Data;
- UINT8 *PreData;
- UINTN IsBufferAligned;
UINTN DataBufferSize;
- BOOLEAN LastRead;
+ DISK_IO_SUBTASK *Subtask;
+ VOID *WorkingBuffer;
+ LIST_ENTRY *Link;
- Private = DISK_IO_PRIVATE_DATA_FROM_THIS (This);
+ DEBUG ((EFI_D_BLKIO, "DiskIo: Create subtasks for task: Offset/BufferSize/Buffer = %016lx/%08x/%08x\n", Offset, BufferSize, Buffer));
- BlockIo = Private->BlockIo;
- Media = BlockIo->Media;
- BlockSize = Media->BlockSize;
-
- if (Media->MediaId != MediaId) {
- return EFI_MEDIA_CHANGED;
+ BlockSize = Instance->BlockIo->Media->BlockSize;
+ IoAlign = Instance->BlockIo->Media->IoAlign;
+ if (IoAlign == 0) {
+ IoAlign = 1;
}
-
- WorkingBuffer = Buffer;
- WorkingBufferSize = BufferSize;
+
+ Lba = DivU64x32Remainder (Offset, BlockSize, &UnderRun);
+ BufferPtr = (UINT8 *) Buffer;
//
- // Allocate a temporary buffer for operation
+ // Special handling for zero BufferSize
//
- DataBufferSize = BlockSize * DATA_BUFFER_BLOCK_NUM;
-
- if (Media->IoAlign > 1) {
- PreData = AllocatePool (DataBufferSize + Media->IoAlign);
- Data = PreData - ((UINTN) PreData & (Media->IoAlign - 1)) + Media->IoAlign;
- } else {
- PreData = AllocatePool (DataBufferSize);
- Data = PreData;
- }
-
- if (PreData == NULL) {
- return EFI_OUT_OF_RESOURCES;
+ if (BufferSize == 0) {
+ Subtask = DiskIoCreateSubtask (Write, Lba, UnderRun, 0, NULL, BufferPtr, Blocking);
+ if (Subtask == NULL) {
+ goto Done;
+ }
+ InsertTailList (Subtasks, &Subtask->Link);
+ return TRUE;
}
- Lba = DivU64x32Remainder (Offset, BlockSize, &UnderRun);
-
- Length = BlockSize - UnderRun;
- TransactionComplete = FALSE;
-
- Status = EFI_SUCCESS;
if (UnderRun != 0) {
- //
- // Offset starts in the middle of an Lba, so read the entire block.
- //
- Status = BlockIo->ReadBlocks (
- BlockIo,
- MediaId,
- Lba,
- BlockSize,
- Data
- );
-
- if (EFI_ERROR (Status)) {
- goto Done;
+ Length = MIN (BlockSize - UnderRun, BufferSize);
+ if (Blocking) {
+ WorkingBuffer = SharedWorkingBuffer;
+ } else {
+ WorkingBuffer = AllocateAlignedPages (EFI_SIZE_TO_PAGES (BlockSize), IoAlign);
+ if (WorkingBuffer == NULL) {
+ goto Done;
+ }
+ }
+ if (Write) {
+ //
+ // A half write operation can be splitted to a blocking block-read and half write operation
+ // This can simplify the sub task processing logic
+ //
+ Subtask = DiskIoCreateSubtask (FALSE, Lba, 0, BlockSize, NULL, WorkingBuffer, TRUE);
+ if (Subtask == NULL) {
+ goto Done;
+ }
+ InsertTailList (Subtasks, &Subtask->Link);
}
- if (Length > BufferSize) {
- Length = BufferSize;
- TransactionComplete = TRUE;
+ Subtask = DiskIoCreateSubtask (Write, Lba, UnderRun, Length, WorkingBuffer, BufferPtr, Blocking);
+ if (Subtask == NULL) {
+ goto Done;
}
+ InsertTailList (Subtasks, &Subtask->Link);
+
+ BufferPtr += Length;
+ Offset += Length;
+ BufferSize -= Length;
+ Lba ++;
+ }
- CopyMem (WorkingBuffer, Data + UnderRun, Length);
+ OverRunLba = Lba + DivU64x32Remainder (BufferSize, BlockSize, &OverRun);
+ BufferSize -= OverRun;
- WorkingBuffer += Length;
+ if (OverRun != 0) {
+ if (Blocking) {
+ WorkingBuffer = SharedWorkingBuffer;
+ } else {
+ WorkingBuffer = AllocateAlignedPages (EFI_SIZE_TO_PAGES (BlockSize), IoAlign);
+ if (WorkingBuffer == NULL) {
+ goto Done;
+ }
+ }
+ if (Write) {
+ //
+ // A half write operation can be splitted to a blocking block-read and half write operation
+ // This can simplify the sub task processing logic
+ //
+ Subtask = DiskIoCreateSubtask (FALSE, OverRunLba, 0, BlockSize, NULL, WorkingBuffer, TRUE);
+ if (Subtask == NULL) {
+ goto Done;
+ }
+ InsertTailList (Subtasks, &Subtask->Link);
+ }
- WorkingBufferSize -= Length;
- if (WorkingBufferSize == 0) {
+ Subtask = DiskIoCreateSubtask (Write, OverRunLba, 0, OverRun, WorkingBuffer, BufferPtr + BufferSize, Blocking);
+ if (Subtask == NULL) {
goto Done;
}
-
- Lba += 1;
+ InsertTailList (Subtasks, &Subtask->Link);
}
-
- OverRunLba = Lba + DivU64x32Remainder (WorkingBufferSize, BlockSize, &OverRun);
-
- if (!TransactionComplete && WorkingBufferSize >= BlockSize) {
+
+ if (OverRunLba > Lba) {
//
// If the DiskIo maps directly to a BlockIo device do the read.
//
- if (OverRun != 0) {
- WorkingBufferSize -= OverRun;
- }
- //
- // Check buffer alignment
- //
- IsBufferAligned = (UINTN) WorkingBuffer & (UINTN) (Media->IoAlign - 1);
-
- if (Media->IoAlign <= 1 || IsBufferAligned == 0) {
- //
- // Alignment is satisfied, so read them together
- //
- Status = BlockIo->ReadBlocks (
- BlockIo,
- MediaId,
- Lba,
- WorkingBufferSize,
- WorkingBuffer
- );
-
- if (EFI_ERROR (Status)) {
+ if (ALIGN_POINTER (BufferPtr, IoAlign) == BufferPtr) {
+ Subtask = DiskIoCreateSubtask (Write, Lba, 0, BufferSize, NULL, BufferPtr, Blocking);
+ if (Subtask == NULL) {
goto Done;
}
+ InsertTailList (Subtasks, &Subtask->Link);
- WorkingBuffer += WorkingBufferSize;
+ BufferPtr += BufferSize;
+ Offset += BufferSize;
+ BufferSize -= BufferSize;
} else {
- //
- // Use the allocated buffer instead of the original buffer
- // to avoid alignment issue.
- // Here, the allocated buffer (8-byte align) can satisfy the alignment
- //
- LastRead = FALSE;
- do {
- if (WorkingBufferSize <= DataBufferSize) {
+ if (Blocking) {
+ //
+ // Use the allocated buffer instead of the original buffer
+ // to avoid alignment issue.
+ //
+ for (; Lba < OverRunLba; Lba += DATA_BUFFER_BLOCK_NUM) {
+ DataBufferSize = MIN (BufferSize, DATA_BUFFER_BLOCK_NUM * BlockSize);
+
+ Subtask = DiskIoCreateSubtask (Write, Lba, 0, DataBufferSize, SharedWorkingBuffer, BufferPtr, Blocking);
+ if (Subtask == NULL) {
+ goto Done;
+ }
+ InsertTailList (Subtasks, &Subtask->Link);
+
+ BufferPtr += DataBufferSize;
+ Offset += DataBufferSize;
+ BufferSize -= DataBufferSize;
+ }
+ } else {
+ WorkingBuffer = AllocateAlignedPages (EFI_SIZE_TO_PAGES (BufferSize), IoAlign);
+ if (WorkingBuffer == NULL) {
//
- // It is the last calling to readblocks in this loop
+ // If there is not enough memory, downgrade to blocking access
//
- DataBufferSize = WorkingBufferSize;
- LastRead = TRUE;
- }
-
- Status = BlockIo->ReadBlocks (
- BlockIo,
- MediaId,
- Lba,
- DataBufferSize,
- Data
- );
- if (EFI_ERROR (Status)) {
- goto Done;
+ DEBUG ((EFI_D_VERBOSE, "DiskIo: No enough memory so downgrade to blocking access\n"));
+ if (!DiskIoCreateSubtaskList (Instance, Write, Offset, BufferSize, BufferPtr, TRUE, SharedWorkingBuffer, Subtasks)) {
+ goto Done;
+ }
+ } else {
+ Subtask = DiskIoCreateSubtask (Write, Lba, 0, BufferSize, WorkingBuffer, BufferPtr, Blocking);
+ if (Subtask == NULL) {
+ goto Done;
+ }
+ InsertTailList (Subtasks, &Subtask->Link);
}
- CopyMem (WorkingBuffer, Data, DataBufferSize);
- WorkingBufferSize -= DataBufferSize;
- WorkingBuffer += DataBufferSize;
- Lba += DATA_BUFFER_BLOCK_NUM;
- } while (!LastRead);
+ BufferPtr += BufferSize;
+ Offset += BufferSize;
+ BufferSize -= BufferSize;
+ }
}
}
- if (!TransactionComplete && OverRun != 0) {
- //
- // Last read is not a complete block.
- //
- Status = BlockIo->ReadBlocks (
- BlockIo,
- MediaId,
- OverRunLba,
- BlockSize,
- Data
- );
-
- if (EFI_ERROR (Status)) {
- goto Done;
- }
+ ASSERT (BufferSize == 0);
- CopyMem (WorkingBuffer, Data, OverRun);
- }
+ return TRUE;
Done:
- if (PreData != NULL) {
- FreePool (PreData);
+ //
+ // Remove all the subtasks.
+ //
+ for (Link = GetFirstNode (Subtasks); !IsNull (Subtasks, Link); ) {
+ Subtask = CR (Link, DISK_IO_SUBTASK, Link, DISK_IO_SUBTASK_SIGNATURE);
+ Link = DiskIoDestroySubtask (Instance, Subtask);
}
-
- return Status;
+ return FALSE;
}
-
/**
- Writes BufferSize bytes from Buffer into Offset.
- Writes may require a read modify write to support writes that are not
- aligned on sector boundaries. There are three cases:
- UnderRun - The first byte is not on a sector boundary or the write request
- is less than a sector in length. Read modify write is required.
- Aligned - A write of N contiguous sectors.
- OverRun - The last byte is not on a sector boundary. Read modified write
- required.
+ Terminate outstanding asynchronous requests to a device.
- @param This Protocol instance pointer.
- @param MediaId Id of the media, changes every time the media is replaced.
- @param Offset The starting byte offset to read from
- @param BufferSize Size of Buffer
- @param Buffer Buffer containing read data
-
- @retval EFI_SUCCESS The data was written correctly to the device.
- @retval EFI_WRITE_PROTECTED The device can not be written to.
- @retval EFI_DEVICE_ERROR The device reported an error while performing the write.
- @retval EFI_NO_MEDIA There is no media in the device.
- @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device.
- @retval EFI_INVALID_PARAMETER The write request contains device addresses that are not
- valid for the device.
+ @param This Indicates a pointer to the calling context.
+ @retval EFI_SUCCESS All outstanding requests were successfully terminated.
+ @retval EFI_DEVICE_ERROR The device reported an error while performing the cancel
+ operation.
**/
EFI_STATUS
EFIAPI
-DiskIoWriteDisk (
- IN EFI_DISK_IO_PROTOCOL *This,
- IN UINT32 MediaId,
- IN UINT64 Offset,
- IN UINTN BufferSize,
- IN VOID *Buffer
+DiskIo2Cancel (
+ IN EFI_DISK_IO2_PROTOCOL *This
)
{
- EFI_STATUS Status;
- DISK_IO_PRIVATE_DATA *Private;
- EFI_BLOCK_IO_PROTOCOL *BlockIo;
- EFI_BLOCK_IO_MEDIA *Media;
- UINT32 BlockSize;
- UINT64 Lba;
- UINT64 OverRunLba;
- UINT32 UnderRun;
- UINT32 OverRun;
- BOOLEAN TransactionComplete;
- UINTN WorkingBufferSize;
- UINT8 *WorkingBuffer;
- UINTN Length;
- UINT8 *Data;
- UINT8 *PreData;
- UINTN IsBufferAligned;
- UINTN DataBufferSize;
- BOOLEAN LastWrite;
+ DISK_IO_PRIVATE_DATA *Instance;
+ DISK_IO2_TASK *Task;
+ LIST_ENTRY *Link;
+
+ Instance = DISK_IO_PRIVATE_DATA_FROM_DISK_IO2 (This);
- Private = DISK_IO_PRIVATE_DATA_FROM_THIS (This);
+ EfiAcquireLock (&Instance->TaskQueueLock);
- BlockIo = Private->BlockIo;
- Media = BlockIo->Media;
- BlockSize = Media->BlockSize;
+ for (Link = GetFirstNode (&Instance->TaskQueue)
+ ; !IsNull (&Instance->TaskQueue, Link)
+ ; Link = GetNextNode (&Instance->TaskQueue, Link)
+ ) {
+ Task = CR (Link, DISK_IO2_TASK, Link, DISK_IO2_TASK_SIGNATURE);
- if (Media->ReadOnly) {
- return EFI_WRITE_PROTECTED;
+ if (Task->Token != NULL) {
+ Task->Token->TransactionStatus = EFI_ABORTED;
+ gBS->SignalEvent (Task->Token->Event);
+ //
+ // Set Token to NULL so that the further BlockIo2 responses will be ignored
+ //
+ Task->Token = NULL;
+ }
}
- if (Media->MediaId != MediaId) {
- return EFI_MEDIA_CHANGED;
- }
+ EfiReleaseLock (&Instance->TaskQueueLock);
- DataBufferSize = BlockSize * DATA_BUFFER_BLOCK_NUM;
+ return EFI_SUCCESS;
+}
- if (Media->IoAlign > 1) {
- PreData = AllocatePool (DataBufferSize + Media->IoAlign);
- Data = PreData - ((UINTN) PreData & (Media->IoAlign - 1)) + Media->IoAlign;
- } else {
- PreData = AllocatePool (DataBufferSize);
- Data = PreData;
- }
+/**
+ Common routine to access the disk.
+
+ @param Instance Pointer to the DISK_IO_PRIVATE_DATA.
+ @param Write TRUE: Write operation; FALSE: Read operation.
+ @param MediaId ID of the medium to access.
+ @param Offset The starting byte offset on the logical block I/O device to access.
+ @param Token A pointer to the token associated with the transaction.
+ If this field is NULL, synchronous/blocking IO is performed.
+ @param BufferSize The size in bytes of Buffer. The number of bytes to read from the device.
+ @param Buffer A pointer to the destination buffer for the data.
+ The caller is responsible either having implicit or explicit ownership of the buffer.
+**/
+EFI_STATUS
+DiskIo2ReadWriteDisk (
+ IN DISK_IO_PRIVATE_DATA *Instance,
+ IN BOOLEAN Write,
+ IN UINT32 MediaId,
+ IN UINT64 Offset,
+ IN EFI_DISK_IO2_TOKEN *Token,
+ IN UINTN BufferSize,
+ IN UINT8 *Buffer
+ )
+{
+ EFI_STATUS Status;
+ EFI_BLOCK_IO_PROTOCOL *BlockIo;
+ EFI_BLOCK_IO2_PROTOCOL *BlockIo2;
+ EFI_BLOCK_IO_MEDIA *Media;
+ LIST_ENTRY *Link;
+ LIST_ENTRY Subtasks;
+ DISK_IO_SUBTASK *Subtask;
+ DISK_IO2_TASK *Task;
+ BOOLEAN TaskQueueEmpty;
+ EFI_TPL OldTpl;
+ BOOLEAN Blocking;
+ LIST_ENTRY *SubtasksPtr;
+
+ Task = NULL;
+ BlockIo = Instance->BlockIo;
+ BlockIo2 = Instance->BlockIo2;
+ Media = BlockIo->Media;
+ Status = EFI_SUCCESS;
+ Blocking = (BOOLEAN) ((Token == NULL) || (Token->Event == NULL));
- if (PreData == NULL) {
- return EFI_OUT_OF_RESOURCES;
+ if (Media->MediaId != MediaId) {
+ return EFI_MEDIA_CHANGED;
}
-
- WorkingBuffer = Buffer;
- WorkingBufferSize = BufferSize;
-
- Lba = DivU64x32Remainder (Offset, BlockSize, &UnderRun);
-
- Length = BlockSize - UnderRun;
- TransactionComplete = FALSE;
-
- Status = EFI_SUCCESS;
- if (UnderRun != 0) {
+
+ if (Write && Media->ReadOnly) {
+ return EFI_WRITE_PROTECTED;
+ }
+
+ if (Blocking) {
//
- // Offset starts in the middle of an Lba, so do read modify write.
+ // Wait till pending async task is completed.
//
- Status = BlockIo->ReadBlocks (
- BlockIo,
- MediaId,
- Lba,
- BlockSize,
- Data
- );
+ do {
+ EfiAcquireLock (&Instance->TaskQueueLock);
+ TaskQueueEmpty = IsListEmpty (&Instance->TaskQueue);
+ EfiReleaseLock (&Instance->TaskQueueLock);
+ } while (!TaskQueueEmpty);
- if (EFI_ERROR (Status)) {
- goto Done;
+ SubtasksPtr = &Subtasks;
+ } else {
+ Task = AllocatePool (sizeof (DISK_IO2_TASK));
+ if (Task == NULL) {
+ return EFI_OUT_OF_RESOURCES;
}
+
+ EfiAcquireLock (&Instance->TaskQueueLock);
+ InsertTailList (&Instance->TaskQueue, &Task->Link);
+ EfiReleaseLock (&Instance->TaskQueueLock);
- if (Length > BufferSize) {
- Length = BufferSize;
- TransactionComplete = TRUE;
- }
+ Task->Signature = DISK_IO2_TASK_SIGNATURE;
+ Task->Instance = Instance;
+ Task->Token = Token;
- CopyMem (Data + UnderRun, WorkingBuffer, Length);
+ SubtasksPtr = &Task->Subtasks;
+ }
- Status = BlockIo->WriteBlocks (
- BlockIo,
- MediaId,
- Lba,
- BlockSize,
- Data
- );
- if (EFI_ERROR (Status)) {
- goto Done;
+ InitializeListHead (SubtasksPtr);
+ if (!DiskIoCreateSubtaskList (Instance, Write, Offset, BufferSize, Buffer, Blocking, Instance->SharedWorkingBuffer, SubtasksPtr)) {
+ if (Task != NULL) {
+ FreePool (Task);
}
-
- WorkingBuffer += Length;
- WorkingBufferSize -= Length;
- if (WorkingBufferSize == 0) {
- goto Done;
- }
-
- Lba += 1;
+ return EFI_OUT_OF_RESOURCES;
}
+ ASSERT (!IsListEmpty (SubtasksPtr));
- OverRunLba = Lba + DivU64x32Remainder (WorkingBufferSize, BlockSize, &OverRun);
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
+ for (Link = GetFirstNode (SubtasksPtr); !IsNull (SubtasksPtr, Link); Link = GetNextNode (SubtasksPtr, Link)) {
+ Subtask = CR (Link, DISK_IO_SUBTASK, Link, DISK_IO_SUBTASK_SIGNATURE);
- if (!TransactionComplete && WorkingBufferSize >= BlockSize) {
- //
- // If the DiskIo maps directly to a BlockIo device do the write.
- //
- if (OverRun != 0) {
- WorkingBufferSize -= OverRun;
+ if (!Subtask->Blocking) {
+ Subtask->Task = Task;
}
- //
- // Check buffer alignment
- //
- IsBufferAligned = (UINTN) WorkingBuffer & (UINTN) (Media->IoAlign - 1);
- if (Media->IoAlign <= 1 || IsBufferAligned == 0) {
+ if (Subtask->Write) {
//
- // Alignment is satisfied, so write them together
+ // Write
//
- Status = BlockIo->WriteBlocks (
- BlockIo,
- MediaId,
- Lba,
- WorkingBufferSize,
- WorkingBuffer
- );
-
- if (EFI_ERROR (Status)) {
- goto Done;
+ if (Subtask->WorkingBuffer != NULL) {
+ //
+ // A sub task before this one should be a block read operation, causing the WorkingBuffer filled with the entire one block data.
+ //
+ CopyMem (Subtask->WorkingBuffer + Subtask->Offset, Subtask->Buffer, Subtask->Length);
}
- WorkingBuffer += WorkingBufferSize;
+ if (Subtask->Blocking) {
+ Status = BlockIo->WriteBlocks (
+ BlockIo,
+ MediaId,
+ Subtask->Lba,
+ Subtask->Length < Media->BlockSize ? Media->BlockSize : Subtask->Length,
+ (Subtask->WorkingBuffer != NULL) ? Subtask->WorkingBuffer : Subtask->Buffer
+ );
+ } else {
+ Status = BlockIo2->WriteBlocksEx (
+ BlockIo2,
+ MediaId,
+ Subtask->Lba,
+ &Subtask->BlockIo2Token,
+ Subtask->Length < Media->BlockSize ? Media->BlockSize : Subtask->Length,
+ (Subtask->WorkingBuffer != NULL) ? Subtask->WorkingBuffer : Subtask->Buffer
+ );
+ }
} else {
//
- // The buffer parameter is not aligned with the request
- // So use the allocated instead.
- // It can fit almost all the cases.
+ // Read
//
- LastWrite = FALSE;
- do {
- if (WorkingBufferSize <= DataBufferSize) {
- //
- // It is the last calling to writeblocks in this loop
- //
- DataBufferSize = WorkingBufferSize;
- LastWrite = TRUE;
- }
-
- CopyMem (Data, WorkingBuffer, DataBufferSize);
- Status = BlockIo->WriteBlocks (
+ if (Subtask->Blocking) {
+ Status = BlockIo->ReadBlocks (
BlockIo,
MediaId,
- Lba,
- DataBufferSize,
- Data
+ Subtask->Lba,
+ Subtask->Length < Media->BlockSize ? Media->BlockSize : Subtask->Length,
+ (Subtask->WorkingBuffer != NULL) ? Subtask->WorkingBuffer : Subtask->Buffer
);
- if (EFI_ERROR (Status)) {
- goto Done;
+ if (!EFI_ERROR (Status) && (Subtask->WorkingBuffer != NULL)) {
+ CopyMem (Subtask->Buffer, Subtask->WorkingBuffer + Subtask->Offset, Subtask->Length);
}
-
- WorkingBufferSize -= DataBufferSize;
- WorkingBuffer += DataBufferSize;
- Lba += DATA_BUFFER_BLOCK_NUM;
- } while (!LastWrite);
+ } else {
+ Status = BlockIo2->ReadBlocksEx (
+ BlockIo2,
+ MediaId,
+ Subtask->Lba,
+ &Subtask->BlockIo2Token,
+ Subtask->Length < Media->BlockSize ? Media->BlockSize : Subtask->Length,
+ (Subtask->WorkingBuffer != NULL) ? Subtask->WorkingBuffer : Subtask->Buffer
+ );
+ }
+ }
+
+ if (EFI_ERROR (Status)) {
+ break;
}
}
+
+ gBS->RaiseTPL (TPL_NOTIFY);
- if (!TransactionComplete && OverRun != 0) {
- //
- // Last bit is not a complete block, so do a read modify write.
- //
- Status = BlockIo->ReadBlocks (
- BlockIo,
- MediaId,
- OverRunLba,
- BlockSize,
- Data
- );
+ //
+ // Remove all the remaining subtasks when failure.
+ // We shouldn't remove all the tasks because the non-blocking requests have been submitted and cannot be canceled.
+ //
+ if (EFI_ERROR (Status)) {
+ while (!IsNull (SubtasksPtr, Link)) {
+ Subtask = CR (Link, DISK_IO_SUBTASK, Link, DISK_IO_SUBTASK_SIGNATURE);
+ Link = DiskIoDestroySubtask (Instance, Subtask);
+ }
+ }
- if (EFI_ERROR (Status)) {
- goto Done;
+ //
+ // Remove all the blocking subtasks because the non-blocking callback only removes the non-blocking subtask.
+ //
+ for (Link = GetFirstNode (SubtasksPtr); !IsNull (SubtasksPtr, Link); ) {
+ Subtask = CR (Link, DISK_IO_SUBTASK, Link, DISK_IO_SUBTASK_SIGNATURE);
+ if (Subtask->Blocking) {
+ Link = DiskIoDestroySubtask (Instance, Subtask);
+ } else {
+ Link = GetNextNode (SubtasksPtr, Link);
}
+ }
- CopyMem (Data, WorkingBuffer, OverRun);
+ //
+ // It's possible that the callback runs before raising TPL to NOTIFY,
+ // so the subtasks list only contains blocking subtask.
+ // Remove the Task after the blocking subtasks are removed in above.
+ //
+ if (!Blocking && IsListEmpty (SubtasksPtr)) {
+ EfiAcquireLock (&Instance->TaskQueueLock);
+ RemoveEntryList (&Task->Link);
+ EfiReleaseLock (&Instance->TaskQueueLock);
- Status = BlockIo->WriteBlocks (
- BlockIo,
- MediaId,
- OverRunLba,
- BlockSize,
- Data
- );
- if (EFI_ERROR (Status)) {
- goto Done;
+ if (Task->Token != NULL) {
+ //
+ // Task->Token should be set to NULL by the DiskIo2OnReadWriteComplete
+ // It it's not, that means the non-blocking request was downgraded to blocking request.
+ //
+ DEBUG ((EFI_D_VERBOSE, "DiskIo: Non-blocking request was downgraded to blocking request, signal event directly.\n"));
+ Task->Token->TransactionStatus = Status;
+ gBS->SignalEvent (Task->Token->Event);
}
+
+ FreePool (Task);
}
-Done:
- if (PreData != NULL) {
- FreePool (PreData);
+ gBS->RestoreTPL (OldTpl);
+
+ return Status;
+}
+
+/**
+ Reads a specified number of bytes from a device.
+
+ @param This Indicates a pointer to the calling context.
+ @param MediaId ID of the medium to be read.
+ @param Offset The starting byte offset on the logical block I/O device to read from.
+ @param Token A pointer to the token associated with the transaction.
+ If this field is NULL, synchronous/blocking IO is performed.
+ @param BufferSize The size in bytes of Buffer. The number of bytes to read from the device.
+ @param Buffer A pointer to the destination buffer for the data.
+ The caller is responsible either having implicit or explicit ownership of the buffer.
+
+ @retval EFI_SUCCESS If Event is NULL (blocking I/O): The data was read correctly from the device.
+ If Event is not NULL (asynchronous I/O): The request was successfully queued for processing.
+ Event will be signaled upon completion.
+ @retval EFI_DEVICE_ERROR The device reported an error while performing the write.
+ @retval EFI_NO_MEDIA There is no medium in the device.
+ @retval EFI_MEDIA_CHNAGED The MediaId is not for the current medium.
+ @retval EFI_INVALID_PARAMETER The read request contains device addresses that are not valid for the device.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+
+**/
+EFI_STATUS
+EFIAPI
+DiskIo2ReadDiskEx (
+ IN EFI_DISK_IO2_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN UINT64 Offset,
+ IN OUT EFI_DISK_IO2_TOKEN *Token,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ )
+{
+ return DiskIo2ReadWriteDisk (
+ DISK_IO_PRIVATE_DATA_FROM_DISK_IO2 (This),
+ FALSE, MediaId, Offset, Token, BufferSize, (UINT8 *) Buffer
+ );
+}
+
+/**
+ Writes a specified number of bytes to a device.
+
+ @param This Indicates a pointer to the calling context.
+ @param MediaId ID of the medium to be written.
+ @param Offset The starting byte offset on the logical block I/O device to write to.
+ @param Token A pointer to the token associated with the transaction.
+ If this field is NULL, synchronous/blocking IO is performed.
+ @param BufferSize The size in bytes of Buffer. The number of bytes to write to the device.
+ @param Buffer A pointer to the buffer containing the data to be written.
+
+ @retval EFI_SUCCESS If Event is NULL (blocking I/O): The data was written correctly to the device.
+ If Event is not NULL (asynchronous I/O): The request was successfully queued for processing.
+ Event will be signaled upon completion.
+ @retval EFI_WRITE_PROTECTED The device cannot be written to.
+ @retval EFI_DEVICE_ERROR The device reported an error while performing the write operation.
+ @retval EFI_NO_MEDIA There is no medium in the device.
+ @retval EFI_MEDIA_CHNAGED The MediaId is not for the current medium.
+ @retval EFI_INVALID_PARAMETER The write request contains device addresses that are not valid for the device.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+
+**/
+EFI_STATUS
+EFIAPI
+DiskIo2WriteDiskEx (
+ IN EFI_DISK_IO2_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN UINT64 Offset,
+ IN OUT EFI_DISK_IO2_TOKEN *Token,
+ IN UINTN BufferSize,
+ IN VOID *Buffer
+ )
+{
+ return DiskIo2ReadWriteDisk (
+ DISK_IO_PRIVATE_DATA_FROM_DISK_IO2 (This),
+ TRUE, MediaId, Offset, Token, BufferSize, (UINT8 *) Buffer
+ );
+}
+
+/**
+ The callback for the BlockIo2 FlushBlocksEx.
+ @param Event Event whose notification function is being invoked.
+ @param Context The pointer to the notification function's context,
+ which points to the DISK_IO2_FLUSH_TASK instance.
+**/
+VOID
+EFIAPI
+DiskIo2OnFlushComplete (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ DISK_IO2_FLUSH_TASK *Task;
+
+ gBS->CloseEvent (Event);
+
+ Task = (DISK_IO2_FLUSH_TASK *) Context;
+ ASSERT (Task->Signature == DISK_IO2_FLUSH_TASK_SIGNATURE);
+ Task->Token->TransactionStatus = Task->BlockIo2Token.TransactionStatus;
+ gBS->SignalEvent (Task->Token->Event);
+}
+
+/**
+ Flushes all modified data to the physical device.
+
+ @param This Indicates a pointer to the calling context.
+ @param Token A pointer to the token associated with the transaction.
+ If this field is NULL, synchronous/blocking IO is performed.
+
+ @retval EFI_SUCCESS If Event is NULL (blocking I/O): The data was flushed successfully to the device.
+ If Event is not NULL (asynchronous I/O): The request was successfully queued for processing.
+ Event will be signaled upon completion.
+ @retval EFI_WRITE_PROTECTED The device cannot be written to.
+ @retval EFI_DEVICE_ERROR The device reported an error while performing the write operation.
+ @retval EFI_NO_MEDIA There is no medium in the device.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+**/
+EFI_STATUS
+EFIAPI
+DiskIo2FlushDiskEx (
+ IN EFI_DISK_IO2_PROTOCOL *This,
+ IN OUT EFI_DISK_IO2_TOKEN *Token
+ )
+{
+ EFI_STATUS Status;
+ DISK_IO2_FLUSH_TASK *Task;
+ DISK_IO_PRIVATE_DATA *Private;
+
+ Private = DISK_IO_PRIVATE_DATA_FROM_DISK_IO2 (This);
+
+ if ((Token != NULL) && (Token->Event != NULL)) {
+ Task = AllocatePool (sizeof (DISK_IO2_FLUSH_TASK));
+ if (Task == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Status = gBS->CreateEvent (
+ EVT_NOTIFY_SIGNAL,
+ TPL_CALLBACK,
+ DiskIo2OnFlushComplete,
+ Task,
+ &Task->BlockIo2Token.Event
+ );
+ if (EFI_ERROR (Status)) {
+ FreePool (Task);
+ return Status;
+ }
+ Task->Signature = DISK_IO2_FLUSH_TASK_SIGNATURE;
+ Status = Private->BlockIo2->FlushBlocksEx (Private->BlockIo2, &Task->BlockIo2Token);
+ if (EFI_ERROR (Status)) {
+ gBS->CloseEvent (Task->BlockIo2Token.Event);
+ FreePool (Task);
+ }
+ } else {
+ Status = Private->BlockIo2->FlushBlocksEx (Private->BlockIo2, NULL);
}
return Status;
}
+/**
+ Read BufferSize bytes from Offset into Buffer.
+ Reads may support reads that are not aligned on
+ sector boundaries. There are three cases:
+ UnderRun - The first byte is not on a sector boundary or the read request is
+ less than a sector in length.
+ Aligned - A read of N contiguous sectors.
+ OverRun - The last byte is not on a sector boundary.
+
+ @param This Protocol instance pointer.
+ @param MediaId Id of the media, changes every time the media is replaced.
+ @param Offset The starting byte offset to read from
+ @param BufferSize Size of Buffer
+ @param Buffer Buffer containing read data
+
+ @retval EFI_SUCCESS The data was read correctly from the device.
+ @retval EFI_DEVICE_ERROR The device reported an error while performing the read.
+ @retval EFI_NO_MEDIA There is no media in the device.
+ @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device.
+ @retval EFI_INVALID_PARAMETER The read request contains device addresses that are not
+ valid for the device.
+
+**/
+EFI_STATUS
+EFIAPI
+DiskIoReadDisk (
+ IN EFI_DISK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN UINT64 Offset,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ )
+{
+ return DiskIo2ReadWriteDisk (
+ DISK_IO_PRIVATE_DATA_FROM_DISK_IO (This),
+ FALSE, MediaId, Offset, NULL, BufferSize, (UINT8 *) Buffer
+ );
+}
+
+
+/**
+ Writes BufferSize bytes from Buffer into Offset.
+ Writes may require a read modify write to support writes that are not
+ aligned on sector boundaries. There are three cases:
+ UnderRun - The first byte is not on a sector boundary or the write request
+ is less than a sector in length. Read modify write is required.
+ Aligned - A write of N contiguous sectors.
+ OverRun - The last byte is not on a sector boundary. Read modified write
+ required.
+
+ @param This Protocol instance pointer.
+ @param MediaId Id of the media, changes every time the media is replaced.
+ @param Offset The starting byte offset to read from
+ @param BufferSize Size of Buffer
+ @param Buffer Buffer containing read data
+
+ @retval EFI_SUCCESS The data was written correctly to the device.
+ @retval EFI_WRITE_PROTECTED The device can not be written to.
+ @retval EFI_DEVICE_ERROR The device reported an error while performing the write.
+ @retval EFI_NO_MEDIA There is no media in the device.
+ @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device.
+ @retval EFI_INVALID_PARAMETER The write request contains device addresses that are not
+ valid for the device.
+
+**/
+EFI_STATUS
+EFIAPI
+DiskIoWriteDisk (
+ IN EFI_DISK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN UINT64 Offset,
+ IN UINTN BufferSize,
+ IN VOID *Buffer
+ )
+{
+ return DiskIo2ReadWriteDisk (
+ DISK_IO_PRIVATE_DATA_FROM_DISK_IO (This),
+ TRUE, MediaId, Offset, NULL, BufferSize, (UINT8 *) Buffer
+ );
+}
/**
The user Entry Point for module DiskIo. The user code starts with this function.
@@ -740,7 +1251,5 @@ InitializeDiskIo (
);
ASSERT_EFI_ERROR (Status);
-
return Status;
}
-
diff --git a/MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIo.h b/MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIo.h
index 77f6dbf89..a08d4df79 100644
--- a/MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIo.h
+++ b/MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIo.h
@@ -1,7 +1,7 @@
/** @file
Master header file for DiskIo driver. It includes the module private defininitions.
-Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
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
@@ -17,6 +17,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include <Uefi.h>
#include <Protocol/BlockIo.h>
+#include <Protocol/BlockIo2.h>
+#include <Protocol/DiskIo2.h>
#include <Protocol/ComponentName.h>
#include <Protocol/DriverBinding.h>
#include <Protocol/DiskIo.h>
@@ -28,18 +30,69 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include <Library/MemoryAllocationLib.h>
#include <Library/UefiBootServicesTableLib.h>
-
+//
+// Pre-allocate an aligned buffer of 64 blocks so very large Disk I/O requests
+// will be broken up into 64 * BlockSize chunks to provide better performance
+// than allocating an aligned 1 block buffer.
+//
#define DATA_BUFFER_BLOCK_NUM 64
#define DISK_IO_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('d', 's', 'k', 'I')
-
typedef struct {
- UINTN Signature;
- EFI_DISK_IO_PROTOCOL DiskIo;
- EFI_BLOCK_IO_PROTOCOL *BlockIo;
+ UINT32 Signature;
+
+ EFI_DISK_IO_PROTOCOL DiskIo;
+ EFI_DISK_IO2_PROTOCOL DiskIo2;
+ EFI_BLOCK_IO_PROTOCOL *BlockIo;
+ EFI_BLOCK_IO2_PROTOCOL *BlockIo2;
+
+ UINT8 *SharedWorkingBuffer;
+
+ EFI_LOCK TaskQueueLock;
+ LIST_ENTRY TaskQueue;
} DISK_IO_PRIVATE_DATA;
+#define DISK_IO_PRIVATE_DATA_FROM_DISK_IO(a) CR (a, DISK_IO_PRIVATE_DATA, DiskIo, DISK_IO_PRIVATE_DATA_SIGNATURE)
+#define DISK_IO_PRIVATE_DATA_FROM_DISK_IO2(a) CR (a, DISK_IO_PRIVATE_DATA, DiskIo2, DISK_IO_PRIVATE_DATA_SIGNATURE)
-#define DISK_IO_PRIVATE_DATA_FROM_THIS(a) CR (a, DISK_IO_PRIVATE_DATA, DiskIo, DISK_IO_PRIVATE_DATA_SIGNATURE)
+#define DISK_IO2_TASK_SIGNATURE SIGNATURE_32 ('d', 'i', 'a', 't')
+typedef struct {
+ UINT32 Signature;
+ LIST_ENTRY Link; /// < link to other task
+ LIST_ENTRY Subtasks; /// < header of subtasks
+ EFI_DISK_IO2_TOKEN *Token;
+ DISK_IO_PRIVATE_DATA *Instance;
+} DISK_IO2_TASK;
+
+#define DISK_IO2_FLUSH_TASK_SIGNATURE SIGNATURE_32 ('d', 'i', 'f', 't')
+typedef struct {
+ UINT32 Signature;
+ EFI_BLOCK_IO2_TOKEN BlockIo2Token;
+ EFI_DISK_IO2_TOKEN *Token;
+} DISK_IO2_FLUSH_TASK;
+
+#define DISK_IO_SUBTASK_SIGNATURE SIGNATURE_32 ('d', 'i', 's', 't')
+typedef struct {
+ //
+ // UnderRun: Offset != 0, Length < BlockSize
+ // OverRun: Offset == 0, Length < BlockSize
+ // Middle: Offset is block aligned, Length is multiple of block size
+ //
+ UINT32 Signature;
+ LIST_ENTRY Link;
+ BOOLEAN Write;
+ UINT64 Lba;
+ UINT32 Offset;
+ UINTN Length;
+ UINT8 *WorkingBuffer; /// < NULL indicates using "Buffer" directly
+ UINT8 *Buffer;
+ BOOLEAN Blocking;
+
+ //
+ // Following fields are for DiskIo2
+ //
+ DISK_IO2_TASK *Task;
+ EFI_BLOCK_IO2_TOKEN BlockIo2Token;
+} DISK_IO_SUBTASK;
//
// Global Variables
@@ -189,6 +242,110 @@ DiskIoWriteDisk (
IN VOID *Buffer
);
+
+/**
+ Terminate outstanding asynchronous requests to a device.
+
+ @param This Indicates a pointer to the calling context.
+
+ @retval EFI_SUCCESS All outstanding requests were successfully terminated.
+ @retval EFI_DEVICE_ERROR The device reported an error while performing the cancel
+ operation.
+**/
+EFI_STATUS
+EFIAPI
+DiskIo2Cancel (
+ IN EFI_DISK_IO2_PROTOCOL *This
+ );
+
+/**
+ Reads a specified number of bytes from a device.
+
+ @param This Indicates a pointer to the calling context.
+ @param MediaId ID of the medium to be read.
+ @param Offset The starting byte offset on the logical block I/O device to read from.
+ @param Token A pointer to the token associated with the transaction.
+ If this field is NULL, synchronous/blocking IO is performed.
+ @param BufferSize The size in bytes of Buffer. The number of bytes to read from the device.
+ @param Buffer A pointer to the destination buffer for the data.
+ The caller is responsible either having implicit or explicit ownership of the buffer.
+
+ @retval EFI_SUCCESS If Event is NULL (blocking I/O): The data was read correctly from the device.
+ If Event is not NULL (asynchronous I/O): The request was successfully queued for processing.
+ Event will be signaled upon completion.
+ @retval EFI_DEVICE_ERROR The device reported an error while performing the write.
+ @retval EFI_NO_MEDIA There is no medium in the device.
+ @retval EFI_MEDIA_CHNAGED The MediaId is not for the current medium.
+ @retval EFI_INVALID_PARAMETER The read request contains device addresses that are not valid for the device.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+
+**/
+EFI_STATUS
+EFIAPI
+DiskIo2ReadDiskEx (
+ IN EFI_DISK_IO2_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN UINT64 Offset,
+ IN OUT EFI_DISK_IO2_TOKEN *Token,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ );
+
+/**
+ Writes a specified number of bytes to a device.
+
+ @param This Indicates a pointer to the calling context.
+ @param MediaId ID of the medium to be written.
+ @param Offset The starting byte offset on the logical block I/O device to write to.
+ @param Token A pointer to the token associated with the transaction.
+ If this field is NULL, synchronous/blocking IO is performed.
+ @param BufferSize The size in bytes of Buffer. The number of bytes to write to the device.
+ @param Buffer A pointer to the buffer containing the data to be written.
+
+ @retval EFI_SUCCESS If Event is NULL (blocking I/O): The data was written correctly to the device.
+ If Event is not NULL (asynchronous I/O): The request was successfully queued for processing.
+ Event will be signaled upon completion.
+ @retval EFI_WRITE_PROTECTED The device cannot be written to.
+ @retval EFI_DEVICE_ERROR The device reported an error while performing the write operation.
+ @retval EFI_NO_MEDIA There is no medium in the device.
+ @retval EFI_MEDIA_CHNAGED The MediaId is not for the current medium.
+ @retval EFI_INVALID_PARAMETER The write request contains device addresses that are not valid for the device.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+
+**/
+EFI_STATUS
+EFIAPI
+DiskIo2WriteDiskEx (
+ IN EFI_DISK_IO2_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN UINT64 Offset,
+ IN EFI_DISK_IO2_TOKEN *Token,
+ IN UINTN BufferSize,
+ IN VOID *Buffer
+ );
+
+/**
+ Flushes all modified data to the physical device.
+
+ @param This Indicates a pointer to the calling context.
+ @param Token A pointer to the token associated with the transaction.
+ If this field is NULL, synchronous/blocking IO is performed.
+
+ @retval EFI_SUCCESS If Event is NULL (blocking I/O): The data was flushed successfully to the device.
+ If Event is not NULL (asynchronous I/O): The request was successfully queued for processing.
+ Event will be signaled upon completion.
+ @retval EFI_WRITE_PROTECTED The device cannot be written to.
+ @retval EFI_DEVICE_ERROR The device reported an error while performing the write operation.
+ @retval EFI_NO_MEDIA There is no medium in the device.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+**/
+EFI_STATUS
+EFIAPI
+DiskIo2FlushDiskEx (
+ IN EFI_DISK_IO2_PROTOCOL *This,
+ IN OUT EFI_DISK_IO2_TOKEN *Token
+ );
+
//
// EFI Component Name Functions
//
diff --git a/MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIoDxe.inf b/MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIoDxe.inf
index 1a270e7f9..8cf2595df 100644
--- a/MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIoDxe.inf
+++ b/MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIoDxe.inf
@@ -8,7 +8,7 @@
# already have a Disk I/O protocol. File systems and other disk access
# code utilize the Disk I/O protocol.
#
-# Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
# 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
@@ -59,5 +59,7 @@
[Protocols]
gEfiDiskIoProtocolGuid ## BY_START
+ gEfiDiskIo2ProtocolGuid ## BY_START
gEfiBlockIoProtocolGuid ## TO_START
+ gEfiBlockIo2ProtocolGuid ## TO_START
diff --git a/MdeModulePkg/Universal/Disk/PartitionDxe/ElTorito.c b/MdeModulePkg/Universal/Disk/PartitionDxe/ElTorito.c
index 13b94c307..3d7cf2dc6 100644
--- a/MdeModulePkg/Universal/Disk/PartitionDxe/ElTorito.c
+++ b/MdeModulePkg/Universal/Disk/PartitionDxe/ElTorito.c
@@ -1,7 +1,7 @@
/** @file
Decode an El Torito formatted CD-ROM
-Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
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
@@ -22,6 +22,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
@param[in] This Calling context.
@param[in] Handle Parent Handle.
@param[in] DiskIo Parent DiskIo interface.
+ @param[in] DiskIo2 Parent DiskIo2 interface.
@param[in] BlockIo Parent BlockIo interface.
@param[in] BlockIo2 Parent BlockIo2 interface.
@param[in] DevicePath Parent Device Path
@@ -37,6 +38,7 @@ PartitionInstallElToritoChildHandles (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE Handle,
IN EFI_DISK_IO_PROTOCOL *DiskIo,
+ IN EFI_DISK_IO2_PROTOCOL *DiskIo2,
IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
IN EFI_BLOCK_IO2_PROTOCOL *BlockIo2,
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
@@ -258,6 +260,7 @@ PartitionInstallElToritoChildHandles (
This,
Handle,
DiskIo,
+ DiskIo2,
BlockIo,
BlockIo2,
DevicePath,
diff --git a/MdeModulePkg/Universal/Disk/PartitionDxe/Gpt.c b/MdeModulePkg/Universal/Disk/PartitionDxe/Gpt.c
index a3910041a..35860515c 100644
--- a/MdeModulePkg/Universal/Disk/PartitionDxe/Gpt.c
+++ b/MdeModulePkg/Universal/Disk/PartitionDxe/Gpt.c
@@ -13,7 +13,7 @@
PartitionValidGptTable(), PartitionCheckGptEntry() routine will accept disk
partition content and validate the GPT table and GPT entry.
-Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
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
@@ -184,6 +184,7 @@ PartitionSetCrc (
@param[in] This Calling context.
@param[in] Handle Parent Handle.
@param[in] DiskIo Parent DiskIo interface.
+ @param[in] DiskIo2 Parent DiskIo2 interface.
@param[in] BlockIo Parent BlockIo interface.
@param[in] BlockIo2 Parent BlockIo2 interface.
@param[in] DevicePath Parent Device Path.
@@ -198,6 +199,7 @@ PartitionInstallGptChildHandles (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE Handle,
IN EFI_DISK_IO_PROTOCOL *DiskIo,
+ IN EFI_DISK_IO2_PROTOCOL *DiskIo2,
IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
IN EFI_BLOCK_IO2_PROTOCOL *BlockIo2,
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
@@ -307,7 +309,7 @@ PartitionInstallGptChildHandles (
DEBUG ((EFI_D_INFO, " Valid primary and !Valid backup partition table\n"));
DEBUG ((EFI_D_INFO, " Restore backup partition table by the primary\n"));
if (!PartitionRestoreGptTable (BlockIo, DiskIo, PrimaryHeader)) {
- DEBUG ((EFI_D_INFO, " Restore backup partition table error\n"));
+ DEBUG ((EFI_D_INFO, " Restore backup partition table error\n"));
}
if (PartitionValidGptTable (BlockIo, DiskIo, PrimaryHeader->AlternateLBA, BackupHeader)) {
@@ -400,6 +402,7 @@ PartitionInstallGptChildHandles (
This,
Handle,
DiskIo,
+ DiskIo2,
BlockIo,
BlockIo2,
DevicePath,
@@ -487,13 +490,22 @@ PartitionValidGptTable (
if ((PartHdr->Header.Signature != EFI_PTAB_HEADER_ID) ||
!PartitionCheckCrc (BlockSize, &PartHdr->Header) ||
- PartHdr->MyLBA != Lba
+ PartHdr->MyLBA != Lba ||
+ (PartHdr->SizeOfPartitionEntry < sizeof (EFI_PARTITION_ENTRY))
) {
DEBUG ((EFI_D_INFO, "Invalid efi partition table header\n"));
FreePool (PartHdr);
return FALSE;
}
+ //
+ // Ensure the NumberOfPartitionEntries * SizeOfPartitionEntry doesn't overflow.
+ //
+ if (PartHdr->NumberOfPartitionEntries > DivU64x32 (MAX_UINTN, PartHdr->SizeOfPartitionEntry)) {
+ FreePool (PartHdr);
+ return FALSE;
+ }
+
CopyMem (PartHeader, PartHdr, sizeof (EFI_PARTITION_TABLE_HEADER));
if (!PartitionCheckGptEntryArrayCRC (BlockIo, DiskIo, PartHeader)) {
FreePool (PartHdr);
diff --git a/MdeModulePkg/Universal/Disk/PartitionDxe/Mbr.c b/MdeModulePkg/Universal/Disk/PartitionDxe/Mbr.c
index f8416d16c..5134310d4 100644
--- a/MdeModulePkg/Universal/Disk/PartitionDxe/Mbr.c
+++ b/MdeModulePkg/Universal/Disk/PartitionDxe/Mbr.c
@@ -11,7 +11,7 @@
always on the first sector of a media. The first sector also contains
the legacy boot strap code.
-Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
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
@@ -104,6 +104,7 @@ PartitionValidMbr (
@param[in] This Calling context.
@param[in] Handle Parent Handle.
@param[in] DiskIo Parent DiskIo interface.
+ @param[in] DiskIo2 Parent DiskIo2 interface.
@param[in] BlockIo Parent BlockIo interface.
@param[in] BlockIo2 Parent BlockIo2 interface.
@param[in] DevicePath Parent Device Path.
@@ -118,6 +119,7 @@ PartitionInstallMbrChildHandles (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE Handle,
IN EFI_DISK_IO_PROTOCOL *DiskIo,
+ IN EFI_DISK_IO2_PROTOCOL *DiskIo2,
IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
IN EFI_BLOCK_IO2_PROTOCOL *BlockIo2,
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
@@ -235,6 +237,7 @@ PartitionInstallMbrChildHandles (
This,
Handle,
DiskIo,
+ DiskIo2,
BlockIo,
BlockIo2,
DevicePath,
@@ -296,6 +299,7 @@ PartitionInstallMbrChildHandles (
This,
Handle,
DiskIo,
+ DiskIo2,
BlockIo,
BlockIo2,
DevicePath,
diff --git a/MdeModulePkg/Universal/Disk/PartitionDxe/Partition.c b/MdeModulePkg/Universal/Disk/PartitionDxe/Partition.c
index 318bfe432..5cc1397e7 100644
--- a/MdeModulePkg/Universal/Disk/PartitionDxe/Partition.c
+++ b/MdeModulePkg/Universal/Disk/PartitionDxe/Partition.c
@@ -4,7 +4,7 @@
of the raw block devices media. Currently "El Torito CD-ROM", Legacy
MBR, and GPT partition schemes are supported.
-Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
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
@@ -200,6 +200,7 @@ PartitionDriverBindingStart (
EFI_BLOCK_IO_PROTOCOL *BlockIo;
EFI_BLOCK_IO2_PROTOCOL *BlockIo2;
EFI_DISK_IO_PROTOCOL *DiskIo;
+ EFI_DISK_IO2_PROTOCOL *DiskIo2;
EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
PARTITION_DETECT_ROUTINE *Routine;
BOOLEAN MediaPresent;
@@ -243,8 +244,11 @@ PartitionDriverBindingStart (
(VOID **) &BlockIo2,
This->DriverBindingHandle,
ControllerHandle,
- EFI_OPEN_PROTOCOL_BY_DRIVER
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
+ if (EFI_ERROR (Status)) {
+ BlockIo2 = NULL;
+ }
//
// Get the Device Path Protocol on ControllerHandle's handle.
@@ -261,6 +265,9 @@ PartitionDriverBindingStart (
goto Exit;
}
+ //
+ // Get the DiskIo and DiskIo2.
+ //
Status = gBS->OpenProtocol (
ControllerHandle,
&gEfiDiskIoProtocolGuid,
@@ -281,6 +288,18 @@ PartitionDriverBindingStart (
OpenStatus = Status;
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiDiskIo2ProtocolGuid,
+ (VOID **) &DiskIo2,
+ This->DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
+ DiskIo2 = NULL;
+ }
+
//
// Try to read blocks when there's media or it is removable physical partition.
//
@@ -299,6 +318,7 @@ PartitionDriverBindingStart (
This,
ControllerHandle,
DiskIo,
+ DiskIo2,
BlockIo,
BlockIo2,
ParentDevicePath
@@ -404,7 +424,7 @@ PartitionDriverBindingStop (
//
gBS->CloseProtocol (
ControllerHandle,
- &gEfiBlockIo2ProtocolGuid,
+ &gEfiDiskIo2ProtocolGuid,
This->DriverBindingHandle,
ControllerHandle
);
@@ -699,7 +719,7 @@ PartitionFlushBlocks (
Probe the media status and return EFI_NO_MEDIA or EFI_MEDIA_CHANGED
for no media or media change case. Otherwise DefaultStatus is returned.
- @param BlockIo2 Pointer to the BlockIo2 instance.
+ @param DiskIo2 Pointer to the DiskIo2 instance.
@param MediaId Id of the media, changes every time the media is replaced.
@param DefaultStatus The default status to return when it's not the no media
or media change case.
@@ -710,7 +730,7 @@ PartitionFlushBlocks (
**/
EFI_STATUS
ProbeMediaStatusEx (
- IN EFI_BLOCK_IO2_PROTOCOL *BlockIo2,
+ IN EFI_DISK_IO2_PROTOCOL *DiskIo2,
IN UINT32 MediaId,
IN EFI_STATUS DefaultStatus
)
@@ -718,16 +738,9 @@ ProbeMediaStatusEx (
EFI_STATUS Status;
//
- // Read from LBA 0 but passing NULL as buffer pointer to detect the media status.
+ // Read 1 byte from offset 0 but passing NULL as buffer pointer
//
- Status = BlockIo2->ReadBlocksEx (
- BlockIo2,
- MediaId,
- 0,
- NULL,
- 0,
- NULL
- );
+ Status = DiskIo2->ReadDiskEx (DiskIo2, MediaId, 0, NULL, 1, NULL);
if ((Status == EFI_NO_MEDIA) || (Status == EFI_MEDIA_CHANGED)) {
return Status;
}
@@ -763,6 +776,68 @@ PartitionResetEx (
}
/**
+ The general callback for the DiskIo2 interfaces.
+ @param Event Event whose notification function is being invoked.
+ @param Context The pointer to the notification function's context,
+ which points to the PARTITION_ACCESS_TASK instance.
+**/
+VOID
+EFIAPI
+PartitionOnAccessComplete (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ PARTITION_ACCESS_TASK *Task;
+
+ Task = (PARTITION_ACCESS_TASK *) Context;
+
+ gBS->CloseEvent (Event);
+
+ Task->BlockIo2Token->TransactionStatus = Task->DiskIo2Token.TransactionStatus;
+ gBS->SignalEvent (Task->BlockIo2Token->Event);
+
+ FreePool (Task);
+}
+
+/**
+ Create a new PARTITION_ACCESS_TASK instance.
+
+ @param Token Pointer to the EFI_BLOCK_IO2_TOKEN.
+
+ @return Pointer to the created PARTITION_ACCESS_TASK instance or NULL upon failure.
+**/
+PARTITION_ACCESS_TASK *
+PartitionCreateAccessTask (
+ IN EFI_BLOCK_IO2_TOKEN *Token
+ )
+{
+ EFI_STATUS Status;
+ PARTITION_ACCESS_TASK *Task;
+
+ Task = AllocatePool (sizeof (*Task));
+ if (Task == NULL) {
+ return NULL;
+ }
+
+ Status = gBS->CreateEvent (
+ EVT_NOTIFY_SIGNAL,
+ TPL_CALLBACK,
+ PartitionOnAccessComplete,
+ Task,
+ &Task->DiskIo2Token.Event
+ );
+ if (EFI_ERROR (Status)) {
+ FreePool (Task);
+ return NULL;
+ }
+
+ Task->BlockIo2Token = Token;
+
+ return Task;
+}
+
+/**
Read BufferSize bytes from Lba into Buffer.
This function reads the requested number of blocks from the device. All the
@@ -806,44 +881,38 @@ PartitionReadBlocksEx (
OUT VOID *Buffer
)
{
+ EFI_STATUS Status;
PARTITION_PRIVATE_DATA *Private;
UINT64 Offset;
- UINT32 UnderRun;
+ PARTITION_ACCESS_TASK *Task;
Private = PARTITION_DEVICE_FROM_BLOCK_IO2_THIS (This);
- if (Token == NULL) {
- return ProbeMediaStatusEx (Private->ParentBlockIo2, MediaId, EFI_INVALID_PARAMETER);
- }
-
if (BufferSize % Private->BlockSize != 0) {
- return ProbeMediaStatusEx (Private->ParentBlockIo2, MediaId, EFI_BAD_BUFFER_SIZE);
+ return ProbeMediaStatusEx (Private->DiskIo2, MediaId, EFI_BAD_BUFFER_SIZE);
}
Offset = MultU64x32 (Lba, Private->BlockSize) + Private->Start;
if (Offset + BufferSize > Private->End) {
- return ProbeMediaStatusEx (Private->ParentBlockIo2, MediaId, EFI_INVALID_PARAMETER);
+ return ProbeMediaStatusEx (Private->DiskIo2, MediaId, EFI_INVALID_PARAMETER);
}
- //
- // Since the BlockIO2 call Parent BlockIO2 directly, so here the offset must
- // be multiple of BlockSize. If the Spec will be updated the DiskIO to support
- // BlockIO2, this limitation will be removed and call DiskIO here.
- //
- Lba = DivU64x32Remainder (Offset, Private->BlockSize, &UnderRun);
- if (UnderRun != 0) {
- return ProbeMediaStatusEx (Private->ParentBlockIo2, MediaId, EFI_UNSUPPORTED);
- }
+ if ((Token != NULL) && (Token->Event != NULL)) {
+ Task = PartitionCreateAccessTask (Token);
+ if (Task == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
- //
- // Because some partitions have different block size from their parent
- // device, in that case the Block I/O2 couldn't be called.
- //
- if (Private->BlockSize != Private->ParentBlockIo->Media->BlockSize) {
- return ProbeMediaStatusEx (Private->ParentBlockIo2, MediaId, EFI_UNSUPPORTED);
+ Status = Private->DiskIo2->ReadDiskEx (Private->DiskIo2, MediaId, Offset, &Task->DiskIo2Token, BufferSize, Buffer);
+ if (EFI_ERROR (Status)) {
+ gBS->CloseEvent (Task->DiskIo2Token.Event);
+ FreePool (Task);
+ }
+ } else {
+ Status = Private->DiskIo2->ReadDiskEx (Private->DiskIo2, MediaId, Offset, NULL, BufferSize, Buffer);
}
- return Private->ParentBlockIo2->ReadBlocksEx (Private->ParentBlockIo2, MediaId, Lba, Token, BufferSize, Buffer);
+ return Status;
}
/**
@@ -888,44 +957,37 @@ PartitionWriteBlocksEx (
IN VOID *Buffer
)
{
+ EFI_STATUS Status;
PARTITION_PRIVATE_DATA *Private;
UINT64 Offset;
- UINT32 UnderRun;
+ PARTITION_ACCESS_TASK *Task;
Private = PARTITION_DEVICE_FROM_BLOCK_IO2_THIS (This);
- if (Token == NULL) {
- return ProbeMediaStatusEx (Private->ParentBlockIo2, MediaId, EFI_INVALID_PARAMETER);
- }
-
if (BufferSize % Private->BlockSize != 0) {
- return ProbeMediaStatusEx (Private->ParentBlockIo2, MediaId, EFI_BAD_BUFFER_SIZE);
+ return ProbeMediaStatusEx (Private->DiskIo2, MediaId, EFI_BAD_BUFFER_SIZE);
}
Offset = MultU64x32 (Lba, Private->BlockSize) + Private->Start;
if (Offset + BufferSize > Private->End) {
- return ProbeMediaStatusEx (Private->ParentBlockIo2, MediaId, EFI_INVALID_PARAMETER);
- }
-
- //
- // Since the BlockIO2 call Parent BlockIO2 directly, so here the offset must
- // be multiple of BlockSize. If the Spec will be updated the DiskIO to support
- // BlockIO2, this limitation will be removed and call DiskIO here.
- //
- Lba = DivU64x32Remainder (Offset, Private->BlockSize, &UnderRun);
- if (UnderRun != 0) {
- return ProbeMediaStatusEx (Private->ParentBlockIo2, MediaId, EFI_UNSUPPORTED);
+ return ProbeMediaStatusEx (Private->DiskIo2, MediaId, EFI_INVALID_PARAMETER);
}
+
+ if ((Token != NULL) && (Token->Event != NULL)) {
+ Task = PartitionCreateAccessTask (Token);
+ if (Task == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
- //
- // Because some kinds of partition have different block size from their parent,
- // in that case it couldn't call parent Block I/O2.
- //
- if (Private->BlockSize != Private->ParentBlockIo->Media->BlockSize) {
- return ProbeMediaStatusEx (Private->ParentBlockIo2, MediaId, EFI_UNSUPPORTED);
+ Status = Private->DiskIo2->WriteDiskEx (Private->DiskIo2, MediaId, Offset, &Task->DiskIo2Token, BufferSize, Buffer);
+ if (EFI_ERROR (Status)) {
+ gBS->CloseEvent (Task->DiskIo2Token.Event);
+ FreePool (Task);
+ }
+ } else {
+ Status = Private->DiskIo2->WriteDiskEx (Private->DiskIo2, MediaId, Offset, NULL, BufferSize, Buffer);
}
-
- return Private->ParentBlockIo2->WriteBlocksEx (Private->ParentBlockIo2, MediaId, Lba, Token, BufferSize, Buffer);
+ return Status;
}
/**
@@ -957,19 +1019,27 @@ PartitionFlushBlocksEx (
IN OUT EFI_BLOCK_IO2_TOKEN *Token
)
{
+ EFI_STATUS Status;
PARTITION_PRIVATE_DATA *Private;
+ PARTITION_ACCESS_TASK *Task;
Private = PARTITION_DEVICE_FROM_BLOCK_IO2_THIS (This);
- //
- // Because some kinds of partition have different block size from their parent,
- // in that case it couldn't call parent Block I/O2.
- //
- if (Private->BlockSize != Private->ParentBlockIo->Media->BlockSize) {
- return EFI_UNSUPPORTED;
- }
+ if ((Token != NULL) && (Token->Event != NULL)) {
+ Task = PartitionCreateAccessTask (Token);
+ if (Task == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
- return Private->ParentBlockIo2->FlushBlocksEx (Private->ParentBlockIo2, Token);
+ Status = Private->DiskIo2->FlushDiskEx (Private->DiskIo2, &Task->DiskIo2Token);
+ if (EFI_ERROR (Status)) {
+ gBS->CloseEvent (Task->DiskIo2Token.Event);
+ FreePool (Task);
+ }
+ } else {
+ Status = Private->DiskIo2->FlushDiskEx (Private->DiskIo2, NULL);
+ }
+ return Status;
}
@@ -980,6 +1050,7 @@ PartitionFlushBlocksEx (
@param[in] This Protocol instance pointer.
@param[in] ParentHandle Parent Handle for new child.
@param[in] ParentDiskIo Parent DiskIo interface.
+ @param[in] ParentDiskIo2 Parent DiskIo2 interface.
@param[in] ParentBlockIo Parent BlockIo interface.
@param[in] ParentBlockIo2 Parent BlockIo2 interface.
@param[in] ParentDevicePath Parent Device Path.
@@ -998,6 +1069,7 @@ PartitionInstallChildHandle (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE ParentHandle,
IN EFI_DISK_IO_PROTOCOL *ParentDiskIo,
+ IN EFI_DISK_IO2_PROTOCOL *ParentDiskIo2,
IN EFI_BLOCK_IO_PROTOCOL *ParentBlockIo,
IN EFI_BLOCK_IO2_PROTOCOL *ParentBlockIo2,
IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,
@@ -1026,6 +1098,7 @@ PartitionInstallChildHandle (
Private->ParentBlockIo = ParentBlockIo;
Private->ParentBlockIo2 = ParentBlockIo2;
Private->DiskIo = ParentDiskIo;
+ Private->DiskIo2 = ParentDiskIo2;
//
// Set the BlockIO into Private Data.
@@ -1043,7 +1116,8 @@ PartitionInstallChildHandle (
//
// Set the BlockIO2 into Private Data.
//
- if (Private->ParentBlockIo2 != NULL) {
+ if (Private->DiskIo2 != NULL) {
+ ASSERT (Private->ParentBlockIo2 != NULL);
Private->BlockIo2.Media = &Private->Media2;
CopyMem (Private->BlockIo2.Media, ParentBlockIo2->Media, sizeof (EFI_BLOCK_IO_MEDIA));
@@ -1065,9 +1139,7 @@ PartitionInstallChildHandle (
Private->Media.BlockSize = (UINT32) BlockSize;
- //
- // For BlockIO2, it should keep the same alignment with the parent BlockIO2's.
- //
+ Private->Media2.IoAlign = 0;
Private->Media2.LogicalPartition = TRUE;
Private->Media2.LastBlock = Private->Media.LastBlock;
Private->Media2.BlockSize = (UINT32) BlockSize;
@@ -1105,17 +1177,9 @@ PartitionInstallChildHandle (
//
// Create the new handle.
- // BlockIO2 will be installed on the condition that the blocksize of parent BlockIO
- // is same with the child BlockIO's. Instead of calling the DiskIO, the child BlockIO2
- // directly call the parent BlockIO and doesn't handle the different block size issue.
- // If SPEC will update the DiskIO to support the Non-Blocking model, the BlockIO2 will call
- // DiskIO to handle the blocksize unequal issue and the limitation will be remove from
- // here.
//
Private->Handle = NULL;
- if ((Private->ParentBlockIo2 != NULL) &&
- (Private->ParentBlockIo2->Media->BlockSize == BlockSize)
- ) {
+ if (Private->DiskIo2 != NULL) {
Status = gBS->InstallMultipleProtocolInterfaces (
&Private->Handle,
&gEfiDevicePathProtocolGuid,
diff --git a/MdeModulePkg/Universal/Disk/PartitionDxe/Partition.h b/MdeModulePkg/Universal/Disk/PartitionDxe/Partition.h
index 7a4ca8a31..06470f689 100644
--- a/MdeModulePkg/Universal/Disk/PartitionDxe/Partition.h
+++ b/MdeModulePkg/Universal/Disk/PartitionDxe/Partition.h
@@ -26,6 +26,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include <Protocol/DevicePath.h>
#include <Protocol/DriverBinding.h>
#include <Protocol/DiskIo.h>
+#include <Protocol/DiskIo2.h>
#include <Library/DebugLib.h>
#include <Library/UefiDriverEntryPoint.h>
#include <Library/BaseLib.h>
@@ -54,6 +55,7 @@ typedef struct {
EFI_BLOCK_IO_MEDIA Media2;//For BlockIO2
EFI_DISK_IO_PROTOCOL *DiskIo;
+ EFI_DISK_IO2_PROTOCOL *DiskIo2;
EFI_BLOCK_IO_PROTOCOL *ParentBlockIo;
EFI_BLOCK_IO2_PROTOCOL *ParentBlockIo2;
UINT64 Start;
@@ -64,6 +66,11 @@ typedef struct {
} PARTITION_PRIVATE_DATA;
+typedef struct {
+ EFI_DISK_IO2_TOKEN DiskIo2Token;
+ EFI_BLOCK_IO2_TOKEN *BlockIo2Token;
+} PARTITION_ACCESS_TASK;
+
#define PARTITION_DEVICE_FROM_BLOCK_IO_THIS(a) CR (a, PARTITION_PRIVATE_DATA, BlockIo, PARTITION_PRIVATE_DATA_SIGNATURE)
#define PARTITION_DEVICE_FROM_BLOCK_IO2_THIS(a) CR (a, PARTITION_PRIVATE_DATA, BlockIo2, PARTITION_PRIVATE_DATA_SIGNATURE)
@@ -308,6 +315,7 @@ PartitionComponentNameGetControllerName (
@param[in] This Protocol instance pointer.
@param[in] ParentHandle Parent Handle for new child.
@param[in] ParentDiskIo Parent DiskIo interface.
+ @param[in] ParentDiskIo2 Parent DiskIo2 interface.
@param[in] ParentBlockIo Parent BlockIo interface.
@param[in] ParentBlockIo2 Parent BlockIo2 interface.
@param[in] ParentDevicePath Parent Device Path.
@@ -326,6 +334,7 @@ PartitionInstallChildHandle (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE ParentHandle,
IN EFI_DISK_IO_PROTOCOL *ParentDiskIo,
+ IN EFI_DISK_IO2_PROTOCOL *ParentDiskIo2,
IN EFI_BLOCK_IO_PROTOCOL *ParentBlockIo,
IN EFI_BLOCK_IO2_PROTOCOL *ParentBlockIo2,
IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,
@@ -342,6 +351,7 @@ PartitionInstallChildHandle (
@param[in] This Calling context.
@param[in] Handle Parent Handle.
@param[in] DiskIo Parent DiskIo interface.
+ @param[in] DiskIo2 Parent DiskIo2 interface.
@param[in] BlockIo Parent BlockIo interface.
@param[in] BlockIo2 Parent BlockIo2 interface.
@param[in] DevicePath Parent Device Path.
@@ -357,6 +367,7 @@ PartitionInstallGptChildHandles (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE Handle,
IN EFI_DISK_IO_PROTOCOL *DiskIo,
+ IN EFI_DISK_IO2_PROTOCOL *DiskIo2,
IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
IN EFI_BLOCK_IO2_PROTOCOL *BlockIo2,
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
@@ -368,6 +379,7 @@ PartitionInstallGptChildHandles (
@param[in] This Calling context.
@param[in] Handle Parent Handle.
@param[in] DiskIo Parent DiskIo interface.
+ @param[in] DiskIo2 Parent DiskIo2 interface.
@param[in] BlockIo Parent BlockIo interface.
@param[in] BlockIo2 Parent BlockIo2 interface.
@param[in] DevicePath Parent Device Path
@@ -383,6 +395,7 @@ PartitionInstallElToritoChildHandles (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE Handle,
IN EFI_DISK_IO_PROTOCOL *DiskIo,
+ IN EFI_DISK_IO2_PROTOCOL *DiskIo2,
IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
IN EFI_BLOCK_IO2_PROTOCOL *BlockIo2,
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
@@ -394,6 +407,7 @@ PartitionInstallElToritoChildHandles (
@param[in] This Calling context.
@param[in] Handle Parent Handle.
@param[in] DiskIo Parent DiskIo interface.
+ @param[in] DiskIo2 Parent DiskIo2 interface.
@param[in] BlockIo Parent BlockIo interface.
@param[in] BlockIo2 Parent BlockIo2 interface.
@param[in] DevicePath Parent Device Path.
@@ -408,6 +422,7 @@ PartitionInstallMbrChildHandles (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE Handle,
IN EFI_DISK_IO_PROTOCOL *DiskIo,
+ IN EFI_DISK_IO2_PROTOCOL *DiskIo2,
IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
IN EFI_BLOCK_IO2_PROTOCOL *BlockIo2,
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
@@ -419,6 +434,7 @@ EFI_STATUS
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE Handle,
IN EFI_DISK_IO_PROTOCOL *DiskIo,
+ IN EFI_DISK_IO2_PROTOCOL *DiskIo2,
IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
IN EFI_BLOCK_IO2_PROTOCOL *BlockIo2,
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
diff --git a/MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf b/MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf
index aac20a13b..089918f5a 100644
--- a/MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf
+++ b/MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf
@@ -12,7 +12,7 @@
# This external input must be validated carefully to avoid security issue like
# buffer overflow, integer overflow.
#
-# Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
# 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
@@ -74,7 +74,9 @@
gEfiBlockIoProtocolGuid ## BY_START
gEfiDevicePathProtocolGuid ## BY_START
gEfiDiskIoProtocolGuid ## BY_START
+ gEfiDiskIo2ProtocolGuid ## BY_START
gEfiBlockIoProtocolGuid ## TO_START
gEfiBlockIo2ProtocolGuid ## TO_START
gEfiDevicePathProtocolGuid ## TO_START
gEfiDiskIoProtocolGuid ## TO_START
+ gEfiDiskIo2ProtocolGuid ## TO_START
diff --git a/MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf b/MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf
new file mode 100644
index 000000000..323fcadb8
--- /dev/null
+++ b/MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf
@@ -0,0 +1,66 @@
+## @file
+# The DXE driver produces FORM BROWSER protocols defined in UEFI HII 2.1 specificatin.
+#
+# Copyright (c) 2007 - 2013, Intel Corporation. All rights reserved.<BR>
+#
+# 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]
+ INF_VERSION = 0x00010005
+ BASE_NAME = DisplayEngine
+ FILE_GUID = E660EA85-058E-4b55-A54B-F02F83A24707
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = InitializeDisplayEngine
+ UNLOAD_IMAGE = UnloadDisplayEngine
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources]
+ FormDisplayStr.uni
+ FormDisplay.c
+ FormDisplay.h
+ ProcessOptions.c
+ InputHandler.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ UefiDriverEntryPoint
+ UefiBootServicesTableLib
+ DebugLib
+ BaseMemoryLib
+ BaseLib
+ PrintLib
+ HiiLib
+ MemoryAllocationLib
+ CustomizedDisplayLib
+
+[Protocols]
+ gEdkiiFormDisplayEngineProtocolGuid
+ gEdkiiFormBrowserEx2ProtocolGuid
+
+[Guids]
+ gEfiIfrTianoGuid ## CONSUMES ## GUID
+
+[Depex]
+ gEfiHiiDatabaseProtocolGuid AND gEfiHiiConfigRoutingProtocolGuid AND gEdkiiFormBrowserEx2ProtocolGuid
+
+[FeaturePcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdBrowserGrayOutTextStatement ## CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdBrowerGrayOutReadOnlyMenu ## CONSUMES
+
diff --git a/MdeModulePkg/Universal/DisplayEngineDxe/FormDisplay.c b/MdeModulePkg/Universal/DisplayEngineDxe/FormDisplay.c
new file mode 100644
index 000000000..a07cc75a4
--- /dev/null
+++ b/MdeModulePkg/Universal/DisplayEngineDxe/FormDisplay.c
@@ -0,0 +1,3255 @@
+/** @file
+Entry and initialization module for the browser.
+
+Copyright (c) 2007 - 2013, Intel Corporation. All rights reserved.<BR>
+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 "FormDisplay.h"
+
+//
+// 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_LEFT,
+ UiLeft,
+ },
+ {
+ SCAN_RIGHT,
+ UiRight,
+ }
+};
+
+UINTN mScanCodeNumber = sizeof (gScanCodeToOperation) / sizeof (gScanCodeToOperation[0]);
+
+SCREEN_OPERATION_T0_CONTROL_FLAG gScreenOperationToControlFlag[] = {
+ {
+ UiNoOperation,
+ CfUiNoOperation,
+ },
+ {
+ UiSelect,
+ CfUiSelect,
+ },
+ {
+ UiUp,
+ CfUiUp,
+ },
+ {
+ UiDown,
+ CfUiDown,
+ },
+ {
+ UiLeft,
+ CfUiLeft,
+ },
+ {
+ UiRight,
+ CfUiRight,
+ },
+ {
+ UiReset,
+ CfUiReset,
+ },
+ {
+ UiPageUp,
+ CfUiPageUp,
+ },
+ {
+ UiPageDown,
+ CfUiPageDown
+ },
+ {
+ UiHotKey,
+ CfUiHotKey
+ }
+};
+
+EFI_GUID gDisplayEngineGuid = {
+ 0xE38C1029, 0xE38F, 0x45b9, {0x8F, 0x0D, 0xE2, 0xE6, 0x0B, 0xC9, 0xB2, 0x62}
+};
+
+FORM_ENTRY_INFO gFormEntryInfo;
+UINTN gSequence;
+EFI_SCREEN_DESCRIPTOR gStatementDimensions;
+BOOLEAN mStatementLayoutIsChanged = TRUE;
+USER_INPUT *gUserInput;
+FORM_DISPLAY_ENGINE_FORM *gFormData;
+EFI_HII_HANDLE gHiiHandle;
+UINT16 gDirection;
+LIST_ENTRY gMenuOption;
+DISPLAY_HIGHLIGHT_MENU_INFO gHighligthMenuInfo = {0};
+BOOLEAN mIsFirstForm = TRUE;
+FORM_ENTRY_INFO gOldFormEntry = {0};
+
+//
+// Browser Global Strings
+//
+CHAR16 *gFormNotFound;
+CHAR16 *gNoSubmitIf;
+CHAR16 *gBrwoserError;
+CHAR16 *gSaveFailed;
+CHAR16 *gPromptForData;
+CHAR16 *gPromptForPassword;
+CHAR16 *gPromptForNewPassword;
+CHAR16 *gConfirmPassword;
+CHAR16 *gConfirmError;
+CHAR16 *gPassowordInvalid;
+CHAR16 *gPressEnter;
+CHAR16 *gEmptyString;
+CHAR16 *gMiniString;
+CHAR16 *gOptionMismatch;
+CHAR16 *gFormSuppress;
+CHAR16 *gProtocolNotFound;
+
+CHAR16 gPromptBlockWidth;
+CHAR16 gOptionBlockWidth;
+CHAR16 gHelpBlockWidth;
+CHAR16 *mUnknownString;
+
+FORM_DISPLAY_DRIVER_PRIVATE_DATA mPrivateData = {
+ FORM_DISPLAY_DRIVER_SIGNATURE,
+ NULL,
+ {
+ FormDisplay,
+ DriverClearDisplayPage,
+ ConfirmDataChange
+ }
+};
+
+
+/**
+ Get the string based on the StringId and HII Package List Handle.
+
+ @param Token The String's ID.
+ @param HiiHandle The package list in the HII database to search for
+ the specified string.
+
+ @return The output string.
+
+**/
+CHAR16 *
+GetToken (
+ IN EFI_STRING_ID Token,
+ IN EFI_HII_HANDLE HiiHandle
+ )
+{
+ EFI_STRING String;
+
+ String = HiiGetString (HiiHandle, Token, NULL);
+ if (String == NULL) {
+ String = AllocateCopyPool (StrSize (mUnknownString), mUnknownString);
+ ASSERT (String != NULL);
+ }
+
+ return (CHAR16 *) String;
+}
+
+
+/**
+ Initialize the HII String Token to the correct values.
+
+**/
+VOID
+InitializeDisplayStrings (
+ VOID
+ )
+{
+ mUnknownString = GetToken (STRING_TOKEN (UNKNOWN_STRING), gHiiHandle);
+ gSaveFailed = GetToken (STRING_TOKEN (SAVE_FAILED), gHiiHandle);
+ gPromptForData = GetToken (STRING_TOKEN (PROMPT_FOR_DATA), 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);
+ gPassowordInvalid = GetToken (STRING_TOKEN (PASSWORD_INVALID), gHiiHandle);
+ gPressEnter = GetToken (STRING_TOKEN (PRESS_ENTER), gHiiHandle);
+ gEmptyString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);
+ gMiniString = GetToken (STRING_TOKEN (MINI_STRING), gHiiHandle);
+ gOptionMismatch = GetToken (STRING_TOKEN (OPTION_MISMATCH), gHiiHandle);
+ gFormSuppress = GetToken (STRING_TOKEN (FORM_SUPPRESSED), gHiiHandle);
+ gProtocolNotFound = GetToken (STRING_TOKEN (PROTOCOL_NOT_FOUND), gHiiHandle);
+ gFormNotFound = GetToken (STRING_TOKEN (STATUS_BROWSER_FORM_NOT_FOUND), gHiiHandle);
+ gNoSubmitIf = GetToken (STRING_TOKEN (STATUS_BROWSER_NO_SUBMIT_IF), gHiiHandle);
+ gBrwoserError = GetToken (STRING_TOKEN (STATUS_BROWSER_ERROR), gHiiHandle);
+}
+
+/**
+ Free up the resource allocated for all strings required
+ by Setup Browser.
+
+**/
+VOID
+FreeDisplayStrings (
+ VOID
+ )
+{
+ FreePool (mUnknownString);
+ FreePool (gEmptyString);
+ FreePool (gSaveFailed);
+ FreePool (gPromptForData);
+ FreePool (gPromptForPassword);
+ FreePool (gPromptForNewPassword);
+ FreePool (gConfirmPassword);
+ FreePool (gConfirmError);
+ FreePool (gPassowordInvalid);
+ FreePool (gPressEnter);
+ FreePool (gMiniString);
+ FreePool (gOptionMismatch);
+ FreePool (gFormSuppress);
+ FreePool (gProtocolNotFound);
+ FreePool (gBrwoserError);
+ FreePool (gNoSubmitIf);
+ FreePool (gFormNotFound);
+}
+
+/**
+ Get prompt string id from the opcode data buffer.
+
+ @param OpCode The input opcode buffer.
+
+ @return The prompt string id.
+
+**/
+EFI_STRING_ID
+GetPrompt (
+ IN EFI_IFR_OP_HEADER *OpCode
+ )
+{
+ EFI_IFR_STATEMENT_HEADER *Header;
+
+ if (OpCode->Length <= sizeof (EFI_IFR_OP_HEADER)) {
+ return 0;
+ }
+
+ Header = (EFI_IFR_STATEMENT_HEADER *) (OpCode + 1);
+
+ return Header->Prompt;
+}
+
+/**
+ Get the supported width for a particular op-code
+
+ @param Statement The curent statement.
+
+ @return Returns the number of CHAR16 characters that is support.
+
+**/
+UINT16
+GetWidth (
+ IN FORM_DISPLAY_ENGINE_STATEMENT *Statement
+ )
+{
+ CHAR16 *String;
+ UINTN Size;
+ UINT16 Width;
+ EFI_IFR_TEXT *TestOp;
+
+ Size = 0;
+
+ //
+ // See if the second text parameter is really NULL
+ //
+ if (Statement->OpCode->OpCode == EFI_IFR_TEXT_OP) {
+ TestOp = (EFI_IFR_TEXT *) Statement->OpCode;
+ if (TestOp->TextTwo != 0) {
+ String = GetToken (TestOp->TextTwo, gFormData->HiiHandle);
+ Size = StrLen (String);
+ FreePool (String);
+ }
+ }
+
+ if ((Statement->OpCode->OpCode == EFI_IFR_SUBTITLE_OP) ||
+ (Statement->OpCode->OpCode == EFI_IFR_REF_OP) ||
+ (Statement->OpCode->OpCode == EFI_IFR_PASSWORD_OP) ||
+ (Statement->OpCode->OpCode == EFI_IFR_ACTION_OP) ||
+ (Statement->OpCode->OpCode == EFI_IFR_RESET_BUTTON_OP) ||
+ //
+ // Allow a wide display if text op-code and no secondary text op-code
+ //
+ ((Statement->OpCode->OpCode == EFI_IFR_TEXT_OP) && (Size == 0))
+ ) {
+ Width = (UINT16) (gPromptBlockWidth + gOptionBlockWidth);
+ } else {
+ Width = (UINT16) gPromptBlockWidth;
+ }
+
+ return (UINT16) (Width - LEFT_SKIPPED_COLUMNS);
+}
+
+/**
+ 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.
+ The output string format is:
+ Glyph Info + String info + '\0'.
+
+ In the code, it deals \r,\n,\r\n same as \n\r, also it not process the \r or \g.
+
+ @param InputString String description for this option.
+ @param LineWidth Width of the desired string to extract in CHAR16
+ characters
+ @param GlyphWidth The glyph width of the begin of the char in the string.
+ @param Index Where in InputString to start the copy process
+ @param OutputString Buffer to copy the string into
+
+ @return Returns the number of CHAR16 characters that were copied into the OutputString
+ buffer, include extra glyph info and '\0' info.
+
+**/
+UINT16
+GetLineByWidth (
+ IN CHAR16 *InputString,
+ IN UINT16 LineWidth,
+ IN OUT UINT16 *GlyphWidth,
+ IN OUT UINTN *Index,
+ OUT CHAR16 **OutputString
+ )
+{
+ UINT16 StrOffset;
+ UINT16 GlyphOffset;
+ UINT16 OriginalGlyphWidth;
+ BOOLEAN ReturnFlag;
+ UINT16 LastSpaceOffset;
+ UINT16 LastGlyphWidth;
+
+ if (InputString == NULL || Index == NULL || OutputString == NULL) {
+ return 0;
+ }
+
+ if (LineWidth == 0 || *GlyphWidth == 0) {
+ return 0;
+ }
+
+ //
+ // Save original glyph width.
+ //
+ OriginalGlyphWidth = *GlyphWidth;
+ LastGlyphWidth = OriginalGlyphWidth;
+ ReturnFlag = FALSE;
+ LastSpaceOffset = 0;
+
+ //
+ // 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 (StrOffset = 0, GlyphOffset = 0; GlyphOffset <= LineWidth; StrOffset++) {
+ switch (InputString[*Index + StrOffset]) {
+ case NARROW_CHAR:
+ *GlyphWidth = 1;
+ break;
+
+ case WIDE_CHAR:
+ *GlyphWidth = 2;
+ break;
+
+ case CHAR_CARRIAGE_RETURN:
+ case CHAR_LINEFEED:
+ case CHAR_NULL:
+ ReturnFlag = TRUE;
+ break;
+
+ default:
+ GlyphOffset = GlyphOffset + *GlyphWidth;
+
+ //
+ // Record the last space info in this line. Will be used in rewind.
+ //
+ if ((InputString[*Index + StrOffset] == CHAR_SPACE) && (GlyphOffset <= LineWidth)) {
+ LastSpaceOffset = StrOffset;
+ LastGlyphWidth = *GlyphWidth;
+ }
+ break;
+ }
+
+ if (ReturnFlag) {
+ break;
+ }
+ }
+
+ //
+ // Rewind the string from the maximum size until we see a space to break the line
+ //
+ if (GlyphOffset > LineWidth) {
+ //
+ // Rewind the string to last space char in this line.
+ //
+ if (LastSpaceOffset != 0) {
+ StrOffset = LastSpaceOffset;
+ *GlyphWidth = LastGlyphWidth;
+ } else {
+ //
+ // Roll back to last char in the line width.
+ //
+ StrOffset--;
+ }
+ }
+
+ //
+ // The CHAR_NULL has process last time, this time just return 0 to stand for the end.
+ //
+ if (StrOffset == 0 && (InputString[*Index + StrOffset] == CHAR_NULL)) {
+ return 0;
+ }
+
+ //
+ // Need extra glyph info and '\0' info, so +2.
+ //
+ *OutputString = AllocateZeroPool (((UINTN) (StrOffset + 2) * sizeof(CHAR16)));
+ if (*OutputString == NULL) {
+ return 0;
+ }
+
+ //
+ // Save the glyph info at the begin of the string, will used by Print function.
+ //
+ if (OriginalGlyphWidth == 1) {
+ *(*OutputString) = NARROW_CHAR;
+ } else {
+ *(*OutputString) = WIDE_CHAR;
+ }
+
+ CopyMem ((*OutputString) + 1, &InputString[*Index], StrOffset * sizeof(CHAR16));
+
+ if (InputString[*Index + StrOffset] == CHAR_SPACE) {
+ //
+ // Skip the space info at the begin of next line.
+ //
+ *Index = (UINT16) (*Index + StrOffset + 1);
+ } else if (InputString[*Index + StrOffset] == CHAR_LINEFEED) {
+ //
+ // Skip the /n or /n/r info.
+ //
+ if (InputString[*Index + StrOffset + 1] == CHAR_CARRIAGE_RETURN) {
+ *Index = (UINT16) (*Index + StrOffset + 2);
+ } else {
+ *Index = (UINT16) (*Index + StrOffset + 1);
+ }
+ } else if (InputString[*Index + StrOffset] == CHAR_CARRIAGE_RETURN) {
+ //
+ // Skip the /r or /r/n info.
+ //
+ if (InputString[*Index + StrOffset + 1] == CHAR_LINEFEED) {
+ *Index = (UINT16) (*Index + StrOffset + 2);
+ } else {
+ *Index = (UINT16) (*Index + StrOffset + 1);
+ }
+ } else {
+ *Index = (UINT16) (*Index + StrOffset);
+ }
+
+ //
+ // Include extra glyph info and '\0' info, so +2.
+ //
+ return StrOffset + 2;
+}
+
+/**
+ Add one menu option by specified description and context.
+
+ @param Statement Statement of this Menu Option.
+ @param MenuItemCount The index for this Option in the Menu.
+ @param NestIn Whether this statement is nest in another statement.
+
+**/
+VOID
+UiAddMenuOption (
+ IN FORM_DISPLAY_ENGINE_STATEMENT *Statement,
+ IN UINT16 *MenuItemCount,
+ IN BOOLEAN NestIn
+ )
+{
+ UI_MENU_OPTION *MenuOption;
+ UINTN Index;
+ UINTN Count;
+ CHAR16 *String;
+ UINT16 NumberOfLines;
+ UINT16 GlyphWidth;
+ UINT16 Width;
+ UINTN ArrayEntry;
+ CHAR16 *OutputString;
+ EFI_STRING_ID PromptId;
+
+ NumberOfLines = 1;
+ ArrayEntry = 0;
+ GlyphWidth = 1;
+ Count = 1;
+ MenuOption = NULL;
+
+ PromptId = GetPrompt (Statement->OpCode);
+ ASSERT (PromptId != 0);
+
+ String = GetToken (PromptId, gFormData->HiiHandle);
+ ASSERT (String != NULL);
+
+ Width = GetWidth (Statement);
+ for (; GetLineByWidth (String, Width, &GlyphWidth,&ArrayEntry, &OutputString) != 0x0000;) {
+ //
+ // If there is more string to process print on the next row and increment the Skip value
+ //
+ if (StrLen (&String[ArrayEntry]) != 0) {
+ NumberOfLines++;
+ }
+ FreePool (OutputString);
+ }
+
+ if (Statement->OpCode->OpCode == EFI_IFR_DATE_OP || Statement->OpCode->OpCode == EFI_IFR_TIME_OP) {
+ //
+ // Add three MenuOptions for Date/Time
+ // Data format : [01/02/2004] [11:22:33]
+ // Line number : 0 0 1 0 0 1
+ //
+ NumberOfLines = 0;
+ Count = 3;
+ }
+
+ for (Index = 0; Index < Count; Index++) {
+ MenuOption = AllocateZeroPool (sizeof (UI_MENU_OPTION));
+ ASSERT (MenuOption);
+
+ MenuOption->Signature = UI_MENU_OPTION_SIGNATURE;
+ MenuOption->Description = String;
+ MenuOption->Handle = gFormData->HiiHandle;
+ MenuOption->ThisTag = Statement;
+ MenuOption->NestInStatement = NestIn;
+ MenuOption->EntryNumber = *MenuItemCount;
+
+ if (Index == 2) {
+ //
+ // Override LineNumber for the MenuOption in Date/Time sequence
+ //
+ MenuOption->Skip = 1;
+ } else {
+ MenuOption->Skip = NumberOfLines;
+ }
+ MenuOption->Sequence = Index;
+
+ if ((Statement->Attribute & HII_DISPLAY_GRAYOUT) != 0) {
+ MenuOption->GrayOut = TRUE;
+ } else {
+ MenuOption->GrayOut = FALSE;
+ }
+
+ if ((Statement->Attribute & HII_DISPLAY_LOCK) != 0 || (gFormData->Attribute & HII_DISPLAY_LOCK) != 0) {
+ MenuOption->GrayOut = TRUE;
+ }
+
+ //
+ // If the form or the question has the lock attribute, deal same as grayout.
+ //
+ if ((gFormData->Attribute & HII_DISPLAY_LOCK) != 0 || (Statement->Attribute & HII_DISPLAY_LOCK) != 0) {
+ MenuOption->GrayOut = TRUE;
+ }
+
+ switch (Statement->OpCode->OpCode) {
+ 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:
+ case EFI_IFR_CHECKBOX_OP:
+ case EFI_IFR_PASSWORD_OP:
+ case EFI_IFR_STRING_OP:
+ //
+ // User could change the value of these items
+ //
+ MenuOption->IsQuestion = TRUE;
+ break;
+ case EFI_IFR_TEXT_OP:
+ if (FeaturePcdGet (PcdBrowserGrayOutTextStatement)) {
+ //
+ // Initializing GrayOut option as TRUE for Text setup options
+ // so that those options will be Gray in colour and un selectable.
+ //
+ MenuOption->GrayOut = TRUE;
+ }
+ break;
+ default:
+ MenuOption->IsQuestion = FALSE;
+ break;
+ }
+
+ if ((Statement->Attribute & HII_DISPLAY_READONLY) != 0) {
+ MenuOption->ReadOnly = TRUE;
+ if (FeaturePcdGet (PcdBrowerGrayOutReadOnlyMenu)) {
+ MenuOption->GrayOut = TRUE;
+ }
+ }
+
+ InsertTailList (&gMenuOption, &MenuOption->Link);
+ }
+
+ (*MenuItemCount)++;
+}
+
+/**
+ Create the menu list base on the form data info.
+
+**/
+VOID
+ConvertStatementToMenu (
+ VOID
+ )
+{
+ UINT16 MenuItemCount;
+ LIST_ENTRY *Link;
+ LIST_ENTRY *NestLink;
+ FORM_DISPLAY_ENGINE_STATEMENT *Statement;
+ FORM_DISPLAY_ENGINE_STATEMENT *NestStatement;
+
+ MenuItemCount = 0;
+ InitializeListHead (&gMenuOption);
+
+ Link = GetFirstNode (&gFormData->StatementListHead);
+ while (!IsNull (&gFormData->StatementListHead, Link)) {
+ Statement = FORM_DISPLAY_ENGINE_STATEMENT_FROM_LINK (Link);
+ Link = GetNextNode (&gFormData->StatementListHead, Link);
+
+ //
+ // Skip the opcode not recognized by Display core.
+ //
+ if (Statement->OpCode->OpCode == EFI_IFR_GUID_OP) {
+ continue;
+ }
+
+ UiAddMenuOption (Statement, &MenuItemCount, FALSE);
+
+ //
+ // Check the statement nest in this host statement.
+ //
+ NestLink = GetFirstNode (&Statement->NestStatementList);
+ while (!IsNull (&Statement->NestStatementList, NestLink)) {
+ NestStatement = FORM_DISPLAY_ENGINE_STATEMENT_FROM_LINK (NestLink);
+ NestLink = GetNextNode (&Statement->NestStatementList, NestLink);
+
+ UiAddMenuOption (NestStatement, &MenuItemCount, TRUE);
+ }
+ }
+}
+
+/**
+ Count the storage space of a Unicode string.
+
+ This function handles the Unicode string with NARROW_CHAR
+ and WIDE_CHAR control characters. NARROW_HCAR and WIDE_CHAR
+ does not count in the resultant output. If a WIDE_CHAR is
+ hit, then 2 Unicode character will consume an output storage
+ space with size of CHAR16 till a NARROW_CHAR is hit.
+
+ If String is NULL, then ASSERT ().
+
+ @param String The input string to be counted.
+
+ @return Storage space for the input string.
+
+**/
+UINTN
+GetStringWidth (
+ IN CHAR16 *String
+ )
+{
+ UINTN Index;
+ UINTN Count;
+ UINTN IncrementValue;
+
+ ASSERT (String != NULL);
+ if (String == NULL) {
+ return 0;
+ }
+
+ 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);
+}
+
+/**
+ Base on the input option string to update the skip value for a menu option.
+
+ @param MenuOption The MenuOption to be checked.
+ @param OptionString The input option string.
+
+**/
+VOID
+UpdateSkipInfoForMenu (
+ IN UI_MENU_OPTION *MenuOption,
+ IN CHAR16 *OptionString
+ )
+{
+ UINTN Index;
+ UINT16 Width;
+ UINTN Row;
+ CHAR16 *OutputString;
+ UINT16 GlyphWidth;
+
+ Width = (UINT16) gOptionBlockWidth;
+ GlyphWidth = 1;
+ Row = 1;
+
+ for (Index = 0; GetLineByWidth (OptionString, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {
+ if (StrLen (&OptionString[Index]) != 0) {
+ Row++;
+ }
+
+ FreePool (OutputString);
+ }
+
+ if ((Row > MenuOption->Skip) &&
+ (MenuOption->ThisTag->OpCode->OpCode != EFI_IFR_DATE_OP) &&
+ (MenuOption->ThisTag->OpCode->OpCode != EFI_IFR_TIME_OP)) {
+ MenuOption->Skip = Row;
+ }
+}
+
+/**
+ Update display lines for a Menu Option.
+
+ @param MenuOption The MenuOption to be checked.
+
+**/
+VOID
+UpdateOptionSkipLines (
+ IN UI_MENU_OPTION *MenuOption
+ )
+{
+ CHAR16 *OptionString;
+
+ OptionString = NULL;
+
+ ProcessOptions (MenuOption, FALSE, &OptionString, TRUE);
+ if (OptionString != NULL) {
+ UpdateSkipInfoForMenu (MenuOption, OptionString);
+
+ FreePool (OptionString);
+ }
+
+ if ((MenuOption->ThisTag->OpCode->OpCode == EFI_IFR_TEXT_OP) && (((EFI_IFR_TEXT*)MenuOption->ThisTag->OpCode)->TextTwo != 0)) {
+ OptionString = GetToken (((EFI_IFR_TEXT*)MenuOption->ThisTag->OpCode)->TextTwo, gFormData->HiiHandle);
+
+ if (OptionString != NULL) {
+ UpdateSkipInfoForMenu (MenuOption, OptionString);
+
+ FreePool (OptionString);
+ }
+ }
+}
+
+/**
+ Check whether this Menu Option could be highlighted.
+
+ This is an internal function.
+
+ @param MenuOption The MenuOption to be checked.
+
+ @retval TRUE This Menu Option is selectable.
+ @retval FALSE This Menu Option could not be selected.
+
+**/
+BOOLEAN
+IsSelectable (
+ UI_MENU_OPTION *MenuOption
+ )
+{
+ if ((MenuOption->ThisTag->OpCode->OpCode == EFI_IFR_SUBTITLE_OP) ||
+ MenuOption->GrayOut || MenuOption->ReadOnly) {
+ return FALSE;
+ } else {
+ return TRUE;
+ }
+}
+
+/**
+ Move to next selectable statement.
+
+ This is an internal function.
+
+ @param GoUp The navigation direction. TRUE: up, FALSE: down.
+ @param CurrentPosition Current position.
+ @param GapToTop Gap position to top or bottom.
+
+ @return The row distance from current MenuOption to next selectable MenuOption.
+
+ @retval -1 Reach the begin of the menu, still can't find the selectable menu.
+ @retval Value Find the selectable menu, maybe the truly selectable, maybe the l
+ last menu showing at current form.
+
+**/
+INTN
+MoveToNextStatement (
+ IN BOOLEAN GoUp,
+ IN OUT LIST_ENTRY **CurrentPosition,
+ IN UINTN GapToTop
+ )
+{
+ INTN Distance;
+ LIST_ENTRY *Pos;
+ UI_MENU_OPTION *NextMenuOption;
+ UI_MENU_OPTION *PreMenuOption;
+
+ Distance = 0;
+ Pos = *CurrentPosition;
+ PreMenuOption = MENU_OPTION_FROM_LINK (Pos);
+
+ while (TRUE) {
+ NextMenuOption = MENU_OPTION_FROM_LINK (Pos);
+ //
+ // NextMenuOption->Row == 0 means this menu has not calculate
+ // the NextMenuOption->Skip value yet, just calculate here.
+ //
+ if (NextMenuOption->Row == 0) {
+ UpdateOptionSkipLines (NextMenuOption);
+ }
+
+ if (GoUp && (PreMenuOption != NextMenuOption)) {
+ //
+ // In this case, still can't find the selectable menu,
+ // return the last one in the showing form.
+ //
+ if ((UINTN) Distance + NextMenuOption->Skip > GapToTop) {
+ NextMenuOption = PreMenuOption;
+ break;
+ }
+
+ //
+ // Current Position doesn't need to be caculated when go up.
+ // Caculate distanct at first when go up
+ //
+ Distance += NextMenuOption->Skip;
+ }
+
+ if (IsSelectable (NextMenuOption)) {
+ break;
+ }
+
+ //
+ // Arrive at begin of the menu list.
+ //
+ if ((GoUp ? Pos->BackLink : Pos->ForwardLink) == &gMenuOption) {
+ Distance = -1;
+ break;
+ }
+
+ if (!GoUp) {
+ //
+ // In this case, still can't find the selectable menu,
+ // return the last one in the showing form.
+ //
+ if ((UINTN) Distance + NextMenuOption->Skip > GapToTop) {
+ NextMenuOption = PreMenuOption;
+ break;
+ }
+
+ Distance += NextMenuOption->Skip;
+ }
+
+ PreMenuOption = NextMenuOption;
+ Pos = (GoUp ? Pos->BackLink : Pos->ForwardLink);
+ }
+
+ *CurrentPosition = &NextMenuOption->Link;
+ return Distance;
+}
+
+
+/**
+ Process option string for date/time opcode.
+
+ @param MenuOption Menu option point to date/time.
+ @param OptionString Option string input for process.
+ @param AddOptCol Whether need to update MenuOption->OptCol.
+
+**/
+VOID
+ProcessStringForDateTime (
+ UI_MENU_OPTION *MenuOption,
+ CHAR16 *OptionString,
+ BOOLEAN AddOptCol
+ )
+{
+ UINTN Index;
+ UINTN Count;
+ FORM_DISPLAY_ENGINE_STATEMENT *Statement;
+ EFI_IFR_DATE *Date;
+ EFI_IFR_TIME *Time;
+
+ ASSERT (MenuOption != NULL && OptionString != NULL);
+
+ Statement = MenuOption->ThisTag;
+ Date = NULL;
+ Time = NULL;
+ if (Statement->OpCode->OpCode == EFI_IFR_DATE_OP) {
+ Date = (EFI_IFR_DATE *) Statement->OpCode;
+ } else if (Statement->OpCode->OpCode == EFI_IFR_TIME_OP) {
+ Time = (EFI_IFR_TIME *) Statement->OpCode;
+ }
+
+ //
+ // If leading spaces on OptionString - remove the spaces
+ //
+ for (Index = 0; OptionString[Index] == L' '; Index++) {
+ //
+ // Base on the blockspace to get the option column info.
+ //
+ if (AddOptCol) {
+ MenuOption->OptCol++;
+ }
+ }
+
+ for (Count = 0; OptionString[Index] != CHAR_NULL; Index++) {
+ OptionString[Count] = OptionString[Index];
+ Count++;
+ }
+ OptionString[Count] = CHAR_NULL;
+
+ //
+ // Enable to suppress field in the opcode base on the flag.
+ //
+ if (Statement->OpCode->OpCode == EFI_IFR_DATE_OP) {
+ //
+ // OptionString format is: <**: **: ****>
+ // |month|day|year|
+ // 4 3 5
+ //
+ if ((Date->Flags & EFI_QF_DATE_MONTH_SUPPRESS) && (MenuOption->Sequence == 0)) {
+ //
+ // At this point, only "<**:" in the optionstring.
+ // Clean the day's ** field, after clean, the format is "< :"
+ //
+ SetUnicodeMem (&OptionString[1], 2, L' ');
+ } else if ((Date->Flags & EFI_QF_DATE_DAY_SUPPRESS) && (MenuOption->Sequence == 1)) {
+ //
+ // At this point, only "**:" in the optionstring.
+ // Clean the month's "**" field, after clean, the format is " :"
+ //
+ SetUnicodeMem (&OptionString[0], 2, L' ');
+ } else if ((Date->Flags & EFI_QF_DATE_YEAR_SUPPRESS) && (MenuOption->Sequence == 2)) {
+ //
+ // At this point, only "****>" in the optionstring.
+ // Clean the year's "****" field, after clean, the format is " >"
+ //
+ SetUnicodeMem (&OptionString[0], 4, L' ');
+ }
+ } else if (Statement->OpCode->OpCode == EFI_IFR_TIME_OP) {
+ //
+ // OptionString format is: <**: **: **>
+ // |hour|minute|second|
+ // 4 3 3
+ //
+ if ((Time->Flags & QF_TIME_HOUR_SUPPRESS) && (MenuOption->Sequence == 0)) {
+ //
+ // At this point, only "<**:" in the optionstring.
+ // Clean the hour's ** field, after clean, the format is "< :"
+ //
+ SetUnicodeMem (&OptionString[1], 2, L' ');
+ } else if ((Time->Flags & QF_TIME_MINUTE_SUPPRESS) && (MenuOption->Sequence == 1)) {
+ //
+ // At this point, only "**:" in the optionstring.
+ // Clean the minute's "**" field, after clean, the format is " :"
+ //
+ SetUnicodeMem (&OptionString[0], 2, L' ');
+ } else if ((Time->Flags & QF_TIME_SECOND_SUPPRESS) && (MenuOption->Sequence == 2)) {
+ //
+ // At this point, only "**>" in the optionstring.
+ // Clean the second's "**" field, after clean, the format is " >"
+ //
+ SetUnicodeMem (&OptionString[0], 2, L' ');
+ }
+ }
+}
+
+
+/**
+ Adjust Data and Time position accordingly.
+ Data format : [01/02/2004] [11:22:33]
+ Line number : 0 0 1 0 0 1
+
+ This is an internal function.
+
+ @param DirectionUp the up or down direction. False is down. True is
+ up.
+ @param CurrentPosition Current position. On return: Point to the last
+ Option (Year or Second) if up; Point to the first
+ Option (Month or Hour) if down.
+
+ @return Return line number to pad. It is possible that we stand on a zero-advance
+ @return data or time opcode, so pad one line when we judge if we are going to scroll outside.
+
+**/
+UINTN
+AdjustDateAndTimePosition (
+ IN BOOLEAN DirectionUp,
+ IN OUT LIST_ENTRY **CurrentPosition
+ )
+{
+ UINTN Count;
+ LIST_ENTRY *NewPosition;
+ UI_MENU_OPTION *MenuOption;
+ UINTN PadLineNumber;
+
+ PadLineNumber = 0;
+ NewPosition = *CurrentPosition;
+ MenuOption = MENU_OPTION_FROM_LINK (NewPosition);
+
+ if ((MenuOption->ThisTag->OpCode->OpCode == EFI_IFR_DATE_OP) ||
+ (MenuOption->ThisTag->OpCode->OpCode == EFI_IFR_TIME_OP)) {
+ //
+ // Calculate the distance from current position to the last Date/Time MenuOption
+ //
+ Count = 0;
+ while (MenuOption->Skip == 0) {
+ Count++;
+ NewPosition = NewPosition->ForwardLink;
+ MenuOption = MENU_OPTION_FROM_LINK (NewPosition);
+ PadLineNumber = 1;
+ }
+
+ NewPosition = *CurrentPosition;
+ if (DirectionUp) {
+ //
+ // Since the behavior of hitting the up arrow on a Date/Time MenuOption is intended
+ // to be one that back to the previous set of MenuOptions, we need to advance to the first
+ // Date/Time MenuOption 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 MenuOption is intended
+ // to be one that progresses to the next set of MenuOptions, we need to advance to the last
+ // Date/Time MenuOption 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;
+}
+
+/**
+ Get step info from numeric opcode.
+
+ @param[in] OpCode The input numeric op code.
+
+ @return step info for this opcode.
+**/
+UINT64
+GetFieldFromNum (
+ IN EFI_IFR_OP_HEADER *OpCode
+ )
+{
+ EFI_IFR_NUMERIC *NumericOp;
+ UINT64 Step;
+
+ NumericOp = (EFI_IFR_NUMERIC *) OpCode;
+
+ switch (NumericOp->Flags & EFI_IFR_NUMERIC_SIZE) {
+ case EFI_IFR_NUMERIC_SIZE_1:
+ Step = NumericOp->data.u8.Step;
+ break;
+
+ case EFI_IFR_NUMERIC_SIZE_2:
+ Step = NumericOp->data.u16.Step;
+ break;
+
+ case EFI_IFR_NUMERIC_SIZE_4:
+ Step = NumericOp->data.u32.Step;
+ break;
+
+ case EFI_IFR_NUMERIC_SIZE_8:
+ Step = NumericOp->data.u64.Step;
+ break;
+
+ default:
+ Step = 0;
+ break;
+ }
+
+ return Step;
+}
+
+/**
+ Find the registered HotKey based on KeyData.
+
+ @param[in] KeyData A pointer to a buffer that describes the keystroke
+ information for the hot key.
+
+ @return The registered HotKey context. If no found, NULL will return.
+**/
+BROWSER_HOT_KEY *
+GetHotKeyFromRegisterList (
+ IN EFI_INPUT_KEY *KeyData
+ )
+{
+ LIST_ENTRY *Link;
+ BROWSER_HOT_KEY *HotKey;
+
+ Link = GetFirstNode (&gFormData->HotKeyListHead);
+ while (!IsNull (&gFormData->HotKeyListHead, Link)) {
+ HotKey = BROWSER_HOT_KEY_FROM_LINK (Link);
+
+ if (HotKey->KeyData->ScanCode == KeyData->ScanCode) {
+ return HotKey;
+ }
+
+ Link = GetNextNode (&gFormData->HotKeyListHead, Link);
+ }
+
+ return NULL;
+}
+
+
+/**
+ Determine if the menu is the last menu that can be selected.
+
+ This is an internal function.
+
+ @param Direction The scroll direction. False is down. True is up.
+ @param CurrentPos The current focus.
+
+ @return FALSE -- the menu isn't the last menu that can be selected.
+ @return TRUE -- the menu is the last menu that can be selected.
+
+**/
+BOOLEAN
+ValueIsScroll (
+ IN BOOLEAN Direction,
+ IN LIST_ENTRY *CurrentPos
+ )
+{
+ LIST_ENTRY *Temp;
+
+ Temp = Direction ? CurrentPos->BackLink : CurrentPos->ForwardLink;
+
+ if (Temp == &gMenuOption) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ Wait for a given event to fire, or for an optional timeout to expire.
+
+ @param Event The event to wait for
+
+ @retval UI_EVENT_TYPE The type of the event which is trigged.
+
+**/
+UI_EVENT_TYPE
+UiWaitForEvent (
+ IN EFI_EVENT Event
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ UINTN EventNum;
+ UINT64 Timeout;
+ EFI_EVENT TimerEvent;
+ EFI_EVENT WaitList[3];
+ UI_EVENT_TYPE EventType;
+
+ TimerEvent = NULL;
+ Timeout = FormExitTimeout(gFormData);
+
+ if (Timeout != 0) {
+ Status = gBS->CreateEvent (EVT_TIMER, 0, NULL, NULL, &TimerEvent);
+
+ //
+ // Set the timer event
+ //
+ gBS->SetTimer (
+ TimerEvent,
+ TimerRelative,
+ Timeout
+ );
+ }
+
+ WaitList[0] = Event;
+ EventNum = 1;
+ if (gFormData->FormRefreshEvent != NULL) {
+ WaitList[EventNum] = gFormData->FormRefreshEvent;
+ EventNum ++;
+ }
+
+ if (Timeout != 0) {
+ WaitList[EventNum] = TimerEvent;
+ EventNum ++;
+ }
+
+ Status = gBS->WaitForEvent (EventNum, WaitList, &Index);
+ ASSERT_EFI_ERROR (Status);
+
+ switch (Index) {
+ case 0:
+ EventType = UIEventKey;
+ break;
+
+ case 1:
+ if (gFormData->FormRefreshEvent != NULL) {
+ EventType = UIEventDriver;
+ } else {
+ ASSERT (Timeout != 0 && EventNum == 2);
+ EventType = UIEventTimeOut;
+ }
+ break;
+
+ default:
+ ASSERT (Index == 2 && EventNum == 3);
+ EventType = UIEventTimeOut;
+ break;
+ }
+
+ if (Timeout != 0) {
+ gBS->CloseEvent (TimerEvent);
+ }
+
+ return EventType;
+}
+
+/**
+ Get question id info from the input opcode header.
+
+ @param OpCode The input opcode header pointer.
+
+ @retval The question id for this opcode.
+
+**/
+EFI_QUESTION_ID
+GetQuestionIdInfo (
+ IN EFI_IFR_OP_HEADER *OpCode
+ )
+{
+ EFI_IFR_QUESTION_HEADER *QuestionHeader;
+
+ if (OpCode->Length < sizeof (EFI_IFR_OP_HEADER) + sizeof (EFI_IFR_QUESTION_HEADER)) {
+ return 0;
+ }
+
+ QuestionHeader = (EFI_IFR_QUESTION_HEADER *)((UINT8 *) OpCode + sizeof(EFI_IFR_OP_HEADER));
+
+ return QuestionHeader->QuestionId;
+}
+
+/**
+ Find the first menu which will be show at the top.
+
+ @param FormData The data info for this form.
+ @param TopOfScreen The link_entry pointer to top menu.
+ @param HighlightMenu The menu which will be highlight.
+ @param SkipValue The skip value for the top menu.
+
+**/
+VOID
+FindTopMenu (
+ IN FORM_DISPLAY_ENGINE_FORM *FormData,
+ OUT LIST_ENTRY **TopOfScreen,
+ OUT LIST_ENTRY **HighlightMenu,
+ OUT INTN *SkipValue
+ )
+{
+ LIST_ENTRY *Link;
+ LIST_ENTRY *NewPos;
+ UINTN TopRow;
+ UINTN BottomRow;
+ UINTN Index;
+ UI_MENU_OPTION *SavedMenuOption;
+ UINTN EndRow;
+
+ TopRow = gStatementDimensions.TopRow + SCROLL_ARROW_HEIGHT;
+ BottomRow = gStatementDimensions.BottomRow - SCROLL_ARROW_HEIGHT;
+
+ //
+ // If not has input highlight statement, just return the first one in this form.
+ //
+ if (FormData->HighLightedStatement == NULL) {
+ *TopOfScreen = gMenuOption.ForwardLink;
+ *HighlightMenu = gMenuOption.ForwardLink;
+ if (!IsListEmpty (&gMenuOption)) {
+ MoveToNextStatement (FALSE, HighlightMenu, BottomRow - TopRow);
+ }
+ *SkipValue = 0;
+ return;
+ }
+
+ //
+ // Now base on the input highlight menu to find the top menu in this page.
+ // Will base on the highlight menu show at the bottom to find the top menu.
+ //
+ NewPos = gMenuOption.ForwardLink;
+ SavedMenuOption = MENU_OPTION_FROM_LINK (NewPos);
+
+ while ((SavedMenuOption->ThisTag != FormData->HighLightedStatement) ||
+ (SavedMenuOption->Sequence != gSequence)) {
+ NewPos = NewPos->ForwardLink;
+ if (NewPos == &gMenuOption) {
+ //
+ // Not Found it, break
+ //
+ break;
+ }
+ SavedMenuOption = MENU_OPTION_FROM_LINK (NewPos);
+ }
+ ASSERT (SavedMenuOption->ThisTag == FormData->HighLightedStatement);
+
+ *HighlightMenu = NewPos;
+
+ AdjustDateAndTimePosition(FALSE, &NewPos);
+ SavedMenuOption = MENU_OPTION_FROM_LINK (NewPos);
+ UpdateOptionSkipLines (SavedMenuOption);
+
+ //
+ // If highlight opcode is date/time, keep the highlight row info not change.
+ //
+ if ((SavedMenuOption->ThisTag->OpCode->OpCode == EFI_IFR_DATE_OP || SavedMenuOption->ThisTag->OpCode->OpCode == EFI_IFR_TIME_OP) &&
+ (gHighligthMenuInfo.QuestionId != 0) &&
+ (gHighligthMenuInfo.QuestionId == GetQuestionIdInfo(SavedMenuOption->ThisTag->OpCode))) {
+ //
+ // Still show the highlight menu before exit from display engine.
+ //
+ EndRow = gHighligthMenuInfo.DisplayRow + SavedMenuOption->Skip;
+ } else {
+ EndRow = BottomRow;
+ }
+
+ //
+ // Base on the selected menu will show at the bottome of next page,
+ // select the menu show at the top of the next page.
+ //
+ Link = NewPos;
+ for (Index = TopRow + SavedMenuOption->Skip; Index <= EndRow; ) {
+ Link = Link->BackLink;
+ //
+ // Already find the first menu in this form, means highlight menu
+ // will show in first page of this form.
+ //
+ if (Link == &gMenuOption) {
+ *TopOfScreen = gMenuOption.ForwardLink;
+ *SkipValue = 0;
+ return;
+ }
+ SavedMenuOption = MENU_OPTION_FROM_LINK (Link);
+ UpdateOptionSkipLines (SavedMenuOption);
+ Index += SavedMenuOption->Skip;
+ }
+
+ //
+ // Found the menu which will show at the top of the page.
+ //
+ if (Link == NewPos) {
+ //
+ // The menu can show more than one pages, just show the menu at the top of the page.
+ //
+ *SkipValue = 0;
+ *TopOfScreen = Link;
+ } else {
+ //
+ // Check whether need to skip some line for menu shows at the top of the page.
+ //
+ *SkipValue = Index - EndRow;
+ if (*SkipValue > 0 && *SkipValue < (INTN) SavedMenuOption->Skip) {
+ *TopOfScreen = Link;
+ } else {
+ *SkipValue = 0;
+ *TopOfScreen = Link->ForwardLink;
+ }
+ }
+}
+
+/**
+ 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.
+
+ @param FormData The current form data info.
+
+ @retval EFI_SUCESSS Process the user selection success.
+ @retval EFI_NOT_FOUND Process option string for orderedlist/Oneof fail.
+
+**/
+EFI_STATUS
+UiDisplayMenu (
+ IN FORM_DISPLAY_ENGINE_FORM *FormData
+ )
+{
+ INTN SkipValue;
+ INTN Difference;
+ UINTN DistanceValue;
+ UINTN Row;
+ UINTN Col;
+ UINTN TempRightCol;
+ UINTN Temp;
+ UINTN Temp2;
+ UINTN Temp3;
+ UINTN TopRow;
+ UINTN BottomRow;
+ UINTN OriginalRow;
+ UINTN Index;
+ UINT16 Width;
+ CHAR16 *StringPtr;
+ CHAR16 *OptionString;
+ CHAR16 *OutputString;
+ CHAR16 *HelpString;
+ CHAR16 *HelpHeaderString;
+ CHAR16 *HelpBottomString;
+ BOOLEAN NewLine;
+ BOOLEAN Repaint;
+ BOOLEAN UpArrow;
+ BOOLEAN DownArrow;
+ EFI_STATUS Status;
+ EFI_INPUT_KEY Key;
+ LIST_ENTRY *Link;
+ LIST_ENTRY *NewPos;
+ LIST_ENTRY *TopOfScreen;
+ LIST_ENTRY *SavedListEntry;
+ UI_MENU_OPTION *MenuOption;
+ UI_MENU_OPTION *NextMenuOption;
+ UI_MENU_OPTION *SavedMenuOption;
+ UI_MENU_OPTION *PreviousMenuOption;
+ UI_CONTROL_FLAG ControlFlag;
+ UI_SCREEN_OPERATION ScreenOperation;
+ UINT16 DefaultId;
+ FORM_DISPLAY_ENGINE_STATEMENT *Statement;
+ UINTN ModalSkipColumn;
+ BROWSER_HOT_KEY *HotKey;
+ UINTN HelpPageIndex;
+ UINTN HelpPageCount;
+ UINTN RowCount;
+ UINTN HelpLine;
+ UINTN HelpHeaderLine;
+ UINTN HelpBottomLine;
+ BOOLEAN MultiHelpPage;
+ UINT16 GlyphWidth;
+ UINT16 EachLineWidth;
+ UINT16 HeaderLineWidth;
+ UINT16 BottomLineWidth;
+ EFI_STRING_ID HelpInfo;
+ UI_EVENT_TYPE EventType;
+ FORM_DISPLAY_ENGINE_STATEMENT *InitialHighlight;
+
+ EventType = UIEventNone;
+ Status = EFI_SUCCESS;
+ HelpString = NULL;
+ HelpHeaderString = NULL;
+ HelpBottomString = NULL;
+ OptionString = NULL;
+ ScreenOperation = UiNoOperation;
+ NewLine = TRUE;
+ DefaultId = 0;
+ HelpPageCount = 0;
+ HelpLine = 0;
+ RowCount = 0;
+ HelpBottomLine = 0;
+ HelpHeaderLine = 0;
+ HelpPageIndex = 0;
+ MultiHelpPage = FALSE;
+ EachLineWidth = 0;
+ HeaderLineWidth = 0;
+ BottomLineWidth = 0;
+ OutputString = NULL;
+ UpArrow = FALSE;
+ DownArrow = FALSE;
+ SkipValue = 0;
+
+ NextMenuOption = NULL;
+ PreviousMenuOption = NULL;
+ SavedMenuOption = NULL;
+ HotKey = NULL;
+ Repaint = TRUE;
+ MenuOption = NULL;
+ ModalSkipColumn = (gStatementDimensions.RightColumn - gStatementDimensions.LeftColumn) / 6;
+ InitialHighlight = gFormData->HighLightedStatement;
+
+ ZeroMem (&Key, sizeof (EFI_INPUT_KEY));
+
+ gOptionBlockWidth = (CHAR16) ((gStatementDimensions.RightColumn - gStatementDimensions.LeftColumn) / 3);
+ gPromptBlockWidth = (CHAR16) (gOptionBlockWidth + LEFT_SKIPPED_COLUMNS);
+ gHelpBlockWidth = (CHAR16) (gOptionBlockWidth - LEFT_SKIPPED_COLUMNS);
+
+ TopRow = gStatementDimensions.TopRow + SCROLL_ARROW_HEIGHT;
+ BottomRow = gStatementDimensions.BottomRow - SCROLL_ARROW_HEIGHT - 1;
+
+ Row = TopRow;
+ if ((FormData->Attribute & HII_DISPLAY_MODAL) != 0) {
+ Col = gStatementDimensions.LeftColumn + LEFT_SKIPPED_COLUMNS + ModalSkipColumn;
+ } else {
+ Col = gStatementDimensions.LeftColumn + LEFT_SKIPPED_COLUMNS;
+ }
+
+ FindTopMenu(FormData, &TopOfScreen, &NewPos, &SkipValue);
+
+ gST->ConOut->EnableCursor (gST->ConOut, FALSE);
+
+ ControlFlag = CfInitialization;
+ while (TRUE) {
+ switch (ControlFlag) {
+ case CfInitialization:
+ if (IsListEmpty (&gMenuOption)) {
+
+ if ((FormData->Attribute & HII_DISPLAY_MODAL) == 0) {
+ //
+ // Clear Statement range.
+ //
+ ClearLines (
+ gStatementDimensions.LeftColumn,
+ gStatementDimensions.RightColumn,
+ TopRow - SCROLL_ARROW_HEIGHT,
+ BottomRow + SCROLL_ARROW_HEIGHT,
+ GetFieldTextColor ()
+ );
+
+ //
+ // Clear Key Range
+ //
+ RefreshKeyHelp (gFormData, NULL, FALSE);
+ }
+
+ ControlFlag = CfReadKey;
+ } else {
+ ControlFlag = CfRepaint;
+ }
+ break;
+
+ case CfRepaint:
+ ControlFlag = CfRefreshHighLight;
+
+ if (Repaint) {
+ //
+ // Display menu
+ //
+ DownArrow = FALSE;
+ UpArrow = FALSE;
+ Row = TopRow;
+
+ Temp = (UINTN) SkipValue;
+ Temp2 = (UINTN) SkipValue;
+ Temp3 = (UINTN) SkipValue;
+
+ //
+ // 1. Clear the screen.
+ //
+ if ((FormData->Attribute & HII_DISPLAY_MODAL) != 0) {
+ ClearLines (
+ gStatementDimensions.LeftColumn + ModalSkipColumn,
+ gStatementDimensions.LeftColumn + ModalSkipColumn + gPromptBlockWidth + gOptionBlockWidth,
+ TopRow - SCROLL_ARROW_HEIGHT,
+ BottomRow + SCROLL_ARROW_HEIGHT,
+ GetFieldTextColor ()
+ );
+ } else {
+ TempRightCol = gStatementDimensions.RightColumn;
+ if (!mStatementLayoutIsChanged) {
+ TempRightCol = gStatementDimensions.RightColumn - gHelpBlockWidth;
+ }
+ ClearLines (
+ gStatementDimensions.LeftColumn,
+ gStatementDimensions.RightColumn,
+ TopRow - SCROLL_ARROW_HEIGHT,
+ TopRow - 1,
+ GetFieldTextColor ()
+ );
+ ClearLines (
+ gStatementDimensions.LeftColumn,
+ TempRightCol,
+ TopRow,
+ BottomRow,
+ GetFieldTextColor ()
+ );
+ ClearLines (
+ gStatementDimensions.LeftColumn,
+ gStatementDimensions.RightColumn,
+ BottomRow + 1,
+ BottomRow + SCROLL_ARROW_HEIGHT,
+ GetFieldTextColor ()
+ );
+ }
+
+ //
+ // 2.Paint the menu.
+ //
+ for (Link = TopOfScreen; Link != &gMenuOption; Link = Link->ForwardLink) {
+ MenuOption = MENU_OPTION_FROM_LINK (Link);
+ MenuOption->Row = Row;
+ MenuOption->Col = Col;
+ if ((FormData->Attribute & HII_DISPLAY_MODAL) != 0) {
+ MenuOption->OptCol = gPromptBlockWidth + 1 + gStatementDimensions.LeftColumn + ModalSkipColumn;
+ } else {
+ MenuOption->OptCol = gPromptBlockWidth + 1 + gStatementDimensions.LeftColumn;
+ }
+
+ Statement = MenuOption->ThisTag;
+ if (MenuOption->NestInStatement) {
+ MenuOption->Col += SUBTITLE_INDENT;
+ }
+
+ if (MenuOption->GrayOut) {
+ gST->ConOut->SetAttribute (gST->ConOut, GetGrayedTextColor ());
+ } else {
+ if (Statement->OpCode->OpCode == EFI_IFR_SUBTITLE_OP) {
+ gST->ConOut->SetAttribute (gST->ConOut, GetSubTitleTextColor ());
+ }
+ }
+
+ Width = GetWidth (Statement);
+ OriginalRow = Row;
+ GlyphWidth = 1;
+
+ if (Statement->OpCode->OpCode == EFI_IFR_REF_OP && MenuOption->Col >= 2) {
+ //
+ // Print Arrow for Goto button.
+ //
+ PrintCharAt (
+ MenuOption->Col - 2,
+ Row,
+ GEOMETRICSHAPE_RIGHT_TRIANGLE
+ );
+ }
+
+ //
+ // 2.1. Paint the description.
+ //
+ for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {
+ //
+ // Temp means need to skip how many lines from the start.
+ //
+ if ((Temp == 0) && (Row <= BottomRow)) {
+ PrintStringAt (MenuOption->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]) != 0) {
+ if (Temp == 0) {
+ Row++;
+ }
+ }
+
+ FreePool (OutputString);
+ if (Temp != 0) {
+ Temp--;
+ }
+ }
+
+ Temp = 0;
+ Row = OriginalRow;
+
+ //
+ // 2.2. Paint the option string.
+ //
+ Status = ProcessOptions (MenuOption, FALSE, &OptionString, FALSE);
+ //
+ // If Error occur, question value update in ProcessOptions.
+ // Exit current FormDisplay with new question value.
+ //
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (OptionString != NULL) {
+ if (Statement->OpCode->OpCode == EFI_IFR_DATE_OP || Statement->OpCode->OpCode == EFI_IFR_TIME_OP) {
+ ProcessStringForDateTime(MenuOption, OptionString, TRUE);
+ }
+
+ Width = (UINT16) gOptionBlockWidth;
+ OriginalRow = Row;
+ GlyphWidth = 1;
+
+ for (Index = 0; GetLineByWidth (OptionString, Width, &GlyphWidth, &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]) != 0) {
+ 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 (OptionString);
+ }
+ Temp2 = 0;
+
+ //
+ // If this is a text op with secondary text information
+ //
+ if ((Statement->OpCode->OpCode == EFI_IFR_TEXT_OP) && (((EFI_IFR_TEXT*)Statement->OpCode)->TextTwo != 0)) {
+ StringPtr = GetToken (((EFI_IFR_TEXT*)Statement->OpCode)->TextTwo, gFormData->HiiHandle);
+
+ Width = (UINT16) gOptionBlockWidth;
+ OriginalRow = Row;
+ GlyphWidth = 1;
+
+ for (Index = 0; GetLineByWidth (StringPtr, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {
+ if ((Temp3 == 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]) != 0) {
+ if (Temp3 == 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 (Temp3 != 0) {
+ Temp3--;
+ }
+ }
+
+ Row = OriginalRow;
+ FreePool (StringPtr);
+ }
+ Temp3 = 0;
+
+ gST->ConOut->SetAttribute (gST->ConOut, GetFieldTextColor ());
+
+ //
+ // 3. Update the row info which will be used by next menu.
+ //
+ if (Link == TopOfScreen) {
+ Row += MenuOption->Skip - SkipValue;
+ } else {
+ Row += MenuOption->Skip;
+ }
+
+ if (Row > BottomRow) {
+ if (!ValueIsScroll (FALSE, Link)) {
+ DownArrow = TRUE;
+ }
+
+ Row = BottomRow + 1;
+ break;
+ }
+ }
+
+ if (!ValueIsScroll (TRUE, TopOfScreen)) {
+ UpArrow = TRUE;
+ }
+
+ if (UpArrow) {
+ gST->ConOut->SetAttribute (gST->ConOut, GetArrowColor ());
+ PrintCharAt (
+ gStatementDimensions.LeftColumn + gPromptBlockWidth + gOptionBlockWidth + 1,
+ TopRow - SCROLL_ARROW_HEIGHT,
+ ARROW_UP
+ );
+ gST->ConOut->SetAttribute (gST->ConOut, GetFieldTextColor ());
+ }
+
+ if (DownArrow) {
+ gST->ConOut->SetAttribute (gST->ConOut, GetArrowColor ());
+ PrintCharAt (
+ gStatementDimensions.LeftColumn + gPromptBlockWidth + gOptionBlockWidth + 1,
+ BottomRow + SCROLL_ARROW_HEIGHT,
+ ARROW_DOWN
+ );
+ gST->ConOut->SetAttribute (gST->ConOut, GetFieldTextColor ());
+ }
+
+ MenuOption = NULL;
+ }
+ break;
+
+ case CfRefreshHighLight:
+
+ //
+ // MenuOption: Last menu option that need to remove hilight
+ // MenuOption is set to NULL in Repaint
+ // NewPos: Current menu option that need to hilight
+ //
+ ControlFlag = CfUpdateHelpString;
+
+ if (MenuOption != NULL && TopOfScreen == &MenuOption->Link) {
+ Temp = SkipValue;
+ } else {
+ Temp = 0;
+ }
+ if (NewPos == TopOfScreen) {
+ Temp2 = SkipValue;
+ } else {
+ Temp2 = 0;
+ }
+
+ if (NewPos != NULL && (MenuOption == NULL || NewPos != &MenuOption->Link)) {
+ if (MenuOption != NULL) {
+ //
+ // Remove highlight on last Menu Option
+ //
+ gST->ConOut->SetCursorPosition (gST->ConOut, MenuOption->Col, MenuOption->Row);
+ ProcessOptions (MenuOption, FALSE, &OptionString, TRUE);
+ gST->ConOut->SetAttribute (gST->ConOut, GetFieldTextColor ());
+ if (OptionString != NULL) {
+ if ((MenuOption->ThisTag->OpCode->OpCode == EFI_IFR_DATE_OP) ||
+ (MenuOption->ThisTag->OpCode->OpCode == EFI_IFR_TIME_OP)
+ ) {
+ ProcessStringForDateTime(MenuOption, OptionString, FALSE);
+ }
+
+ Width = (UINT16) gOptionBlockWidth;
+ OriginalRow = MenuOption->Row;
+ GlyphWidth = 1;
+
+ for (Index = 0; GetLineByWidth (OptionString, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {
+ if ((Temp == 0) && (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]) != 0) {
+ if (Temp == 0) {
+ MenuOption->Row++;
+ }
+ }
+
+ FreePool (OutputString);
+ if (Temp != 0) {
+ Temp--;
+ }
+ }
+
+ MenuOption->Row = OriginalRow;
+
+ FreePool (OptionString);
+ } else {
+ if (NewLine) {
+ if (MenuOption->GrayOut) {
+ gST->ConOut->SetAttribute (gST->ConOut, GetGrayedTextColor ());
+ } else if (MenuOption->ThisTag->OpCode->OpCode == EFI_IFR_SUBTITLE_OP) {
+ gST->ConOut->SetAttribute (gST->ConOut, GetSubTitleTextColor ());
+ }
+
+ OriginalRow = MenuOption->Row;
+ Width = GetWidth (MenuOption->ThisTag);
+ GlyphWidth = 1;
+
+ for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {
+ if ((Temp == 0) && (MenuOption->Row >= TopRow) && (MenuOption->Row <= BottomRow)) {
+ PrintStringAt (MenuOption->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]) != 0) {
+ if (Temp == 0) {
+ MenuOption->Row++;
+ }
+ }
+
+ FreePool (OutputString);
+ if (Temp != 0) {
+ Temp--;
+ }
+ }
+
+ MenuOption->Row = OriginalRow;
+ gST->ConOut->SetAttribute (gST->ConOut, GetFieldTextColor ());
+ }
+ }
+ }
+
+ //
+ // This is the current selected statement
+ //
+ MenuOption = MENU_OPTION_FROM_LINK (NewPos);
+ Statement = MenuOption->ThisTag;
+
+ //
+ // Get the highlight statement.
+ //
+ gUserInput->SelectedStatement = Statement;
+ gSequence = (UINT16) MenuOption->Sequence;
+
+ //
+ // Record highlight row info for date/time opcode.
+ //
+ if (Statement->OpCode->OpCode == EFI_IFR_DATE_OP || Statement->OpCode->OpCode == EFI_IFR_TIME_OP) {
+ gHighligthMenuInfo.QuestionId = GetQuestionIdInfo(Statement->OpCode);
+ gHighligthMenuInfo.DisplayRow = (UINT16) MenuOption->Row;
+ } else {
+ gHighligthMenuInfo.QuestionId = 0;
+ gHighligthMenuInfo.DisplayRow = 0;
+ }
+
+ if (!IsSelectable (MenuOption)) {
+ RefreshKeyHelp(gFormData, Statement, FALSE);
+ break;
+ }
+
+ //
+ // Set reverse attribute
+ //
+ gST->ConOut->SetAttribute (gST->ConOut, GetHighlightTextColor ());
+ gST->ConOut->SetCursorPosition (gST->ConOut, MenuOption->Col, MenuOption->Row);
+
+ ProcessOptions (MenuOption, FALSE, &OptionString, TRUE);
+ if (OptionString != NULL) {
+ if (Statement->OpCode->OpCode == EFI_IFR_DATE_OP || Statement->OpCode->OpCode == EFI_IFR_TIME_OP) {
+ ProcessStringForDateTime(MenuOption, OptionString, FALSE);
+ }
+ Width = (UINT16) gOptionBlockWidth;
+
+ OriginalRow = MenuOption->Row;
+ GlyphWidth = 1;
+
+ for (Index = 0; GetLineByWidth (OptionString, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {
+ if ((Temp2 == 0) && (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]) != 0) {
+ if (Temp2 == 0) {
+ MenuOption->Row++;
+ }
+ }
+
+ FreePool (OutputString);
+ if (Temp2 != 0) {
+ Temp2--;
+ }
+ }
+
+ MenuOption->Row = OriginalRow;
+
+ FreePool (OptionString);
+ } else {
+ if (NewLine) {
+ OriginalRow = MenuOption->Row;
+
+ Width = GetWidth (Statement);
+ GlyphWidth = 1;
+
+ for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {
+ if ((Temp2 == 0) && (MenuOption->Row >= TopRow) && (MenuOption->Row <= BottomRow) ) {
+ PrintStringAt (MenuOption->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]) != 0) {
+ if (Temp2 == 0) {
+ MenuOption->Row++;
+ }
+ }
+
+ FreePool (OutputString);
+ if (Temp2 != 0) {
+ Temp2--;
+ }
+ }
+
+ MenuOption->Row = OriginalRow;
+
+ }
+ }
+
+ RefreshKeyHelp(gFormData, MenuOption->ThisTag, FALSE);
+
+ //
+ // Clear reverse attribute
+ //
+ gST->ConOut->SetAttribute (gST->ConOut, GetFieldTextColor ());
+ }
+ break;
+
+ case CfUpdateHelpString:
+ ControlFlag = CfPrepareToReadKey;
+ if ((FormData->Attribute & HII_DISPLAY_MODAL) != 0) {
+ break;
+ }
+
+ if (Repaint || NewLine) {
+ //
+ // Don't print anything if it is a NULL help token
+ //
+ ASSERT(MenuOption != NULL);
+ HelpInfo = ((EFI_IFR_STATEMENT_HEADER *) ((CHAR8 *)MenuOption->ThisTag->OpCode + sizeof (EFI_IFR_OP_HEADER)))->Help;
+ if (HelpInfo == 0 || !IsSelectable (MenuOption)) {
+ StringPtr = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);
+ } else {
+ StringPtr = GetToken (HelpInfo, gFormData->HiiHandle);
+ }
+
+ RowCount = BottomRow - TopRow + 1;
+ HelpPageIndex = 0;
+ //
+ // 1.Calculate how many line the help string need to print.
+ //
+ if (HelpString != NULL) {
+ FreePool (HelpString);
+ HelpString = NULL;
+ }
+ HelpLine = ProcessHelpString (StringPtr, &HelpString, &EachLineWidth, RowCount);
+ FreePool (StringPtr);
+
+ if (HelpLine > RowCount) {
+ MultiHelpPage = TRUE;
+ StringPtr = GetToken (STRING_TOKEN(ADJUST_HELP_PAGE_UP), gHiiHandle);
+ if (HelpHeaderString != NULL) {
+ FreePool (HelpHeaderString);
+ HelpHeaderString = NULL;
+ }
+ HelpHeaderLine = ProcessHelpString (StringPtr, &HelpHeaderString, &HeaderLineWidth, 0);
+ FreePool (StringPtr);
+ StringPtr = GetToken (STRING_TOKEN(ADJUST_HELP_PAGE_DOWN), gHiiHandle);
+ if (HelpBottomString != NULL) {
+ FreePool (HelpBottomString);
+ HelpBottomString = NULL;
+ }
+ HelpBottomLine = ProcessHelpString (StringPtr, &HelpBottomString, &BottomLineWidth, 0);
+ FreePool (StringPtr);
+ //
+ // Calculate the help page count.
+ //
+ if (HelpLine > 2 * RowCount - 2) {
+ HelpPageCount = (HelpLine - RowCount + 1) / (RowCount - 2) + 1;
+ if ((HelpLine - RowCount + 1) % (RowCount - 2) > 1) {
+ HelpPageCount += 1;
+ }
+ } else {
+ HelpPageCount = 2;
+ }
+ } else {
+ MultiHelpPage = FALSE;
+ }
+ }
+
+ //
+ // Check whether need to show the 'More(U/u)' at the begin.
+ // Base on current direct info, here shows aligned to the right side of the column.
+ // If the direction is multi line and aligned to right side may have problem, so
+ // add ASSERT code here.
+ //
+ if (HelpPageIndex > 0) {
+ gST->ConOut->SetAttribute (gST->ConOut, GetInfoTextColor ());
+ for (Index = 0; Index < HelpHeaderLine; Index++) {
+ ASSERT (HelpHeaderLine == 1);
+ ASSERT (GetStringWidth (HelpHeaderString) / 2 < (UINTN) (gHelpBlockWidth - 1));
+ PrintStringAtWithWidth (
+ gStatementDimensions.RightColumn - gHelpBlockWidth,
+ Index + TopRow,
+ gEmptyString,
+ gHelpBlockWidth
+ );
+ PrintStringAt (
+ gStatementDimensions.RightColumn - GetStringWidth (HelpHeaderString) / 2 - 1,
+ Index + TopRow,
+ &HelpHeaderString[Index * HeaderLineWidth]
+ );
+ }
+ }
+
+ gST->ConOut->SetAttribute (gST->ConOut, GetHelpTextColor ());
+ //
+ // Print the help string info.
+ //
+ if (!MultiHelpPage) {
+ for (Index = 0; Index < HelpLine; Index++) {
+ PrintStringAtWithWidth (
+ gStatementDimensions.RightColumn - gHelpBlockWidth,
+ Index + TopRow,
+ &HelpString[Index * EachLineWidth],
+ gHelpBlockWidth
+ );
+ }
+ for (; Index < RowCount; Index ++) {
+ PrintStringAtWithWidth (
+ gStatementDimensions.RightColumn - gHelpBlockWidth,
+ Index + TopRow,
+ gEmptyString,
+ gHelpBlockWidth
+ );
+ }
+ gST->ConOut->SetCursorPosition(gST->ConOut, gStatementDimensions.RightColumn-1, BottomRow);
+ } else {
+ if (HelpPageIndex == 0) {
+ for (Index = 0; Index < RowCount - HelpBottomLine; Index++) {
+ PrintStringAtWithWidth (
+ gStatementDimensions.RightColumn - gHelpBlockWidth,
+ Index + TopRow,
+ &HelpString[Index * EachLineWidth],
+ gHelpBlockWidth
+ );
+ }
+ } else {
+ for (Index = 0; (Index < RowCount - HelpBottomLine - HelpHeaderLine) &&
+ (Index + HelpPageIndex * (RowCount - 2) + 1 < HelpLine); Index++) {
+ PrintStringAtWithWidth (
+ gStatementDimensions.RightColumn - gHelpBlockWidth,
+ Index + TopRow + HelpHeaderLine,
+ &HelpString[(Index + HelpPageIndex * (RowCount - 2) + 1)* EachLineWidth],
+ gHelpBlockWidth
+ );
+ }
+ if (HelpPageIndex == HelpPageCount - 1) {
+ for (; Index < RowCount - HelpHeaderLine; Index ++) {
+ PrintStringAtWithWidth (
+ gStatementDimensions.RightColumn - gHelpBlockWidth,
+ Index + TopRow + HelpHeaderLine,
+ gEmptyString,
+ gHelpBlockWidth
+ );
+ }
+ gST->ConOut->SetCursorPosition(gST->ConOut, gStatementDimensions.RightColumn-1, BottomRow);
+ }
+ }
+ }
+
+ //
+ // Check whether need to print the 'More(D/d)' at the bottom.
+ // Base on current direct info, here shows aligned to the right side of the column.
+ // If the direction is multi line and aligned to right side may have problem, so
+ // add ASSERT code here.
+ //
+ if (HelpPageIndex < HelpPageCount - 1 && MultiHelpPage) {
+ gST->ConOut->SetAttribute (gST->ConOut, GetInfoTextColor ());
+ for (Index = 0; Index < HelpBottomLine; Index++) {
+ ASSERT (HelpBottomLine == 1);
+ ASSERT (GetStringWidth (HelpBottomString) / 2 < (UINTN) (gHelpBlockWidth - 1));
+ PrintStringAtWithWidth (
+ gStatementDimensions.RightColumn - gHelpBlockWidth,
+ BottomRow + Index - HelpBottomLine + 1,
+ gEmptyString,
+ gHelpBlockWidth
+ );
+ PrintStringAt (
+ gStatementDimensions.RightColumn - GetStringWidth (HelpBottomString) / 2 - 1,
+ BottomRow + Index - HelpBottomLine + 1,
+ &HelpBottomString[Index * BottomLineWidth]
+ );
+ }
+ }
+ //
+ // Reset this flag every time we finish using it.
+ //
+ Repaint = FALSE;
+ NewLine = FALSE;
+ break;
+
+ case CfPrepareToReadKey:
+ ControlFlag = CfReadKey;
+ ScreenOperation = UiNoOperation;
+ break;
+
+ case CfReadKey:
+ ControlFlag = CfScreenOperation;
+
+ //
+ // Wait for user's selection
+ //
+ while (TRUE) {
+ Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
+ if (!EFI_ERROR (Status)) {
+ EventType = UIEventKey;
+ break;
+ }
+
+ //
+ // If we encounter error, continue to read another key in.
+ //
+ if (Status != EFI_NOT_READY) {
+ continue;
+ }
+
+ EventType = UiWaitForEvent(gST->ConIn->WaitForKey);
+ if (EventType == UIEventKey) {
+ gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
+ }
+ break;
+ }
+
+ if (EventType == UIEventDriver) {
+ gUserInput->Action = BROWSER_ACTION_NONE;
+ ControlFlag = CfExit;
+ break;
+ }
+
+ if (EventType == UIEventTimeOut) {
+ gUserInput->Action = BROWSER_ACTION_FORM_EXIT;
+ ControlFlag = CfExit;
+ break;
+ }
+
+ switch (Key.UnicodeChar) {
+ case CHAR_CARRIAGE_RETURN:
+ if(MenuOption == NULL || MenuOption->GrayOut || MenuOption->ReadOnly) {
+ ControlFlag = CfReadKey;
+ break;
+ }
+
+ ScreenOperation = UiSelect;
+ gDirection = 0;
+ break;
+
+ //
+ // We will push the adjustment of these numeric values directly to the input handler
+ // NOTE: we won't handle manual input numeric
+ //
+ case '+':
+ case '-':
+ //
+ // If the screen has no menu items, and the user didn't select UiReset
+ // ignore the selection and go back to reading keys.
+ //
+ if(IsListEmpty (&gMenuOption) || MenuOption->GrayOut || MenuOption->ReadOnly) {
+ ControlFlag = CfReadKey;
+ break;
+ }
+
+ ASSERT(MenuOption != NULL);
+ Statement = MenuOption->ThisTag;
+ if ((Statement->OpCode->OpCode == EFI_IFR_DATE_OP)
+ || (Statement->OpCode->OpCode == EFI_IFR_TIME_OP)
+ || ((Statement->OpCode->OpCode == EFI_IFR_NUMERIC_OP) && (GetFieldFromNum(Statement->OpCode) != 0))
+ ){
+ if (Key.UnicodeChar == '+') {
+ gDirection = SCAN_RIGHT;
+ } else {
+ gDirection = SCAN_LEFT;
+ }
+
+ Status = ProcessOptions (MenuOption, TRUE, &OptionString, TRUE);
+ if (OptionString != NULL) {
+ FreePool (OptionString);
+ }
+ if (EFI_ERROR (Status)) {
+ //
+ // Repaint to clear possible error prompt pop-up
+ //
+ Repaint = TRUE;
+ NewLine = TRUE;
+ } else {
+ ControlFlag = CfExit;
+ }
+ }
+ break;
+
+ case '^':
+ ScreenOperation = UiUp;
+ break;
+
+ case 'V':
+ case 'v':
+ ScreenOperation = UiDown;
+ break;
+
+ case ' ':
+ if(IsListEmpty (&gMenuOption)) {
+ ControlFlag = CfReadKey;
+ break;
+ }
+
+ ASSERT(MenuOption != NULL);
+ if (MenuOption->ThisTag->OpCode->OpCode == EFI_IFR_CHECKBOX_OP && !MenuOption->GrayOut && !MenuOption->ReadOnly) {
+ ScreenOperation = UiSelect;
+ }
+ break;
+
+ case 'D':
+ case 'd':
+ if (!MultiHelpPage) {
+ ControlFlag = CfReadKey;
+ break;
+ }
+ ControlFlag = CfUpdateHelpString;
+ HelpPageIndex = HelpPageIndex < HelpPageCount - 1 ? HelpPageIndex + 1 : HelpPageCount - 1;
+ break;
+
+ case 'U':
+ case 'u':
+ if (!MultiHelpPage) {
+ ControlFlag = CfReadKey;
+ break;
+ }
+ ControlFlag = CfUpdateHelpString;
+ HelpPageIndex = HelpPageIndex > 0 ? HelpPageIndex - 1 : 0;
+ break;
+
+ case CHAR_NULL:
+ for (Index = 0; Index < mScanCodeNumber; Index++) {
+ if (Key.ScanCode == gScanCodeToOperation[Index].ScanCode) {
+ ScreenOperation = gScanCodeToOperation[Index].ScreenOperation;
+ break;
+ }
+ }
+
+ if (((FormData->Attribute & HII_DISPLAY_MODAL) != 0) && (Key.ScanCode == SCAN_ESC || Index == mScanCodeNumber)) {
+ //
+ // ModalForm has no ESC key and Hot Key.
+ //
+ ControlFlag = CfReadKey;
+ } else if (Index == mScanCodeNumber) {
+ //
+ // Check whether Key matches the registered hot key.
+ //
+ HotKey = NULL;
+ HotKey = GetHotKeyFromRegisterList (&Key);
+ if (HotKey != NULL) {
+ ScreenOperation = UiHotKey;
+ }
+ }
+ break;
+ }
+ break;
+
+ case CfScreenOperation:
+ if (ScreenOperation != UiReset) {
+ //
+ // If the screen has no menu items, and the user didn't select UiReset
+ // ignore the selection and go back to reading keys.
+ //
+ if (IsListEmpty (&gMenuOption)) {
+ ControlFlag = CfReadKey;
+ break;
+ }
+ }
+
+ for (Index = 0;
+ Index < sizeof (gScreenOperationToControlFlag) / sizeof (gScreenOperationToControlFlag[0]);
+ Index++
+ ) {
+ if (ScreenOperation == gScreenOperationToControlFlag[Index].ScreenOperation) {
+ ControlFlag = gScreenOperationToControlFlag[Index].ControlFlag;
+ break;
+ }
+ }
+ break;
+
+ case CfUiSelect:
+ ControlFlag = CfRepaint;
+
+ ASSERT(MenuOption != NULL);
+ Statement = MenuOption->ThisTag;
+ if (Statement->OpCode->OpCode == EFI_IFR_TEXT_OP) {
+ break;
+ }
+
+ switch (Statement->OpCode->OpCode) {
+ case EFI_IFR_REF_OP:
+ case EFI_IFR_ACTION_OP:
+ case EFI_IFR_RESET_BUTTON_OP:
+ ControlFlag = CfExit;
+ break;
+
+ default:
+ //
+ // Editable Questions: oneof, ordered list, checkbox, numeric, string, password
+ //
+ RefreshKeyHelp (gFormData, Statement, TRUE);
+ Status = ProcessOptions (MenuOption, TRUE, &OptionString, TRUE);
+
+ if (OptionString != NULL) {
+ FreePool (OptionString);
+ }
+
+ if (EFI_ERROR (Status)) {
+ Repaint = TRUE;
+ NewLine = TRUE;
+ RefreshKeyHelp (gFormData, Statement, FALSE);
+ break;
+ } else {
+ ControlFlag = CfExit;
+ break;
+ }
+ }
+ break;
+
+ case CfUiReset:
+ //
+ // We come here when someone press ESC
+ // If the policy is not exit front page when user press ESC, process here.
+ //
+ if (!FormExitPolicy()) {
+ Repaint = TRUE;
+ NewLine = TRUE;
+ ControlFlag = CfRepaint;
+ break;
+ }
+
+ //
+ // When user press ESC, it will try to show another menu, should clean the gSequence info.
+ //
+ if (gSequence != 0) {
+ gSequence = 0;
+ }
+
+ gUserInput->Action = BROWSER_ACTION_FORM_EXIT;
+ ControlFlag = CfExit;
+ break;
+
+ case CfUiHotKey:
+ ControlFlag = CfRepaint;
+
+ gUserInput->Action = HotKey->Action;
+ ControlFlag = CfExit;
+ break;
+
+ case CfUiLeft:
+ ControlFlag = CfRepaint;
+ ASSERT(MenuOption != NULL);
+ if ((MenuOption->ThisTag->OpCode->OpCode == EFI_IFR_DATE_OP) || (MenuOption->ThisTag->OpCode->OpCode == EFI_IFR_TIME_OP)) {
+ if (MenuOption->Sequence != 0) {
+ //
+ // In the middle or tail of the Date/Time op-code set, go left.
+ //
+ ASSERT(NewPos != NULL);
+ NewPos = NewPos->BackLink;
+ }
+ }
+ break;
+
+ case CfUiRight:
+ ControlFlag = CfRepaint;
+ ASSERT(MenuOption != NULL);
+ if ((MenuOption->ThisTag->OpCode->OpCode == EFI_IFR_DATE_OP) || (MenuOption->ThisTag->OpCode->OpCode == EFI_IFR_TIME_OP)) {
+ if (MenuOption->Sequence != 2) {
+ //
+ // In the middle or tail of the Date/Time op-code set, go left.
+ //
+ ASSERT(NewPos != NULL);
+ NewPos = NewPos->ForwardLink;
+ }
+ }
+ break;
+
+ case CfUiUp:
+ ControlFlag = CfRepaint;
+
+ SavedListEntry = NewPos;
+
+ ASSERT(NewPos != NULL);
+ //
+ // Adjust Date/Time position before we advance forward.
+ //
+ AdjustDateAndTimePosition (TRUE, &NewPos);
+ if (NewPos->BackLink != &gMenuOption) {
+ MenuOption = MENU_OPTION_FROM_LINK (NewPos);
+ ASSERT (MenuOption != NULL);
+ NewLine = TRUE;
+ NewPos = NewPos->BackLink;
+
+ PreviousMenuOption = MENU_OPTION_FROM_LINK (NewPos);
+ if (PreviousMenuOption->Row == 0) {
+ UpdateOptionSkipLines (PreviousMenuOption);
+ }
+ DistanceValue = PreviousMenuOption->Skip;
+ Difference = 0;
+ if (MenuOption->Row >= DistanceValue + TopRow) {
+ Difference = MoveToNextStatement (TRUE, &NewPos, MenuOption->Row - TopRow - DistanceValue);
+ }
+ NextMenuOption = MENU_OPTION_FROM_LINK (NewPos);
+
+ if (Difference < 0) {
+ //
+ // We hit the begining MenuOption that can be focused
+ // so we simply scroll to the top.
+ //
+ if (TopOfScreen != gMenuOption.ForwardLink) {
+ TopOfScreen = gMenuOption.ForwardLink;
+ Repaint = TRUE;
+ } else {
+ //
+ // Scroll up to the last page when we have arrived at top page.
+ //
+ NewPos = &gMenuOption;
+ TopOfScreen = &gMenuOption;
+ MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry);
+ ScreenOperation = UiPageUp;
+ ControlFlag = CfScreenOperation;
+ break;
+ }
+ } else if (MenuOption->Row < TopRow + DistanceValue + Difference) {
+ //
+ // Previous focus MenuOption is above the TopOfScreen, so we need to scroll
+ //
+ TopOfScreen = NewPos;
+ Repaint = TRUE;
+ SkipValue = 0;
+ } else if (!IsSelectable (NextMenuOption)) {
+ //
+ // Continue to go up until scroll to next page or the selectable option is found.
+ //
+ ScreenOperation = UiUp;
+ ControlFlag = CfScreenOperation;
+ }
+
+ //
+ // If we encounter a Date/Time op-code set, rewind to the first op-code of the set.
+ //
+ AdjustDateAndTimePosition (TRUE, &TopOfScreen);
+ AdjustDateAndTimePosition (TRUE, &NewPos);
+ MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry);
+ UpdateStatusBar (INPUT_ERROR, FALSE);
+ } else {
+ //
+ // Scroll up to the last page.
+ //
+ NewPos = &gMenuOption;
+ TopOfScreen = &gMenuOption;
+ MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry);
+ ScreenOperation = UiPageUp;
+ ControlFlag = CfScreenOperation;
+ }
+ break;
+
+ case CfUiPageUp:
+ //
+ // SkipValue means lines is skipped when show the top menu option.
+ //
+ ControlFlag = CfRepaint;
+
+ ASSERT(NewPos != NULL);
+ //
+ // Already at the first menu option, Check the skip value.
+ //
+ if (NewPos->BackLink == &gMenuOption) {
+ if (SkipValue == 0) {
+ NewLine = FALSE;
+ Repaint = FALSE;
+ } else {
+ NewLine = TRUE;
+ Repaint = TRUE;
+ SkipValue = 0;
+ }
+ break;
+ }
+
+ NewLine = TRUE;
+ Repaint = TRUE;
+
+ //
+ // SkipValue > (BottomRow - TopRow + 1) means current menu has more than one
+ // form of options to be show, so just update the SkipValue to show the next
+ // parts of options.
+ //
+ if (SkipValue > (INTN) (BottomRow - TopRow + 1)) {
+ SkipValue -= BottomRow - TopRow + 1;
+ break;
+ }
+
+ Link = TopOfScreen;
+ //
+ // First minus the menu of the top screen, it's value is SkipValue.
+ //
+ Index = (BottomRow + 1) - SkipValue;
+ while ((Index > TopRow) && (Link->BackLink != &gMenuOption)) {
+ Link = Link->BackLink;
+ PreviousMenuOption = MENU_OPTION_FROM_LINK (Link);
+ if (PreviousMenuOption->Row == 0) {
+ UpdateOptionSkipLines (PreviousMenuOption);
+ }
+ if (Index < PreviousMenuOption->Skip) {
+ break;
+ }
+ Index = Index - PreviousMenuOption->Skip;
+ }
+
+ if ((Link->BackLink == &gMenuOption) && (Index >= TopRow)) {
+ SkipValue = 0;
+ if (TopOfScreen == &gMenuOption) {
+ TopOfScreen = gMenuOption.ForwardLink;
+ NewPos = gMenuOption.BackLink;
+ MoveToNextStatement (TRUE, &NewPos, BottomRow - TopRow);
+ Repaint = FALSE;
+ } else if (TopOfScreen != Link) {
+ TopOfScreen = Link;
+ NewPos = Link;
+ MoveToNextStatement (FALSE, &NewPos, BottomRow - TopRow);
+ } else {
+ //
+ // Finally we know that NewPos is the last MenuOption can be focused.
+ //
+ Repaint = FALSE;
+ NewPos = Link;
+ MoveToNextStatement (FALSE, &NewPos, BottomRow - TopRow);
+ }
+ } else {
+ if (Index > TopRow) {
+ //
+ // At here, only case "Index < PreviousMenuOption->Skip" can reach here.
+ //
+ SkipValue = PreviousMenuOption->Skip - (Index - TopRow);
+ } else if (Index == TopRow) {
+ SkipValue = 0;
+ } else {
+ SkipValue = TopRow - Index;
+ }
+
+ //
+ // Move to the option in Next page.
+ //
+ if (TopOfScreen == &gMenuOption) {
+ NewPos = gMenuOption.BackLink;
+ MoveToNextStatement (TRUE, &NewPos, BottomRow - TopRow);
+ } else {
+ NewPos = Link;
+ MoveToNextStatement (FALSE, &NewPos, BottomRow - TopRow);
+ }
+
+ //
+ // There are more MenuOption needing scrolling up.
+ //
+ TopOfScreen = Link;
+ MenuOption = NULL;
+ }
+
+ //
+ // 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.
+ //
+ AdjustDateAndTimePosition (TRUE, &TopOfScreen);
+ AdjustDateAndTimePosition (TRUE, &NewPos);
+ break;
+
+ case CfUiPageDown:
+ //
+ // SkipValue means lines is skipped when show the top menu option.
+ //
+ ControlFlag = CfRepaint;
+
+ ASSERT (NewPos != NULL);
+ if (NewPos->ForwardLink == &gMenuOption) {
+ NewLine = FALSE;
+ Repaint = FALSE;
+ break;
+ }
+
+ NewLine = TRUE;
+ Repaint = TRUE;
+ Link = TopOfScreen;
+ NextMenuOption = MENU_OPTION_FROM_LINK (Link);
+ Index = TopRow + NextMenuOption->Skip - SkipValue;
+ //
+ // Count to the menu option which will show at the top of the next form.
+ //
+ while ((Index <= BottomRow + 1) && (Link->ForwardLink != &gMenuOption)) {
+ Link = Link->ForwardLink;
+ NextMenuOption = MENU_OPTION_FROM_LINK (Link);
+ Index = Index + NextMenuOption->Skip;
+ }
+
+ if ((Link->ForwardLink == &gMenuOption) && (Index <= BottomRow + 1)) {
+ //
+ // Finally we know that NewPos is the last MenuOption can be focused.
+ //
+ Repaint = FALSE;
+ MoveToNextStatement (TRUE, &Link, Index - TopRow);
+ } else {
+ //
+ // Calculate the skip line for top of screen menu.
+ //
+ if (Link == TopOfScreen) {
+ //
+ // The top of screen menu option occupies the entire form.
+ //
+ SkipValue += BottomRow - TopRow + 1;
+ } else {
+ SkipValue = NextMenuOption->Skip - (Index - (BottomRow + 1));
+ }
+
+ TopOfScreen = Link;
+ MenuOption = NULL;
+ //
+ // Move to the Next selectable menu.
+ //
+ MoveToNextStatement (FALSE, &Link, BottomRow - TopRow);
+ }
+
+ //
+ // Save the menu as the next highlight menu.
+ //
+ 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 last page.
+ //
+ AdjustDateAndTimePosition (TRUE, &TopOfScreen);
+ AdjustDateAndTimePosition (TRUE, &NewPos);
+ break;
+
+ case CfUiDown:
+ //
+ // SkipValue means lines is skipped when show the top menu option.
+ // NewPos points to the menu which is highlighted now.
+ //
+ ControlFlag = CfRepaint;
+
+ //
+ // 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.
+ //
+ SavedListEntry = NewPos;
+ AdjustDateAndTimePosition (FALSE, &NewPos);
+
+ if (NewPos->ForwardLink != &gMenuOption) {
+ MenuOption = MENU_OPTION_FROM_LINK (NewPos);
+ NewLine = TRUE;
+ NewPos = NewPos->ForwardLink;
+
+ Difference = 0;
+ //
+ // Current menu not at the bottom of the form.
+ //
+ if (BottomRow >= MenuOption->Row + MenuOption->Skip) {
+ //
+ // Find the next selectable menu.
+ //
+ Difference = MoveToNextStatement (FALSE, &NewPos, BottomRow - MenuOption->Row - MenuOption->Skip);
+ //
+ // We hit the end of MenuOption that can be focused
+ // so we simply scroll to the first page.
+ //
+ if (Difference < 0) {
+ //
+ // Scroll to the first page.
+ //
+ if (TopOfScreen != gMenuOption.ForwardLink) {
+ TopOfScreen = gMenuOption.ForwardLink;
+ Repaint = TRUE;
+ MenuOption = NULL;
+ } else {
+ MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry);
+ }
+ NewPos = gMenuOption.ForwardLink;
+ MoveToNextStatement (FALSE, &NewPos, BottomRow - TopRow);
+
+ SkipValue = 0;
+ //
+ // If we are at the end of the list and sitting on a Date/Time op, rewind to the head.
+ //
+ AdjustDateAndTimePosition (TRUE, &TopOfScreen);
+ AdjustDateAndTimePosition (TRUE, &NewPos);
+ break;
+ }
+ }
+ NextMenuOption = MENU_OPTION_FROM_LINK (NewPos);
+ if (NextMenuOption->Row == 0) {
+ UpdateOptionSkipLines (NextMenuOption);
+ }
+ DistanceValue = Difference + NextMenuOption->Skip;
+
+ Temp = MenuOption->Row + MenuOption->Skip + DistanceValue - 1;
+ if ((MenuOption->Row + MenuOption->Skip == BottomRow + 1) &&
+ (NextMenuOption->ThisTag->OpCode->OpCode == EFI_IFR_DATE_OP ||
+ NextMenuOption->ThisTag->OpCode->OpCode == EFI_IFR_TIME_OP)
+ ) {
+ Temp ++;
+ }
+
+ //
+ // If we are going to scroll, update TopOfScreen
+ //
+ 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 = MENU_OPTION_FROM_LINK (TopOfScreen);
+
+ //
+ // If bottom op-code is more than one line or top op-code is more than one line
+ //
+ if ((DistanceValue > 1) || (SavedMenuOption->Skip > 1)) {
+ //
+ // Is the bottom op-code greater than or equal in size to the top op-code?
+ //
+ if ((Temp - BottomRow) >= (SavedMenuOption->Skip - SkipValue)) {
+ //
+ // Skip the top op-code
+ //
+ TopOfScreen = TopOfScreen->ForwardLink;
+ Difference = (Temp - BottomRow) - (SavedMenuOption->Skip - SkipValue);
+
+ SavedMenuOption = MENU_OPTION_FROM_LINK (TopOfScreen);
+
+ //
+ // If we have a remainder, skip that many more op-codes until we drain the remainder
+ //
+ while (Difference >= (INTN) SavedMenuOption->Skip) {
+ //
+ // Since the Difference is greater than or equal to this op-code's skip value, skip it
+ //
+ Difference = Difference - (INTN) SavedMenuOption->Skip;
+ TopOfScreen = TopOfScreen->ForwardLink;
+ SavedMenuOption = MENU_OPTION_FROM_LINK (TopOfScreen);
+ }
+ //
+ // 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 += (Temp - BottomRow) - 1;
+ }
+ } else {
+ if ((SkipValue + 1) == (INTN) SavedMenuOption->Skip) {
+ TopOfScreen = TopOfScreen->ForwardLink;
+ break;
+ }
+ }
+ //
+ // 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 if (SavedMenuOption->Skip == 1) {
+ SkipValue = 0;
+ } else {
+ SkipValue = 0;
+ TopOfScreen = TopOfScreen->ForwardLink;
+ }
+ } while (SavedMenuOption->Skip == 0);
+
+ Repaint = TRUE;
+ } else if (!IsSelectable (NextMenuOption)) {
+ //
+ // Continue to go down until scroll to next page or the selectable option is found.
+ //
+ ScreenOperation = UiDown;
+ ControlFlag = CfScreenOperation;
+ }
+
+ MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry);
+
+ UpdateStatusBar (INPUT_ERROR, FALSE);
+
+ } else {
+ //
+ // Scroll to the first page.
+ //
+ if (TopOfScreen != gMenuOption.ForwardLink) {
+ TopOfScreen = gMenuOption.ForwardLink;
+ Repaint = TRUE;
+ MenuOption = NULL;
+ } else {
+ //
+ // Need to remove the current highlight menu.
+ // MenuOption saved the last highlight menu info.
+ //
+ MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry);
+ }
+
+ SkipValue = 0;
+ NewLine = TRUE;
+ //
+ // Get the next highlight menu.
+ //
+ NewPos = gMenuOption.ForwardLink;
+ MoveToNextStatement (FALSE, &NewPos, BottomRow - TopRow);
+ }
+
+ //
+ // If we are at the end of the list and sitting on a Date/Time op, rewind to the head.
+ //
+ AdjustDateAndTimePosition (TRUE, &TopOfScreen);
+ AdjustDateAndTimePosition (TRUE, &NewPos);
+ break;
+
+ case CfUiNoOperation:
+ ControlFlag = CfRepaint;
+ break;
+
+ case CfExit:
+ gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));
+ if (HelpString != NULL) {
+ FreePool (HelpString);
+ }
+ if (HelpHeaderString != NULL) {
+ FreePool (HelpHeaderString);
+ }
+ if (HelpBottomString != NULL) {
+ FreePool (HelpBottomString);
+ }
+ return EFI_SUCCESS;
+
+ default:
+ break;
+ }
+ }
+}
+
+/**
+
+ Base on the browser status info to show an pop up message.
+
+**/
+VOID
+BrowserStatusProcess (
+ VOID
+ )
+{
+ CHAR16 *ErrorInfo;
+ EFI_INPUT_KEY Key;
+
+ if (gFormData->BrowserStatus == BROWSER_SUCCESS) {
+ return;
+ }
+
+ if (gFormData->ErrorString != NULL) {
+ ErrorInfo = gFormData->ErrorString;
+ } else {
+ switch (gFormData->BrowserStatus) {
+ case BROWSER_SUBMIT_FAIL:
+ ErrorInfo = gSaveFailed;
+ break;
+
+ case BROWSER_NO_SUBMIT_IF:
+ ErrorInfo = gNoSubmitIf;
+ break;
+
+ case BROWSER_FORM_NOT_FOUND:
+ ErrorInfo = gFormNotFound;
+ break;
+
+ case BROWSER_FORM_SUPPRESS:
+ ErrorInfo = gFormSuppress;
+ break;
+
+ case BROWSER_PROTOCOL_NOT_FOUND:
+ ErrorInfo = gProtocolNotFound;
+ break;
+
+ default:
+ ErrorInfo = gBrwoserError;
+ break;
+ }
+ }
+
+ //
+ // Error occur, prompt error message.
+ //
+ do {
+ CreateDialog (&Key, gEmptyString, ErrorInfo, gPressEnter, gEmptyString, NULL);
+ } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
+}
+
+/**
+ Display one form, and return user input.
+
+ @param FormData Form Data to be shown.
+ @param UserInputData User input data.
+
+ @retval EFI_SUCCESS 1.Form Data is shown, and user input is got.
+ 2.Error info has show and return.
+ @retval EFI_INVALID_PARAMETER The input screen dimension is not valid
+ @retval EFI_NOT_FOUND New form data has some error.
+**/
+EFI_STATUS
+EFIAPI
+FormDisplay (
+ IN FORM_DISPLAY_ENGINE_FORM *FormData,
+ OUT USER_INPUT *UserInputData
+ )
+{
+ EFI_STATUS Status;
+
+ ASSERT (FormData != NULL);
+ if (FormData == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ gUserInput = UserInputData;
+ gFormData = FormData;
+
+ //
+ // Process the status info first.
+ //
+ BrowserStatusProcess();
+ if (UserInputData == NULL) {
+ //
+ // UserInputData == NULL, means only need to print the error info, return here.
+ //
+ return EFI_SUCCESS;
+ }
+
+ ConvertStatementToMenu();
+
+ Status = DisplayPageFrame (FormData, &gStatementDimensions);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Check whether layout is changed.
+ //
+ if (mIsFirstForm
+ || (gOldFormEntry.HiiHandle != FormData->HiiHandle)
+ || (!CompareGuid (&gOldFormEntry.FormSetGuid, &FormData->FormSetGuid))
+ || (gOldFormEntry.FormId != FormData->FormId)) {
+ mStatementLayoutIsChanged = TRUE;
+ } else {
+ mStatementLayoutIsChanged = FALSE;
+ }
+
+ Status = UiDisplayMenu(FormData);
+
+ //
+ // Backup last form info.
+ //
+ mIsFirstForm = FALSE;
+ gOldFormEntry.HiiHandle = FormData->HiiHandle;
+ CopyGuid (&gOldFormEntry.FormSetGuid, &FormData->FormSetGuid);
+ gOldFormEntry.FormId = FormData->FormId;
+
+ return Status;
+}
+
+/**
+ Clear Screen to the initial state.
+**/
+VOID
+EFIAPI
+DriverClearDisplayPage (
+ VOID
+ )
+{
+ ClearDisplayPage ();
+ mIsFirstForm = TRUE;
+}
+
+/**
+ Set Buffer to Value for Size bytes.
+
+ @param Buffer Memory to set.
+ @param Size Number of bytes to set
+ @param Value Value of the set operation.
+
+**/
+VOID
+SetUnicodeMem (
+ IN VOID *Buffer,
+ IN UINTN Size,
+ IN CHAR16 Value
+ )
+{
+ CHAR16 *Ptr;
+
+ Ptr = Buffer;
+ while ((Size--) != 0) {
+ *(Ptr++) = Value;
+ }
+}
+
+/**
+ Initialize Setup Browser driver.
+
+ @param ImageHandle The image handle.
+ @param SystemTable The system table.
+
+ @retval EFI_SUCCESS The Setup Browser module is initialized correctly..
+ @return Other value if failed to initialize the Setup Browser module.
+
+**/
+EFI_STATUS
+EFIAPI
+InitializeDisplayEngine (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_INPUT_KEY HotKey;
+ EFI_STRING NewString;
+ EDKII_FORM_BROWSER_EXTENSION2_PROTOCOL *FormBrowserEx2;
+
+ //
+ // Publish our HII data
+ //
+ gHiiHandle = HiiAddPackages (
+ &gDisplayEngineGuid,
+ ImageHandle,
+ DisplayEngineStrings,
+ NULL
+ );
+ ASSERT (gHiiHandle != NULL);
+
+ //
+ // Install Form Display protocol
+ //
+ Status = gBS->InstallProtocolInterface (
+ &mPrivateData.Handle,
+ &gEdkiiFormDisplayEngineProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &mPrivateData.FromDisplayProt
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ InitializeDisplayStrings();
+
+ ZeroMem (&gHighligthMenuInfo, sizeof (gHighligthMenuInfo));
+ ZeroMem (&gOldFormEntry, sizeof (gOldFormEntry));
+
+ //
+ // Use BrowserEx2 protocol to register HotKey.
+ //
+ Status = gBS->LocateProtocol (&gEdkiiFormBrowserEx2ProtocolGuid, NULL, (VOID **) &FormBrowserEx2);
+ if (!EFI_ERROR (Status)) {
+ //
+ // Register the default HotKey F9 and F10 again.
+ //
+ HotKey.UnicodeChar = CHAR_NULL;
+ HotKey.ScanCode = SCAN_F10;
+ NewString = HiiGetString (gHiiHandle, STRING_TOKEN (FUNCTION_TEN_STRING), NULL);
+ ASSERT (NewString != NULL);
+ FormBrowserEx2->RegisterHotKey (&HotKey, BROWSER_ACTION_SUBMIT, 0, NewString);
+
+ HotKey.ScanCode = SCAN_F9;
+ NewString = HiiGetString (gHiiHandle, STRING_TOKEN (FUNCTION_NINE_STRING), NULL);
+ ASSERT (NewString != NULL);
+ FormBrowserEx2->RegisterHotKey (&HotKey, BROWSER_ACTION_DEFAULT, EFI_HII_DEFAULT_CLASS_STANDARD, NewString);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This is the default unload handle for display core drivers.
+
+ @param[in] ImageHandle The drivers' driver image.
+
+ @retval EFI_SUCCESS The image is unloaded.
+ @retval Others Failed to unload the image.
+
+**/
+EFI_STATUS
+EFIAPI
+UnloadDisplayEngine (
+ IN EFI_HANDLE ImageHandle
+ )
+{
+ HiiRemovePackages(gHiiHandle);
+
+ FreeDisplayStrings ();
+
+ return EFI_SUCCESS;
+}
diff --git a/MdeModulePkg/Universal/DisplayEngineDxe/FormDisplay.h b/MdeModulePkg/Universal/DisplayEngineDxe/FormDisplay.h
new file mode 100644
index 000000000..45bcadc7e
--- /dev/null
+++ b/MdeModulePkg/Universal/DisplayEngineDxe/FormDisplay.h
@@ -0,0 +1,589 @@
+/** @file
+ FormDiplay protocol to show Form
+
+Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that 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 __FORM_DISPLAY_H__
+#define __FORM_DISPLAY_H__
+
+
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/BaseLib.h>
+#include <Library/HiiLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PrintLib.h>
+#include <Library/CustomizedDisplayLib.h>
+
+#include <Protocol/FormBrowserEx2.h>
+#include <Protocol/SimpleTextIn.h>
+#include <Protocol/DisplayProtocol.h>
+
+#include <Guid/MdeModuleHii.h>
+
+//
+// This is the generated header file which includes whatever needs to be exported (strings + IFR)
+//
+extern UINT8 DisplayEngineStrings[];
+extern EFI_SCREEN_DESCRIPTOR gStatementDimensions;
+extern USER_INPUT *gUserInput;
+extern FORM_DISPLAY_ENGINE_FORM *gFormData;
+extern EFI_HII_HANDLE gHiiHandle;
+extern UINT16 gDirection;
+extern LIST_ENTRY gMenuOption;
+
+//
+// Browser Global Strings
+//
+extern CHAR16 *gSaveFailed;
+extern CHAR16 *gPromptForData;
+extern CHAR16 *gPromptForPassword;
+extern CHAR16 *gPromptForNewPassword;
+extern CHAR16 *gConfirmPassword;
+extern CHAR16 *gConfirmError;
+extern CHAR16 *gPassowordInvalid;
+extern CHAR16 *gPressEnter;
+extern CHAR16 *gEmptyString;
+extern CHAR16 *gMiniString;
+extern CHAR16 *gOptionMismatch;
+extern CHAR16 *gFormSuppress;
+extern CHAR16 *gProtocolNotFound;
+
+extern CHAR16 gPromptBlockWidth;
+extern CHAR16 gOptionBlockWidth;
+extern CHAR16 gHelpBlockWidth;
+extern CHAR16 *mUnknownString;
+
+//
+// Screen definitions
+//
+
+#define LEFT_SKIPPED_COLUMNS 3
+#define SCROLL_ARROW_HEIGHT 1
+#define POPUP_PAD_SPACE_COUNT 5
+#define POPUP_FRAME_WIDTH 2
+
+//
+// Display definitions
+//
+#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 SUBTITLE_INDENT 2
+
+//
+// This is the Input Error Message
+//
+#define INPUT_ERROR 1
+
+//
+// This is the NV RAM update required Message
+//
+#define NV_UPDATE_REQUIRED 2
+//
+// Time definitions
+//
+#define ONE_SECOND 10000000
+
+//
+// It take 23 characters including the NULL to print a 64 bits number with "[" and "]".
+// pow(2, 64) = [18446744073709551616]
+//
+#define MAX_NUMERIC_INPUT_WIDTH 23
+
+#define EFI_HII_EXPRESSION_INCONSISTENT_IF 0
+#define EFI_HII_EXPRESSION_NO_SUBMIT_IF 1
+#define EFI_HII_EXPRESSION_GRAY_OUT_IF 2
+#define EFI_HII_EXPRESSION_SUPPRESS_IF 3
+#define EFI_HII_EXPRESSION_DISABLE_IF 4
+
+//
+// Character definitions
+//
+#define CHAR_SPACE 0x0020
+
+#define FORM_DISPLAY_DRIVER_SIGNATURE SIGNATURE_32 ('F', 'D', 'D', 'V')
+typedef struct {
+ UINT32 Signature;
+
+ EFI_HANDLE Handle;
+
+ //
+ // Produced protocol
+ //
+ EDKII_FORM_DISPLAY_ENGINE_PROTOCOL FromDisplayProt;
+} FORM_DISPLAY_DRIVER_PRIVATE_DATA;
+
+
+typedef enum {
+ UiNoOperation,
+ UiSelect,
+ UiUp,
+ UiDown,
+ UiLeft,
+ UiRight,
+ UiReset,
+ UiPrevious,
+ UiPageUp,
+ UiPageDown,
+ UiHotKey,
+ UiMaxOperation
+} UI_SCREEN_OPERATION;
+
+typedef enum {
+ CfInitialization,
+ CfCheckSelection,
+ CfRepaint,
+ CfRefreshHighLight,
+ CfUpdateHelpString,
+ CfPrepareToReadKey,
+ CfReadKey,
+ CfScreenOperation,
+ CfUiSelect,
+ CfUiReset,
+ CfUiLeft,
+ CfUiRight,
+ CfUiUp,
+ CfUiPageUp,
+ CfUiPageDown,
+ CfUiDown,
+ CfUiDefault,
+ CfUiNoOperation,
+ CfExit,
+ CfUiHotKey,
+ CfMaxControlFlag
+} UI_CONTROL_FLAG;
+
+typedef enum {
+ UIEventNone,
+ UIEventKey,
+ UIEventTimeOut,
+ UIEventDriver
+} UI_EVENT_TYPE;
+
+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;
+
+typedef struct {
+ EFI_QUESTION_ID QuestionId;
+ UINT16 DisplayRow;
+} DISPLAY_HIGHLIGHT_MENU_INFO;
+
+#define UI_MENU_OPTION_SIGNATURE SIGNATURE_32 ('u', 'i', 'm', 'm')
+
+typedef struct {
+ UINTN Signature;
+ LIST_ENTRY Link;
+
+ EFI_HII_HANDLE Handle;
+ FORM_DISPLAY_ENGINE_STATEMENT *ThisTag;
+ UINT16 EntryNumber;
+
+ UINTN Row;
+ UINTN Col;
+ UINTN OptCol;
+ CHAR16 *Description;
+ UINTN Skip; // Number of lines
+
+ //
+ // Display item sequence for date/time
+ // Date: Month/Day/Year
+ // Sequence: 0 1 2
+ //
+ // Time: Hour : Minute : Second
+ // Sequence: 0 1 2
+ //
+ //
+ UINTN Sequence;
+
+ BOOLEAN GrayOut;
+ BOOLEAN ReadOnly;
+
+ //
+ // Whether user could change value of this item
+ //
+ BOOLEAN IsQuestion;
+ BOOLEAN NestInStatement;
+} UI_MENU_OPTION;
+
+#define MENU_OPTION_FROM_LINK(a) CR (a, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE)
+
+/**
+ Print Question Value according to it's storage width and display attributes.
+
+ @param Question The Question to be printed.
+ @param FormattedNumber Buffer for output string.
+ @param BufferSize The FormattedNumber buffer size in bytes.
+
+ @retval EFI_SUCCESS Print success.
+ @retval EFI_BUFFER_TOO_SMALL Buffer size is not enough for formatted number.
+
+**/
+EFI_STATUS
+PrintFormattedNumber (
+ IN FORM_DISPLAY_ENGINE_STATEMENT *Question,
+ IN OUT CHAR16 *FormattedNumber,
+ IN UINTN BufferSize
+ );
+
+/**
+ Set value of a data element in an Array by its Index.
+
+ @param Array The data array.
+ @param Type Type of the data in this array.
+ @param Index Zero based index for data in this array.
+ @param Value The value to be set.
+
+**/
+VOID
+SetArrayData (
+ IN VOID *Array,
+ IN UINT8 Type,
+ IN UINTN Index,
+ IN UINT64 Value
+ );
+
+/**
+ Return data element in an Array by its Index.
+
+ @param Array The data array.
+ @param Type Type of the data in this array.
+ @param Index Zero based index for data in this array.
+
+ @retval Value The data to be returned
+
+**/
+UINT64
+GetArrayData (
+ IN VOID *Array,
+ IN UINT8 Type,
+ IN UINTN Index
+ );
+
+/**
+ Search an Option of a Question by its value.
+
+ @param Question The Question
+ @param OptionValue Value for Option to be searched.
+
+ @retval Pointer Pointer to the found Option.
+ @retval NULL Option not found.
+
+**/
+DISPLAY_QUESTION_OPTION *
+ValueToOption (
+ IN FORM_DISPLAY_ENGINE_STATEMENT *Question,
+ IN EFI_HII_VALUE *OptionValue
+ );
+
+/**
+ Compare two Hii value.
+
+ @param Value1 Expression value to compare on left-hand.
+ @param Value2 Expression value to compare on right-hand.
+ @param Result Return value after compare.
+ retval 0 Two operators equal.
+ return Positive value if Value1 is greater than Value2.
+ retval Negative value if Value1 is less than Value2.
+ @param HiiHandle Only required for string compare.
+
+ @retval other Could not perform compare on two values.
+ @retval EFI_SUCCESS Compare the value success.
+
+**/
+EFI_STATUS
+CompareHiiValue (
+ IN EFI_HII_VALUE *Value1,
+ IN EFI_HII_VALUE *Value2,
+ OUT INTN *Result,
+ IN EFI_HII_HANDLE HiiHandle OPTIONAL
+ );
+
+/**
+ Draw a pop up windows based on the dimension, number of lines and
+ strings specified.
+
+ @param RequestedWidth The width of the pop-up.
+ @param NumberOfLines The number of lines.
+ @param ... A series of text strings that displayed in the pop-up.
+
+**/
+VOID
+EFIAPI
+CreateMultiStringPopUp (
+ IN UINTN RequestedWidth,
+ IN UINTN NumberOfLines,
+ ...
+ );
+
+/**
+ 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.
+ The output string format is:
+ Glyph Info + String info + '\0'.
+
+ In the code, it deals \r,\n,\r\n same as \n\r, also it not process the \r or \g.
+
+ @param InputString String description for this option.
+ @param LineWidth Width of the desired string to extract in CHAR16
+ characters
+ @param GlyphWidth The glyph width of the begin of the char in the string.
+ @param Index Where in InputString to start the copy process
+ @param OutputString Buffer to copy the string into
+
+ @return Returns the number of CHAR16 characters that were copied into the OutputString
+ buffer, include extra glyph info and '\0' info.
+
+**/
+UINT16
+GetLineByWidth (
+ IN CHAR16 *InputString,
+ IN UINT16 LineWidth,
+ IN OUT UINT16 *GlyphWidth,
+ IN OUT UINTN *Index,
+ OUT CHAR16 **OutputString
+ );
+
+
+/**
+ Get the string based on the StringId and HII Package List Handle.
+
+ @param Token The String's ID.
+ @param HiiHandle The Hii handle for this string package.
+
+ @return The output string.
+
+**/
+CHAR16 *
+GetToken (
+ IN EFI_STRING_ID Token,
+ IN EFI_HII_HANDLE HiiHandle
+ );
+
+/**
+ Count the storage space of a Unicode string.
+
+ This function handles the Unicode string with NARROW_CHAR
+ and WIDE_CHAR control characters. NARROW_HCAR and WIDE_CHAR
+ does not count in the resultant output. If a WIDE_CHAR is
+ hit, then 2 Unicode character will consume an output storage
+ space with size of CHAR16 till a NARROW_CHAR is hit.
+
+ If String is NULL, then ASSERT ().
+
+ @param String The input string to be counted.
+
+ @return Storage space for the input string.
+
+**/
+UINTN
+GetStringWidth (
+ IN CHAR16 *String
+ );
+
+/**
+ This routine reads a numeric value from the user input.
+
+ @param MenuOption Pointer to the current input menu.
+
+ @retval EFI_SUCCESS If numerical input is read successfully
+ @retval EFI_DEVICE_ERROR If operation fails
+
+**/
+EFI_STATUS
+GetNumericInput (
+ IN UI_MENU_OPTION *MenuOption
+ );
+
+/**
+ Get string or password input from user.
+
+ @param MenuOption Pointer to the current input menu.
+ @param Prompt The prompt string shown on popup window.
+ @param StringPtr Old user input and destination for use input string.
+
+ @retval EFI_SUCCESS If string input is read successfully
+ @retval EFI_DEVICE_ERROR If operation fails
+
+**/
+EFI_STATUS
+ReadString (
+ IN UI_MENU_OPTION *MenuOption,
+ IN CHAR16 *Prompt,
+ IN OUT CHAR16 *StringPtr
+ );
+
+/**
+ Draw a pop up windows based on the dimension, number of lines and
+ strings specified.
+
+ @param RequestedWidth The width of the pop-up.
+ @param NumberOfLines The number of lines.
+ @param Marker The variable argument list for the list of string to be printed.
+
+**/
+VOID
+CreateSharedPopUp (
+ IN UINTN RequestedWidth,
+ IN UINTN NumberOfLines,
+ IN VA_LIST Marker
+ );
+
+/**
+ Wait for a key to be pressed by user.
+
+ @param Key The key which is pressed by user.
+
+ @retval EFI_SUCCESS The function always completed successfully.
+
+**/
+EFI_STATUS
+WaitForKeyStroke (
+ OUT EFI_INPUT_KEY *Key
+ );
+
+/**
+ Get selection for OneOf and OrderedList (Left/Right will be ignored).
+
+ @param MenuOption Pointer to the current input menu.
+
+ @retval EFI_SUCCESS If Option input is processed successfully
+ @retval EFI_DEVICE_ERROR If operation fails
+
+**/
+EFI_STATUS
+GetSelectionInputPopUp (
+ IN UI_MENU_OPTION *MenuOption
+ );
+
+/**
+ Process the help string: Split StringPtr to several lines of strings stored in
+ FormattedString and the glyph width of each line cannot exceed gHelpBlockWidth.
+
+ @param StringPtr The entire help string.
+ @param FormattedString The oupput formatted string.
+ @param EachLineWidth The max string length of each line in the formatted string.
+ @param RowCount TRUE: if Question is selected.
+
+**/
+UINTN
+ProcessHelpString (
+ IN CHAR16 *StringPtr,
+ OUT CHAR16 **FormattedString,
+ OUT UINT16 *EachLineWidth,
+ IN UINTN RowCount
+ );
+
+/**
+ Process a Question's Option (whether selected or un-selected).
+
+ @param MenuOption The MenuOption for this Question.
+ @param Selected TRUE: if Question is selected.
+ @param OptionString Pointer of the Option String to be displayed.
+ @param SkipErrorValue Whether need to return when value without option for it.
+
+ @retval EFI_SUCCESS Question Option process success.
+ @retval Other Question Option process fail.
+
+**/
+EFI_STATUS
+ProcessOptions (
+ IN UI_MENU_OPTION *MenuOption,
+ IN BOOLEAN Selected,
+ OUT CHAR16 **OptionString,
+ IN BOOLEAN SkipErrorValue
+ );
+
+/**
+ Set Buffer to Value for Size bytes.
+
+ @param Buffer Memory to set.
+ @param Size Number of bytes to set
+ @param Value Value of the set operation.
+
+**/
+VOID
+SetUnicodeMem (
+ IN VOID *Buffer,
+ IN UINTN Size,
+ IN CHAR16 Value
+ );
+
+/**
+ Display one form, and return user input.
+
+ @param FormData Form Data to be shown.
+ @param UserInputData User input data.
+
+ @retval EFI_SUCCESS Form Data is shown, and user input is got.
+**/
+EFI_STATUS
+EFIAPI
+FormDisplay (
+ IN FORM_DISPLAY_ENGINE_FORM *FormData,
+ OUT USER_INPUT *UserInputData
+ );
+
+/**
+ Clear Screen to the initial state.
+**/
+VOID
+EFIAPI
+DriverClearDisplayPage (
+ VOID
+ );
+
+/**
+ Exit Display and Clear Screen to the original state.
+
+**/
+VOID
+EFIAPI
+ExitDisplay (
+ VOID
+ );
+
+/**
+ Process validate for one question.
+
+ @param Question The question which need to validate.
+
+ @retval EFI_SUCCESS Question Option process success.
+ @retval Other Question Option process fail.
+
+**/
+EFI_STATUS
+ValidateQuestion (
+ IN FORM_DISPLAY_ENGINE_STATEMENT *Question
+ );
+
+#endif
diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserStr.uni b/MdeModulePkg/Universal/DisplayEngineDxe/FormDisplayStr.uni
index bb6414d20..0ee7f4630 100644
--- a/MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserStr.uni
+++ b/MdeModulePkg/Universal/DisplayEngineDxe/FormDisplayStr.uni
Binary files differ
diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/InputHandler.c b/MdeModulePkg/Universal/DisplayEngineDxe/InputHandler.c
index 844590770..a58e12f12 100644
--- a/MdeModulePkg/Universal/SetupBrowserDxe/InputHandler.c
+++ b/MdeModulePkg/Universal/DisplayEngineDxe/InputHandler.c
@@ -12,8 +12,38 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
-#include "Setup.h"
+#include "FormDisplay.h"
+/**
+ Get maximum and minimum info from this opcode.
+
+ @param OpCode Pointer to the current input opcode.
+ @param Minimum The minimum size info for this opcode.
+ @param Maximum The maximum size info for this opcode.
+
+**/
+VOID
+GetFieldFromOp (
+ IN EFI_IFR_OP_HEADER *OpCode,
+ OUT UINTN *Minimum,
+ OUT UINTN *Maximum
+ )
+{
+ EFI_IFR_STRING *StringOp;
+ EFI_IFR_PASSWORD *PasswordOp;
+ if (OpCode->OpCode == EFI_IFR_STRING_OP) {
+ StringOp = (EFI_IFR_STRING *) OpCode;
+ *Minimum = StringOp->MinSize;
+ *Maximum = StringOp->MaxSize;
+ } else if (OpCode->OpCode == EFI_IFR_PASSWORD_OP) {
+ PasswordOp = (EFI_IFR_PASSWORD *) OpCode;
+ *Minimum = PasswordOp->MinSize;
+ *Maximum = PasswordOp->MaxSize;
+ } else {
+ *Minimum = 0;
+ *Maximum = 0;
+ }
+}
/**
Get string or password input from user.
@@ -52,11 +82,11 @@ ReadString (
BOOLEAN CursorVisible;
UINTN Minimum;
UINTN Maximum;
- FORM_BROWSER_STATEMENT *Question;
+ FORM_DISPLAY_ENGINE_STATEMENT *Question;
BOOLEAN IsPassword;
- DimensionsWidth = gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn;
- DimensionsHeight = gScreenDimensions.BottomRow - gScreenDimensions.TopRow;
+ DimensionsWidth = gStatementDimensions.RightColumn - gStatementDimensions.LeftColumn;
+ DimensionsHeight = gStatementDimensions.BottomRow - gStatementDimensions.TopRow;
NullCharacter = CHAR_NULL;
ScreenSize = GetStringWidth (Prompt) / sizeof (CHAR16);
@@ -64,10 +94,9 @@ ReadString (
Space[1] = CHAR_NULL;
Question = MenuOption->ThisTag;
- Minimum = (UINTN) Question->Minimum;
- Maximum = (UINTN) Question->Maximum;
+ GetFieldFromOp(Question->OpCode, &Minimum, &Maximum);
- if (Question->Operand == EFI_IFR_PASSWORD_OP) {
+ if (Question->OpCode->OpCode == EFI_IFR_PASSWORD_OP) {
IsPassword = TRUE;
} else {
IsPassword = FALSE;
@@ -87,14 +116,14 @@ ReadString (
BufferedString = AllocateZeroPool (ScreenSize * 2);
ASSERT (BufferedString);
- Start = (DimensionsWidth - ScreenSize - 2) / 2 + gScreenDimensions.LeftColumn + 1;
- Top = ((DimensionsHeight - 6) / 2) + gScreenDimensions.TopRow - 1;
+ Start = (DimensionsWidth - ScreenSize - 2) / 2 + gStatementDimensions.LeftColumn + 1;
+ Top = ((DimensionsHeight - 6) / 2) + gStatementDimensions.TopRow - 1;
//
// Display prompt for string
//
+ // CreateDialog (NULL, "", Prompt, Space, "", NULL);
CreateMultiStringPopUp (ScreenSize, 4, &NullCharacter, Prompt, Space, &NullCharacter);
-
gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_BLACK, EFI_LIGHTGRAY));
CursorVisible = gST->ConOut->Mode->CursorVisible;
@@ -122,7 +151,7 @@ ReadString (
BufferedString[Count] = StringPtr[Index];
if (IsPassword) {
- PrintChar (L'*');
+ PrintCharAt ((UINTN)-1, (UINTN)-1, L'*');
}
}
@@ -181,7 +210,7 @@ ReadString (
// To save code space, we can then treat this as an error and return back to the menu.
//
do {
- CreateDialog (4, TRUE, 0, NULL, &Key, &NullCharacter, gMiniString, gPressEnter, &NullCharacter);
+ CreateDialog (&Key, &NullCharacter, gMiniString, gPressEnter, &NullCharacter, NULL);
} while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
FreePool (TempString);
@@ -258,7 +287,7 @@ ReadString (
BufferedString[Count] = StringPtr[Index];
if (IsPassword) {
- PrintChar (L'*');
+ PrintCharAt ((UINTN)-1, (UINTN)-1, L'*');
}
}
@@ -279,12 +308,12 @@ ReadString (
like: Year change: 2012.02.29 -> 2013.02.29 -> 2013.02.01
Month change: 2013.03.29 -> 2013.02.29 -> 2013.02.28
- @param Question Pointer to current question.
+ @param QuestionValue Pointer to current question.
@param Sequence The sequence of the field in the question.
**/
VOID
AdjustQuestionValue (
- IN FORM_BROWSER_STATEMENT *Question,
+ IN EFI_HII_VALUE *QuestionValue,
IN UINT8 Sequence
)
{
@@ -293,12 +322,8 @@ AdjustQuestionValue (
UINT8 Maximum;
UINT8 Minimum;
- if (Question->Operand != EFI_IFR_DATE_OP) {
- return;
- }
-
- Month = Question->HiiValue.Value.date.Month;
- Year = Question->HiiValue.Value.date.Year;
+ Month = QuestionValue->Value.date.Month;
+ Year = QuestionValue->Value.date.Year;
Minimum = 1;
switch (Month) {
@@ -324,8 +349,8 @@ AdjustQuestionValue (
// Change the month area.
//
if (Sequence == 0) {
- if (Question->HiiValue.Value.date.Day > Maximum) {
- Question->HiiValue.Value.date.Day = Maximum;
+ if (QuestionValue->Value.date.Day > Maximum) {
+ QuestionValue->Value.date.Day = Maximum;
}
}
@@ -333,16 +358,76 @@ AdjustQuestionValue (
// Change the Year area.
//
if (Sequence == 2) {
- if (Question->HiiValue.Value.date.Day > Maximum) {
- Question->HiiValue.Value.date.Day = Minimum;
+ if (QuestionValue->Value.date.Day > Maximum) {
+ QuestionValue->Value.date.Day = Minimum;
}
}
}
/**
+ Get field info from numeric opcode.
+
+ @param OpCode Pointer to the current input opcode.
+ @param Minimum The minimum size info for this opcode.
+ @param Maximum The maximum size info for this opcode.
+ @param Step The step size info for this opcode.
+ @param StorageWidth The storage width info for this opcode.
+
+**/
+VOID
+GetValueFromNum (
+ IN EFI_IFR_OP_HEADER *OpCode,
+ OUT UINT64 *Minimum,
+ OUT UINT64 *Maximum,
+ OUT UINT64 *Step,
+ OUT UINT16 *StorageWidth
+)
+{
+ EFI_IFR_NUMERIC *NumericOp;
+
+ NumericOp = (EFI_IFR_NUMERIC *) OpCode;
+
+ switch (NumericOp->Flags & EFI_IFR_NUMERIC_SIZE) {
+ case EFI_IFR_NUMERIC_SIZE_1:
+ *Minimum = NumericOp->data.u8.MinValue;
+ *Maximum = NumericOp->data.u8.MaxValue;
+ *Step = NumericOp->data.u8.Step;
+ *StorageWidth = (UINT16) sizeof (UINT8);
+ break;
+
+ case EFI_IFR_NUMERIC_SIZE_2:
+ *Minimum = NumericOp->data.u16.MinValue;
+ *Maximum = NumericOp->data.u16.MaxValue;
+ *Step = NumericOp->data.u16.Step;
+ *StorageWidth = (UINT16) sizeof (UINT16);
+ break;
+
+ case EFI_IFR_NUMERIC_SIZE_4:
+ *Minimum = NumericOp->data.u32.MinValue;
+ *Maximum = NumericOp->data.u32.MaxValue;
+ *Step = NumericOp->data.u32.Step;
+ *StorageWidth = (UINT16) sizeof (UINT32);
+ break;
+
+ case EFI_IFR_NUMERIC_SIZE_8:
+ *Minimum = NumericOp->data.u64.MinValue;
+ *Maximum = NumericOp->data.u64.MaxValue;
+ *Step = NumericOp->data.u64.Step;
+ *StorageWidth = (UINT16) sizeof (UINT64);
+ break;
+
+ default:
+ break;
+ }
+
+ if (*Maximum == 0) {
+ *Maximum = (UINT64) -1;
+ }
+}
+
+/**
This routine reads a numeric value from the user input.
- @param Selection Pointer to current selection.
@param MenuOption Pointer to the current input menu.
@retval EFI_SUCCESS If numerical input is read successfully
@@ -351,7 +436,6 @@ AdjustQuestionValue (
**/
EFI_STATUS
GetNumericInput (
- IN UI_MENU_SELECTION *Selection,
IN UI_MENU_OPTION *MenuOption
)
{
@@ -375,9 +459,9 @@ GetNumericInput (
UINT8 Digital;
EFI_INPUT_KEY Key;
EFI_HII_VALUE *QuestionValue;
- FORM_BROWSER_FORM *Form;
- FORM_BROWSER_FORMSET *FormSet;
- FORM_BROWSER_STATEMENT *Question;
+ FORM_DISPLAY_ENGINE_STATEMENT *Question;
+ EFI_IFR_NUMERIC *NumericOp;
+ UINT16 StorageWidth;
Column = MenuOption->OptCol;
Row = MenuOption->Row;
@@ -385,14 +469,13 @@ GetNumericInput (
Count = 0;
InputWidth = 0;
Digital = 0;
+ StorageWidth = 0;
+ Minimum = 0;
+ Maximum = 0;
+ NumericOp = NULL;
- FormSet = Selection->FormSet;
- Form = Selection->Form;
Question = MenuOption->ThisTag;
- QuestionValue = &Question->HiiValue;
- Step = Question->Step;
- Minimum = Question->Minimum;
- Maximum = Question->Maximum;
+ QuestionValue = &Question->CurrentValue;
//
// Only two case, user can enter to this function: Enter and +/- case.
@@ -400,7 +483,7 @@ GetNumericInput (
//
ManualInput = (BOOLEAN)(gDirection == 0 ? TRUE : FALSE);
- if ((Question->Operand == EFI_IFR_DATE_OP) || (Question->Operand == EFI_IFR_TIME_OP)) {
+ if ((Question->OpCode->OpCode == EFI_IFR_DATE_OP) || (Question->OpCode->OpCode == EFI_IFR_TIME_OP)) {
DateOrTime = TRUE;
} else {
DateOrTime = FALSE;
@@ -411,7 +494,7 @@ GetNumericInput (
//
EraseLen = 0;
EditValue = 0;
- if (Question->Operand == EFI_IFR_DATE_OP) {
+ if (Question->OpCode->OpCode == EFI_IFR_DATE_OP) {
Step = 1;
Minimum = 1;
@@ -457,7 +540,7 @@ GetNumericInput (
default:
break;
}
- } else if (Question->Operand == EFI_IFR_TIME_OP) {
+ } else if (Question->OpCode->OpCode == EFI_IFR_TIME_OP) {
Step = 1;
Minimum = 0;
@@ -484,18 +567,15 @@ GetNumericInput (
break;
}
} else {
- //
- // Numeric
- //
- EraseLen = gOptionBlockWidth;
+ ASSERT (Question->OpCode->OpCode == EFI_IFR_NUMERIC_OP);
+ NumericOp = (EFI_IFR_NUMERIC *) Question->OpCode;
+ GetValueFromNum(Question->OpCode, &Minimum, &Maximum, &Step, &StorageWidth);
EditValue = QuestionValue->Value.u64;
- if (Maximum == 0) {
- Maximum = (UINT64) -1;
- }
+ EraseLen = gOptionBlockWidth;
}
- if ((Question->Operand == EFI_IFR_NUMERIC_OP) &&
- ((Question->Flags & EFI_IFR_DISPLAY) == EFI_IFR_DISPLAY_UINT_HEX)) {
+ if ((Question->OpCode->OpCode == EFI_IFR_NUMERIC_OP) && (NumericOp != NULL) &&
+ ((NumericOp->Flags & EFI_IFR_DISPLAY) == EFI_IFR_DISPLAY_UINT_HEX)) {
HexInput = TRUE;
} else {
HexInput = FALSE;
@@ -505,11 +585,11 @@ GetNumericInput (
// Enter from "Enter" input, clear the old word showing.
//
if (ManualInput) {
- if (Question->Operand == EFI_IFR_NUMERIC_OP) {
+ if (Question->OpCode->OpCode == EFI_IFR_NUMERIC_OP) {
if (HexInput) {
- InputWidth = Question->StorageWidth * 2;
+ InputWidth = StorageWidth * 2;
} else {
- switch (Question->StorageWidth) {
+ switch (StorageWidth) {
case 1:
InputWidth = 3;
break;
@@ -538,11 +618,11 @@ GetNumericInput (
InputText[InputWidth + 1] = RIGHT_NUMERIC_DELIMITER;
InputText[InputWidth + 2] = L'\0';
- PrintAt (Column, Row, InputText);
+ PrintStringAt (Column, Row, InputText);
Column++;
}
- if (Question->Operand == EFI_IFR_DATE_OP) {
+ if (Question->OpCode->OpCode == EFI_IFR_DATE_OP) {
if (MenuOption->Sequence == 2) {
InputWidth = 4;
} else {
@@ -563,13 +643,13 @@ GetNumericInput (
}
InputText[InputWidth + 2] = L'\0';
- PrintAt (Column, Row, InputText);
+ PrintStringAt (Column, Row, InputText);
if (MenuOption->Sequence == 0) {
Column++;
}
}
- if (Question->Operand == EFI_IFR_TIME_OP) {
+ if (Question->OpCode->OpCode == EFI_IFR_TIME_OP) {
InputWidth = 2;
if (MenuOption->Sequence == 0) {
@@ -586,7 +666,7 @@ GetNumericInput (
}
InputText[InputWidth + 2] = L'\0';
- PrintAt (Column, Row, InputText);
+ PrintStringAt (Column, Row, InputText);
if (MenuOption->Sequence == 0) {
Column++;
}
@@ -654,7 +734,7 @@ TheKey2:
}
ZeroMem (FormattedNumber, 21 * sizeof (CHAR16));
- if (Question->Operand == EFI_IFR_DATE_OP) {
+ if (Question->OpCode->OpCode == EFI_IFR_DATE_OP) {
if (MenuOption->Sequence == 2) {
//
// Year
@@ -674,7 +754,7 @@ TheKey2:
ASSERT (EraseLen >= 1);
FormattedNumber[EraseLen - 1] = DATE_SEPARATOR;
}
- } else if (Question->Operand == EFI_IFR_TIME_OP) {
+ } else if (Question->OpCode->OpCode == EFI_IFR_TIME_OP) {
UnicodeSPrint (FormattedNumber, 21 * sizeof (CHAR16), L"%02d", (UINT8) EditValue);
if (MenuOption->Sequence == 0) {
@@ -689,11 +769,11 @@ TheKey2:
PrintFormattedNumber (Question, FormattedNumber, 21 * sizeof (CHAR16));
}
- gST->ConOut->SetAttribute (gST->ConOut, PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND);
+ gST->ConOut->SetAttribute (gST->ConOut, GetFieldTextColor ());
for (Loop = 0; Loop < EraseLen; Loop++) {
- PrintAt (MenuOption->OptCol + Loop, MenuOption->Row, L" ");
+ PrintStringAt (MenuOption->OptCol + Loop, MenuOption->Row, L" ");
}
- gST->ConOut->SetAttribute (gST->ConOut, PcdGet8 (PcdBrowserFieldTextHighlightColor) | PcdGet8 (PcdBrowserFieldBackgroundHighlightColor));
+ gST->ConOut->SetAttribute (gST->ConOut, GetHighlightTextColor ());
if (MenuOption->Sequence == 0) {
PrintCharAt (MenuOption->OptCol, Row, LEFT_NUMERIC_DELIMITER);
@@ -703,7 +783,7 @@ TheKey2:
PrintStringAt (Column, Row, FormattedNumber);
if (!DateOrTime || MenuOption->Sequence == 2) {
- PrintChar (RIGHT_NUMERIC_DELIMITER);
+ PrintCharAt ((UINTN)-1, (UINTN)-1, RIGHT_NUMERIC_DELIMITER);
}
}
@@ -730,16 +810,18 @@ EnterCarriageReturn:
// Validate input value with Minimum value.
//
if (EditValue < Minimum) {
- UpdateStatusBar (Selection, INPUT_ERROR, Question->QuestionFlags, TRUE);
+ UpdateStatusBar (INPUT_ERROR, TRUE);
break;
} else {
- UpdateStatusBar (Selection, INPUT_ERROR, Question->QuestionFlags, FALSE);
+ UpdateStatusBar (INPUT_ERROR, FALSE);
}
-
+
+ CopyMem (&gUserInput->InputValue, &Question->CurrentValue, sizeof (EFI_HII_VALUE));
+ QuestionValue = &gUserInput->InputValue;
//
// Store Edit value back to Question
//
- if (Question->Operand == EFI_IFR_DATE_OP) {
+ if (Question->OpCode->OpCode == EFI_IFR_DATE_OP) {
switch (MenuOption->Sequence) {
case 0:
QuestionValue->Value.date.Month = (UINT8) EditValue;
@@ -756,7 +838,7 @@ EnterCarriageReturn:
default:
break;
}
- } else if (Question->Operand == EFI_IFR_TIME_OP) {
+ } else if (Question->OpCode->OpCode == EFI_IFR_TIME_OP) {
switch (MenuOption->Sequence) {
case 0:
QuestionValue->Value.time.Hour = (UINT8) EditValue;
@@ -785,32 +867,12 @@ EnterCarriageReturn:
// Sample like: 2012.02.29 -> 2013.02.29 -> 2013.02.01
// 2013.03.29 -> 2013.02.29 -> 2013.02.28
//
- if (Question->Operand == EFI_IFR_DATE_OP &&
+ if (Question->OpCode->OpCode == EFI_IFR_DATE_OP &&
(MenuOption->Sequence == 0 || MenuOption->Sequence == 2)) {
- AdjustQuestionValue (Question, (UINT8)MenuOption->Sequence);
- }
-
- //
- // Check to see if the Value is something reasonable against consistency limitations.
- // If not, let's kick the error specified.
- //
- Status = ValidateQuestion (FormSet, Form, Question, EFI_HII_EXPRESSION_INCONSISTENT_IF);
- if (EFI_ERROR (Status)) {
- //
- // Input value is not valid, restore Question Value
- //
- GetQuestionValue (FormSet, Form, Question, GetSetValueWithEditBuffer);
- } else {
- SetQuestionValue (FormSet, Form, Question, GetSetValueWithEditBuffer);
- if (!DateOrTime || (Question->Storage != NULL)) {
- //
- // NV flag is unnecessary for RTC type of Date/Time
- //
- UpdateStatusBar (Selection, NV_UPDATE_REQUIRED, Question->QuestionFlags, TRUE);
- }
+ AdjustQuestionValue (QuestionValue, (UINT8)MenuOption->Sequence);
}
- return Status;
+ return ValidateQuestion (Question);
break;
case CHAR_BACKSPACE:
@@ -822,10 +884,10 @@ EnterCarriageReturn:
// Remove a character
//
EditValue = PreviousNumber[Count - 1];
- UpdateStatusBar (Selection, INPUT_ERROR, Question->QuestionFlags, FALSE);
+ UpdateStatusBar (INPUT_ERROR, FALSE);
Count--;
Column--;
- PrintAt (Column, Row, L" ");
+ PrintStringAt (Column, Row, L" ");
}
break;
@@ -839,12 +901,12 @@ EnterCarriageReturn:
} else if ((Key.UnicodeChar >= L'a') && (Key.UnicodeChar <= L'f')) {
Digital = (UINT8) (Key.UnicodeChar - L'a' + 0x0A);
} else {
- UpdateStatusBar (Selection, INPUT_ERROR, Question->QuestionFlags, TRUE);
+ UpdateStatusBar (INPUT_ERROR, TRUE);
break;
}
} else {
if (Key.UnicodeChar > L'9' || Key.UnicodeChar < L'0') {
- UpdateStatusBar (Selection, INPUT_ERROR, Question->QuestionFlags, TRUE);
+ UpdateStatusBar (INPUT_ERROR, TRUE);
break;
}
}
@@ -873,32 +935,178 @@ EnterCarriageReturn:
}
if (EditValue > Maximum) {
- UpdateStatusBar (Selection, INPUT_ERROR, Question->QuestionFlags, TRUE);
+ UpdateStatusBar (INPUT_ERROR, TRUE);
ASSERT (Count < sizeof (PreviousNumber) / sizeof (PreviousNumber[0]));
EditValue = PreviousNumber[Count];
break;
} else {
- UpdateStatusBar (Selection, INPUT_ERROR, Question->QuestionFlags, FALSE);
+ UpdateStatusBar (INPUT_ERROR, FALSE);
}
Count++;
ASSERT (Count < (sizeof (PreviousNumber) / sizeof (PreviousNumber[0])));
PreviousNumber[Count] = EditValue;
+ gST->ConOut->SetAttribute (gST->ConOut, GetHighlightTextColor ());
PrintCharAt (Column, Row, Key.UnicodeChar);
Column++;
}
break;
}
} while (TRUE);
+}
+
+/**
+ Adjust option order base on the question value.
+
+ @param Question Pointer to current question.
+ @param PopUpMenuLines The line number of the pop up menu.
+
+ @retval EFI_SUCCESS If Option input is processed successfully
+ @retval EFI_DEVICE_ERROR If operation fails
+
+**/
+EFI_STATUS
+AdjustOptionOrder (
+ IN FORM_DISPLAY_ENGINE_STATEMENT *Question,
+ OUT UINTN *PopUpMenuLines
+ )
+{
+ UINTN Index;
+ EFI_IFR_ORDERED_LIST *OrderList;
+ UINT8 *ValueArray;
+ UINT8 ValueType;
+ LIST_ENTRY *Link;
+ DISPLAY_QUESTION_OPTION *OneOfOption;
+ EFI_HII_VALUE *HiiValueArray;
+
+ Link = GetFirstNode (&Question->OptionListHead);
+ OneOfOption = DISPLAY_QUESTION_OPTION_FROM_LINK (Link);
+ ValueArray = Question->CurrentValue.Buffer;
+ ValueType = OneOfOption->OptionOpCode->Type;
+ OrderList = (EFI_IFR_ORDERED_LIST *) Question->OpCode;
+
+ for (Index = 0; Index < OrderList->MaxContainers; Index++) {
+ if (GetArrayData (ValueArray, ValueType, Index) == 0) {
+ break;
+ }
+ }
+
+ *PopUpMenuLines = Index;
+
+ //
+ // Prepare HiiValue array
+ //
+ HiiValueArray = AllocateZeroPool (*PopUpMenuLines * sizeof (EFI_HII_VALUE));
+ ASSERT (HiiValueArray != NULL);
+
+ for (Index = 0; Index < *PopUpMenuLines; Index++) {
+ HiiValueArray[Index].Type = ValueType;
+ HiiValueArray[Index].Value.u64 = GetArrayData (ValueArray, ValueType, Index);
+ }
+
+ for (Index = 0; Index < *PopUpMenuLines; Index++) {
+ OneOfOption = ValueToOption (Question, &HiiValueArray[*PopUpMenuLines - Index - 1]);
+ if (OneOfOption == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ RemoveEntryList (&OneOfOption->Link);
+
+ //
+ // Insert to head.
+ //
+ InsertHeadList (&Question->OptionListHead, &OneOfOption->Link);
+ }
+
+ FreePool (HiiValueArray);
+ return EFI_SUCCESS;
}
+/**
+ Base on the type to compare the value.
+
+ @param Value1 The first value need to compare.
+ @param Value2 The second value need to compare.
+ @param Type The value type for above two values.
+
+ @retval TRUE The two value are same.
+ @retval FALSE The two value are different.
+
+**/
+BOOLEAN
+IsValuesEqual (
+ IN EFI_IFR_TYPE_VALUE *Value1,
+ IN EFI_IFR_TYPE_VALUE *Value2,
+ IN UINT8 Type
+ )
+{
+ switch (Type) {
+ case EFI_IFR_TYPE_BOOLEAN:
+ case EFI_IFR_TYPE_NUM_SIZE_8:
+ return (BOOLEAN) (Value1->u8 == Value2->u8);
+
+ case EFI_IFR_TYPE_NUM_SIZE_16:
+ return (BOOLEAN) (Value1->u16 == Value2->u16);
+
+ case EFI_IFR_TYPE_NUM_SIZE_32:
+ return (BOOLEAN) (Value1->u32 == Value2->u32);
+
+ case EFI_IFR_TYPE_NUM_SIZE_64:
+ return (BOOLEAN) (Value1->u64 == Value2->u64);
+
+ default:
+ ASSERT (FALSE);
+ return FALSE;
+ }
+}
+
+/**
+ Base on the type to set the value.
+
+ @param Dest The dest value.
+ @param Source The source value.
+ @param Type The value type for above two values.
+
+**/
+VOID
+SetValuesByType (
+ OUT EFI_IFR_TYPE_VALUE *Dest,
+ IN EFI_IFR_TYPE_VALUE *Source,
+ IN UINT8 Type
+ )
+{
+ switch (Type) {
+ case EFI_IFR_TYPE_BOOLEAN:
+ Dest->b = Source->b;
+ break;
+
+ case EFI_IFR_TYPE_NUM_SIZE_8:
+ Dest->u8 = Source->u8;
+ break;
+
+ case EFI_IFR_TYPE_NUM_SIZE_16:
+ Dest->u16 = Source->u16;
+ break;
+
+ case EFI_IFR_TYPE_NUM_SIZE_32:
+ Dest->u32 = Source->u32;
+ break;
+
+ case EFI_IFR_TYPE_NUM_SIZE_64:
+ Dest->u64 = Source->u64;
+ break;
+
+ default:
+ ASSERT (FALSE);
+ break;
+ }
+}
/**
Get selection for OneOf and OrderedList (Left/Right will be ignored).
- @param Selection Pointer to current selection.
@param MenuOption Pointer to the current input menu.
@retval EFI_SUCCESS If Option input is processed successfully
@@ -907,7 +1115,6 @@ EnterCarriageReturn:
**/
EFI_STATUS
GetSelectionInputPopUp (
- IN UI_MENU_SELECTION *Selection,
IN UI_MENU_OPTION *MenuOption
)
{
@@ -934,16 +1141,16 @@ GetSelectionInputPopUp (
LIST_ENTRY *Link;
BOOLEAN OrderedList;
UINT8 *ValueArray;
+ UINT8 *ReturnValue;
UINT8 ValueType;
EFI_HII_VALUE HiiValue;
- EFI_HII_VALUE *HiiValueArray;
- UINTN OptionCount;
- QUESTION_OPTION *OneOfOption;
- QUESTION_OPTION *CurrentOption;
- FORM_BROWSER_STATEMENT *Question;
+ DISPLAY_QUESTION_OPTION *OneOfOption;
+ DISPLAY_QUESTION_OPTION *CurrentOption;
+ FORM_DISPLAY_ENGINE_STATEMENT *Question;
INTN Result;
+ EFI_IFR_ORDERED_LIST *OrderList;
- DimensionsWidth = gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn;
+ DimensionsWidth = gStatementDimensions.RightColumn - gStatementDimensions.LeftColumn;
ValueArray = NULL;
ValueType = 0;
@@ -954,81 +1161,33 @@ GetSelectionInputPopUp (
StringPtr = AllocateZeroPool ((gOptionBlockWidth + 1) * 2);
ASSERT (StringPtr);
+ ZeroMem (&HiiValue, sizeof (EFI_HII_VALUE));
+
Question = MenuOption->ThisTag;
- if (Question->Operand == EFI_IFR_ORDERED_LIST_OP) {
- ValueArray = Question->BufferValue;
- ValueType = Question->ValueType;
+ if (Question->OpCode->OpCode == EFI_IFR_ORDERED_LIST_OP) {
+ Link = GetFirstNode (&Question->OptionListHead);
+ OneOfOption = DISPLAY_QUESTION_OPTION_FROM_LINK (Link);
+ ValueArray = Question->CurrentValue.Buffer;
+ ValueType = OneOfOption->OptionOpCode->Type;
OrderedList = TRUE;
+ OrderList = (EFI_IFR_ORDERED_LIST *) Question->OpCode;
} else {
OrderedList = FALSE;
+ OrderList = NULL;
}
//
// Calculate Option count
//
+ PopUpMenuLines = 0;
if (OrderedList) {
- for (Index = 0; Index < Question->MaxContainers; Index++) {
- if (GetArrayData (ValueArray, ValueType, Index) == 0) {
- break;
- }
- }
-
- OptionCount = Index;
+ AdjustOptionOrder(Question, &PopUpMenuLines);
} else {
- OptionCount = 0;
Link = GetFirstNode (&Question->OptionListHead);
while (!IsNull (&Question->OptionListHead, Link)) {
- OneOfOption = QUESTION_OPTION_FROM_LINK (Link);
-
- OptionCount++;
-
- Link = GetNextNode (&Question->OptionListHead, Link);
- }
- }
-
- //
- // Move valid Option to list head.
- //
- PopUpMenuLines = 0;
- if (OrderedList) {
- //
- // Prepare HiiValue array
- //
- HiiValueArray = AllocateZeroPool (OptionCount * sizeof (EFI_HII_VALUE));
- ASSERT (HiiValueArray != NULL);
- for (Index = 0; Index < OptionCount; Index++) {
- HiiValueArray[Index].Type = ValueType;
- HiiValueArray[Index].Value.u64 = GetArrayData (ValueArray, ValueType, Index);
- }
-
- for (Index = 0; Index < OptionCount; Index++) {
- OneOfOption = ValueToOption (Question, &HiiValueArray[OptionCount - Index - 1]);
- if (OneOfOption == NULL) {
- return EFI_NOT_FOUND;
- }
-
- RemoveEntryList (&OneOfOption->Link);
-
- //
- // Insert to head.
- //
- InsertHeadList (&Question->OptionListHead, &OneOfOption->Link);
-
+ OneOfOption = DISPLAY_QUESTION_OPTION_FROM_LINK (Link);
PopUpMenuLines++;
- }
-
- FreePool (HiiValueArray);
- } else {
- Link = GetFirstNode (&Question->OptionListHead);
- for (Index = 0; Index < OptionCount; Index++) {
- OneOfOption = QUESTION_OPTION_FROM_LINK (Link);
Link = GetNextNode (&Question->OptionListHead, Link);
- if ((OneOfOption->SuppressExpression != NULL) &&
- EvaluateExpressionList(OneOfOption->SuppressExpression, FALSE, NULL, NULL) > ExpressFalse) {
- continue;
- } else {
- PopUpMenuLines++;
- }
}
}
@@ -1039,27 +1198,23 @@ GetSelectionInputPopUp (
HighlightOptionIndex = 0;
Link = GetFirstNode (&Question->OptionListHead);
for (Index = 0; Index < PopUpMenuLines; Index++) {
- OneOfOption = QUESTION_OPTION_FROM_LINK (Link);
- Link = GetNextNode (&Question->OptionListHead, Link);
-
- if (!OrderedList && (OneOfOption->SuppressExpression != NULL) &&
- EvaluateExpressionList(OneOfOption->SuppressExpression, FALSE, NULL, NULL) > ExpressFalse) {
- Index--;
- continue;
- }
+ OneOfOption = DISPLAY_QUESTION_OPTION_FROM_LINK (Link);
- StringPtr = GetToken (OneOfOption->Text, MenuOption->Handle);
+ StringPtr = GetToken (OneOfOption->OptionOpCode->Option, gFormData->HiiHandle);
if (StrLen (StringPtr) > PopUpWidth) {
PopUpWidth = StrLen (StringPtr);
}
FreePool (StringPtr);
-
- if (!OrderedList && (CompareHiiValue (&Question->HiiValue, &OneOfOption->Value, &Result, NULL) == EFI_SUCCESS) && (Result == 0)) {
+ HiiValue.Type = OneOfOption->OptionOpCode->Type;
+ SetValuesByType (&HiiValue.Value, &OneOfOption->OptionOpCode->Value, HiiValue.Type);
+ if (!OrderedList && (CompareHiiValue (&Question->CurrentValue, &HiiValue, &Result, NULL) == EFI_SUCCESS) && (Result == 0)) {
//
// Find current selected Option for OneOf
//
HighlightOptionIndex = Index;
}
+
+ Link = GetNextNode (&Question->OptionListHead, Link);
}
//
@@ -1068,16 +1223,16 @@ GetSelectionInputPopUp (
PopUpWidth = PopUpWidth + POPUP_PAD_SPACE_COUNT;
SavedAttribute = gST->ConOut->Mode->Attribute;
- gST->ConOut->SetAttribute (gST->ConOut, POPUP_TEXT | POPUP_BACKGROUND);
+ gST->ConOut->SetAttribute (gST->ConOut, GetPopupColor ());
if ((PopUpWidth + POPUP_FRAME_WIDTH) > DimensionsWidth) {
PopUpWidth = DimensionsWidth - POPUP_FRAME_WIDTH;
}
- Start = (DimensionsWidth - PopUpWidth - POPUP_FRAME_WIDTH) / 2 + gScreenDimensions.LeftColumn;
+ Start = (DimensionsWidth - PopUpWidth - POPUP_FRAME_WIDTH) / 2 + gStatementDimensions.LeftColumn;
End = Start + PopUpWidth + POPUP_FRAME_WIDTH;
- Top = gScreenDimensions.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT;
- Bottom = gScreenDimensions.BottomRow - STATUS_BAR_HEIGHT - gFooterHeight - 1;
+ Top = gStatementDimensions.TopRow;
+ Bottom = gStatementDimensions.BottomRow - 1;
MenuLinesInView = Bottom - Top - 1;
if (MenuLinesInView >= PopUpMenuLines) {
@@ -1097,7 +1252,7 @@ GetSelectionInputPopUp (
//
// Clear that portion of the screen
//
- ClearLines (Start, End, Top, Bottom, POPUP_TEXT | POPUP_BACKGROUND);
+ ClearLines (Start, End, Top, Bottom, GetPopupColor ());
//
// Draw "One of" pop-up menu
@@ -1111,11 +1266,11 @@ GetSelectionInputPopUp (
Character = BOXDRAW_HORIZONTAL;
}
- PrintChar (Character);
+ PrintCharAt ((UINTN)-1, (UINTN)-1, Character);
}
Character = BOXDRAW_DOWN_LEFT;
- PrintChar (Character);
+ PrintCharAt ((UINTN)-1, (UINTN)-1, Character);
Character = BOXDRAW_VERTICAL;
for (Index = Top + 1; Index < Bottom; Index++) {
PrintCharAt (Start, Index, Character);
@@ -1128,13 +1283,6 @@ GetSelectionInputPopUp (
Link = GetFirstNode (&Question->OptionListHead);
for (Index = 0; Index < TopOptionIndex; Index++) {
Link = GetNextNode (&Question->OptionListHead, Link);
-
- OneOfOption = QUESTION_OPTION_FROM_LINK (Link);
- if (!OrderedList && (OneOfOption->SuppressExpression != NULL) &&
- EvaluateExpressionList(OneOfOption->SuppressExpression, FALSE, NULL, NULL) > ExpressFalse) {
- Index--;
- continue;
- }
}
//
@@ -1142,16 +1290,10 @@ GetSelectionInputPopUp (
//
Index2 = Top + 1;
for (Index = TopOptionIndex; (Index < PopUpMenuLines) && (Index2 < Bottom); Index++) {
- OneOfOption = QUESTION_OPTION_FROM_LINK (Link);
+ OneOfOption = DISPLAY_QUESTION_OPTION_FROM_LINK (Link);
Link = GetNextNode (&Question->OptionListHead, Link);
- if (!OrderedList && (OneOfOption->SuppressExpression != NULL) &&
- EvaluateExpressionList(OneOfOption->SuppressExpression, FALSE, NULL, NULL) > ExpressFalse) {
- Index--;
- continue;
- }
-
- StringPtr = GetToken (OneOfOption->Text, MenuOption->Handle);
+ StringPtr = GetToken (OneOfOption->OptionOpCode->Option, gFormData->HiiHandle);
ASSERT (StringPtr != NULL);
//
// If the string occupies multiple lines, truncate it to fit in one line,
@@ -1172,11 +1314,11 @@ GetSelectionInputPopUp (
//
CurrentOption = OneOfOption;
- gST->ConOut->SetAttribute (gST->ConOut, PICKLIST_HIGHLIGHT_TEXT | PICKLIST_HIGHLIGHT_BACKGROUND);
+ gST->ConOut->SetAttribute (gST->ConOut, GetPickListColor ());
PrintStringAt (Start + 2, Index2, StringPtr);
- gST->ConOut->SetAttribute (gST->ConOut, POPUP_TEXT | POPUP_BACKGROUND);
+ gST->ConOut->SetAttribute (gST->ConOut, GetPopupColor ());
} else {
- gST->ConOut->SetAttribute (gST->ConOut, POPUP_TEXT | POPUP_BACKGROUND);
+ gST->ConOut->SetAttribute (gST->ConOut, GetPopupColor ());
PrintStringAt (Start + 2, Index2, StringPtr);
}
@@ -1193,11 +1335,11 @@ GetSelectionInputPopUp (
Character = BOXDRAW_HORIZONTAL;
}
- PrintChar (Character);
+ PrintCharAt ((UINTN)-1, (UINTN)-1, Character);
}
Character = BOXDRAW_UP_LEFT;
- PrintChar (Character);
+ PrintCharAt ((UINTN)-1, (UINTN)-1, Character);
//
// Get User selection
@@ -1313,7 +1455,7 @@ TheKey:
if (OrderedList) {
HiiValue.Type = ValueType;
HiiValue.Value.u64 = 0;
- for (Index = 0; Index < Question->MaxContainers; Index++) {
+ for (Index = 0; Index < OrderList->MaxContainers; Index++) {
HiiValue.Value.u64 = GetArrayData (ValueArray, ValueType, Index);
if (HiiValue.Value.u64 == 0) {
break;
@@ -1342,44 +1484,44 @@ TheKey:
// return the current selection
//
if (OrderedList) {
+ ReturnValue = AllocateZeroPool (Question->CurrentValue.BufferLen);
+ ASSERT (ReturnValue != NULL);
Index = 0;
Link = GetFirstNode (&Question->OptionListHead);
while (!IsNull (&Question->OptionListHead, Link)) {
- OneOfOption = QUESTION_OPTION_FROM_LINK (Link);
+ OneOfOption = DISPLAY_QUESTION_OPTION_FROM_LINK (Link);
Link = GetNextNode (&Question->OptionListHead, Link);
- if ((OneOfOption->SuppressExpression != NULL) &&
- EvaluateExpressionList(OneOfOption->SuppressExpression, FALSE, NULL, NULL) != ExpressFalse) {
- continue;
- }
-
- SetArrayData (ValueArray, ValueType, Index, OneOfOption->Value.Value.u64);
+ SetArrayData (ReturnValue, ValueType, Index, OneOfOption->OptionOpCode->Value.u64);
Index++;
- if (Index > Question->MaxContainers) {
+ if (Index > OrderList->MaxContainers) {
break;
}
}
+ if (CompareMem (ReturnValue, ValueArray, Question->CurrentValue.BufferLen) == 0) {
+ FreePool (ReturnValue);
+ return EFI_DEVICE_ERROR;
+ } else {
+ gUserInput->InputValue.Buffer = ReturnValue;
+ gUserInput->InputValue.BufferLen = Question->CurrentValue.BufferLen;
+ Status = EFI_SUCCESS;
+ }
} else {
ASSERT (CurrentOption != NULL);
- CopyMem (&Question->HiiValue, &CurrentOption->Value, sizeof (EFI_HII_VALUE));
+ gUserInput->InputValue.Type = CurrentOption->OptionOpCode->Type;
+ if (IsValuesEqual (&Question->CurrentValue.Value, &CurrentOption->OptionOpCode->Value, gUserInput->InputValue.Type)) {
+ return EFI_DEVICE_ERROR;
+ } else {
+ SetValuesByType (&gUserInput->InputValue.Value, &CurrentOption->OptionOpCode->Value, gUserInput->InputValue.Type);
+ Status = EFI_SUCCESS;
+ }
}
gST->ConOut->SetAttribute (gST->ConOut, SavedAttribute);
- Status = ValidateQuestion (Selection->FormSet, Selection->Form, Question, EFI_HII_EXPRESSION_INCONSISTENT_IF);
- if (EFI_ERROR (Status)) {
- //
- // Input value is not valid, restore Question Value
- //
- GetQuestionValue (Selection->FormSet, Selection->Form, Question, GetSetValueWithEditBuffer);
- } else {
- SetQuestionValue (Selection->FormSet, Selection->Form, Question, GetSetValueWithEditBuffer);
- UpdateStatusBar (Selection, NV_UPDATE_REQUIRED, Question->QuestionFlags, TRUE);
- }
-
- return Status;
-
+ return ValidateQuestion (Question);
+
default:
break;
}
@@ -1387,32 +1529,3 @@ TheKey:
}
-/**
- Wait for a key to be pressed by user.
-
- @param Key The key which is pressed by user.
-
- @retval EFI_SUCCESS The function always completed successfully.
-
-**/
-EFI_STATUS
-WaitForKeyStroke (
- OUT EFI_INPUT_KEY *Key
- )
-{
- EFI_STATUS Status;
-
- while (TRUE) {
- Status = gST->ConIn->ReadKeyStroke (gST->ConIn, Key);
- if (!EFI_ERROR (Status)) {
- break;
- }
-
- if (Status != EFI_NOT_READY) {
- continue;
- }
-
- UiWaitForSingleEvent (gST->ConIn->WaitForKey, 0, 0);
- }
- return Status;
-}
diff --git a/MdeModulePkg/Universal/DisplayEngineDxe/ProcessOptions.c b/MdeModulePkg/Universal/DisplayEngineDxe/ProcessOptions.c
new file mode 100644
index 000000000..cf9f6836b
--- /dev/null
+++ b/MdeModulePkg/Universal/DisplayEngineDxe/ProcessOptions.c
@@ -0,0 +1,1431 @@
+/** @file
+Implementation for handling the User Interface option processing.
+
+
+Copyright (c) 2004 - 2012, Intel Corporation. All rights reserved.<BR>
+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 "FormDisplay.h"
+
+typedef struct {
+ EFI_EVENT SyncEvent;
+ UINT8 *TimeOut;
+ CHAR16 *ErrorInfo;
+} WARNING_IF_CONTEXT;
+
+#define MAX_TIME_OUT_LEN 0x10
+
+/**
+ Concatenate a narrow string to another string.
+
+ @param Destination The destination string.
+ @param Source The source string. The string to be concatenated.
+ to the end of Destination.
+
+**/
+VOID
+NewStrCat (
+ IN OUT CHAR16 *Destination,
+ IN 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] = NARROW_CHAR;
+ Length++;
+
+ StrCpy (Destination + Length, Source);
+}
+
+/**
+ Compare two Hii value.
+
+ @param Value1 Expression value to compare on left-hand.
+ @param Value2 Expression value to compare on right-hand.
+ @param Result Return value after compare.
+ retval 0 Two operators equal.
+ return Positive value if Value1 is greater than Value2.
+ retval Negative value if Value1 is less than Value2.
+ @param HiiHandle Only required for string compare.
+
+ @retval other Could not perform compare on two values.
+ @retval EFI_SUCCESS Compare the value success.
+
+**/
+EFI_STATUS
+CompareHiiValue (
+ IN EFI_HII_VALUE *Value1,
+ IN EFI_HII_VALUE *Value2,
+ OUT INTN *Result,
+ IN EFI_HII_HANDLE HiiHandle OPTIONAL
+ )
+{
+ INT64 Temp64;
+ CHAR16 *Str1;
+ CHAR16 *Str2;
+ UINTN Len;
+
+ if (Value1->Type >= EFI_IFR_TYPE_OTHER || Value2->Type >= EFI_IFR_TYPE_OTHER ) {
+ if (Value1->Type != EFI_IFR_TYPE_BUFFER && Value2->Type != EFI_IFR_TYPE_BUFFER) {
+ return EFI_UNSUPPORTED;
+ }
+ }
+
+ if (Value1->Type == EFI_IFR_TYPE_STRING || Value2->Type == EFI_IFR_TYPE_STRING ) {
+ if (Value1->Type != Value2->Type) {
+ //
+ // Both Operator should be type of String
+ //
+ return EFI_UNSUPPORTED;
+ }
+
+ if (Value1->Value.string == 0 || Value2->Value.string == 0) {
+ //
+ // StringId 0 is reserved
+ //
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Value1->Value.string == Value2->Value.string) {
+ *Result = 0;
+ return EFI_SUCCESS;
+ }
+
+ Str1 = GetToken (Value1->Value.string, HiiHandle);
+ if (Str1 == NULL) {
+ //
+ // String not found
+ //
+ return EFI_NOT_FOUND;
+ }
+
+ Str2 = GetToken (Value2->Value.string, HiiHandle);
+ if (Str2 == NULL) {
+ FreePool (Str1);
+ return EFI_NOT_FOUND;
+ }
+
+ *Result = StrCmp (Str1, Str2);
+
+ FreePool (Str1);
+ FreePool (Str2);
+
+ return EFI_SUCCESS;
+ }
+
+ if (Value1->Type == EFI_IFR_TYPE_BUFFER || Value2->Type == EFI_IFR_TYPE_BUFFER ) {
+ if (Value1->Type != Value2->Type) {
+ //
+ // Both Operator should be type of Buffer.
+ //
+ return EFI_UNSUPPORTED;
+ }
+ Len = Value1->BufferLen > Value2->BufferLen ? Value2->BufferLen : Value1->BufferLen;
+ *Result = CompareMem (Value1->Buffer, Value2->Buffer, Len);
+ if ((*Result == 0) && (Value1->BufferLen != Value2->BufferLen))
+ {
+ //
+ // In this case, means base on samll number buffer, the data is same
+ // So which value has more data, which value is bigger.
+ //
+ *Result = Value1->BufferLen > Value2->BufferLen ? 1 : -1;
+ }
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Take remain types(integer, boolean, date/time) as integer
+ //
+ Temp64 = (INT64) (Value1->Value.u64 - Value2->Value.u64);
+ if (Temp64 > 0) {
+ *Result = 1;
+ } else if (Temp64 < 0) {
+ *Result = -1;
+ } else {
+ *Result = 0;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Search an Option of a Question by its value.
+
+ @param Question The Question
+ @param OptionValue Value for Option to be searched.
+
+ @retval Pointer Pointer to the found Option.
+ @retval NULL Option not found.
+
+**/
+DISPLAY_QUESTION_OPTION *
+ValueToOption (
+ IN FORM_DISPLAY_ENGINE_STATEMENT *Question,
+ IN EFI_HII_VALUE *OptionValue
+ )
+{
+ LIST_ENTRY *Link;
+ DISPLAY_QUESTION_OPTION *Option;
+ INTN Result;
+ EFI_HII_VALUE Value;
+
+ Link = GetFirstNode (&Question->OptionListHead);
+ while (!IsNull (&Question->OptionListHead, Link)) {
+ Option = DISPLAY_QUESTION_OPTION_FROM_LINK (Link);
+
+ ZeroMem (&Value, sizeof (EFI_HII_VALUE));
+ Value.Type = Option->OptionOpCode->Type;
+ CopyMem (&Value.Value, &Option->OptionOpCode->Value, Option->OptionOpCode->Header.Length - OFFSET_OF (EFI_IFR_ONE_OF_OPTION, Value));
+
+ if ((CompareHiiValue (&Value, OptionValue, &Result, NULL) == EFI_SUCCESS) && (Result == 0)) {
+ return Option;
+ }
+
+ Link = GetNextNode (&Question->OptionListHead, Link);
+ }
+
+ return NULL;
+}
+
+
+/**
+ Return data element in an Array by its Index.
+
+ @param Array The data array.
+ @param Type Type of the data in this array.
+ @param Index Zero based index for data in this array.
+
+ @retval Value The data to be returned
+
+**/
+UINT64
+GetArrayData (
+ IN VOID *Array,
+ IN UINT8 Type,
+ IN UINTN Index
+ )
+{
+ UINT64 Data;
+
+ ASSERT (Array != NULL);
+
+ Data = 0;
+ switch (Type) {
+ case EFI_IFR_TYPE_NUM_SIZE_8:
+ Data = (UINT64) *(((UINT8 *) Array) + Index);
+ break;
+
+ case EFI_IFR_TYPE_NUM_SIZE_16:
+ Data = (UINT64) *(((UINT16 *) Array) + Index);
+ break;
+
+ case EFI_IFR_TYPE_NUM_SIZE_32:
+ Data = (UINT64) *(((UINT32 *) Array) + Index);
+ break;
+
+ case EFI_IFR_TYPE_NUM_SIZE_64:
+ Data = (UINT64) *(((UINT64 *) Array) + Index);
+ break;
+
+ default:
+ break;
+ }
+
+ return Data;
+}
+
+
+/**
+ Set value of a data element in an Array by its Index.
+
+ @param Array The data array.
+ @param Type Type of the data in this array.
+ @param Index Zero based index for data in this array.
+ @param Value The value to be set.
+
+**/
+VOID
+SetArrayData (
+ IN VOID *Array,
+ IN UINT8 Type,
+ IN UINTN Index,
+ IN UINT64 Value
+ )
+{
+
+ ASSERT (Array != NULL);
+
+ switch (Type) {
+ case EFI_IFR_TYPE_NUM_SIZE_8:
+ *(((UINT8 *) Array) + Index) = (UINT8) Value;
+ break;
+
+ case EFI_IFR_TYPE_NUM_SIZE_16:
+ *(((UINT16 *) Array) + Index) = (UINT16) Value;
+ break;
+
+ case EFI_IFR_TYPE_NUM_SIZE_32:
+ *(((UINT32 *) Array) + Index) = (UINT32) Value;
+ break;
+
+ case EFI_IFR_TYPE_NUM_SIZE_64:
+ *(((UINT64 *) Array) + Index) = (UINT64) Value;
+ break;
+
+ default:
+ break;
+ }
+}
+
+/**
+ Check whether this value already in the array, if yes, return the index.
+
+ @param Array The data array.
+ @param Type Type of the data in this array.
+ @param Value The value to be find.
+ @param Index The index in the array which has same value with Value.
+
+ @retval TRUE Found the value in the array.
+ @retval FALSE Not found the value.
+
+**/
+BOOLEAN
+FindArrayData (
+ IN VOID *Array,
+ IN UINT8 Type,
+ IN UINT64 Value,
+ OUT UINTN *Index OPTIONAL
+ )
+{
+ UINTN Count;
+ UINT64 TmpValue;
+ UINT64 ValueComp;
+
+ ASSERT (Array != NULL);
+
+ Count = 0;
+ TmpValue = 0;
+
+ switch (Type) {
+ case EFI_IFR_TYPE_NUM_SIZE_8:
+ ValueComp = (UINT8) Value;
+ break;
+
+ case EFI_IFR_TYPE_NUM_SIZE_16:
+ ValueComp = (UINT16) Value;
+ break;
+
+ case EFI_IFR_TYPE_NUM_SIZE_32:
+ ValueComp = (UINT32) Value;
+ break;
+
+ case EFI_IFR_TYPE_NUM_SIZE_64:
+ ValueComp = (UINT64) Value;
+ break;
+
+ default:
+ ValueComp = 0;
+ break;
+ }
+
+ while ((TmpValue = GetArrayData (Array, Type, Count)) != 0) {
+ if (ValueComp == TmpValue) {
+ if (Index != NULL) {
+ *Index = Count;
+ }
+ return TRUE;
+ }
+
+ Count ++;
+ }
+
+ return FALSE;
+}
+
+/**
+ Print Question Value according to it's storage width and display attributes.
+
+ @param Question The Question to be printed.
+ @param FormattedNumber Buffer for output string.
+ @param BufferSize The FormattedNumber buffer size in bytes.
+
+ @retval EFI_SUCCESS Print success.
+ @retval EFI_BUFFER_TOO_SMALL Buffer size is not enough for formatted number.
+
+**/
+EFI_STATUS
+PrintFormattedNumber (
+ IN FORM_DISPLAY_ENGINE_STATEMENT *Question,
+ IN OUT CHAR16 *FormattedNumber,
+ IN UINTN BufferSize
+ )
+{
+ INT64 Value;
+ CHAR16 *Format;
+ EFI_HII_VALUE *QuestionValue;
+ EFI_IFR_NUMERIC *NumericOp;
+
+ if (BufferSize < (21 * sizeof (CHAR16))) {
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ QuestionValue = &Question->CurrentValue;
+ NumericOp = (EFI_IFR_NUMERIC *) Question->OpCode;
+
+ Value = (INT64) QuestionValue->Value.u64;
+ switch (NumericOp->Flags & EFI_IFR_DISPLAY) {
+ case EFI_IFR_DISPLAY_INT_DEC:
+ switch (QuestionValue->Type) {
+ case EFI_IFR_NUMERIC_SIZE_1:
+ Value = (INT64) ((INT8) QuestionValue->Value.u8);
+ break;
+
+ case EFI_IFR_NUMERIC_SIZE_2:
+ Value = (INT64) ((INT16) QuestionValue->Value.u16);
+ break;
+
+ case EFI_IFR_NUMERIC_SIZE_4:
+ Value = (INT64) ((INT32) QuestionValue->Value.u32);
+ break;
+
+ case EFI_IFR_NUMERIC_SIZE_8:
+ default:
+ break;
+ }
+
+ if (Value < 0) {
+ Value = -Value;
+ Format = L"-%ld";
+ } else {
+ Format = L"%ld";
+ }
+ break;
+
+ case EFI_IFR_DISPLAY_UINT_DEC:
+ Format = L"%ld";
+ break;
+
+ case EFI_IFR_DISPLAY_UINT_HEX:
+ Format = L"%lx";
+ break;
+
+ default:
+ return EFI_UNSUPPORTED;
+ break;
+ }
+
+ UnicodeSPrint (FormattedNumber, BufferSize, Format, Value);
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Draw a pop up windows based on the dimension, number of lines and
+ strings specified.
+
+ @param RequestedWidth The width of the pop-up.
+ @param NumberOfLines The number of lines.
+ @param Marker The variable argument list for the list of string to be printed.
+
+**/
+VOID
+CreateSharedPopUp (
+ IN UINTN RequestedWidth,
+ IN UINTN NumberOfLines,
+ IN VA_LIST Marker
+ )
+{
+ UINTN Index;
+ UINTN Count;
+ CHAR16 Character;
+ UINTN Start;
+ UINTN End;
+ UINTN Top;
+ UINTN Bottom;
+ CHAR16 *String;
+ UINTN DimensionsWidth;
+ UINTN DimensionsHeight;
+
+ DimensionsWidth = gStatementDimensions.RightColumn - gStatementDimensions.LeftColumn;
+ DimensionsHeight = gStatementDimensions.BottomRow - gStatementDimensions.TopRow;
+
+ gST->ConOut->SetAttribute (gST->ConOut, GetPopupColor ());
+
+ 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 + gStatementDimensions.LeftColumn + 1;
+ End = Start + RequestedWidth + 1;
+
+ Top = ((DimensionsHeight - NumberOfLines - 2) / 2) + gStatementDimensions.TopRow - 1;
+ Bottom = Top + NumberOfLines + 2;
+
+ Character = BOXDRAW_DOWN_RIGHT;
+ PrintCharAt (Start, Top, Character);
+ Character = BOXDRAW_HORIZONTAL;
+ for (Index = Start; Index + 2 < End; Index++) {
+ PrintCharAt ((UINTN)-1, (UINTN)-1, Character);
+ }
+
+ Character = BOXDRAW_DOWN_LEFT;
+ PrintCharAt ((UINTN)-1, (UINTN)-1, Character);
+ Character = BOXDRAW_VERTICAL;
+
+ Count = 0;
+ for (Index = Top; Index + 2 < Bottom; Index++, Count++) {
+ String = VA_ARG (Marker, CHAR16*);
+
+ //
+ // 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, GetPopupColor ());
+ }
+
+ //
+ // 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, GetPopupInverseColor ());
+ }
+
+ //
+ // Passing in a NULL results in a blank space
+ //
+ if (String[0] == CHAR_NULL) {
+ ClearLines (Start, End, Index + 1, Index + 1, GetPopupColor ());
+ }
+
+ PrintStringAt (
+ ((DimensionsWidth - GetStringWidth (String) / 2) / 2) + gStatementDimensions.LeftColumn + 1,
+ Index + 1,
+ String
+ );
+ gST->ConOut->SetAttribute (gST->ConOut, GetPopupColor ());
+ PrintCharAt (Start, Index + 1, Character);
+ PrintCharAt (End - 1, Index + 1, Character);
+ }
+
+ Character = BOXDRAW_UP_RIGHT;
+ PrintCharAt (Start, Bottom - 1, Character);
+ Character = BOXDRAW_HORIZONTAL;
+ for (Index = Start; Index + 2 < End; Index++) {
+ PrintCharAt ((UINTN)-1, (UINTN)-1, Character);
+ }
+
+ Character = BOXDRAW_UP_LEFT;
+ PrintCharAt ((UINTN)-1, (UINTN)-1, Character);
+}
+
+/**
+ Draw a pop up windows based on the dimension, number of lines and
+ strings specified.
+
+ @param RequestedWidth The width of the pop-up.
+ @param NumberOfLines The number of lines.
+ @param ... A series of text strings that displayed in the pop-up.
+
+**/
+VOID
+EFIAPI
+CreateMultiStringPopUp (
+ IN UINTN RequestedWidth,
+ IN UINTN NumberOfLines,
+ ...
+ )
+{
+ VA_LIST Marker;
+
+ VA_START (Marker, NumberOfLines);
+
+ CreateSharedPopUp (RequestedWidth, NumberOfLines, Marker);
+
+ VA_END (Marker);
+}
+
+/**
+ Process nothing.
+
+ @param Event The Event need to be process
+ @param Context The context of the event.
+
+**/
+VOID
+EFIAPI
+EmptyEventProcess (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+}
+
+/**
+ Process for the refresh interval statement.
+
+ @param Event The Event need to be process
+ @param Context The context of the event.
+
+**/
+VOID
+EFIAPI
+RefreshTimeOutProcess (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ WARNING_IF_CONTEXT *EventInfo;
+ CHAR16 TimeOutString[MAX_TIME_OUT_LEN];
+
+ EventInfo = (WARNING_IF_CONTEXT *) Context;
+
+ if (*(EventInfo->TimeOut) == 0) {
+ gBS->CloseEvent (Event);
+
+ gBS->SignalEvent (EventInfo->SyncEvent);
+ return;
+ }
+
+ UnicodeSPrint(TimeOutString, MAX_TIME_OUT_LEN, L"%d", *(EventInfo->TimeOut));
+
+ CreateDialog (NULL, gEmptyString, EventInfo->ErrorInfo, gPressEnter, gEmptyString, TimeOutString, NULL);
+
+ *(EventInfo->TimeOut) -= 1;
+}
+
+/**
+ Show the warning message.
+
+ @param RetInfo The input warning string and timeout info.
+
+**/
+VOID
+WarningIfCheck (
+ IN STATEMENT_ERROR_INFO *RetInfo
+ )
+{
+ CHAR16 *ErrorInfo;
+ EFI_EVENT WaitList[2];
+ EFI_EVENT RefreshIntervalEvent;
+ EFI_EVENT TimeOutEvent;
+ UINT8 TimeOut;
+ EFI_STATUS Status;
+ UINTN Index;
+ WARNING_IF_CONTEXT EventContext;
+ EFI_INPUT_KEY Key;
+
+ TimeOutEvent = NULL;
+ RefreshIntervalEvent = NULL;
+
+ ASSERT (RetInfo->StringId != 0);
+ ErrorInfo = GetToken (RetInfo->StringId, gFormData->HiiHandle);
+ TimeOut = RetInfo->TimeOut;
+ if (RetInfo->TimeOut == 0) {
+ do {
+ CreateDialog (&Key, gEmptyString, ErrorInfo, gPressEnter, gEmptyString, NULL);
+ } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
+ } else {
+ Status = gBS->CreateEvent (EVT_NOTIFY_WAIT, TPL_CALLBACK, EmptyEventProcess, NULL, &TimeOutEvent);
+ ASSERT_EFI_ERROR (Status);
+
+ EventContext.SyncEvent = TimeOutEvent;
+ EventContext.TimeOut = &TimeOut;
+ EventContext.ErrorInfo = ErrorInfo;
+
+ Status = gBS->CreateEvent (EVT_TIMER | EVT_NOTIFY_SIGNAL, TPL_CALLBACK, RefreshTimeOutProcess, &EventContext, &RefreshIntervalEvent);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Show the dialog first to avoid long time not reaction.
+ //
+ gBS->SignalEvent (RefreshIntervalEvent);
+
+ Status = gBS->SetTimer (RefreshIntervalEvent, TimerPeriodic, ONE_SECOND);
+ ASSERT_EFI_ERROR (Status);
+
+ while (TRUE) {
+ Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
+ if (!EFI_ERROR (Status) && Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {
+ break;
+ }
+
+ if (Status != EFI_NOT_READY) {
+ continue;
+ }
+
+ WaitList[0] = TimeOutEvent;
+ WaitList[1] = gST->ConIn->WaitForKey;
+
+ Status = gBS->WaitForEvent (2, WaitList, &Index);
+ ASSERT_EFI_ERROR (Status);
+
+ if (Index == 0) {
+ //
+ // Timeout occur, close the hoot time out event.
+ //
+ break;
+ }
+ }
+ }
+
+ gBS->CloseEvent (TimeOutEvent);
+ gBS->CloseEvent (RefreshIntervalEvent);
+
+ FreePool (ErrorInfo);
+}
+
+/**
+ Process validate for one question.
+
+ @param Question The question need to be validate.
+
+ @retval EFI_SUCCESS Question Option process success.
+ @retval EFI_INVALID_PARAMETER Question Option process fail.
+
+**/
+EFI_STATUS
+ValidateQuestion (
+ IN FORM_DISPLAY_ENGINE_STATEMENT *Question
+ )
+{
+ CHAR16 *ErrorInfo;
+ EFI_INPUT_KEY Key;
+ EFI_STATUS Status;
+ STATEMENT_ERROR_INFO RetInfo;
+ UINT32 RetVal;
+
+ if (Question->ValidateQuestion == NULL) {
+ return EFI_SUCCESS;
+ }
+
+ Status = EFI_SUCCESS;
+ RetVal = Question->ValidateQuestion(gFormData, Question, &gUserInput->InputValue, &RetInfo);
+
+ switch (RetVal) {
+ case INCOSISTENT_IF_TRUE:
+ //
+ // Condition meet, show up error message
+ //
+ ASSERT (RetInfo.StringId != 0);
+ ErrorInfo = GetToken (RetInfo.StringId, gFormData->HiiHandle);
+ do {
+ CreateDialog (&Key, gEmptyString, ErrorInfo, gPressEnter, gEmptyString, NULL);
+ } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
+ FreePool (ErrorInfo);
+
+ Status = EFI_INVALID_PARAMETER;
+ break;
+
+ case WARNING_IF_TRUE:
+ //
+ // Condition meet, show up warning message
+ //
+ WarningIfCheck (&RetInfo);
+ break;
+
+ default:
+ break;
+ }
+
+ return Status;
+}
+
+/**
+ Display error message for invalid password.
+
+**/
+VOID
+PasswordInvalid (
+ VOID
+ )
+{
+ EFI_INPUT_KEY Key;
+
+ //
+ // Invalid password, prompt error message
+ //
+ do {
+ CreateDialog (&Key, gEmptyString, gPassowordInvalid, gPressEnter, gEmptyString, NULL);
+ } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
+}
+
+/**
+ Process password op code.
+
+ @param MenuOption The menu for current password op code.
+
+ @retval EFI_SUCCESS Question Option process success.
+ @retval Other Question Option process fail.
+
+**/
+EFI_STATUS
+PasswordProcess (
+ IN UI_MENU_OPTION *MenuOption
+ )
+{
+ CHAR16 *StringPtr;
+ CHAR16 *TempString;
+ UINTN Maximum;
+ EFI_STATUS Status;
+ EFI_IFR_PASSWORD *PasswordInfo;
+ FORM_DISPLAY_ENGINE_STATEMENT *Question;
+ EFI_INPUT_KEY Key;
+
+ Question = MenuOption->ThisTag;
+ PasswordInfo = (EFI_IFR_PASSWORD *) Question->OpCode;
+ Maximum = PasswordInfo->MaxSize;
+ Status = EFI_SUCCESS;
+
+ StringPtr = AllocateZeroPool ((Maximum + 1) * sizeof (CHAR16));
+ ASSERT (StringPtr);
+
+ //
+ // Use a NULL password to test whether old password is required
+ //
+ *StringPtr = 0;
+ Status = Question->PasswordCheck (gFormData, Question, StringPtr);
+ if (Status == EFI_NOT_AVAILABLE_YET || Status == EFI_UNSUPPORTED) {
+ //
+ // Password can't be set now.
+ //
+ FreePool (StringPtr);
+ return EFI_SUCCESS;
+ }
+
+ if (EFI_ERROR (Status)) {
+ //
+ // Old password exist, ask user for the old password
+ //
+ Status = ReadString (MenuOption, gPromptForPassword, StringPtr);
+ if (EFI_ERROR (Status)) {
+ FreePool (StringPtr);
+ return Status;
+ }
+
+ //
+ // Check user input old password
+ //
+ Status = Question->PasswordCheck (gFormData, Question, StringPtr);
+ if (EFI_ERROR (Status)) {
+ if (Status == EFI_NOT_READY) {
+ //
+ // Typed in old password incorrect
+ //
+ PasswordInvalid ();
+ } else {
+ Status = EFI_SUCCESS;
+ }
+
+ FreePool (StringPtr);
+ return Status;
+ }
+ }
+
+ //
+ // Ask for new password
+ //
+ ZeroMem (StringPtr, (Maximum + 1) * sizeof (CHAR16));
+ Status = ReadString (MenuOption, gPromptForNewPassword, StringPtr);
+ if (EFI_ERROR (Status)) {
+ //
+ // Reset state machine for password
+ //
+ Question->PasswordCheck (gFormData, Question, NULL);
+ FreePool (StringPtr);
+ return Status;
+ }
+
+ //
+ // Confirm new password
+ //
+ TempString = AllocateZeroPool ((Maximum + 1) * sizeof (CHAR16));
+ ASSERT (TempString);
+ Status = ReadString (MenuOption, gConfirmPassword, TempString);
+ if (EFI_ERROR (Status)) {
+ //
+ // Reset state machine for password
+ //
+ Question->PasswordCheck (gFormData, Question, NULL);
+ FreePool (StringPtr);
+ FreePool (TempString);
+ return Status;
+ }
+
+ //
+ // Compare two typed-in new passwords
+ //
+ if (StrCmp (StringPtr, TempString) == 0) {
+ gUserInput->InputValue.Buffer = AllocateCopyPool (Question->CurrentValue.BufferLen, StringPtr);
+ gUserInput->InputValue.BufferLen = Question->CurrentValue.BufferLen;
+ gUserInput->InputValue.Type = Question->CurrentValue.Type;
+ gUserInput->InputValue.Value.string = HiiSetString(gFormData->HiiHandle, gUserInput->InputValue.Value.string, StringPtr, NULL);
+ FreePool (StringPtr);
+
+ Status = ValidateQuestion (Question);
+
+ if (EFI_ERROR (Status)) {
+ //
+ // Reset state machine for password
+ //
+ Question->PasswordCheck (gFormData, Question, NULL);
+ }
+
+ return Status;
+ } else {
+ //
+ // Reset state machine for password
+ //
+ Question->PasswordCheck (gFormData, Question, NULL);
+
+ //
+ // Two password mismatch, prompt error message
+ //
+ do {
+ CreateDialog (&Key, gEmptyString, gConfirmError, gPressEnter, gEmptyString, NULL);
+ } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
+
+ Status = EFI_INVALID_PARAMETER;
+ }
+
+ FreePool (TempString);
+ FreePool (StringPtr);
+
+ return Status;
+}
+
+/**
+ Process a Question's Option (whether selected or un-selected).
+
+ @param MenuOption The MenuOption for this Question.
+ @param Selected TRUE: if Question is selected.
+ @param OptionString Pointer of the Option String to be displayed.
+ @param SkipErrorValue Whether need to return when value without option for it.
+
+ @retval EFI_SUCCESS Question Option process success.
+ @retval Other Question Option process fail.
+
+**/
+EFI_STATUS
+ProcessOptions (
+ IN UI_MENU_OPTION *MenuOption,
+ IN BOOLEAN Selected,
+ OUT CHAR16 **OptionString,
+ IN BOOLEAN SkipErrorValue
+ )
+{
+ EFI_STATUS Status;
+ CHAR16 *StringPtr;
+ UINTN Index;
+ FORM_DISPLAY_ENGINE_STATEMENT *Question;
+ CHAR16 FormattedNumber[21];
+ UINT16 Number;
+ CHAR16 Character[2];
+ EFI_INPUT_KEY Key;
+ UINTN BufferSize;
+ DISPLAY_QUESTION_OPTION *OneOfOption;
+ LIST_ENTRY *Link;
+ EFI_HII_VALUE HiiValue;
+ EFI_HII_VALUE *QuestionValue;
+ DISPLAY_QUESTION_OPTION *Option;
+ UINTN Index2;
+ UINT8 *ValueArray;
+ UINT8 ValueType;
+ EFI_STRING_ID StringId;
+ EFI_IFR_ORDERED_LIST *OrderList;
+ BOOLEAN ValueInvalid;
+
+ Status = EFI_SUCCESS;
+
+ StringPtr = NULL;
+ Character[1] = L'\0';
+ *OptionString = NULL;
+ StringId = 0;
+ ValueInvalid = FALSE;
+
+ ZeroMem (FormattedNumber, 21 * sizeof (CHAR16));
+ BufferSize = (gOptionBlockWidth + 1) * 2 * gStatementDimensions.BottomRow;
+
+ Question = MenuOption->ThisTag;
+ QuestionValue = &Question->CurrentValue;
+
+ switch (Question->OpCode->OpCode) {
+ case EFI_IFR_ORDERED_LIST_OP:
+
+ //
+ // Check whether there are Options of this OrderedList
+ //
+ if (IsListEmpty (&Question->OptionListHead)) {
+ break;
+ }
+
+ OrderList = (EFI_IFR_ORDERED_LIST *) Question->OpCode;
+
+ Link = GetFirstNode (&Question->OptionListHead);
+ OneOfOption = DISPLAY_QUESTION_OPTION_FROM_LINK (Link);
+
+ ValueType = OneOfOption->OptionOpCode->Type;
+ ValueArray = Question->CurrentValue.Buffer;
+
+ if (Selected) {
+ //
+ // Go ask for input
+ //
+ Status = GetSelectionInputPopUp (MenuOption);
+ } else {
+ //
+ // We now know how many strings we will have, so we can allocate the
+ // space required for the array or strings.
+ //
+ *OptionString = AllocateZeroPool (OrderList->MaxContainers * BufferSize);
+ ASSERT (*OptionString);
+
+ HiiValue.Type = ValueType;
+ HiiValue.Value.u64 = 0;
+ for (Index = 0; Index < OrderList->MaxContainers; Index++) {
+ HiiValue.Value.u64 = GetArrayData (ValueArray, ValueType, Index);
+ if (HiiValue.Value.u64 == 0) {
+ //
+ // Values for the options in ordered lists should never be a 0
+ //
+ break;
+ }
+
+ OneOfOption = ValueToOption (Question, &HiiValue);
+ if (OneOfOption == NULL) {
+ if (SkipErrorValue) {
+ //
+ // Just try to get the option string, skip the value which not has option.
+ //
+ continue;
+ }
+
+ //
+ // Show error message
+ //
+ do {
+ CreateDialog (&Key, gEmptyString, gOptionMismatch, gPressEnter, gEmptyString, NULL);
+ } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
+
+ //
+ // The initial value of the orderedlist is invalid, force to be valid value
+ // Exit current DisplayForm with new value.
+ //
+ gUserInput->SelectedStatement = Question;
+
+ ValueArray = AllocateZeroPool (Question->CurrentValue.BufferLen);
+ ASSERT (ValueArray != NULL);
+ gUserInput->InputValue.Buffer = ValueArray;
+ gUserInput->InputValue.BufferLen = Question->CurrentValue.BufferLen;
+ gUserInput->InputValue.Type = Question->CurrentValue.Type;
+
+ Link = GetFirstNode (&Question->OptionListHead);
+ Index2 = 0;
+ while (!IsNull (&Question->OptionListHead, Link) && Index2 < OrderList->MaxContainers) {
+ Option = DISPLAY_QUESTION_OPTION_FROM_LINK (Link);
+ Link = GetNextNode (&Question->OptionListHead, Link);
+ SetArrayData (ValueArray, ValueType, Index2, Option->OptionOpCode->Value.u64);
+ Index2++;
+ }
+ SetArrayData (ValueArray, ValueType, Index2, 0);
+
+ FreePool (*OptionString);
+ *OptionString = NULL;
+ return EFI_NOT_FOUND;
+ }
+
+ Character[0] = LEFT_ONEOF_DELIMITER;
+ NewStrCat (OptionString[0], Character);
+ StringPtr = GetToken (OneOfOption->OptionOpCode->Option, gFormData->HiiHandle);
+ ASSERT (StringPtr != NULL);
+ NewStrCat (OptionString[0], StringPtr);
+ Character[0] = RIGHT_ONEOF_DELIMITER;
+ NewStrCat (OptionString[0], Character);
+ Character[0] = CHAR_CARRIAGE_RETURN;
+ NewStrCat (OptionString[0], Character);
+ FreePool (StringPtr);
+ }
+
+ //
+ // If valid option more than the max container, skip these options.
+ //
+ if (Index >= OrderList->MaxContainers) {
+ break;
+ }
+
+ //
+ // Search the other options, try to find the one not in the container.
+ //
+ Link = GetFirstNode (&Question->OptionListHead);
+ while (!IsNull (&Question->OptionListHead, Link)) {
+ OneOfOption = DISPLAY_QUESTION_OPTION_FROM_LINK (Link);
+ Link = GetNextNode (&Question->OptionListHead, Link);
+
+ if (FindArrayData (ValueArray, ValueType, OneOfOption->OptionOpCode->Value.u64, NULL)) {
+ continue;
+ }
+
+ if (SkipErrorValue) {
+ //
+ // Not report error, just get the correct option string info.
+ //
+ Character[0] = LEFT_ONEOF_DELIMITER;
+ NewStrCat (OptionString[0], Character);
+ StringPtr = GetToken (OneOfOption->OptionOpCode->Option, gFormData->HiiHandle);
+ ASSERT (StringPtr != NULL);
+ NewStrCat (OptionString[0], StringPtr);
+ Character[0] = RIGHT_ONEOF_DELIMITER;
+ NewStrCat (OptionString[0], Character);
+ Character[0] = CHAR_CARRIAGE_RETURN;
+ NewStrCat (OptionString[0], Character);
+ FreePool (StringPtr);
+
+ continue;
+ }
+
+ if (!ValueInvalid) {
+ ValueInvalid = TRUE;
+ //
+ // Show error message
+ //
+ do {
+ CreateDialog (&Key, gEmptyString, gOptionMismatch, gPressEnter, gEmptyString, NULL);
+ } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
+
+ //
+ // The initial value of the orderedlist is invalid, force to be valid value
+ // Exit current DisplayForm with new value.
+ //
+ gUserInput->SelectedStatement = Question;
+
+ ValueArray = AllocateCopyPool (Question->CurrentValue.BufferLen, Question->CurrentValue.Buffer);
+ ASSERT (ValueArray != NULL);
+ gUserInput->InputValue.Buffer = ValueArray;
+ gUserInput->InputValue.BufferLen = Question->CurrentValue.BufferLen;
+ gUserInput->InputValue.Type = Question->CurrentValue.Type;
+ }
+
+ SetArrayData (ValueArray, ValueType, Index++, OneOfOption->OptionOpCode->Value.u64);
+ }
+
+ if (ValueInvalid) {
+ FreePool (*OptionString);
+ *OptionString = NULL;
+ return EFI_NOT_FOUND;
+ }
+ }
+ break;
+
+ case EFI_IFR_ONE_OF_OP:
+ //
+ // Check whether there are Options of this OneOf
+ //
+ if (IsListEmpty (&Question->OptionListHead)) {
+ break;
+ }
+ if (Selected) {
+ //
+ // Go ask for input
+ //
+ Status = GetSelectionInputPopUp (MenuOption);
+ } else {
+ *OptionString = AllocateZeroPool (BufferSize);
+ ASSERT (*OptionString);
+
+ OneOfOption = ValueToOption (Question, QuestionValue);
+ if (OneOfOption == NULL) {
+ if (SkipErrorValue) {
+ //
+ // Not report error, just get the correct option string info.
+ //
+ Link = GetFirstNode (&Question->OptionListHead);
+ OneOfOption = DISPLAY_QUESTION_OPTION_FROM_LINK (Link);
+ } else {
+ //
+ // Show error message
+ //
+ do {
+ CreateDialog (&Key, gEmptyString, gOptionMismatch, gPressEnter, gEmptyString, NULL);
+ } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
+
+ //
+ // Force the Question value to be valid
+ // Exit current DisplayForm with new value.
+ //
+ Link = GetFirstNode (&Question->OptionListHead);
+ Option = DISPLAY_QUESTION_OPTION_FROM_LINK (Link);
+
+ CopyMem (&gUserInput->InputValue.Value, &Option->OptionOpCode->Value, sizeof (EFI_IFR_TYPE_VALUE));
+ gUserInput->InputValue.Type = Option->OptionOpCode->Type;
+ gUserInput->SelectedStatement = Question;
+
+ FreePool (*OptionString);
+ *OptionString = NULL;
+ return EFI_NOT_FOUND;
+ }
+ }
+
+ Character[0] = LEFT_ONEOF_DELIMITER;
+ NewStrCat (OptionString[0], Character);
+ StringPtr = GetToken (OneOfOption->OptionOpCode->Option, gFormData->HiiHandle);
+ ASSERT (StringPtr != NULL);
+ NewStrCat (OptionString[0], StringPtr);
+ Character[0] = RIGHT_ONEOF_DELIMITER;
+ NewStrCat (OptionString[0], Character);
+
+ FreePool (StringPtr);
+ }
+ break;
+
+ case EFI_IFR_CHECKBOX_OP:
+ if (Selected) {
+ //
+ // Since this is a BOOLEAN operation, flip it upon selection
+ //
+ gUserInput->InputValue.Type = QuestionValue->Type;
+ gUserInput->InputValue.Value.b = (BOOLEAN) (QuestionValue->Value.b ? FALSE : TRUE);
+
+ //
+ // Perform inconsistent check
+ //
+ return ValidateQuestion (Question);
+ } else {
+ *OptionString = AllocateZeroPool (BufferSize);
+ ASSERT (*OptionString);
+
+ *OptionString[0] = LEFT_CHECKBOX_DELIMITER;
+
+ if (QuestionValue->Value.b) {
+ *(OptionString[0] + 1) = CHECK_ON;
+ } else {
+ *(OptionString[0] + 1) = CHECK_OFF;
+ }
+ *(OptionString[0] + 2) = RIGHT_CHECKBOX_DELIMITER;
+ }
+ break;
+
+ case EFI_IFR_NUMERIC_OP:
+ if (Selected) {
+ //
+ // Go ask for input
+ //
+ Status = GetNumericInput (MenuOption);
+ } else {
+ *OptionString = AllocateZeroPool (BufferSize);
+ ASSERT (*OptionString);
+
+ *OptionString[0] = LEFT_NUMERIC_DELIMITER;
+
+ //
+ // Formatted print
+ //
+ PrintFormattedNumber (Question, FormattedNumber, 21 * sizeof (CHAR16));
+ Number = (UINT16) GetStringWidth (FormattedNumber);
+ CopyMem (OptionString[0] + 1, FormattedNumber, Number);
+
+ *(OptionString[0] + Number / 2) = RIGHT_NUMERIC_DELIMITER;
+ }
+ break;
+
+ case EFI_IFR_DATE_OP:
+ if (Selected) {
+ //
+ // This is similar to numerics
+ //
+ Status = GetNumericInput (MenuOption);
+ } else {
+ *OptionString = AllocateZeroPool (BufferSize);
+ ASSERT (*OptionString);
+
+ switch (MenuOption->Sequence) {
+ case 0:
+ *OptionString[0] = LEFT_NUMERIC_DELIMITER;
+ UnicodeSPrint (OptionString[0] + 1, 21 * sizeof (CHAR16), L"%02d", QuestionValue->Value.date.Month);
+ *(OptionString[0] + 3) = DATE_SEPARATOR;
+ break;
+
+ case 1:
+ SetUnicodeMem (OptionString[0], 4, L' ');
+ UnicodeSPrint (OptionString[0] + 4, 21 * sizeof (CHAR16), L"%02d", QuestionValue->Value.date.Day);
+ *(OptionString[0] + 6) = DATE_SEPARATOR;
+ break;
+
+ case 2:
+ SetUnicodeMem (OptionString[0], 7, L' ');
+ UnicodeSPrint (OptionString[0] + 7, 21 * sizeof (CHAR16), L"%04d", QuestionValue->Value.date.Year);
+ *(OptionString[0] + 11) = RIGHT_NUMERIC_DELIMITER;
+ break;
+ }
+ }
+ break;
+
+ case EFI_IFR_TIME_OP:
+ if (Selected) {
+ //
+ // This is similar to numerics
+ //
+ Status = GetNumericInput (MenuOption);
+ } else {
+ *OptionString = AllocateZeroPool (BufferSize);
+ ASSERT (*OptionString);
+
+ switch (MenuOption->Sequence) {
+ case 0:
+ *OptionString[0] = LEFT_NUMERIC_DELIMITER;
+ UnicodeSPrint (OptionString[0] + 1, 21 * sizeof (CHAR16), L"%02d", QuestionValue->Value.time.Hour);
+ *(OptionString[0] + 3) = TIME_SEPARATOR;
+ break;
+
+ case 1:
+ SetUnicodeMem (OptionString[0], 4, L' ');
+ UnicodeSPrint (OptionString[0] + 4, 21 * sizeof (CHAR16), L"%02d", QuestionValue->Value.time.Minute);
+ *(OptionString[0] + 6) = TIME_SEPARATOR;
+ break;
+
+ case 2:
+ SetUnicodeMem (OptionString[0], 7, L' ');
+ UnicodeSPrint (OptionString[0] + 7, 21 * sizeof (CHAR16), L"%02d", QuestionValue->Value.time.Second);
+ *(OptionString[0] + 9) = RIGHT_NUMERIC_DELIMITER;
+ break;
+ }
+ }
+ break;
+
+ case EFI_IFR_STRING_OP:
+ if (Selected) {
+ StringPtr = AllocateZeroPool (Question->CurrentValue.BufferLen + sizeof (CHAR16));
+ ASSERT (StringPtr);
+ CopyMem(StringPtr, Question->CurrentValue.Buffer, Question->CurrentValue.BufferLen);
+
+ Status = ReadString (MenuOption, gPromptForData, StringPtr);
+ if (EFI_ERROR (Status)) {
+ FreePool (StringPtr);
+ return Status;
+ }
+
+ gUserInput->InputValue.Buffer = AllocateCopyPool (Question->CurrentValue.BufferLen, StringPtr);
+ gUserInput->InputValue.BufferLen = Question->CurrentValue.BufferLen;
+ gUserInput->InputValue.Type = Question->CurrentValue.Type;
+ gUserInput->InputValue.Value.string = HiiSetString(gFormData->HiiHandle, gUserInput->InputValue.Value.string, StringPtr, NULL);
+ FreePool (StringPtr);
+ return ValidateQuestion (Question);
+ } else {
+ *OptionString = AllocateZeroPool (BufferSize);
+ ASSERT (*OptionString);
+
+ if (((CHAR16 *) Question->CurrentValue.Buffer)[0] == 0x0000) {
+ *(OptionString[0]) = '_';
+ } else {
+ if (Question->CurrentValue.BufferLen < BufferSize) {
+ BufferSize = Question->CurrentValue.BufferLen;
+ }
+ CopyMem (OptionString[0], (CHAR16 *) Question->CurrentValue.Buffer, BufferSize);
+ }
+ }
+ break;
+
+ case EFI_IFR_PASSWORD_OP:
+ if (Selected) {
+ Status = PasswordProcess (MenuOption);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return Status;
+}
+
+
+/**
+ Process the help string: Split StringPtr to several lines of strings stored in
+ FormattedString and the glyph width of each line cannot exceed gHelpBlockWidth.
+
+ @param StringPtr The entire help string.
+ @param FormattedString The oupput formatted string.
+ @param EachLineWidth The max string length of each line in the formatted string.
+ @param RowCount TRUE: if Question is selected.
+
+**/
+UINTN
+ProcessHelpString (
+ IN CHAR16 *StringPtr,
+ OUT CHAR16 **FormattedString,
+ OUT UINT16 *EachLineWidth,
+ IN UINTN RowCount
+ )
+{
+ UINTN Index;
+ CHAR16 *OutputString;
+ UINTN TotalRowNum;
+ UINTN CheckedNum;
+ UINT16 GlyphWidth;
+ UINT16 LineWidth;
+ UINT16 MaxStringLen;
+ UINT16 StringLen;
+
+ TotalRowNum = 0;
+ CheckedNum = 0;
+ GlyphWidth = 1;
+ Index = 0;
+ MaxStringLen = 0;
+ StringLen = 0;
+
+ //
+ // Set default help string width.
+ //
+ LineWidth = (UINT16) (gHelpBlockWidth - 1);
+
+ //
+ // Get row number of the String.
+ //
+ while ((StringLen = GetLineByWidth (StringPtr, LineWidth, &GlyphWidth, &Index, &OutputString)) != 0) {
+ if (StringLen > MaxStringLen) {
+ MaxStringLen = StringLen;
+ }
+
+ TotalRowNum ++;
+ FreePool (OutputString);
+ }
+ *EachLineWidth = MaxStringLen;
+
+ *FormattedString = AllocateZeroPool (TotalRowNum * MaxStringLen * sizeof (CHAR16));
+ ASSERT (*FormattedString != NULL);
+
+ //
+ // Generate formatted help string array.
+ //
+ GlyphWidth = 1;
+ Index = 0;
+ while((StringLen = GetLineByWidth (StringPtr, LineWidth, &GlyphWidth, &Index, &OutputString)) != 0) {
+ CopyMem (*FormattedString + CheckedNum * MaxStringLen, OutputString, StringLen * sizeof (CHAR16));
+ CheckedNum ++;
+ FreePool (OutputString);
+ }
+
+ return TotalRowNum;
+}
diff --git a/MdeModulePkg/Universal/DriverSampleDxe/DriverSample.c b/MdeModulePkg/Universal/DriverSampleDxe/DriverSample.c
index 3ae55de2b..d79a81a6d 100644
--- a/MdeModulePkg/Universal/DriverSampleDxe/DriverSample.c
+++ b/MdeModulePkg/Universal/DriverSampleDxe/DriverSample.c
@@ -1794,17 +1794,16 @@ DriverSampleInit (
DRIVER_SAMPLE_CONFIGURATION *Configuration;
BOOLEAN ActionFlag;
EFI_STRING ConfigRequestHdr;
+ EFI_STRING NameRequestHdr;
MY_EFI_VARSTORE_DATA *VarStoreConfig;
EFI_INPUT_KEY HotKey;
EFI_FORM_BROWSER_EXTENSION_PROTOCOL *FormBrowserEx;
- EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *PathToText;
//
// Initialize the local variables.
//
ConfigRequestHdr = NULL;
NewString = NULL;
- PathToText = NULL;
//
// Initialize screen dimensions for SendForm().
@@ -1921,18 +1920,11 @@ DriverSampleInit (
}
PrivateData->HiiHandle[1] = HiiHandle[1];
-
- Status = gBS->LocateProtocol (
- &gEfiDevicePathToTextProtocolGuid,
- NULL,
- (VOID **) &PathToText
- );
- ASSERT_EFI_ERROR (Status);
//
// Update the device path string.
//
- NewString = PathToText->ConvertDevicePathToText((EFI_DEVICE_PATH_PROTOCOL*)&mHiiVendorDevicePath0, FALSE, FALSE);
+ NewString = ConvertDevicePathToText((EFI_DEVICE_PATH_PROTOCOL*)&mHiiVendorDevicePath0, FALSE, FALSE);
if (HiiSetString (HiiHandle[0], STRING_TOKEN (STR_DEVICE_PATH), NewString, NULL) == 0) {
DriverSampleUnload (ImageHandle);
return EFI_OUT_OF_RESOURCES;
@@ -1973,6 +1965,9 @@ DriverSampleInit (
ConfigRequestHdr = HiiConstructConfigHdr (&gDriverSampleFormSetGuid, VariableName, DriverHandle[0]);
ASSERT (ConfigRequestHdr != NULL);
+ NameRequestHdr = HiiConstructConfigHdr (&gDriverSampleFormSetGuid, NULL, DriverHandle[0]);
+ ASSERT (NameRequestHdr != NULL);
+
BufferSize = sizeof (DRIVER_SAMPLE_CONFIGURATION);
Status = gRT->GetVariable (VariableName, &gDriverSampleFormSetGuid, NULL, &BufferSize, Configuration);
if (EFI_ERROR (Status)) {
@@ -1991,12 +1986,18 @@ DriverSampleInit (
// EFI variable for NV config doesn't exit, we should build this variable
// based on default values stored in IFR
//
+ ActionFlag = HiiSetToDefaults (NameRequestHdr, EFI_HII_DEFAULT_CLASS_STANDARD);
+ ASSERT (ActionFlag);
+
ActionFlag = HiiSetToDefaults (ConfigRequestHdr, EFI_HII_DEFAULT_CLASS_STANDARD);
ASSERT (ActionFlag);
} else {
//
// EFI variable does exist and Validate Current Setting
//
+ ActionFlag = HiiValidateSettings (NameRequestHdr);
+ ASSERT (ActionFlag);
+
ActionFlag = HiiValidateSettings (ConfigRequestHdr);
ASSERT (ActionFlag);
}
diff --git a/MdeModulePkg/Universal/DriverSampleDxe/DriverSample.h b/MdeModulePkg/Universal/DriverSampleDxe/DriverSample.h
index cd546bf38..29870c0f1 100644
--- a/MdeModulePkg/Universal/DriverSampleDxe/DriverSample.h
+++ b/MdeModulePkg/Universal/DriverSampleDxe/DriverSample.h
@@ -32,7 +32,6 @@ Revision History
#include <Protocol/HiiDatabase.h>
#include <Protocol/HiiString.h>
#include <Protocol/FormBrowserEx.h>
-#include <Protocol/DevicePathToText.h>
#include <Guid/MdeModuleHii.h>
#include <Library/DebugLib.h>
diff --git a/MdeModulePkg/Universal/DriverSampleDxe/DriverSampleDxe.inf b/MdeModulePkg/Universal/DriverSampleDxe/DriverSampleDxe.inf
index 36511e66d..1affe874b 100644
--- a/MdeModulePkg/Universal/DriverSampleDxe/DriverSampleDxe.inf
+++ b/MdeModulePkg/Universal/DriverSampleDxe/DriverSampleDxe.inf
@@ -55,6 +55,7 @@
HiiLib
PrintLib
UefiLib
+ DevicePathLib
[Guids]
gEfiIfrTianoGuid ## CONSUMES ## Guid
@@ -70,7 +71,6 @@
gEfiHiiDatabaseProtocolGuid ## CONSUMES
gEfiSimpleTextInputExProtocolGuid ## CONSUMES
gEfiFormBrowserExProtocolGuid ## CONSUMES
- gEfiDevicePathToTextProtocolGuid ## CONSUMES
[Depex]
gEfiSimpleTextOutProtocolGuid AND gEfiHiiDatabaseProtocolGuid AND gEfiVariableArchProtocolGuid AND gEfiVariableWriteArchProtocolGuid
diff --git a/MdeModulePkg/Universal/DriverSampleDxe/Vfr.vfr b/MdeModulePkg/Universal/DriverSampleDxe/Vfr.vfr
index 60e9cf2a3..affd45ad1 100644
--- a/MdeModulePkg/Universal/DriverSampleDxe/Vfr.vfr
+++ b/MdeModulePkg/Universal/DriverSampleDxe/Vfr.vfr
@@ -359,6 +359,8 @@ formset
maximum = 0xff,
step = 0,
locked,
+ default = 16, defaultstore = MyStandardDefault, // This is standard default value
+ default = 17, defaultstore = MyManufactureDefault, // This is manufacture default value
endnumeric;
numeric varid = MyNameValueVar[1], // This numeric take NameValueVar1 as storage
@@ -368,6 +370,8 @@ formset
minimum = 0,
maximum = 0xffff,
step = 0,
+ default = 18, defaultstore = MyStandardDefault, // This is standard default value
+ default = 19, defaultstore = MyManufactureDefault, // This is manufacture default value
endnumeric;
//
@@ -517,30 +521,12 @@ formset
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_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_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_HELP),
- minimum = 1,
- maximum = 31,
- step = 0x1,
- default = 1,
+ date
+ name = Date,
+ prompt = STRING_TOKEN(STR_DATE_PROMPT),
+ help = STRING_TOKEN(STR_DATE_HELP),
+ flags = STORAGE_TIME,
+ default = 1/1/2004,
inconsistentif prompt = STRING_TOKEN(STR_ERROR_POPUP),
ideqval Date.Day == 31
@@ -585,30 +571,10 @@ formset
flags = INTERACTIVE,
key = 0x1242;
- time hour varid = Time.Hour, // 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_HELP),
- minimum = 0,
- maximum = 23,
- step = 1,
- default = 0,
-
- minute varid = Time.Minute, // 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_HELP),
- minimum = 0,
- maximum = 59,
- step = 1,
- default = 0,
-
- second varid = Time.Second, // 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_HELP),
- minimum = 0,
- maximum = 59,
- step = 1,
- default = 0,
-
+ time
+ prompt = STRING_TOKEN(STR_TIME_PROMPT),
+ help = STRING_TOKEN(STR_TIME_HELP),
+ flags = STORAGE_TIME,
endtime;
time
diff --git a/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWrite.c b/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWrite.c
index 2f110167d..3d1d29dfd 100644
--- a/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWrite.c
+++ b/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWrite.c
@@ -3,7 +3,7 @@
These are the common Fault Tolerant Write (FTW) functions that are shared
by DXE FTW driver and SMM FTW driver.
-Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
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
@@ -95,7 +95,7 @@ FtwAllocate (
//
// Check if there is enough space for the coming allocation
//
- if (WRITE_TOTAL_SIZE (NumberOfWrites, PrivateDataSize) > FtwDevice->FtwWorkSpaceHeader->WriteQueueSize) {
+ if (FTW_WRITE_TOTAL_SIZE (NumberOfWrites, PrivateDataSize) > FtwDevice->FtwWorkSpaceHeader->WriteQueueSize) {
DEBUG ((EFI_D_ERROR, "Ftw: Allocate() request exceed Workspace, Caller: %g\n", CallerId));
return EFI_BUFFER_TOO_SMALL;
}
@@ -115,7 +115,7 @@ FtwAllocate (
// If workspace is not enough, then reclaim workspace
//
Offset = (UINT8 *) FtwHeader - (UINT8 *) FtwDevice->FtwWorkSpace;
- if (Offset + WRITE_TOTAL_SIZE (NumberOfWrites, PrivateDataSize) > FtwDevice->FtwWorkSpaceSize) {
+ if (Offset + FTW_WRITE_TOTAL_SIZE (NumberOfWrites, PrivateDataSize) > FtwDevice->FtwWorkSpaceSize) {
Status = FtwReclaimWorkSpace (FtwDevice, TRUE);
if (EFI_ERROR (Status)) {
return EFI_ABORTED;
@@ -365,7 +365,7 @@ FtwWrite (
//
// If Record is out of the range of Header, return access denied.
//
- if (((UINTN)((UINT8 *) Record - (UINT8 *) Header)) > WRITE_TOTAL_SIZE (Header->NumberOfWrites - 1, Header->PrivateDataSize)) {
+ if (((UINTN)((UINT8 *) Record - (UINT8 *) Header)) > FTW_WRITE_TOTAL_SIZE (Header->NumberOfWrites - 1, Header->PrivateDataSize)) {
return EFI_ACCESS_DENIED;
}
@@ -415,13 +415,13 @@ FtwWrite (
Record->Lba = Lba;
Record->Offset = Offset;
Record->Length = Length;
- Record->FvBaseAddress = FvbPhysicalAddress;
+ Record->RelativeOffset = (INT64) (FvbPhysicalAddress + (UINTN) Lba * FtwDevice->BlockSize) - (INT64) FtwDevice->SpareAreaAddress;
if (PrivateData != NULL) {
- CopyMem ((Record + 1), PrivateData, Header->PrivateDataSize);
+ CopyMem ((Record + 1), PrivateData, (UINTN) Header->PrivateDataSize);
}
MyOffset = (UINT8 *) Record - FtwDevice->FtwWorkSpace;
- MyLength = RECORD_SIZE (Header->PrivateDataSize);
+ MyLength = FTW_RECORD_SIZE (Header->PrivateDataSize);
Status = FtwDevice->FtwFvBlock->Write (
FtwDevice->FtwFvBlock,
@@ -693,6 +693,10 @@ FtwAbort (
return EFI_ABORTED;
}
+ if (FtwDevice->FtwLastWriteHeader->HeaderAllocated != FTW_VALID_STATE) {
+ return EFI_NOT_FOUND;
+ }
+
if (FtwDevice->FtwLastWriteHeader->Complete == FTW_VALID_STATE) {
return EFI_NOT_FOUND;
}
@@ -809,16 +813,16 @@ FtwGetLastWrite (
//
CopyMem (CallerId, &Header->CallerId, sizeof (EFI_GUID));
*Lba = Record->Lba;
- *Offset = Record->Offset;
- *Length = Record->Length;
+ *Offset = (UINTN) Record->Offset;
+ *Length = (UINTN) Record->Length;
*Complete = (BOOLEAN) (Record->DestinationComplete == FTW_VALID_STATE);
if (*PrivateDataSize < Header->PrivateDataSize) {
- *PrivateDataSize = Header->PrivateDataSize;
+ *PrivateDataSize = (UINTN) Header->PrivateDataSize;
PrivateData = NULL;
Status = EFI_BUFFER_TOO_SMALL;
} else {
- *PrivateDataSize = Header->PrivateDataSize;
+ *PrivateDataSize = (UINTN) Header->PrivateDataSize;
CopyMem (PrivateData, Record + 1, *PrivateDataSize);
Status = EFI_SUCCESS;
}
diff --git a/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWrite.h b/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWrite.h
index 8deae8851..a460694d6 100644
--- a/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWrite.h
+++ b/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWrite.h
@@ -3,7 +3,7 @@
The internal header file includes the common header files, defines
internal structure and functions used by FtwLite module.
-Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
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
@@ -32,65 +32,24 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include <Library/BaseMemoryLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/UefiBootServicesTableLib.h>
+#include <Library/ReportStatusCodeLib.h>
//
// Flash erase polarity is 1
//
#define FTW_ERASE_POLARITY 1
-#define FTW_VALID_STATE 0
-#define FTW_INVALID_STATE 1
-
#define FTW_ERASED_BYTE ((UINT8) (255))
#define FTW_POLARITY_REVERT ((UINT8) (255))
-//
-// EFI Fault tolerant block update write queue entry
-//
-typedef struct {
- UINT8 HeaderAllocated : 1;
- UINT8 WritesAllocated : 1;
- UINT8 Complete : 1;
#define HEADER_ALLOCATED 0x1
#define WRITES_ALLOCATED 0x2
#define WRITES_COMPLETED 0x4
- UINT8 Reserved : 5;
- EFI_GUID CallerId;
- UINTN NumberOfWrites;
- UINTN PrivateDataSize;
-} EFI_FAULT_TOLERANT_WRITE_HEADER;
-//
-// EFI Fault tolerant block update write queue record
-//
-typedef struct {
- UINT8 BootBlockUpdate : 1;
- UINT8 SpareComplete : 1;
- UINT8 DestinationComplete : 1;
#define BOOT_BLOCK_UPDATE 0x1
#define SPARE_COMPLETED 0x2
#define DEST_COMPLETED 0x4
- UINT8 Reserved : 5;
- EFI_LBA Lba;
- UINTN Offset;
- UINTN Length;
- EFI_PHYSICAL_ADDRESS FvBaseAddress;
- //
- // UINT8 PrivateData[PrivateDataSize]
- //
-} EFI_FAULT_TOLERANT_WRITE_RECORD;
-
-
-#define RECORD_SIZE(PrivateDataSize) (sizeof (EFI_FAULT_TOLERANT_WRITE_RECORD) + PrivateDataSize)
-
-#define RECORD_TOTAL_SIZE(NumberOfWrites, PrivateDataSize) \
- ((NumberOfWrites) * (sizeof (EFI_FAULT_TOLERANT_WRITE_RECORD) + PrivateDataSize))
-#define WRITE_TOTAL_SIZE(NumberOfWrites, PrivateDataSize) \
- ( \
- sizeof (EFI_FAULT_TOLERANT_WRITE_HEADER) + (NumberOfWrites) * \
- (sizeof (EFI_FAULT_TOLERANT_WRITE_RECORD) + PrivateDataSize) \
- )
#define FTW_DEVICE_SIGNATURE SIGNATURE_32 ('F', 'T', 'W', 'D')
diff --git a/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf b/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf
index f60ab287e..f4576447d 100644
--- a/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf
+++ b/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf
@@ -3,7 +3,7 @@
# which provides fault tolerant write capability for block devices.
# Its implementation depends on the full functionality FVB protocol that support read, write/erase flash access.
#
-# Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
#
# This program and the accompanying materials
# are licensed and made available under the terms and conditions of the BSD License
@@ -47,9 +47,10 @@
DebugLib
UefiLib
PcdLib
+ ReportStatusCodeLib
[Guids]
- gEfiSystemNvDataFvGuid ## CONSUMES ## FV Signature of Working Space Header
+ gEdkiiWorkingBlockSignatureGuid ## CONSUMES ## FV Signature of Working Space Header
[Protocols]
gEfiSwapAddressRangeProtocolGuid | gEfiMdeModulePkgTokenSpaceGuid.PcdFullFtwServiceEnable ## CONSUMES
diff --git a/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmm.inf b/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmm.inf
index c39f84ca3..7740efa35 100644
--- a/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmm.inf
+++ b/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmm.inf
@@ -50,9 +50,10 @@
DebugLib
UefiLib
PcdLib
+ ReportStatusCodeLib
[Guids]
- gEfiSystemNvDataFvGuid ## CONSUMES ## FV Signature of Working Space Header
+ gEdkiiWorkingBlockSignatureGuid ## CONSUMES ## FV Signature of Working Space Header
[Protocols]
gEfiSmmSwapAddressRangeProtocolGuid | gEfiMdeModulePkgTokenSpaceGuid.PcdFullFtwServiceEnable ## CONSUMES
diff --git a/MdeModulePkg/Universal/FaultTolerantWriteDxe/FtwMisc.c b/MdeModulePkg/Universal/FaultTolerantWriteDxe/FtwMisc.c
index c5f41d737..b3352bbe0 100644
--- a/MdeModulePkg/Universal/FaultTolerantWriteDxe/FtwMisc.c
+++ b/MdeModulePkg/Universal/FaultTolerantWriteDxe/FtwMisc.c
@@ -2,7 +2,7 @@
Internal generic functions to operate flash block.
-Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
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
@@ -411,7 +411,7 @@ FlushSpareBlockToBootBlock (
return EFI_ABORTED;
}
//
- // Write memory buffer currenet spare block. Still top block.
+ // Write memory buffer to current spare block. Still top block.
//
Ptr = Buffer;
for (Index = 0; Index < FtwDevice->NumberOfSpareBlock; Index += 1) {
@@ -689,6 +689,7 @@ FlushSpareBlockToWorkingBlock (
return EFI_ABORTED;
}
+ FtwDevice->FtwWorkSpaceHeader->WorkingBlockInvalid = FTW_INVALID_STATE;
FtwDevice->FtwWorkSpaceHeader->WorkingBlockValid = FTW_VALID_STATE;
return EFI_SUCCESS;
@@ -775,7 +776,7 @@ FtwGetLastWriteHeader (
Offset = sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER);
while (FtwHeader->Complete == FTW_VALID_STATE) {
- Offset += WRITE_TOTAL_SIZE (FtwHeader->NumberOfWrites, FtwHeader->PrivateDataSize);
+ Offset += FTW_WRITE_TOTAL_SIZE (FtwHeader->NumberOfWrites, FtwHeader->PrivateDataSize);
//
// If Offset exceed the FTW work space boudary, return error.
//
@@ -834,7 +835,7 @@ FtwGetLastWriteRecord (
FtwRecord++;
if (FtwWriteHeader->PrivateDataSize != 0) {
- FtwRecord = (EFI_FAULT_TOLERANT_WRITE_RECORD *) ((UINTN) FtwRecord + FtwWriteHeader->PrivateDataSize);
+ FtwRecord = (EFI_FAULT_TOLERANT_WRITE_RECORD *) ((UINTN) FtwRecord + (UINTN) FtwWriteHeader->PrivateDataSize);
}
}
//
@@ -844,7 +845,7 @@ FtwGetLastWriteRecord (
// also return the last record.
//
if (Index == FtwWriteHeader->NumberOfWrites) {
- *FtwWriteRecord = (EFI_FAULT_TOLERANT_WRITE_RECORD *) ((UINTN) FtwRecord - RECORD_SIZE (FtwWriteHeader->PrivateDataSize));
+ *FtwWriteRecord = (EFI_FAULT_TOLERANT_WRITE_RECORD *) ((UINTN) FtwRecord - FTW_RECORD_SIZE (FtwWriteHeader->PrivateDataSize));
return EFI_SUCCESS;
}
@@ -901,7 +902,7 @@ IsLastRecordOfWrites (
Head = (UINT8 *) FtwHeader;
Ptr = (UINT8 *) FtwRecord;
- Head += WRITE_TOTAL_SIZE (FtwHeader->NumberOfWrites - 1, FtwHeader->PrivateDataSize);
+ Head += FTW_WRITE_TOTAL_SIZE (FtwHeader->NumberOfWrites - 1, FtwHeader->PrivateDataSize);
return (BOOLEAN) (Head == Ptr);
}
@@ -929,7 +930,7 @@ GetPreviousRecordOfWrites (
}
Ptr = (UINT8 *) (*FtwRecord);
- Ptr -= RECORD_SIZE (FtwHeader->PrivateDataSize);
+ Ptr -= FTW_RECORD_SIZE (FtwHeader->PrivateDataSize);
*FtwRecord = (EFI_FAULT_TOLERANT_WRITE_RECORD *) Ptr;
return EFI_SUCCESS;
}
@@ -1110,6 +1111,20 @@ FindFvbForFtw (
ASSERT (FALSE);
return EFI_ABORTED;
}
+ //
+ // Check the alignment of spare area address and length, they should be block size aligned
+ //
+ if (((FtwDevice->SpareAreaAddress & (FtwDevice->BlockSize - 1)) != 0) ||
+ ((FtwDevice->SpareAreaLength & (FtwDevice->BlockSize - 1)) != 0)) {
+ DEBUG ((EFI_D_ERROR, "Ftw: Spare area address or length is not block size aligned\n"));
+ FreePool (HandleBuffer);
+ //
+ // Report Status Code EFI_SW_EC_ABORTED.
+ //
+ REPORT_STATUS_CODE ( (EFI_ERROR_CODE | EFI_ERROR_UNRECOVERED), (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_EC_ABORTED));
+ ASSERT (FALSE);
+ CpuDeadLoop ();
+ }
break;
}
}
@@ -1117,12 +1132,12 @@ FindFvbForFtw (
}
}
FreePool (HandleBuffer);
-
+
if ((FtwDevice->FtwBackupFvb == NULL) || (FtwDevice->FtwFvBlock == NULL) ||
(FtwDevice->FtwWorkSpaceLba == (EFI_LBA) (-1)) || (FtwDevice->FtwSpareLba == (EFI_LBA) (-1))) {
return EFI_ABORTED;
}
-
+
return EFI_SUCCESS;
}
@@ -1147,6 +1162,7 @@ InitFtwProtocol (
EFI_FAULT_TOLERANT_WRITE_HEADER *FtwHeader;
UINTN Offset;
EFI_HANDLE FvbHandle;
+ EFI_LBA WorkSpaceLbaOffset;
//
// Find the right SMM Fvb protocol instance for FTW.
@@ -1188,10 +1204,11 @@ InitFtwProtocol (
//
// Read from spare block
//
+ WorkSpaceLbaOffset = FtwDevice->FtwWorkSpaceLba - FtwDevice->FtwWorkBlockLba;
Length = FtwDevice->FtwWorkSpaceSize;
Status = FtwDevice->FtwBackupFvb->Read (
FtwDevice->FtwBackupFvb,
- FtwDevice->FtwSpareLba,
+ FtwDevice->FtwSpareLba + WorkSpaceLbaOffset,
FtwDevice->FtwWorkSpaceBase,
&Length,
FtwDevice->FtwWorkSpace
@@ -1257,7 +1274,7 @@ InitFtwProtocol (
FtwHeader = FtwDevice->FtwLastWriteHeader;
Offset = (UINT8 *) FtwHeader - FtwDevice->FtwWorkSpace;
if (FtwDevice->FtwWorkSpace[Offset] != FTW_ERASED_BYTE) {
- Offset += WRITE_TOTAL_SIZE (FtwHeader->NumberOfWrites, FtwHeader->PrivateDataSize);
+ Offset += FTW_WRITE_TOTAL_SIZE (FtwHeader->NumberOfWrites, FtwHeader->PrivateDataSize);
}
if (!IsErasedFlashBuffer (FtwDevice->FtwWorkSpace + Offset, FtwDevice->FtwWorkSpaceSize - Offset)) {
@@ -1281,7 +1298,7 @@ InitFtwProtocol (
// if (SpareCompleted) THEN Restart to fault tolerant write.
//
FvbHandle = NULL;
- FvbHandle = GetFvbByAddress (FtwDevice->FtwLastWriteRecord->FvBaseAddress, &Fvb);
+ FvbHandle = GetFvbByAddress ((EFI_PHYSICAL_ADDRESS) (UINTN) ((INT64) FtwDevice->SpareAreaAddress + FtwDevice->FtwLastWriteRecord->RelativeOffset), &Fvb);
if (FvbHandle != NULL) {
Status = FtwRestart (&FtwDevice->FtwInstance, FvbHandle);
DEBUG ((EFI_D_ERROR, "FtwLite: Restart last write - %r\n", Status));
diff --git a/MdeModulePkg/Universal/FaultTolerantWriteDxe/UpdateWorkingBlock.c b/MdeModulePkg/Universal/FaultTolerantWriteDxe/UpdateWorkingBlock.c
index bd8285d00..4c658b297 100644
--- a/MdeModulePkg/Universal/FaultTolerantWriteDxe/UpdateWorkingBlock.c
+++ b/MdeModulePkg/Universal/FaultTolerantWriteDxe/UpdateWorkingBlock.c
@@ -2,7 +2,7 @@
Internal functions to operate Working Block Space.
-Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
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
@@ -32,9 +32,9 @@ InitializeLocalWorkSpaceHeader (
EFI_STATUS Status;
//
- // Check signature with gEfiSystemNvDataFvGuid.
+ // Check signature with gEdkiiWorkingBlockSignatureGuid.
//
- if (CompareGuid (&gEfiSystemNvDataFvGuid, &mWorkingBlockHeader.Signature)) {
+ if (CompareGuid (&gEdkiiWorkingBlockSignatureGuid, &mWorkingBlockHeader.Signature)) {
//
// The local work space header has been initialized.
//
@@ -48,11 +48,11 @@ InitializeLocalWorkSpaceHeader (
);
//
- // Here using gEfiSystemNvDataFvGuid as the signature.
+ // Here using gEdkiiWorkingBlockSignatureGuid as the signature.
//
CopyMem (
&mWorkingBlockHeader.Signature,
- &gEfiSystemNvDataFvGuid,
+ &gEdkiiWorkingBlockSignatureGuid,
sizeof (EFI_GUID)
);
mWorkingBlockHeader.WriteQueueSize = (UINT64) (PcdGet32 (PcdFlashNvStorageFtwWorkingSize) - sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER));
@@ -322,7 +322,7 @@ FtwReclaimWorkSpace (
CopyMem (
Ptr + sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER),
FtwDevice->FtwLastWriteHeader,
- WRITE_TOTAL_SIZE (Header->NumberOfWrites, Header->PrivateDataSize)
+ FTW_WRITE_TOTAL_SIZE (Header->NumberOfWrites, Header->PrivateDataSize)
);
}
}
diff --git a/MdeModulePkg/Universal/FaultTolerantWritePei/FaultTolerantWritePei.c b/MdeModulePkg/Universal/FaultTolerantWritePei/FaultTolerantWritePei.c
new file mode 100644
index 000000000..14e18e5ae
--- /dev/null
+++ b/MdeModulePkg/Universal/FaultTolerantWritePei/FaultTolerantWritePei.c
@@ -0,0 +1,321 @@
+/** @file
+ This driver installs gEdkiiFaultTolerantWriteGuid PPI to inform
+ the check for FTW last write data has been done.
+
+Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>
+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 <PiPei.h>
+
+#include <Guid/SystemNvDataGuid.h>
+#include <Guid/FaultTolerantWrite.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/PcdLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/HobLib.h>
+
+EFI_PEI_PPI_DESCRIPTOR mPpiListVariable = {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEdkiiFaultTolerantWriteGuid,
+ NULL
+};
+
+/**
+ Get the last Write Header pointer.
+ The last write header is the header whose 'complete' state hasn't been set.
+ After all, this header may be a EMPTY header entry for next Allocate.
+
+
+ @param FtwWorkSpaceHeader Pointer of the working block header
+ @param FtwWorkSpaceSize Size of the work space
+ @param FtwWriteHeader Pointer to retrieve the last write header
+
+ @retval EFI_SUCCESS Get the last write record successfully
+ @retval EFI_ABORTED The FTW work space is damaged
+
+**/
+EFI_STATUS
+FtwGetLastWriteHeader (
+ IN EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *FtwWorkSpaceHeader,
+ IN UINTN FtwWorkSpaceSize,
+ OUT EFI_FAULT_TOLERANT_WRITE_HEADER **FtwWriteHeader
+ )
+{
+ UINTN Offset;
+ EFI_FAULT_TOLERANT_WRITE_HEADER *FtwHeader;
+
+ *FtwWriteHeader = NULL;
+ FtwHeader = (EFI_FAULT_TOLERANT_WRITE_HEADER *) (FtwWorkSpaceHeader + 1);
+ Offset = sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER);
+
+ while (FtwHeader->Complete == FTW_VALID_STATE) {
+ Offset += FTW_WRITE_TOTAL_SIZE (FtwHeader->NumberOfWrites, FtwHeader->PrivateDataSize);
+ //
+ // If Offset exceed the FTW work space boudary, return error.
+ //
+ if (Offset >= FtwWorkSpaceSize) {
+ *FtwWriteHeader = FtwHeader;
+ return EFI_ABORTED;
+ }
+
+ FtwHeader = (EFI_FAULT_TOLERANT_WRITE_HEADER *) ((UINT8 *) FtwWorkSpaceHeader + Offset);
+ }
+ //
+ // Last write header is found
+ //
+ *FtwWriteHeader = FtwHeader;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Get the last Write Record pointer. The last write Record is the Record
+ whose DestinationCompleted state hasn't been set. After all, this Record
+ may be a EMPTY record entry for next write.
+
+
+ @param FtwWriteHeader Pointer to the write record header
+ @param FtwWriteRecord Pointer to retrieve the last write record
+
+ @retval EFI_SUCCESS Get the last write record successfully
+ @retval EFI_ABORTED The FTW work space is damaged
+
+**/
+EFI_STATUS
+FtwGetLastWriteRecord (
+ IN EFI_FAULT_TOLERANT_WRITE_HEADER *FtwWriteHeader,
+ OUT EFI_FAULT_TOLERANT_WRITE_RECORD **FtwWriteRecord
+ )
+{
+ UINTN Index;
+ EFI_FAULT_TOLERANT_WRITE_RECORD *FtwRecord;
+
+ *FtwWriteRecord = NULL;
+ FtwRecord = (EFI_FAULT_TOLERANT_WRITE_RECORD *) (FtwWriteHeader + 1);
+
+ //
+ // Try to find the last write record "that has not completed"
+ //
+ for (Index = 0; Index < FtwWriteHeader->NumberOfWrites; Index += 1) {
+ if (FtwRecord->DestinationComplete != FTW_VALID_STATE) {
+ //
+ // The last write record is found
+ //
+ *FtwWriteRecord = FtwRecord;
+ return EFI_SUCCESS;
+ }
+
+ FtwRecord++;
+
+ if (FtwWriteHeader->PrivateDataSize != 0) {
+ FtwRecord = (EFI_FAULT_TOLERANT_WRITE_RECORD *) ((UINTN) FtwRecord + (UINTN) FtwWriteHeader->PrivateDataSize);
+ }
+ }
+ //
+ // if Index == NumberOfWrites, then
+ // the last record has been written successfully,
+ // but the Header->Complete Flag has not been set.
+ // also return the last record.
+ //
+ if (Index == FtwWriteHeader->NumberOfWrites) {
+ *FtwWriteRecord = (EFI_FAULT_TOLERANT_WRITE_RECORD *) ((UINTN) FtwRecord - FTW_RECORD_SIZE (FtwWriteHeader->PrivateDataSize));
+ return EFI_SUCCESS;
+ }
+
+ return EFI_ABORTED;
+}
+
+/**
+ Check to see if it is a valid work space.
+
+
+ @param WorkingHeader Pointer of working block header
+ @param WorkingLength Working block length
+
+ @retval TRUE The work space is valid.
+ @retval FALSE The work space is invalid.
+
+**/
+BOOLEAN
+IsValidWorkSpace (
+ IN EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *WorkingHeader,
+ IN UINTN WorkingLength
+ )
+{
+ UINT8 Data;
+
+ if (WorkingHeader == NULL) {
+ return FALSE;
+ }
+
+ if ((WorkingHeader->WorkingBlockValid != FTW_VALID_STATE) || (WorkingHeader->WorkingBlockInvalid == FTW_VALID_STATE)) {
+ DEBUG ((EFI_D_ERROR, "FtwPei: Work block header valid bit check error\n"));
+ return FALSE;
+ }
+
+ if (WorkingHeader->WriteQueueSize != (WorkingLength - sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER))) {
+ DEBUG ((EFI_D_ERROR, "FtwPei: Work block header WriteQueueSize check error\n"));
+ return FALSE;
+ }
+
+ //
+ // Check signature with gEdkiiWorkingBlockSignatureGuid
+ //
+ if (!CompareGuid (&gEdkiiWorkingBlockSignatureGuid, &WorkingHeader->Signature)) {
+ DEBUG ((EFI_D_ERROR, "FtwPei: Work block header signature check error, it should be gEdkiiWorkingBlockSignatureGuid\n"));
+ //
+ // To be compatible with old signature gEfiSystemNvDataFvGuid.
+ //
+ if (!CompareGuid (&gEfiSystemNvDataFvGuid, &WorkingHeader->Signature)) {
+ return FALSE;
+ } else {
+ Data = *(UINT8 *) (WorkingHeader + 1);
+ if (Data != 0xff) {
+ DEBUG ((EFI_D_ERROR, "FtwPei: Old format FTW structure can't be handled\n"));
+ ASSERT (FALSE);
+ return FALSE;
+ }
+ }
+ }
+
+ return TRUE;
+
+}
+
+/**
+ Main entry for Fault Tolerant Write PEIM.
+
+ @param[in] FileHandle Handle of the file being invoked.
+ @param[in] PeiServices Pointer to PEI Services table.
+
+ @retval EFI_SUCCESS If the interface could be successfully installed
+ @retval Others Returned from PeiServicesInstallPpi()
+
+**/
+EFI_STATUS
+EFIAPI
+PeimFaultTolerantWriteInitialize (
+ IN EFI_PEI_FILE_HANDLE FileHandle,
+ IN CONST EFI_PEI_SERVICES **PeiServices
+ )
+{
+ EFI_STATUS Status;
+ EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *FtwWorkingBlockHeader;
+ EFI_FAULT_TOLERANT_WRITE_HEADER *FtwLastWriteHeader;
+ EFI_FAULT_TOLERANT_WRITE_RECORD *FtwLastWriteRecord;
+ EFI_PHYSICAL_ADDRESS WorkSpaceAddress;
+ UINTN WorkSpaceLength;
+ EFI_PHYSICAL_ADDRESS SpareAreaAddress;
+ UINTN SpareAreaLength;
+ EFI_PHYSICAL_ADDRESS WorkSpaceInSpareArea;
+ FAULT_TOLERANT_WRITE_LAST_WRITE_DATA FtwLastWrite;
+
+ FtwWorkingBlockHeader = NULL;
+ FtwLastWriteHeader = NULL;
+ FtwLastWriteRecord = NULL;
+
+ WorkSpaceAddress = (EFI_PHYSICAL_ADDRESS) PcdGet64 (PcdFlashNvStorageFtwWorkingBase64);
+ if (WorkSpaceAddress == 0) {
+ WorkSpaceAddress = (EFI_PHYSICAL_ADDRESS) PcdGet32 (PcdFlashNvStorageFtwWorkingBase);
+ }
+ WorkSpaceLength = (UINTN) PcdGet32 (PcdFlashNvStorageFtwWorkingSize);
+
+ SpareAreaAddress = (EFI_PHYSICAL_ADDRESS) PcdGet64 (PcdFlashNvStorageFtwSpareBase64);
+ if (SpareAreaAddress == 0) {
+ SpareAreaAddress = (EFI_PHYSICAL_ADDRESS) PcdGet32 (PcdFlashNvStorageFtwSpareBase);
+ }
+ SpareAreaLength = (UINTN) PcdGet32 (PcdFlashNvStorageFtwSpareSize);
+
+ //
+ // The address of FTW working base and spare base must not be 0.
+ //
+ ASSERT ((WorkSpaceAddress != 0) && (SpareAreaAddress != 0));
+
+ FtwWorkingBlockHeader = (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *) (UINTN) WorkSpaceAddress;
+ if (IsValidWorkSpace (FtwWorkingBlockHeader, WorkSpaceLength)) {
+ Status = FtwGetLastWriteHeader (
+ FtwWorkingBlockHeader,
+ WorkSpaceLength,
+ &FtwLastWriteHeader
+ );
+ if (!EFI_ERROR (Status)) {
+ Status = FtwGetLastWriteRecord (
+ FtwLastWriteHeader,
+ &FtwLastWriteRecord
+ );
+ }
+
+ if (!EFI_ERROR (Status)) {
+ ASSERT (FtwLastWriteRecord != NULL);
+ if ((FtwLastWriteRecord->SpareComplete == FTW_VALID_STATE) && (FtwLastWriteRecord->DestinationComplete != FTW_VALID_STATE)) {
+ //
+ // If FTW last write was still in progress with SpareComplete set and DestinationComplete not set.
+ // It means the target buffer has been backed up in spare block, then target block has been erased,
+ // but the target buffer has not been writen in target block from spare block, we need to build
+ // FAULT_TOLERANT_WRITE_LAST_WRITE_DATA GUID hob to hold the FTW last write data.
+ //
+ FtwLastWrite.TargetAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) ((INT64) SpareAreaAddress + FtwLastWriteRecord->RelativeOffset);
+ FtwLastWrite.SpareAddress = SpareAreaAddress;
+ FtwLastWrite.Length = SpareAreaLength;
+ DEBUG ((
+ EFI_D_INFO,
+ "FtwPei last write data: TargetAddress - 0x%x SpareAddress - 0x%x Length - 0x%x\n",
+ (UINTN) FtwLastWrite.TargetAddress,
+ (UINTN) FtwLastWrite.SpareAddress,
+ (UINTN) FtwLastWrite.Length));
+ BuildGuidDataHob (&gEdkiiFaultTolerantWriteGuid, (VOID *) &FtwLastWrite, sizeof (FAULT_TOLERANT_WRITE_LAST_WRITE_DATA));
+ }
+ }
+ } else {
+ FtwWorkingBlockHeader = NULL;
+ //
+ // If the working block workspace is not valid, try to find workspace in the spare block.
+ //
+ WorkSpaceInSpareArea = SpareAreaAddress + SpareAreaLength - WorkSpaceLength;
+ while (WorkSpaceInSpareArea >= SpareAreaAddress) {
+ if (CompareGuid (&gEdkiiWorkingBlockSignatureGuid, (EFI_GUID *) (UINTN) WorkSpaceInSpareArea)) {
+ //
+ // Found the workspace.
+ //
+ DEBUG ((EFI_D_INFO, "FtwPei: workspace in spare block is at 0x%x.\n", (UINTN) WorkSpaceInSpareArea));
+ FtwWorkingBlockHeader = (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *) (UINTN) WorkSpaceInSpareArea;
+ break;
+ }
+ WorkSpaceInSpareArea = WorkSpaceInSpareArea - sizeof (EFI_GUID);
+ }
+ if ((FtwWorkingBlockHeader != NULL) && IsValidWorkSpace (FtwWorkingBlockHeader, WorkSpaceLength)) {
+ //
+ // It was workspace self reclaim, build FAULT_TOLERANT_WRITE_LAST_WRITE_DATA GUID hob for it.
+ //
+ FtwLastWrite.TargetAddress = WorkSpaceAddress - (WorkSpaceInSpareArea - SpareAreaAddress);
+ FtwLastWrite.SpareAddress = SpareAreaAddress;
+ FtwLastWrite.Length = SpareAreaLength;
+ DEBUG ((
+ EFI_D_INFO,
+ "FtwPei last write data: TargetAddress - 0x%x SpareAddress - 0x%x Length - 0x%x\n",
+ (UINTN) FtwLastWrite.TargetAddress,
+ (UINTN) FtwLastWrite.SpareAddress,
+ (UINTN) FtwLastWrite.Length));
+ BuildGuidDataHob (&gEdkiiFaultTolerantWriteGuid, (VOID *) &FtwLastWrite, sizeof (FAULT_TOLERANT_WRITE_LAST_WRITE_DATA));
+ } else {
+ //
+ // Both are invalid.
+ //
+ DEBUG ((EFI_D_ERROR, "FtwPei: Both working and spare block are invalid.\n"));
+ }
+ }
+
+ //
+ // Install gEdkiiFaultTolerantWriteGuid PPI to inform the check for FTW last write data has been done.
+ //
+ return PeiServicesInstallPpi (&mPpiListVariable);
+}
diff --git a/MdeModulePkg/Universal/FaultTolerantWritePei/FaultTolerantWritePei.inf b/MdeModulePkg/Universal/FaultTolerantWritePei/FaultTolerantWritePei.inf
new file mode 100644
index 000000000..bcc2313a6
--- /dev/null
+++ b/MdeModulePkg/Universal/FaultTolerantWritePei/FaultTolerantWritePei.inf
@@ -0,0 +1,61 @@
+## @file
+# This driver installs gEdkiiFaultTolerantWriteGuid PPI to inform
+# the check for FTW last write data has been done.
+#
+# Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>
+#
+# 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]
+ INF_VERSION = 0x00010005
+ BASE_NAME = FaultTolerantWritePei
+ FILE_GUID = AAC33064-9ED0-4b89-A5AD-3EA767960B22
+ MODULE_TYPE = PEIM
+ VERSION_STRING = 1.0
+ ENTRY_POINT = PeimFaultTolerantWriteInitialize
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources]
+ FaultTolerantWritePei.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ PeimEntryPoint
+ PeiServicesLib
+ BaseLib
+ DebugLib
+ HobLib
+ BaseMemoryLib
+ PcdLib
+
+[Guids]
+ gEdkiiFaultTolerantWriteGuid ## CONSUMES
+ gEdkiiWorkingBlockSignatureGuid ## CONSUMES
+ gEfiSystemNvDataFvGuid ## CONSUMES
+
+[Pcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase64
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase64
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize
+
+[Depex]
+ TRUE
+
diff --git a/MdeModulePkg/Universal/HiiDatabaseDxe/ConfigRouting.c b/MdeModulePkg/Universal/HiiDatabaseDxe/ConfigRouting.c
index 81cebdabc..4959d8302 100644
--- a/MdeModulePkg/Universal/HiiDatabaseDxe/ConfigRouting.c
+++ b/MdeModulePkg/Universal/HiiDatabaseDxe/ConfigRouting.c
@@ -242,7 +242,7 @@ GenerateSubStr (
if (Buffer == NULL) {
*SubStr = AllocateCopyPool (StrSize (String), String);
ASSERT (*SubStr != NULL);
- return ;
+ return;
}
//
@@ -628,7 +628,7 @@ MergeDefaultString (
// Find next AltCfg String
//
*(AltConfigHdr + HeaderLength) = L'\0';
- StringPtrDefault = StrStr (StringPtrDefault + 1, AltConfigHdr);
+ StringPtrDefault = StrStr (StringPtrDefault + 1, AltConfigHdr);
}
FreePool (AltConfigHdr);
@@ -649,9 +649,12 @@ InsertDefaultValue (
)
{
LIST_ENTRY *Link;
- IFR_DEFAULT_DATA *DefaultValueArray;
+ IFR_DEFAULT_DATA *DefaultValueArray;
+ LIST_ENTRY *DefaultLink;
+
+ DefaultLink = &BlockData->DefaultValueEntry;
- for (Link = BlockData->DefaultValueEntry.ForwardLink; Link != &BlockData->DefaultValueEntry; Link = Link->ForwardLink) {
+ for (Link = DefaultLink->ForwardLink; Link != DefaultLink; Link = Link->ForwardLink) {
DefaultValueArray = BASE_CR (Link, IFR_DEFAULT_DATA, Entry);
if (DefaultValueArray->DefaultId == DefaultValueData->DefaultId) {
//
@@ -681,8 +684,8 @@ InsertDefaultValue (
/**
This function inserts new BlockData into the block link
- @param BlockLink The list entry points to block array.
- @param BlockData The point to BlockData is added.
+ @param BlockLink The list entry points to block array.
+ @param BlockData The point to BlockData is added.
**/
VOID
@@ -691,12 +694,17 @@ InsertBlockData (
IN IFR_BLOCK_DATA **BlockData
)
{
- LIST_ENTRY *Link;
- IFR_BLOCK_DATA *BlockArray;
- IFR_BLOCK_DATA *BlockSingleData;
+ LIST_ENTRY *Link;
+ IFR_BLOCK_DATA *BlockArray;
+ IFR_BLOCK_DATA *BlockSingleData;
BlockSingleData = *BlockData;
-
+
+ if (BlockSingleData->Name != NULL) {
+ InsertTailList (BlockLink, &BlockSingleData->Entry);
+ return;
+ }
+
//
// Insert block data in its Offset and Width order.
//
@@ -715,8 +723,10 @@ InsertBlockData (
//
// The same block array has been added.
//
- FreePool (BlockSingleData);
- *BlockData = BlockArray;
+ if (BlockSingleData != BlockArray) {
+ FreePool (BlockSingleData);
+ *BlockData = BlockArray;
+ }
return;
}
} else if (BlockArray->Offset > BlockSingleData->Offset) {
@@ -731,8 +741,225 @@ InsertBlockData (
//
// Add new block data into the tail.
//
- InsertTailList (Link, &BlockSingleData->Entry);
- return;
+ InsertTailList (Link, &BlockSingleData->Entry);
+}
+
+/**
+ Retrieves a pointer to the a Null-terminated ASCII string containing the list
+ of languages that an HII handle in the HII Database supports. The returned
+ string is allocated using AllocatePool(). The caller is responsible for freeing
+ the returned string using FreePool(). The format of the returned string follows
+ the language format assumed the HII Database.
+
+ If HiiHandle is NULL, then ASSERT().
+
+ @param[in] HiiHandle A handle that was previously registered in the HII Database.
+
+ @retval NULL HiiHandle is not registered in the HII database
+ @retval NULL There are not enough resources available to retrieve the suported
+ languages.
+ @retval NULL The list of suported languages could not be retrieved.
+ @retval Other A pointer to the Null-terminated ASCII string of supported languages.
+
+**/
+CHAR8 *
+GetSupportedLanguages (
+ IN EFI_HII_HANDLE HiiHandle
+ )
+{
+ EFI_STATUS Status;
+ UINTN LanguageSize;
+ CHAR8 TempSupportedLanguages;
+ CHAR8 *SupportedLanguages;
+
+ ASSERT (HiiHandle != NULL);
+
+ //
+ // Retrieve the size required for the supported languages buffer.
+ //
+ LanguageSize = 0;
+ Status = mPrivate.HiiString.GetLanguages (&mPrivate.HiiString, HiiHandle, &TempSupportedLanguages, &LanguageSize);
+
+ //
+ // If GetLanguages() returns EFI_SUCCESS for a zero size,
+ // then there are no supported languages registered for HiiHandle. If GetLanguages()
+ // returns an error other than EFI_BUFFER_TOO_SMALL, then HiiHandle is not present
+ // in the HII Database
+ //
+ if (Status != EFI_BUFFER_TOO_SMALL) {
+ //
+ // Return NULL if the size can not be retrieved, or if HiiHandle is not in the HII Database
+ //
+ return NULL;
+ }
+
+ //
+ // Allocate the supported languages buffer.
+ //
+ SupportedLanguages = AllocateZeroPool (LanguageSize);
+ if (SupportedLanguages == NULL) {
+ //
+ // Return NULL if allocation fails.
+ //
+ return NULL;
+ }
+
+ //
+ // Retrieve the supported languages string
+ //
+ Status = mPrivate.HiiString.GetLanguages (&mPrivate.HiiString, HiiHandle, SupportedLanguages, &LanguageSize);
+ if (EFI_ERROR (Status)) {
+ //
+ // Free the buffer and return NULL if the supported languages can not be retrieved.
+ //
+ FreePool (SupportedLanguages);
+ return NULL;
+ }
+
+ //
+ // Return the Null-terminated ASCII string of supported languages
+ //
+ return SupportedLanguages;
+}
+
+/**
+ Retrieves a string from a string package.
+
+ If HiiHandle is NULL, then ASSERT().
+ If StringId is 0, then ASSET.
+
+ @param[in] HiiHandle A handle that was previously registered in the HII Database.
+ @param[in] StringId The identifier of the string to retrieved from the string
+ package associated with HiiHandle.
+
+ @retval NULL The string specified by StringId is not present in the string package.
+ @retval Other The string was returned.
+
+**/
+EFI_STRING
+InternalGetString (
+ IN EFI_HII_HANDLE HiiHandle,
+ IN EFI_STRING_ID StringId
+ )
+{
+ EFI_STATUS Status;
+ UINTN StringSize;
+ CHAR16 TempString;
+ EFI_STRING String;
+ CHAR8 *SupportedLanguages;
+ CHAR8 *PlatformLanguage;
+ CHAR8 *BestLanguage;
+ CHAR8 *Language;
+
+ ASSERT (HiiHandle != NULL);
+ ASSERT (StringId != 0);
+
+ //
+ // Initialize all allocated buffers to NULL
+ //
+ SupportedLanguages = NULL;
+ PlatformLanguage = NULL;
+ BestLanguage = NULL;
+ String = NULL;
+ Language = "";
+
+ //
+ // Get the languages that the package specified by HiiHandle supports
+ //
+ SupportedLanguages = GetSupportedLanguages (HiiHandle);
+ if (SupportedLanguages == NULL) {
+ goto Error;
+ }
+
+ //
+ // Get the current platform language setting
+ //
+ GetEfiGlobalVariable2 (L"PlatformLang", (VOID**)&PlatformLanguage, NULL);
+
+ //
+ // Get the best matching language from SupportedLanguages
+ //
+ BestLanguage = GetBestLanguage (
+ SupportedLanguages,
+ FALSE, // RFC 4646 mode
+ Language, // Highest priority
+ PlatformLanguage != NULL ? PlatformLanguage : "", // Next highest priority
+ SupportedLanguages, // Lowest priority
+ NULL
+ );
+ if (BestLanguage == NULL) {
+ goto Error;
+ }
+
+ //
+ // Retrieve the size of the string in the string package for the BestLanguage
+ //
+ StringSize = 0;
+ Status = mPrivate.HiiString.GetString (
+ &mPrivate.HiiString,
+ BestLanguage,
+ HiiHandle,
+ StringId,
+ &TempString,
+ &StringSize,
+ NULL
+ );
+ //
+ // If GetString() returns EFI_SUCCESS for a zero size,
+ // then there are no supported languages registered for HiiHandle. If GetString()
+ // returns an error other than EFI_BUFFER_TOO_SMALL, then HiiHandle is not present
+ // in the HII Database
+ //
+ if (Status != EFI_BUFFER_TOO_SMALL) {
+ goto Error;
+ }
+
+ //
+ // Allocate a buffer for the return string
+ //
+ String = AllocateZeroPool (StringSize);
+ if (String == NULL) {
+ goto Error;
+ }
+
+ //
+ // Retrieve the string from the string package
+ //
+ Status = mPrivate.HiiString.GetString (
+ &mPrivate.HiiString,
+ BestLanguage,
+ HiiHandle,
+ StringId,
+ String,
+ &StringSize,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ //
+ // Free the buffer and return NULL if the supported languages can not be retrieved.
+ //
+ FreePool (String);
+ String = NULL;
+ }
+
+Error:
+ //
+ // Free allocated buffers
+ //
+ if (SupportedLanguages != NULL) {
+ FreePool (SupportedLanguages);
+ }
+ if (PlatformLanguage != NULL) {
+ FreePool (PlatformLanguage);
+ }
+ if (BestLanguage != NULL) {
+ FreePool (BestLanguage);
+ }
+
+ //
+ // Return the Null-terminated Unicode string
+ //
+ return String;
}
/**
@@ -741,6 +968,8 @@ InsertBlockData (
@param RequestBlockArray The block array is to be checked.
@param VarOffset Offset of var to the structure
@param VarWidth Width of var.
+ @param IsNameValueType Whether this varstore is name/value varstore or not.
+ @param HiiHandle Hii handle for this hii package.
@retval TRUE This Var is in the block range.
@retval FALSE This Var is not in the block range.
@@ -749,26 +978,41 @@ BOOLEAN
BlockArrayCheck (
IN IFR_BLOCK_DATA *RequestBlockArray,
IN UINT16 VarOffset,
- IN UINT16 VarWidth
+ IN UINT16 VarWidth,
+ IN BOOLEAN IsNameValueType,
+ IN EFI_HII_HANDLE HiiHandle
)
{
LIST_ENTRY *Link;
IFR_BLOCK_DATA *BlockData;
-
+ EFI_STRING Name;
+
//
// No Request Block array, all vars are got.
//
if (RequestBlockArray == NULL) {
return TRUE;
}
-
+
//
// Check the input var is in the request block range.
//
for (Link = RequestBlockArray->Entry.ForwardLink; Link != &RequestBlockArray->Entry; Link = Link->ForwardLink) {
BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);
- if ((VarOffset >= BlockData->Offset) && ((VarOffset + VarWidth) <= (BlockData->Offset + BlockData->Width))) {
- return TRUE;
+
+ if (IsNameValueType) {
+ Name = InternalGetString (HiiHandle, VarOffset);
+ ASSERT (Name != NULL);
+
+ if (StrnCmp (BlockData->Name, Name, StrLen (Name)) == 0) {
+ FreePool (Name);
+ return TRUE;
+ }
+ FreePool (Name);
+ } else {
+ if ((VarOffset >= BlockData->Offset) && ((VarOffset + VarWidth) <= (BlockData->Offset + BlockData->Width))) {
+ return TRUE;
+ }
}
}
@@ -861,7 +1105,6 @@ GetVarStoreType (
IN EFI_STRING ConfigHdr,
OUT BOOLEAN *IsEfiVarstore,
OUT EFI_IFR_VARSTORE_EFI **EfiVarStore
-
)
{
EFI_STATUS Status;
@@ -882,6 +1125,7 @@ GetVarStoreType (
GuidStr = NULL;
NameStr = NULL;
TempStr = NULL;
+ *IsEfiVarstore = FALSE;
Status = GetFormPackageData(DataBaseRecord, &HiiFormPackage, &PackageSize);
if (EFI_ERROR (Status)) {
@@ -957,16 +1201,200 @@ Done:
}
/**
+ Check whether the ConfigRequest string has the request elements.
+ For EFI_HII_VARSTORE_BUFFER type, the request has "&OFFSET=****&WIDTH=****..." format.
+ For EFI_HII_VARSTORE_NAME_VALUE type, the request has "&NAME1**&NAME2..." format.
+
+ @param ConfigRequest The input config request string.
+
+ @retval TRUE The input include config request elements.
+ @retval FALSE The input string not includes.
+
+**/
+BOOLEAN
+GetElementsFromRequest (
+ IN EFI_STRING ConfigRequest
+ )
+{
+ EFI_STRING TmpRequest;
+
+ TmpRequest = StrStr (ConfigRequest, L"PATH=");
+ ASSERT (TmpRequest != NULL);
+
+ if ((StrStr (TmpRequest, L"&OFFSET=") != NULL) || (StrStr (TmpRequest, L"&") != NULL)) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ Check whether the this varstore is the request varstore.
+
+ @param VarstoreGuid Varstore guid.
+ @param Name Varstore name.
+ @param ConfigHdr Current configRequest info.
+
+ @retval TRUE This varstore is the requst one.
+ @retval FALSE This varstore is not the requst one.
+
+**/
+BOOLEAN
+IsThisVarstore (
+ IN EFI_GUID *VarstoreGuid,
+ IN CHAR16 *Name,
+ IN CHAR16 *ConfigHdr
+ )
+{
+ EFI_STRING GuidStr;
+ EFI_STRING NameStr;
+ EFI_STRING TempStr;
+ UINTN LengthString;
+ BOOLEAN RetVal;
+
+ RetVal = FALSE;
+ GuidStr = NULL;
+ TempStr = NULL;
+
+ GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *)VarstoreGuid, 1, &GuidStr);
+ if (Name != NULL) {
+ GenerateSubStr (L"NAME=", StrLen (Name) * sizeof (CHAR16), (VOID *) Name, 2, &NameStr);
+ } else {
+ GenerateSubStr (L"NAME=", 0, NULL, 2, &NameStr);
+ }
+ LengthString = StrLen (GuidStr);
+ LengthString = LengthString + StrLen (NameStr) + 1;
+ TempStr = AllocateZeroPool (LengthString * sizeof (CHAR16));
+ if (TempStr == NULL) {
+ goto Done;
+ }
+
+ StrCpy (TempStr, GuidStr);
+ StrCat (TempStr, NameStr);
+
+ if (ConfigHdr == NULL || StrnCmp (ConfigHdr, TempStr, StrLen (TempStr)) == 0) {
+ RetVal = TRUE;
+ }
+
+Done:
+ if (GuidStr != NULL) {
+ FreePool (GuidStr);
+ }
+
+ if (NameStr != NULL) {
+ FreePool (NameStr);
+ }
+
+ if (TempStr != NULL) {
+ FreePool (TempStr);
+ }
+
+ return RetVal;
+}
+
+/**
+ Check whether the this op code is required.
+
+ @param RequestBlockArray The array includes all the request info or NULL.
+ @param HiiHandle The hii handle for this form package.
+ @param VarStorageData The varstore data strucure.
+ @param IfrOpHdr Ifr opcode header for this opcode.
+ @param VarWidth The buffer width for this opcode.
+ @param ReturnData The data block added for this opcode.
+
+ @retval EFI_SUCCESS This opcode is required.
+ @retval Others This opcode is not required or error occur.
+
+**/
+EFI_STATUS
+IsThisOpcodeRequired (
+ IN IFR_BLOCK_DATA *RequestBlockArray,
+ IN EFI_HII_HANDLE HiiHandle,
+ IN OUT IFR_VARSTORAGE_DATA *VarStorageData,
+ IN EFI_IFR_OP_HEADER *IfrOpHdr,
+ IN UINT16 VarWidth,
+ OUT IFR_BLOCK_DATA **ReturnData
+ )
+{
+ IFR_BLOCK_DATA *BlockData;
+ UINT16 VarOffset;
+ EFI_STRING_ID NameId;
+ EFI_IFR_QUESTION_HEADER *IfrQuestionHdr;
+
+ NameId = 0;
+ VarOffset = 0;
+ IfrQuestionHdr = (EFI_IFR_QUESTION_HEADER *)((CHAR8 *) IfrOpHdr + sizeof (EFI_IFR_OP_HEADER));
+
+ if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {
+ NameId = IfrQuestionHdr->VarStoreInfo.VarName;
+
+ //
+ // Check whether this question is in requested block array.
+ //
+ if (!BlockArrayCheck (RequestBlockArray, NameId, 0, TRUE, HiiHandle)) {
+ //
+ // This question is not in the requested string. Skip it.
+ //
+ return EFI_SUCCESS;
+ }
+ } else {
+ VarOffset = IfrQuestionHdr->VarStoreInfo.VarOffset;
+
+ //
+ // Check whether this question is in requested block array.
+ //
+ if (!BlockArrayCheck (RequestBlockArray, VarOffset, VarWidth, FALSE, HiiHandle)) {
+ //
+ // This question is not in the requested string. Skip it.
+ //
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Check this var question is in the var storage
+ //
+ if (((VarOffset + VarWidth) > VarStorageData->Size)) {
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
+ if (BlockData == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {
+ BlockData->Name = InternalGetString(HiiHandle, NameId);
+ } else {
+ BlockData->Offset = VarOffset;
+ }
+
+ BlockData->Width = VarWidth;
+ BlockData->QuestionId = IfrQuestionHdr->QuestionId;
+ BlockData->OpCode = IfrOpHdr->OpCode;
+ BlockData->Scope = IfrOpHdr->Scope;
+ InitializeListHead (&BlockData->DefaultValueEntry);
+ //
+ // Add Block Data into VarStorageData BlockEntry
+ //
+ InsertBlockData (&VarStorageData->BlockEntry, &BlockData);
+ *ReturnData = BlockData;
+
+ return EFI_SUCCESS;
+}
+
+/**
This function parses Form Package to get the block array and the default
value array according to the request ConfigHdr.
+ @param HiiHandle Hii Handle for this hii package.
@param Package Pointer to the form package data.
@param PackageLength Length of the pacakge.
@param ConfigHdr Request string ConfigHdr. If it is NULL,
the first found varstore will be as ConfigHdr.
@param RequestBlockArray The block array is retrieved from the request string.
@param VarStorageData VarStorage structure contains the got block and default value.
- @param PIfrDefaultIdArray Point to the got default id and default name array.
+ @param DefaultIdArray Point to the got default id and default name array.
@retval EFI_SUCCESS The block array and the default value array are got.
@retval EFI_INVALID_PARAMETER The varstore defintion in the differnt form pacakges
@@ -976,6 +1404,7 @@ Done:
EFI_STATUS
EFIAPI
ParseIfrData (
+ IN EFI_HII_HANDLE HiiHandle,
IN UINT8 *Package,
IN UINT32 PackageLength,
IN EFI_STRING ConfigHdr,
@@ -1003,22 +1432,14 @@ ParseIfrData (
IFR_DEFAULT_DATA *DefaultDataPtr;
IFR_BLOCK_DATA *BlockData;
CHAR16 *VarStoreName;
- UINT16 VarOffset;
UINT16 VarWidth;
UINT16 VarDefaultId;
- EFI_STRING GuidStr;
- EFI_STRING NameStr;
- EFI_STRING TempStr;
- UINTN LengthString;
BOOLEAN FirstOneOfOption;
LIST_ENTRY *LinkData;
LIST_ENTRY *LinkDefault;
+ EFI_IFR_VARSTORE_NAME_VALUE *IfrNameValueVarStore;
- LengthString = 0;
Status = EFI_SUCCESS;
- GuidStr = NULL;
- NameStr = NULL;
- TempStr = NULL;
BlockData = NULL;
DefaultDataPtr = NULL;
FirstOneOfOption = FALSE;
@@ -1030,44 +1451,25 @@ ParseIfrData (
IfrOffset = sizeof (EFI_HII_PACKAGE_HEADER);
while (IfrOffset < PackageLength) {
IfrOpHdr = (EFI_IFR_OP_HEADER *) (Package + IfrOffset);
-
switch (IfrOpHdr->OpCode) {
case EFI_IFR_VARSTORE_OP:
//
// VarStore is found. Don't need to search any more.
//
- if (VarStorageData->Size != 0) {
+ if (VarStorageData->VarStoreId != 0) {
break;
}
- //
- // Get the requied varstore information
- // Add varstore by Guid and Name in ConfigHdr
- // Make sure Offset is in varstore size and varstoreid
- //
IfrVarStore = (EFI_IFR_VARSTORE *) IfrOpHdr;
+
VarStoreName = AllocateZeroPool (AsciiStrSize ((CHAR8 *)IfrVarStore->Name) * sizeof (CHAR16));
if (VarStoreName == NULL) {
Status = EFI_OUT_OF_RESOURCES;
goto Done;
}
- AsciiStrToUnicodeStr ((CHAR8 *) IfrVarStore->Name, VarStoreName);
+ AsciiStrToUnicodeStr ((CHAR8 *)IfrVarStore->Name, VarStoreName);
- GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *) &IfrVarStore->Guid, 1, &GuidStr);
- GenerateSubStr (L"NAME=", StrLen (VarStoreName) * sizeof (CHAR16), (VOID *) VarStoreName, 2, &NameStr);
- LengthString = StrLen (GuidStr);
- LengthString = LengthString + StrLen (NameStr) + 1;
- TempStr = AllocateZeroPool (LengthString * sizeof (CHAR16));
- if (TempStr == NULL) {
- FreePool (GuidStr);
- FreePool (NameStr);
- FreePool (VarStoreName);
- Status = EFI_OUT_OF_RESOURCES;
- goto Done;
- }
- StrCpy (TempStr, GuidStr);
- StrCat (TempStr, NameStr);
- if (ConfigHdr == NULL || StrnCmp (ConfigHdr, TempStr, StrLen (TempStr)) == 0) {
+ if (IsThisVarstore((VOID *)&IfrVarStore->Guid, VarStoreName, ConfigHdr)) {
//
// Find the matched VarStore
//
@@ -1075,33 +1477,18 @@ ParseIfrData (
VarStorageData->VarStoreId = IfrVarStore->VarStoreId;
VarStorageData->Size = IfrVarStore->Size;
VarStorageData->Name = VarStoreName;
- } else {
- //
- // No found, free the allocated memory
- //
- FreePool (VarStoreName);
+ VarStorageData->Type = EFI_HII_VARSTORE_BUFFER;
}
- //
- // Free alllocated temp string.
- //
- FreePool (GuidStr);
- FreePool (NameStr);
- FreePool (TempStr);
break;
case EFI_IFR_VARSTORE_EFI_OP:
//
// VarStore is found. Don't need to search any more.
//
- if (VarStorageData->Size != 0) {
+ if (VarStorageData->VarStoreId != 0) {
break;
}
- //
- // Get the requied varstore information
- // Add varstore by Guid and Name in ConfigHdr
- // Make sure Offset is in varstore size and varstoreid
- //
IfrEfiVarStore = (EFI_IFR_VARSTORE_EFI *) IfrOpHdr;
//
@@ -1118,23 +1505,9 @@ ParseIfrData (
Status = EFI_OUT_OF_RESOURCES;
goto Done;
}
- AsciiStrToUnicodeStr ((CHAR8 *) IfrEfiVarStore->Name, VarStoreName);
+ AsciiStrToUnicodeStr ((CHAR8 *)IfrEfiVarStore->Name, VarStoreName);
- GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *) &IfrEfiVarStore->Guid, 1, &GuidStr);
- GenerateSubStr (L"NAME=", StrLen (VarStoreName) * sizeof (CHAR16), (VOID *) VarStoreName, 2, &NameStr);
- LengthString = StrLen (GuidStr);
- LengthString = LengthString + StrLen (NameStr) + 1;
- TempStr = AllocateZeroPool (LengthString * sizeof (CHAR16));
- if (TempStr == NULL) {
- FreePool (GuidStr);
- FreePool (NameStr);
- FreePool (VarStoreName);
- Status = EFI_OUT_OF_RESOURCES;
- goto Done;
- }
- StrCpy (TempStr, GuidStr);
- StrCat (TempStr, NameStr);
- if (ConfigHdr == NULL || StrnCmp (ConfigHdr, TempStr, StrLen (TempStr)) == 0) {
+ if (IsThisVarstore (&IfrEfiVarStore->Guid, VarStoreName, ConfigHdr)) {
//
// Find the matched VarStore
//
@@ -1142,18 +1515,28 @@ ParseIfrData (
VarStorageData->VarStoreId = IfrEfiVarStore->VarStoreId;
VarStorageData->Size = IfrEfiVarStore->Size;
VarStorageData->Name = VarStoreName;
- } else {
- //
- // No found, free the allocated memory
- //
- FreePool (VarStoreName);
+ VarStorageData->Type = EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER;
}
+ break;
+
+ case EFI_IFR_VARSTORE_NAME_VALUE_OP:
//
- // Free alllocated temp string.
+ // VarStore is found. Don't need to search any more.
//
- FreePool (GuidStr);
- FreePool (NameStr);
- FreePool (TempStr);
+ if (VarStorageData->VarStoreId != 0) {
+ break;
+ }
+
+ IfrNameValueVarStore = (EFI_IFR_VARSTORE_NAME_VALUE *) IfrOpHdr;
+
+ if (IsThisVarstore (&IfrNameValueVarStore->Guid, NULL, ConfigHdr)) {
+ //
+ // Find the matched VarStore
+ //
+ CopyGuid (&VarStorageData->Guid, (EFI_GUID *) (VOID *) &IfrNameValueVarStore->Guid);
+ VarStorageData->VarStoreId = IfrNameValueVarStore->VarStoreId;
+ VarStorageData->Type = EFI_HII_VARSTORE_NAME_VALUE;
+ }
break;
case EFI_IFR_DEFAULTSTORE_OP:
@@ -1175,7 +1558,7 @@ ParseIfrData (
//
// No matched varstore is found and directly return.
//
- if (VarStorageData->Size == 0) {
+ if (VarStorageData->VarStoreId == 0) {
Status = EFI_SUCCESS;
goto Done;
}
@@ -1185,7 +1568,7 @@ ParseIfrData (
//
// Ref question is not in IFR Form. This IFR form is not valid.
//
- if (VarStorageData->Size == 0) {
+ if (VarStorageData->VarStoreId == 0) {
Status = EFI_INVALID_PARAMETER;
goto Done;
}
@@ -1196,48 +1579,12 @@ ParseIfrData (
if (IfrRef->Question.VarStoreId != VarStorageData->VarStoreId) {
break;
}
-
- //
- // Get Offset/Width by Question header.
- //
- VarOffset = IfrRef->Question.VarStoreInfo.VarOffset;
VarWidth = (UINT16) (sizeof (EFI_HII_REF));
- //
- // Check whether this question is in requested block array.
- //
- if (!BlockArrayCheck (RequestBlockArray, VarOffset, VarWidth)) {
- //
- // This question is not in the requested string. Skip it.
- //
- break;
- }
- //
- // Check this var question is in the var storage
- //
- if ((VarOffset + VarWidth) > VarStorageData->Size) {
- Status = EFI_INVALID_PARAMETER;
- goto Done;
- }
-
- //
- // Set Block Data
- //
- BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
- if (BlockData == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
+ Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);
+ if (EFI_ERROR (Status)) {
goto Done;
}
- BlockData->Offset = VarOffset;
- BlockData->Width = VarWidth;
- BlockData->QuestionId = IfrRef->Question.QuestionId;
- BlockData->OpCode = IfrOpHdr->OpCode;
- BlockData->Scope = IfrOpHdr->Scope;
- InitializeListHead (&BlockData->DefaultValueEntry);
- //
- // Add Block Data into VarStorageData BlockEntry
- //
- InsertBlockData (&VarStorageData->BlockEntry, &BlockData);
break;
case EFI_IFR_ONE_OF_OP:
@@ -1249,7 +1596,7 @@ ParseIfrData (
//
// Numeric and OneOf question is not in IFR Form. This IFR form is not valid.
//
- if (VarStorageData->Size == 0) {
+ if (VarStorageData->VarStoreId == 0) {
Status = EFI_INVALID_PARAMETER;
goto Done;
}
@@ -1260,49 +1607,20 @@ ParseIfrData (
if (IfrOneOf->Question.VarStoreId != VarStorageData->VarStoreId) {
break;
}
-
- //
- // Get Offset/Width by Question header and OneOf Flags
- //
- VarOffset = IfrOneOf->Question.VarStoreInfo.VarOffset;
VarWidth = (UINT16) (1 << (IfrOneOf->Flags & EFI_IFR_NUMERIC_SIZE));
- //
- // Check whether this question is in requested block array.
- //
- if (!BlockArrayCheck (RequestBlockArray, VarOffset, VarWidth)) {
- //
- // This question is not in the requested string. Skip it.
- //
- break;
- }
- //
- // Check this var question is in the var storage
- //
- if ((VarOffset + VarWidth) > VarStorageData->Size) {
- Status = EFI_INVALID_PARAMETER;
+ Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);
+ if (EFI_ERROR (Status)) {
goto Done;
}
-
- //
- // Set Block Data
- //
- BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
+
if (BlockData == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto Done;
+ //
+ // BlockData == NULL means this opcode is not in the requst array.
+ //
+ break;
}
- BlockData->Offset = VarOffset;
- BlockData->Width = VarWidth;
- BlockData->QuestionId = IfrOneOf->Question.QuestionId;
- BlockData->OpCode = IfrOpHdr->OpCode;
- BlockData->Scope = IfrOpHdr->Scope;
- InitializeListHead (&BlockData->DefaultValueEntry);
- //
- // Add Block Data into VarStorageData BlockEntry
- //
- InsertBlockData (&VarStorageData->BlockEntry, &BlockData);
-
+
if (IfrOpHdr->OpCode == EFI_IFR_ONE_OF_OP) {
//
// Set this flag to TRUE for the first oneof option.
@@ -1317,24 +1635,28 @@ ParseIfrData (
case EFI_IFR_NUMERIC_SIZE_1:
DefaultData.Value.u8 = IfrOneOf->data.u8.MinValue;
break;
-
+
case EFI_IFR_NUMERIC_SIZE_2:
CopyMem (&DefaultData.Value.u16, &IfrOneOf->data.u16.MinValue, sizeof (UINT16));
break;
-
+
case EFI_IFR_NUMERIC_SIZE_4:
CopyMem (&DefaultData.Value.u32, &IfrOneOf->data.u32.MinValue, sizeof (UINT32));
break;
-
+
case EFI_IFR_NUMERIC_SIZE_8:
CopyMem (&DefaultData.Value.u64, &IfrOneOf->data.u64.MinValue, sizeof (UINT64));
break;
+
+ default:
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
}
//
// Set default value base on the DefaultId list get from IFR data.
//
for (LinkData = DefaultIdArray->Entry.ForwardLink; LinkData != &DefaultIdArray->Entry; LinkData = LinkData->ForwardLink) {
- DefaultDataPtr = BASE_CR (LinkData, IFR_DEFAULT_DATA, Entry);
+ DefaultDataPtr = BASE_CR (LinkData, IFR_DEFAULT_DATA, Entry);
DefaultData.DefaultId = DefaultDataPtr->DefaultId;
InsertDefaultValue (BlockData, &DefaultData);
}
@@ -1351,7 +1673,7 @@ ParseIfrData (
//
// OrderedList question is not in IFR Form. This IFR form is not valid.
//
- if (VarStorageData->Size == 0) {
+ if (VarStorageData->VarStoreId == 0) {
Status = EFI_INVALID_PARAMETER;
goto Done;
}
@@ -1363,27 +1685,11 @@ ParseIfrData (
BlockData = NULL;
break;
}
-
- //
- // Get Offset/Width by Question header and OneOf Flags
- //
- VarOffset = IfrOrderedList->Question.VarStoreInfo.VarOffset;
VarWidth = IfrOrderedList->MaxContainers;
-
- //
- // Set Block Data
- //
- BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
- if (BlockData == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
+ Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);
+ if (EFI_ERROR (Status)) {
goto Done;
}
- BlockData->Offset = VarOffset;
- BlockData->Width = VarWidth;
- BlockData->QuestionId = IfrOrderedList->Question.QuestionId;
- BlockData->OpCode = IfrOpHdr->OpCode;
- BlockData->Scope = IfrOpHdr->Scope;
- InitializeListHead (&BlockData->DefaultValueEntry);
break;
case EFI_IFR_CHECKBOX_OP:
@@ -1399,7 +1705,7 @@ ParseIfrData (
//
// CheckBox question is not in IFR Form. This IFR form is not valid.
//
- if (VarStorageData->Size == 0) {
+ if (VarStorageData->VarStoreId == 0) {
Status = EFI_INVALID_PARAMETER;
goto Done;
}
@@ -1410,51 +1716,20 @@ ParseIfrData (
if (IfrCheckBox->Question.VarStoreId != VarStorageData->VarStoreId) {
break;
}
-
- //
- // Get Offset/Width by Question header and OneOf Flags
- //
- VarOffset = IfrCheckBox->Question.VarStoreInfo.VarOffset;
VarWidth = (UINT16) sizeof (BOOLEAN);
+ Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
- //
- // Check whether this question is in requested block array.
- //
- if (!BlockArrayCheck (RequestBlockArray, VarOffset, VarWidth)) {
+ if (BlockData == NULL) {
//
- // This question is not in the requested string. Skip it.
+ // BlockData == NULL means this opcode is not in the requst array.
//
break;
}
//
- // Check this var question is in the var storage
- //
- if ((VarOffset + VarWidth) > VarStorageData->Size) {
- Status = EFI_INVALID_PARAMETER;
- goto Done;
- }
-
- //
- // Set Block Data
- //
- BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
- if (BlockData == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto Done;
- }
- BlockData->Offset = VarOffset;
- BlockData->Width = VarWidth;
- BlockData->QuestionId = IfrCheckBox->Question.QuestionId;
- BlockData->OpCode = IfrOpHdr->OpCode;
- BlockData->Scope = IfrOpHdr->Scope;
- InitializeListHead (&BlockData->DefaultValueEntry);
- //
- // Add Block Data into VarStorageData BlockEntry
- //
- InsertBlockData (&VarStorageData->BlockEntry, &BlockData);
-
- //
// Add default value for standard ID by CheckBox Flag
//
VarDefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;
@@ -1498,7 +1773,7 @@ ParseIfrData (
//
// When flag is not set, defautl value is FASLE.
//
- DefaultData.Type = DefaultValueFromDefault;
+ DefaultData.Type = DefaultValueFromDefault;
DefaultData.Value.b = FALSE;
}
//
@@ -1517,7 +1792,7 @@ ParseIfrData (
//
// Date question is not in IFR Form. This IFR form is not valid.
//
- if (VarStorageData->Size == 0) {
+ if (VarStorageData->VarStoreId == 0) {
Status = EFI_INVALID_PARAMETER;
goto Done;
}
@@ -1529,49 +1804,11 @@ ParseIfrData (
break;
}
- //
- // Get Offset/Width by Question header and OneOf Flags
- //
- VarOffset = IfrDate->Question.VarStoreInfo.VarOffset;
VarWidth = (UINT16) sizeof (EFI_HII_DATE);
-
- //
- // Check whether this question is in requested block array.
- //
- if (!BlockArrayCheck (RequestBlockArray, VarOffset, VarWidth)) {
- //
- // This question is not in the requested array. Skip it.
- //
- break;
- }
-
- //
- // Check this var question is in the var storage
- //
- if ((VarOffset + VarWidth) > VarStorageData->Size) {
- Status = EFI_INVALID_PARAMETER;
- goto Done;
- }
-
- //
- // Set Block Data
- //
- BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
- if (BlockData == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
+ Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);
+ if (EFI_ERROR (Status)) {
goto Done;
}
- BlockData->Offset = VarOffset;
- BlockData->Width = VarWidth;
- BlockData->QuestionId = IfrDate->Question.QuestionId;
- BlockData->OpCode = IfrOpHdr->OpCode;
- BlockData->Scope = IfrOpHdr->Scope;
- InitializeListHead (&BlockData->DefaultValueEntry);
-
- //
- // Add Block Data into VarStorageData BlockEntry
- //
- InsertBlockData (&VarStorageData->BlockEntry, &BlockData);
break;
case EFI_IFR_TIME_OP:
@@ -1584,7 +1821,7 @@ ParseIfrData (
//
// Time question is not in IFR Form. This IFR form is not valid.
//
- if (VarStorageData->Size == 0) {
+ if (VarStorageData->VarStoreId == 0) {
Status = EFI_INVALID_PARAMETER;
goto Done;
}
@@ -1596,49 +1833,11 @@ ParseIfrData (
break;
}
- //
- // Get Offset/Width by Question header and OneOf Flags
- //
- VarOffset = IfrTime->Question.VarStoreInfo.VarOffset;
VarWidth = (UINT16) sizeof (EFI_HII_TIME);
-
- //
- // Check whether this question is in requested block array.
- //
- if (!BlockArrayCheck (RequestBlockArray, VarOffset, VarWidth)) {
- //
- // This question is not in the requested array. Skip it.
- //
- break;
- }
-
- //
- // Check this var question is in the var storage
- //
- if ((VarOffset + VarWidth) > VarStorageData->Size) {
- Status = EFI_INVALID_PARAMETER;
- goto Done;
- }
-
- //
- // Set Block Data
- //
- BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
- if (BlockData == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
+ Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);
+ if (EFI_ERROR (Status)) {
goto Done;
}
- BlockData->Offset = VarOffset;
- BlockData->Width = VarWidth;
- BlockData->QuestionId = IfrTime->Question.QuestionId;
- BlockData->OpCode = IfrOpHdr->OpCode;
- BlockData->Scope = IfrOpHdr->Scope;
- InitializeListHead (&BlockData->DefaultValueEntry);
-
- //
- // Add Block Data into VarStorageData BlockEntry
- //
- InsertBlockData (&VarStorageData->BlockEntry, &BlockData);
break;
case EFI_IFR_STRING_OP:
@@ -1651,7 +1850,7 @@ ParseIfrData (
//
// String question is not in IFR Form. This IFR form is not valid.
//
- if (VarStorageData->Size == 0) {
+ if (VarStorageData->VarStoreId == 0) {
Status = EFI_INVALID_PARAMETER;
goto Done;
}
@@ -1662,50 +1861,13 @@ ParseIfrData (
if (IfrString->Question.VarStoreId != VarStorageData->VarStoreId) {
break;
}
-
- //
- // Get Offset/Width by Question header and OneOf Flags
- //
- VarOffset = IfrString->Question.VarStoreInfo.VarOffset;
- VarWidth = (UINT16) (IfrString->MaxSize * sizeof (UINT16));
-
- //
- // Check whether this question is in requested block array.
- //
- if (!BlockArrayCheck (RequestBlockArray, VarOffset, VarWidth)) {
- //
- // This question is not in the requested string. Skip it.
- //
- break;
- }
- //
- // Check this var question is in the var storage
- //
- if ((VarOffset + VarWidth) > VarStorageData->Size) {
- Status = EFI_INVALID_PARAMETER;
- goto Done;
- }
-
- //
- // Set Block Data
- //
- BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
- if (BlockData == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
+ VarWidth = (UINT16) (IfrString->MaxSize * sizeof (UINT16));
+ Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);
+ if (EFI_ERROR (Status)) {
goto Done;
}
- BlockData->Offset = VarOffset;
- BlockData->Width = VarWidth;
- BlockData->QuestionId = IfrString->Question.QuestionId;
- BlockData->OpCode = IfrOpHdr->OpCode;
- InitializeListHead (&BlockData->DefaultValueEntry);
-
- //
- // Add Block Data into VarStorageData BlockEntry
- //
- InsertBlockData (&VarStorageData->BlockEntry, &BlockData);
-
+
//
// No default value for string.
//
@@ -1722,7 +1884,7 @@ ParseIfrData (
//
// Password question is not in IFR Form. This IFR form is not valid.
//
- if (VarStorageData->Size == 0) {
+ if (VarStorageData->VarStoreId == 0) {
Status = EFI_INVALID_PARAMETER;
goto Done;
}
@@ -1733,50 +1895,13 @@ ParseIfrData (
if (IfrPassword->Question.VarStoreId != VarStorageData->VarStoreId) {
break;
}
-
- //
- // Get Offset/Width by Question header and OneOf Flags
- //
- VarOffset = IfrPassword->Question.VarStoreInfo.VarOffset;
- VarWidth = (UINT16) (IfrPassword->MaxSize * sizeof (UINT16));
-
- //
- // Check whether this question is in requested block array.
- //
- if (!BlockArrayCheck (RequestBlockArray, VarOffset, VarWidth)) {
- //
- // This question is not in the requested string. Skip it.
- //
- break;
- }
- //
- // Check this var question is in the var storage
- //
- if ((VarOffset + VarWidth) > VarStorageData->Size) {
- Status = EFI_INVALID_PARAMETER;
- goto Done;
- }
-
- //
- // Set Block Data
- //
- BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
- if (BlockData == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
+ VarWidth = (UINT16) (IfrPassword->MaxSize * sizeof (UINT16));
+ Status = IsThisOpcodeRequired(RequestBlockArray, HiiHandle, VarStorageData, IfrOpHdr, VarWidth, &BlockData);
+ if (EFI_ERROR (Status)) {
goto Done;
}
- BlockData->Offset = VarOffset;
- BlockData->Width = VarWidth;
- BlockData->QuestionId = IfrPassword->Question.QuestionId;
- BlockData->OpCode = IfrOpHdr->OpCode;
- InitializeListHead (&BlockData->DefaultValueEntry);
-
- //
- // Add Block Data into VarStorageData BlockEntry
- //
- InsertBlockData (&VarStorageData->BlockEntry, &BlockData);
-
+
//
// No default value for string.
//
@@ -1790,7 +1915,7 @@ ParseIfrData (
if (BlockData == NULL || BlockData->Scope == 0) {
break;
}
-
+
IfrOneOfOption = (EFI_IFR_ONE_OF_OPTION *) IfrOpHdr;
if (BlockData->OpCode == EFI_IFR_ORDERED_LIST_OP) {
//
@@ -1809,6 +1934,9 @@ ParseIfrData (
// Invalid ordered list option data type.
//
Status = EFI_INVALID_PARAMETER;
+ if (BlockData->Name != NULL) {
+ FreePool (BlockData->Name);
+ }
FreePool (BlockData);
goto Done;
}
@@ -1820,10 +1948,13 @@ ParseIfrData (
//
// Check whether this question is in requested block array.
//
- if (!BlockArrayCheck (RequestBlockArray, BlockData->Offset, BlockData->Width)) {
+ if (!BlockArrayCheck (RequestBlockArray, BlockData->Offset, BlockData->Width, (BOOLEAN)(BlockData->Name != NULL), HiiHandle)) {
//
// This question is not in the requested string. Skip it.
//
+ if (BlockData->Name != NULL) {
+ FreePool (BlockData->Name);
+ }
FreePool (BlockData);
BlockData = NULL;
break;
@@ -1831,8 +1962,11 @@ ParseIfrData (
//
// Check this var question is in the var storage
//
- if ((BlockData->Offset + BlockData->Width) > VarStorageData->Size) {
+ if ((BlockData->Name == NULL) && ((BlockData->Offset + BlockData->Width) > VarStorageData->Size)) {
Status = EFI_INVALID_PARAMETER;
+ if (BlockData->Name != NULL) {
+ FreePool (BlockData->Name);
+ }
FreePool (BlockData);
goto Done;
}
@@ -1860,7 +1994,7 @@ ParseIfrData (
// Prepare new DefaultValue
//
- DefaultData.Type = DefaultValueFromFlag;
+ DefaultData.Type = DefaultValueFromFlag;
CopyMem (&DefaultData.Value, &IfrOneOfOption->Value, IfrOneOfOption->Header.Length - OFFSET_OF (EFI_IFR_ONE_OF_OPTION, Value));
if ((IfrOneOfOption->Flags & EFI_IFR_OPTION_DEFAULT) == EFI_IFR_OPTION_DEFAULT) {
DefaultData.DefaultId = EFI_HII_DEFAULT_CLASS_STANDARD;
@@ -1870,10 +2004,8 @@ ParseIfrData (
DefaultData.DefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING;
InsertDefaultValue (BlockData, &DefaultData);
}
-
-
}
-
+
//
// 2. Set as the default value when this is the first option.
// The first oneof option value will be used as default value when no default value is specified.
@@ -1885,13 +2017,13 @@ ParseIfrData (
//
// Prepare new DefaultValue
//
- DefaultData.Type = DefaultValueFromDefault;
+ DefaultData.Type = DefaultValueFromDefault;
CopyMem (&DefaultData.Value, &IfrOneOfOption->Value, IfrOneOfOption->Header.Length - OFFSET_OF (EFI_IFR_ONE_OF_OPTION, Value));
for (LinkData = DefaultIdArray->Entry.ForwardLink; LinkData != &DefaultIdArray->Entry; LinkData = LinkData->ForwardLink) {
DefaultDataPtr = BASE_CR (LinkData, IFR_DEFAULT_DATA, Entry);
DefaultData.DefaultId = DefaultDataPtr->DefaultId;
InsertDefaultValue (BlockData, &DefaultData);
- }
+ }
}
break;
@@ -1901,7 +2033,7 @@ ParseIfrData (
//
if (BlockData == NULL || BlockData->Scope == 0) {
//
- // No matched block data is ignored.
+ // No matched block data is ignored.
//
break;
}
@@ -1923,7 +2055,7 @@ ParseIfrData (
DefaultData.Type = DefaultValueFromOpcode;
DefaultData.DefaultId = VarDefaultId;
CopyMem (&DefaultData.Value, &IfrDefault->Value, IfrDefault->Header.Length - OFFSET_OF (EFI_IFR_DEFAULT, Value));
-
+
// If the value field is expression, set the cleaned flag.
if (IfrDefault->Type == EFI_IFR_TYPE_OTHER) {
DefaultData.Cleaned = TRUE;
@@ -1932,7 +2064,7 @@ ParseIfrData (
// Add DefaultValue into current BlockData
//
InsertDefaultValue (BlockData, &DefaultData);
-
+
//
// After insert the default value, reset the cleaned value for next
// time used. If not set here, need to set the value before everytime
@@ -1940,6 +2072,7 @@ ParseIfrData (
//
DefaultData.Cleaned = FALSE;
break;
+
case EFI_IFR_END_OP:
//
// End Opcode is for Var question.
@@ -1948,6 +2081,7 @@ ParseIfrData (
BlockData->Scope--;
}
break;
+
default:
if (BlockData != NULL && BlockData->Scope > 0) {
BlockData->Scope = (UINT8) (BlockData->Scope + IfrOpHdr->Scope);
@@ -1971,7 +2105,701 @@ Done:
}
}
- return Status;
+ return Status;
+}
+
+/**
+ parse the configrequest string, get the elements.
+
+ @param ConfigRequest The input configrequest string.
+ @param Progress Return the progress data.
+
+ @retval Block data pointer.
+**/
+IFR_BLOCK_DATA *
+GetBlockElement (
+ IN EFI_STRING ConfigRequest,
+ OUT EFI_STRING *Progress
+ )
+{
+ EFI_STRING StringPtr;
+ IFR_BLOCK_DATA *BlockData;
+ IFR_BLOCK_DATA *RequestBlockArray;
+ EFI_STATUS Status;
+ UINT8 *TmpBuffer;
+ UINT16 Offset;
+ UINT16 Width;
+ LIST_ENTRY *Link;
+ IFR_BLOCK_DATA *NextBlockData;
+ UINTN Length;
+
+ //
+ // Init RequestBlockArray
+ //
+ RequestBlockArray = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
+ if (RequestBlockArray == NULL) {
+ goto Done;
+ }
+ InitializeListHead (&RequestBlockArray->Entry);
+
+ //
+ // Get the request Block array from the request string
+ // Offset and Width
+ //
+
+ //
+ // Parse each <RequestElement> if exists
+ // Only <BlockName> format is supported by this help function.
+ // <BlockName> ::= &'OFFSET='<Number>&'WIDTH='<Number>
+ //
+ StringPtr = ConfigRequest;
+ while (*StringPtr != 0 && StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) == 0) {
+ //
+ // Skip the OFFSET string
+ //
+ *Progress = StringPtr;
+ StringPtr += StrLen (L"&OFFSET=");
+ //
+ // Get Offset
+ //
+ Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+ Offset = 0;
+ CopyMem (
+ &Offset,
+ TmpBuffer,
+ (((Length + 1) / 2) < sizeof (UINT16)) ? ((Length + 1) / 2) : sizeof (UINT16)
+ );
+ FreePool (TmpBuffer);
+
+ StringPtr += Length;
+ if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {
+ goto Done;
+ }
+ StringPtr += StrLen (L"&WIDTH=");
+
+ //
+ // Get Width
+ //
+ Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+ Width = 0;
+ CopyMem (
+ &Width,
+ TmpBuffer,
+ (((Length + 1) / 2) < sizeof (UINT16)) ? ((Length + 1) / 2) : sizeof (UINT16)
+ );
+ FreePool (TmpBuffer);
+
+ StringPtr += Length;
+ if (*StringPtr != 0 && *StringPtr != L'&') {
+ goto Done;
+ }
+
+ //
+ // Set Block Data
+ //
+ BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
+ if (BlockData == NULL) {
+ goto Done;
+ }
+ BlockData->Offset = Offset;
+ BlockData->Width = Width;
+ InsertBlockData (&RequestBlockArray->Entry, &BlockData);
+
+ //
+ // Skip &VALUE string if &VALUE does exists.
+ //
+ if (StrnCmp (StringPtr, L"&VALUE=", StrLen (L"&VALUE=")) == 0) {
+ StringPtr += StrLen (L"&VALUE=");
+
+ //
+ // Get Value
+ //
+ Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ StringPtr += Length;
+ if (*StringPtr != 0 && *StringPtr != L'&') {
+ goto Done;
+ }
+ }
+ //
+ // If '\0', parsing is finished.
+ //
+ if (*StringPtr == 0) {
+ break;
+ }
+ }
+
+ //
+ // Merge the requested block data.
+ //
+ Link = RequestBlockArray->Entry.ForwardLink;
+ while ((Link != &RequestBlockArray->Entry) && (Link->ForwardLink != &RequestBlockArray->Entry)) {
+ BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);
+ NextBlockData = BASE_CR (Link->ForwardLink, IFR_BLOCK_DATA, Entry);
+ if ((NextBlockData->Offset >= BlockData->Offset) && (NextBlockData->Offset <= (BlockData->Offset + BlockData->Width))) {
+ if ((NextBlockData->Offset + NextBlockData->Width) > (BlockData->Offset + BlockData->Width)) {
+ BlockData->Width = (UINT16) (NextBlockData->Offset + NextBlockData->Width - BlockData->Offset);
+ }
+ RemoveEntryList (Link->ForwardLink);
+ FreePool (NextBlockData);
+ continue;
+ }
+ Link = Link->ForwardLink;
+ }
+
+ return RequestBlockArray;
+
+Done:
+ if (RequestBlockArray != NULL) {
+ //
+ // Free Link Array RequestBlockArray
+ //
+ while (!IsListEmpty (&RequestBlockArray->Entry)) {
+ BlockData = BASE_CR (RequestBlockArray->Entry.ForwardLink, IFR_BLOCK_DATA, Entry);
+ RemoveEntryList (&BlockData->Entry);
+ FreePool (BlockData);
+ }
+
+ FreePool (RequestBlockArray);
+ }
+
+ return NULL;
+}
+
+/**
+ parse the configrequest string, get the elements.
+
+ @param ConfigRequest The input config request string.
+ @param Progress Return the progress data.
+
+ @retval return data block array.
+**/
+IFR_BLOCK_DATA *
+GetNameElement (
+ IN EFI_STRING ConfigRequest,
+ OUT EFI_STRING *Progress
+ )
+{
+ EFI_STRING StringPtr;
+ EFI_STRING NextTag;
+ IFR_BLOCK_DATA *BlockData;
+ IFR_BLOCK_DATA *RequestBlockArray;
+ BOOLEAN HasValue;
+
+ StringPtr = ConfigRequest;
+
+ //
+ // Init RequestBlockArray
+ //
+ RequestBlockArray = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
+ if (RequestBlockArray == NULL) {
+ goto Done;
+ }
+ InitializeListHead (&RequestBlockArray->Entry);
+
+ //
+ // Get the request Block array from the request string
+ //
+
+ //
+ // Parse each <RequestElement> if exists
+ // Only <BlockName> format is supported by this help function.
+ // <BlockName> ::= &'Name***=***
+ //
+ while (StringPtr != NULL && *StringPtr == L'&') {
+
+ *Progress = StringPtr;
+ //
+ // Skip the L"&" string
+ //
+ StringPtr += 1;
+
+ HasValue = FALSE;
+ if ((NextTag = StrStr (StringPtr, L"=")) != NULL) {
+ *NextTag = L'\0';
+ HasValue = TRUE;
+ } else if ((NextTag = StrStr (StringPtr, L"&")) != NULL) {
+ *NextTag = L'\0';
+ }
+
+ //
+ // Set Block Data
+ //
+ BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
+ if (BlockData == NULL) {
+ goto Done;
+ }
+
+ //
+ // Get Name
+ //
+ BlockData->Name = AllocateCopyPool(StrSize (StringPtr), StringPtr);
+ InsertBlockData (&RequestBlockArray->Entry, &BlockData);
+
+ if (HasValue) {
+ //
+ // If has value, skip the value.
+ //
+ StringPtr = NextTag + 1;
+ *NextTag = L'=';
+ StringPtr = StrStr (StringPtr, L"&");
+ } else if (NextTag != NULL) {
+ //
+ // restore the '&' text.
+ //
+ StringPtr = NextTag;
+ *NextTag = L'&';
+ }
+ }
+
+ return RequestBlockArray;
+
+Done:
+ if (RequestBlockArray != NULL) {
+ //
+ // Free Link Array RequestBlockArray
+ //
+ while (!IsListEmpty (&RequestBlockArray->Entry)) {
+ BlockData = BASE_CR (RequestBlockArray->Entry.ForwardLink, IFR_BLOCK_DATA, Entry);
+ RemoveEntryList (&BlockData->Entry);
+ if (BlockData->Name != NULL) {
+ FreePool (BlockData->Name);
+ }
+ FreePool (BlockData);
+ }
+
+ FreePool (RequestBlockArray);
+ }
+
+ return NULL;
+}
+
+/**
+ Generate ConfigRequest string base on the varstore info.
+
+ @param ConfigHdr The config header for this varstore.
+ @param VarStorageData The varstore info.
+ @param Status Return Status.
+ @param ConfigRequest The ConfigRequest info may be return.
+
+ @retval TRUE Need to continue
+ @retval Others NO need to continue or error occur.
+**/
+BOOLEAN
+GenerateConfigRequest (
+ IN CHAR16 *ConfigHdr,
+ IN IFR_VARSTORAGE_DATA *VarStorageData,
+ OUT EFI_STATUS *Status,
+ IN OUT EFI_STRING *ConfigRequest
+ )
+{
+ BOOLEAN DataExist;
+ UINTN Length;
+ LIST_ENTRY *Link;
+ CHAR16 *FullConfigRequest;
+ CHAR16 *StringPtr;
+ IFR_BLOCK_DATA *BlockData;
+
+ //
+ // Append VarStorageData BlockEntry into *Request string
+ // Now support only one varstore in a form package.
+ //
+
+ //
+ // Go through all VarStorageData Entry and get BlockEntry for each one for the multiple varstore in a single form package
+ // Then construct them all to return MultiRequest string : ConfigHdr BlockConfig
+ //
+
+ //
+ // Compute the length of the entire request starting with <ConfigHdr> and a
+ // Null-terminator
+ //
+ DataExist = FALSE;
+ Length = StrLen (ConfigHdr) + 1;
+
+ for (Link = VarStorageData->BlockEntry.ForwardLink; Link != &VarStorageData->BlockEntry; Link = Link->ForwardLink) {
+ DataExist = TRUE;
+ BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);
+ if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {
+ //
+ // Add <BlockName> length for each Name
+ //
+ // <BlockName> ::= &Name1&Name2&...
+ // |1| StrLen(Name1)
+ //
+ Length = Length + (1 + StrLen (BlockData->Name));
+ } else {
+ //
+ // Add <BlockName> length for each Offset/Width pair
+ //
+ // <BlockName> ::= &OFFSET=1234&WIDTH=1234
+ // | 8 | 4 | 7 | 4 |
+ //
+ Length = Length + (8 + 4 + 7 + 4);
+ }
+ }
+ //
+ // No any request block data is found. The request string can't be constructed.
+ //
+ if (!DataExist) {
+ *Status = EFI_SUCCESS;
+ return FALSE;
+ }
+
+ //
+ // Allocate buffer for the entire <ConfigRequest>
+ //
+ FullConfigRequest = AllocateZeroPool (Length * sizeof (CHAR16));
+ if (FullConfigRequest == NULL) {
+ *Status = EFI_OUT_OF_RESOURCES;
+ return FALSE;
+ }
+ StringPtr = FullConfigRequest;
+
+ //
+ // Start with <ConfigHdr>
+ //
+ StrCpy (StringPtr, ConfigHdr);
+ StringPtr += StrLen (StringPtr);
+
+ //
+ // Loop through all the Offset/Width pairs and append them to ConfigRequest
+ //
+ for (Link = VarStorageData->BlockEntry.ForwardLink; Link != &VarStorageData->BlockEntry; Link = Link->ForwardLink) {
+ BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);
+ if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {
+ //
+ // Append &Name1\0
+ //
+ UnicodeSPrint (
+ StringPtr,
+ (1 + StrLen (BlockData->Name) + 1) * sizeof (CHAR16),
+ L"&%s",
+ BlockData->Name
+ );
+ } else {
+ //
+ // Append &OFFSET=XXXX&WIDTH=YYYY\0
+ //
+ UnicodeSPrint (
+ StringPtr,
+ (8 + 4 + 7 + 4 + 1) * sizeof (CHAR16),
+ L"&OFFSET=%04X&WIDTH=%04X",
+ BlockData->Offset,
+ BlockData->Width
+ );
+ }
+ StringPtr += StrLen (StringPtr);
+ }
+ //
+ // Set to the got full request string.
+ //
+ HiiToLower (FullConfigRequest);
+
+ if (*ConfigRequest != NULL) {
+ FreePool (*ConfigRequest);
+ }
+ *ConfigRequest = FullConfigRequest;
+
+ return TRUE;
+}
+
+/**
+ Generate ConfigRequest Header base on the varstore info.
+
+ @param VarStorageData The varstore info.
+ @param DevicePath Device path for this varstore.
+ @param ConfigHdr The config header for this varstore.
+
+ @retval EFI_SUCCESS Generate the header success.
+ @retval EFI_OUT_OF_RESOURCES Allocate buffer fail.
+**/
+EFI_STATUS
+GenerateHdr (
+ IN IFR_VARSTORAGE_DATA *VarStorageData,
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ OUT EFI_STRING *ConfigHdr
+ )
+{
+ EFI_STRING GuidStr;
+ EFI_STRING NameStr;
+ EFI_STRING PathStr;
+ UINTN Length;
+ EFI_STATUS Status;
+
+ Status = EFI_SUCCESS;
+ NameStr = NULL;
+ GuidStr = NULL;
+ PathStr = NULL;
+
+ //
+ // Construct <ConfigHdr> : "GUID=...&NAME=...&PATH=..." by VarStorageData Guid, Name and DriverHandle
+ //
+ GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *) &VarStorageData->Guid, 1, &GuidStr);
+ if (VarStorageData->Name != NULL) {
+ GenerateSubStr (L"NAME=", StrLen (VarStorageData->Name) * sizeof (CHAR16), (VOID *) VarStorageData->Name, 2, &NameStr);
+ } else {
+ GenerateSubStr (L"NAME=", 0, NULL, 2, &NameStr);
+ }
+ GenerateSubStr (
+ L"PATH=",
+ GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) DevicePath),
+ (VOID *) DevicePath,
+ 1,
+ &PathStr
+ );
+ Length = StrLen (GuidStr) + StrLen (NameStr) + StrLen (PathStr) + 1;
+ if (VarStorageData->Name == NULL) {
+ Length += 1;
+ }
+
+ *ConfigHdr = AllocateZeroPool (Length * sizeof (CHAR16));
+ if (*ConfigHdr == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+ StrCpy (*ConfigHdr, GuidStr);
+ StrCat (*ConfigHdr, NameStr);
+ if (VarStorageData->Name == NULL) {
+ StrCat (*ConfigHdr, L"&");
+ }
+ StrCat (*ConfigHdr, PathStr);
+
+ //
+ // Remove the last character L'&'
+ //
+ *(*ConfigHdr + StrLen (*ConfigHdr) - 1) = L'\0';
+
+Done:
+ if (GuidStr != NULL) {
+ FreePool (GuidStr);
+ }
+
+ if (NameStr != NULL) {
+ FreePool (NameStr);
+ }
+
+ if (PathStr != NULL) {
+ FreePool (PathStr);
+ }
+
+ return Status;
+}
+
+/**
+ Get Data buffer size based on data type.
+
+ @param ValueType The input data type.
+
+ @retval The data buffer size for the input type.
+**/
+UINT16
+GetStorageWidth (
+ IN UINT8 ValueType
+ )
+{
+ UINT16 StorageWidth;
+
+ switch (ValueType) {
+ case EFI_IFR_NUMERIC_SIZE_1:
+ case EFI_IFR_TYPE_BOOLEAN:
+ StorageWidth = (UINT16) sizeof (UINT8);
+ break;
+
+ case EFI_IFR_NUMERIC_SIZE_2:
+ StorageWidth = (UINT16) sizeof (UINT16);
+ break;
+
+ case EFI_IFR_NUMERIC_SIZE_4:
+ StorageWidth = (UINT16) sizeof (UINT32);
+ break;
+
+ case EFI_IFR_NUMERIC_SIZE_8:
+ StorageWidth = (UINT16) sizeof (UINT64);
+ break;
+
+ case EFI_IFR_TYPE_TIME:
+ StorageWidth = (UINT16) sizeof (EFI_IFR_TIME);
+ break;
+
+ case EFI_IFR_TYPE_DATE:
+ StorageWidth = (UINT16) sizeof (EFI_IFR_DATE);
+ break;
+
+ default:
+ StorageWidth = 0;
+ break;
+ }
+
+ return StorageWidth;
+}
+
+/**
+ Generate ConfigAltResp string base on the varstore info.
+
+ @param ConfigHdr The config header for this varstore.
+ @param VarStorageData The varstore info.
+ @param DefaultIdArray The Default id array.
+ @param DefaultAltCfgResp The DefaultAltCfgResp info may be return.
+
+ @retval TRUE Need to continue
+ @retval Others NO need to continue or error occur.
+**/
+EFI_STATUS
+GenerateAltConfigResp (
+ IN CHAR16 *ConfigHdr,
+ IN IFR_VARSTORAGE_DATA *VarStorageData,
+ IN IFR_DEFAULT_DATA *DefaultIdArray,
+ IN OUT EFI_STRING *DefaultAltCfgResp
+ )
+{
+ BOOLEAN DataExist;
+ UINTN Length;
+ LIST_ENTRY *Link;
+ LIST_ENTRY *LinkData;
+ LIST_ENTRY *LinkDefault;
+ LIST_ENTRY *ListEntry;
+ CHAR16 *StringPtr;
+ IFR_BLOCK_DATA *BlockData;
+ IFR_DEFAULT_DATA *DefaultId;
+ IFR_DEFAULT_DATA *DefaultValueData;
+ UINTN Width;
+ UINT8 *TmpBuffer;
+
+ BlockData = NULL;
+ DataExist = FALSE;
+
+ //
+ // Add length for <ConfigHdr> + '\0'
+ //
+ Length = StrLen (ConfigHdr) + 1;
+
+ for (Link = DefaultIdArray->Entry.ForwardLink; Link != &DefaultIdArray->Entry; Link = Link->ForwardLink) {
+ DefaultId = BASE_CR (Link, IFR_DEFAULT_DATA, Entry);
+ //
+ // Add length for "&<ConfigHdr>&ALTCFG=XXXX"
+ // |1| StrLen (ConfigHdr) | 8 | 4 |
+ //
+ Length += (1 + StrLen (ConfigHdr) + 8 + 4);
+
+ for (LinkData = VarStorageData->BlockEntry.ForwardLink; LinkData != &VarStorageData->BlockEntry; LinkData = LinkData->ForwardLink) {
+ BlockData = BASE_CR (LinkData, IFR_BLOCK_DATA, Entry);
+ ListEntry = &BlockData->DefaultValueEntry;
+ for (LinkDefault = ListEntry->ForwardLink; LinkDefault != ListEntry; LinkDefault = LinkDefault->ForwardLink) {
+ DefaultValueData = BASE_CR (LinkDefault, IFR_DEFAULT_DATA, Entry);
+ if (DefaultValueData->DefaultId != DefaultId->DefaultId) {
+ continue;
+ }
+ if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {
+ //
+ // Add length for "&Name1=zzzzzzzzzzzz"
+ // |1|Name|1|Value|
+ //
+ Length += (1 + StrLen (BlockData->Name) + 1 + BlockData->Width * 2);
+ } else {
+ //
+ // Add length for "&OFFSET=XXXX&WIDTH=YYYY&VALUE=zzzzzzzzzzzz"
+ // | 8 | 4 | 7 | 4 | 7 | Width * 2 |
+ //
+ Length += (8 + 4 + 7 + 4 + 7 + BlockData->Width * 2);
+ }
+ DataExist = TRUE;
+ }
+ }
+ }
+
+ //
+ // No default value is found. The default string doesn't exist.
+ //
+ if (!DataExist) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Allocate buffer for the entire <DefaultAltCfgResp>
+ //
+ *DefaultAltCfgResp = AllocateZeroPool (Length * sizeof (CHAR16));
+ if (*DefaultAltCfgResp == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ StringPtr = *DefaultAltCfgResp;
+
+ //
+ // Start with <ConfigHdr>
+ //
+ StrCpy (StringPtr, ConfigHdr);
+ StringPtr += StrLen (StringPtr);
+
+ for (Link = DefaultIdArray->Entry.ForwardLink; Link != &DefaultIdArray->Entry; Link = Link->ForwardLink) {
+ DefaultId = BASE_CR (Link, IFR_DEFAULT_DATA, Entry);
+ //
+ // Add <AltConfigHdr> of the form "&<ConfigHdr>&ALTCFG=XXXX\0"
+ // |1| StrLen (ConfigHdr) | 8 | 4 |
+ //
+ UnicodeSPrint (
+ StringPtr,
+ (1 + StrLen (ConfigHdr) + 8 + 4 + 1) * sizeof (CHAR16),
+ L"&%s&ALTCFG=%04X",
+ ConfigHdr,
+ DefaultId->DefaultId
+ );
+ StringPtr += StrLen (StringPtr);
+
+ for (LinkData = VarStorageData->BlockEntry.ForwardLink; LinkData != &VarStorageData->BlockEntry; LinkData = LinkData->ForwardLink) {
+ BlockData = BASE_CR (LinkData, IFR_BLOCK_DATA, Entry);
+ ListEntry = &BlockData->DefaultValueEntry;
+ for (LinkDefault = ListEntry->ForwardLink; LinkDefault != ListEntry; LinkDefault = LinkDefault->ForwardLink) {
+ DefaultValueData = BASE_CR (LinkDefault, IFR_DEFAULT_DATA, Entry);
+ if (DefaultValueData->DefaultId != DefaultId->DefaultId) {
+ continue;
+ }
+ if (VarStorageData->Type == EFI_HII_VARSTORE_NAME_VALUE) {
+ UnicodeSPrint (
+ StringPtr,
+ (1 + StrLen (ConfigHdr) + 1) * sizeof (CHAR16),
+ L"&%s=",
+ BlockData->Name
+ );
+ StringPtr += StrLen (StringPtr);
+ } else {
+ //
+ // Add <BlockConfig>
+ // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>
+ //
+ UnicodeSPrint (
+ StringPtr,
+ (8 + 4 + 7 + 4 + 7 + 1) * sizeof (CHAR16),
+ L"&OFFSET=%04X&WIDTH=%04X&VALUE=",
+ BlockData->Offset,
+ BlockData->Width
+ );
+ StringPtr += StrLen (StringPtr);
+ }
+ Width = BlockData->Width;
+ //
+ // Convert Value to a hex string in "%x" format
+ // NOTE: This is in the opposite byte that GUID and PATH use
+ //
+ TmpBuffer = (UINT8 *) &(DefaultValueData->Value);
+ for (; Width > 0; Width--) {
+ StringPtr += UnicodeValueToString (StringPtr, PREFIX_ZERO | RADIX_HEX, TmpBuffer[Width - 1], 2);
+ }
+ }
+ }
+ }
+
+ HiiToLower (*DefaultAltCfgResp);
+
+ return EFI_SUCCESS;
}
/**
@@ -2032,27 +2860,14 @@ GetFullStringFromHiiFormPackages (
UINTN PackageSize;
IFR_BLOCK_DATA *RequestBlockArray;
IFR_BLOCK_DATA *BlockData;
- IFR_BLOCK_DATA *NextBlockData;
IFR_DEFAULT_DATA *DefaultValueData;
IFR_DEFAULT_DATA *DefaultId;
IFR_DEFAULT_DATA *DefaultIdArray;
IFR_VARSTORAGE_DATA *VarStorageData;
EFI_STRING DefaultAltCfgResp;
- EFI_STRING FullConfigRequest;
EFI_STRING ConfigHdr;
- EFI_STRING GuidStr;
- EFI_STRING NameStr;
- EFI_STRING PathStr;
EFI_STRING StringPtr;
EFI_STRING Progress;
- UINTN Length;
- UINT8 *TmpBuffer;
- UINT16 Offset;
- UINT16 Width;
- LIST_ENTRY *Link;
- LIST_ENTRY *LinkData;
- LIST_ENTRY *LinkDefault;
- BOOLEAN DataExist;
if (DataBaseRecord == NULL || DevicePath == NULL || Request == NULL || AltCfgResp == NULL) {
return EFI_INVALID_PARAMETER;
@@ -2065,14 +2880,9 @@ GetFullStringFromHiiFormPackages (
DefaultIdArray = NULL;
VarStorageData = NULL;
DefaultAltCfgResp = NULL;
- FullConfigRequest = NULL;
ConfigHdr = NULL;
- GuidStr = NULL;
- NameStr = NULL;
- PathStr = NULL;
HiiFormPackage = NULL;
PackageSize = 0;
- DataExist = FALSE;
Progress = *Request;
Status = GetFormPackageData (DataBaseRecord, &HiiFormPackage, &PackageSize);
@@ -2113,153 +2923,30 @@ GetFullStringFromHiiFormPackages (
while (*StringPtr != L'\0' && *StringPtr != L'&') {
StringPtr ++;
}
- //
- // Check the following string &OFFSET=
- //
- if (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) != 0) {
- Progress = StringPtr;
- Status = EFI_INVALID_PARAMETER;
- goto Done;
- } else if (*StringPtr == L'\0') {
+
+ if (*StringPtr == L'\0') {
//
// No request block is found.
//
StringPtr = NULL;
}
}
+
+ //
+ // If StringPtr != NULL, get the request elements.
+ //
if (StringPtr != NULL) {
- //
- // Init RequestBlockArray
- //
- RequestBlockArray = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
- if (RequestBlockArray == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto Done;
+ if (StrStr (StringPtr, L"&OFFSET=") != NULL) {
+ RequestBlockArray = GetBlockElement(StringPtr, &Progress);
+ } else {
+ RequestBlockArray = GetNameElement(StringPtr, &Progress);
}
- InitializeListHead (&RequestBlockArray->Entry);
-
- //
- // Get the request Block array from the request string
- // Offset and Width
- //
-
- //
- // Parse each <RequestElement> if exists
- // Only <BlockName> format is supported by this help function.
- // <BlockName> ::= &'OFFSET='<Number>&'WIDTH='<Number>
- //
- while (*StringPtr != 0 && StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) == 0) {
- //
- // Skip the OFFSET string
- //
- Progress = StringPtr;
- StringPtr += StrLen (L"&OFFSET=");
- //
- // Get Offset
- //
- Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
- if (EFI_ERROR (Status)) {
- goto Done;
- }
- Offset = 0;
- CopyMem (
- &Offset,
- TmpBuffer,
- (((Length + 1) / 2) < sizeof (UINT16)) ? ((Length + 1) / 2) : sizeof (UINT16)
- );
- FreePool (TmpBuffer);
-
- StringPtr += Length;
- if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {
- Status = EFI_INVALID_PARAMETER;
- goto Done;
- }
- StringPtr += StrLen (L"&WIDTH=");
-
- //
- // Get Width
- //
- Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
- if (EFI_ERROR (Status)) {
- goto Done;
- }
- Width = 0;
- CopyMem (
- &Width,
- TmpBuffer,
- (((Length + 1) / 2) < sizeof (UINT16)) ? ((Length + 1) / 2) : sizeof (UINT16)
- );
- FreePool (TmpBuffer);
- StringPtr += Length;
- if (*StringPtr != 0 && *StringPtr != L'&') {
- Status = EFI_INVALID_PARAMETER;
- goto Done;
- }
-
- //
- // Set Block Data
- //
- BlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
- if (BlockData == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto Done;
- }
- BlockData->Offset = Offset;
- BlockData->Width = Width;
- InsertBlockData (&RequestBlockArray->Entry, &BlockData);
-
- //
- // Skip &VALUE string if &VALUE does exists.
- //
- if (StrnCmp (StringPtr, L"&VALUE=", StrLen (L"&VALUE=")) == 0) {
- StringPtr += StrLen (L"&VALUE=");
-
- //
- // Get Value
- //
- Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
- if (EFI_ERROR (Status)) {
- Status = EFI_INVALID_PARAMETER;
- goto Done;
- }
-
- StringPtr += Length;
- if (*StringPtr != 0 && *StringPtr != L'&') {
- Status = EFI_INVALID_PARAMETER;
- goto Done;
- }
- }
- //
- // If '\0', parsing is finished.
- //
- if (*StringPtr == 0) {
- break;
- }
- }
-
- //
- // Merge the requested block data.
- //
- Link = RequestBlockArray->Entry.ForwardLink;
- while ((Link != &RequestBlockArray->Entry) && (Link->ForwardLink != &RequestBlockArray->Entry)) {
- BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);
- NextBlockData = BASE_CR (Link->ForwardLink, IFR_BLOCK_DATA, Entry);
- if ((NextBlockData->Offset >= BlockData->Offset) && (NextBlockData->Offset <= (BlockData->Offset + BlockData->Width))) {
- if ((NextBlockData->Offset + NextBlockData->Width) > (BlockData->Offset + BlockData->Width)) {
- BlockData->Width = (UINT16) (NextBlockData->Offset + NextBlockData->Width - BlockData->Offset);
- }
- RemoveEntryList (Link->ForwardLink);
- FreePool (NextBlockData);
- continue;
- }
- Link = Link->ForwardLink;
+ if (RequestBlockArray == NULL) {
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
}
}
-
- //
- // 2. Parse FormPackage to get BlockArray and DefaultId Array for the request BlockArray.
- //
//
// Initialize DefaultIdArray to store the map between DeaultId and DefaultName
@@ -2283,17 +2970,27 @@ GetFullStringFromHiiFormPackages (
InitializeListHead (&VarStorageData->BlockEntry);
//
+ // 2. Parse FormPackage to get BlockArray and DefaultId Array for the request BlockArray.
+ //
+
+ //
// Parse the opcode in form pacakge to get the default setting.
//
- Status = ParseIfrData (HiiFormPackage, (UINT32) PackageSize, *Request, RequestBlockArray, VarStorageData, DefaultIdArray);
+ Status = ParseIfrData (DataBaseRecord->Handle,
+ HiiFormPackage,
+ (UINT32) PackageSize,
+ *Request,
+ RequestBlockArray,
+ VarStorageData,
+ DefaultIdArray);
if (EFI_ERROR (Status)) {
goto Done;
}
-
+
//
// No requested varstore in IFR data and directly return
//
- if (VarStorageData->Size == 0) {
+ if (VarStorageData->VarStoreId == 0) {
Status = EFI_SUCCESS;
goto Done;
}
@@ -2301,222 +2998,26 @@ GetFullStringFromHiiFormPackages (
//
// 3. Construct Request Element (Block Name) for 2.1 and 2.2 case.
//
-
- //
- // Construct <ConfigHdr> : "GUID=...&NAME=...&PATH=..." by VarStorageData Guid, Name and DriverHandle
- //
- GenerateSubStr (L"GUID=", sizeof (EFI_GUID), (VOID *) &VarStorageData->Guid, 1, &GuidStr);
- GenerateSubStr (L"NAME=", StrLen (VarStorageData->Name) * sizeof (CHAR16), (VOID *) VarStorageData->Name, 2, &NameStr);
- GenerateSubStr (
- L"PATH=",
- GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) DevicePath),
- (VOID *) DevicePath,
- 1,
- &PathStr
- );
- Length = StrLen (GuidStr);
- Length = Length + StrLen (NameStr);
- Length = Length + StrLen (PathStr) + 1;
- ConfigHdr = AllocateZeroPool (Length * sizeof (CHAR16));
- if (ConfigHdr == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto Done;
+ Status = GenerateHdr (VarStorageData, DevicePath, &ConfigHdr);
+ if (EFI_ERROR (Status)) {
+ goto Done;
}
- StrCpy (ConfigHdr, GuidStr);
- StrCat (ConfigHdr, NameStr);
- StrCat (ConfigHdr, PathStr);
-
- //
- // Remove the last character L'&'
- //
- *(ConfigHdr + StrLen (ConfigHdr) - 1) = L'\0';
if (RequestBlockArray == NULL) {
- //
- // Append VarStorageData BlockEntry into *Request string
- // Now support only one varstore in a form package.
- //
-
- //
- // Go through all VarStorageData Entry and get BlockEntry for each one for the multiple varstore in a single form package
- // Then construct them all to return MultiRequest string : ConfigHdr BlockConfig
- //
-
- //
- // Compute the length of the entire request starting with <ConfigHdr> and a
- // Null-terminator
- //
- DataExist = FALSE;
- Length = StrLen (ConfigHdr) + 1;
-
- for (Link = VarStorageData->BlockEntry.ForwardLink; Link != &VarStorageData->BlockEntry; Link = Link->ForwardLink) {
- //
- // Add <BlockName> length for each Offset/Width pair
- //
- // <BlockName> ::= &OFFSET=1234&WIDTH=1234
- // | 8 | 4 | 7 | 4 |
- //
- DataExist = TRUE;
- Length = Length + (8 + 4 + 7 + 4);
- }
-
- //
- // No any request block data is found. The request string can't be constructed.
- //
- if (!DataExist) {
- Status = EFI_SUCCESS;
- goto Done;
- }
-
- //
- // Allocate buffer for the entire <ConfigRequest>
- //
- FullConfigRequest = AllocateZeroPool (Length * sizeof (CHAR16));
- if (FullConfigRequest == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
+ if (!GenerateConfigRequest(ConfigHdr, VarStorageData, &Status, Request)) {
goto Done;
}
- StringPtr = FullConfigRequest;
-
- //
- // Start with <ConfigHdr>
- //
- StrCpy (StringPtr, ConfigHdr);
- StringPtr += StrLen (StringPtr);
-
- //
- // Loop through all the Offset/Width pairs and append them to ConfigRequest
- //
- for (Link = VarStorageData->BlockEntry.ForwardLink; Link != &VarStorageData->BlockEntry; Link = Link->ForwardLink) {
- BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);
- //
- // Append &OFFSET=XXXX&WIDTH=YYYY\0
- //
- UnicodeSPrint (
- StringPtr,
- (8 + 4 + 7 + 4 + 1) * sizeof (CHAR16),
- L"&OFFSET=%04X&WIDTH=%04X",
- BlockData->Offset,
- BlockData->Width
- );
- StringPtr += StrLen (StringPtr);
- }
- //
- // Set to the got full request string.
- //
- HiiToLower (FullConfigRequest);
- if (*Request != NULL) {
- FreePool (*Request);
- }
- *Request = FullConfigRequest;
}
-
+
//
// 4. Construct Default Value string in AltResp according to request element.
// Go through all VarStorageData Entry and get the DefaultId array for each one
// Then construct them all to : ConfigHdr AltConfigHdr ConfigBody AltConfigHdr ConfigBody
//
- DataExist = FALSE;
- //
- // Add length for <ConfigHdr> + '\0'
- //
- Length = StrLen (ConfigHdr) + 1;
-
- for (Link = DefaultIdArray->Entry.ForwardLink; Link != &DefaultIdArray->Entry; Link = Link->ForwardLink) {
- DefaultId = BASE_CR (Link, IFR_DEFAULT_DATA, Entry);
- //
- // Add length for "&<ConfigHdr>&ALTCFG=XXXX"
- // |1| StrLen (ConfigHdr) | 8 | 4 |
- //
- Length += (1 + StrLen (ConfigHdr) + 8 + 4);
-
- for (LinkData = VarStorageData->BlockEntry.ForwardLink; LinkData != &VarStorageData->BlockEntry; LinkData = LinkData->ForwardLink) {
- BlockData = BASE_CR (LinkData, IFR_BLOCK_DATA, Entry);
- for (LinkDefault = BlockData->DefaultValueEntry.ForwardLink; LinkDefault != &BlockData->DefaultValueEntry; LinkDefault = LinkDefault->ForwardLink) {
- DefaultValueData = BASE_CR (LinkDefault, IFR_DEFAULT_DATA, Entry);
- if (DefaultValueData->DefaultId == DefaultId->DefaultId) {
- //
- // Add length for "&OFFSET=XXXX&WIDTH=YYYY&VALUE=zzzzzzzzzzzz"
- // | 8 | 4 | 7 | 4 | 7 | Width * 2 |
- //
- Length += (8 + 4 + 7 + 4 + 7 + BlockData->Width * 2);
- DataExist = TRUE;
- }
- }
- }
- }
-
- //
- // No default value is found. The default string doesn't exist.
- //
- if (!DataExist) {
- Status = EFI_SUCCESS;
- goto Done;
- }
-
- //
- // Allocate buffer for the entire <DefaultAltCfgResp>
- //
- DefaultAltCfgResp = AllocateZeroPool (Length * sizeof (CHAR16));
- if (DefaultAltCfgResp == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
+ Status = GenerateAltConfigResp (ConfigHdr, VarStorageData, DefaultIdArray, &DefaultAltCfgResp);
+ if (EFI_ERROR (Status)) {
goto Done;
}
- StringPtr = DefaultAltCfgResp;
-
- //
- // Start with <ConfigHdr>
- //
- StrCpy (StringPtr, ConfigHdr);
- StringPtr += StrLen (StringPtr);
-
- for (Link = DefaultIdArray->Entry.ForwardLink; Link != &DefaultIdArray->Entry; Link = Link->ForwardLink) {
- DefaultId = BASE_CR (Link, IFR_DEFAULT_DATA, Entry);
- //
- // Add <AltConfigHdr> of the form "&<ConfigHdr>&ALTCFG=XXXX\0"
- // |1| StrLen (ConfigHdr) | 8 | 4 |
- //
- UnicodeSPrint (
- StringPtr,
- (1 + StrLen (ConfigHdr) + 8 + 4 + 1) * sizeof (CHAR16),
- L"&%s&ALTCFG=%04X",
- ConfigHdr,
- DefaultId->DefaultId
- );
- StringPtr += StrLen (StringPtr);
-
- for (LinkData = VarStorageData->BlockEntry.ForwardLink; LinkData != &VarStorageData->BlockEntry; LinkData = LinkData->ForwardLink) {
- BlockData = BASE_CR (LinkData, IFR_BLOCK_DATA, Entry);
- for (LinkDefault = BlockData->DefaultValueEntry.ForwardLink; LinkDefault != &BlockData->DefaultValueEntry; LinkDefault = LinkDefault->ForwardLink) {
- DefaultValueData = BASE_CR (LinkDefault, IFR_DEFAULT_DATA, Entry);
- if (DefaultValueData->DefaultId == DefaultId->DefaultId) {
- //
- // Add <BlockConfig>
- // <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>
- //
- UnicodeSPrint (
- StringPtr,
- (8 + 4 + 7 + 4 + 7 + 1) * sizeof (CHAR16),
- L"&OFFSET=%04X&WIDTH=%04X&VALUE=",
- BlockData->Offset,
- BlockData->Width
- );
- StringPtr += StrLen (StringPtr);
-
- //
- // Convert Value to a hex string in "%x" format
- // NOTE: This is in the opposite byte that GUID and PATH use
- //
- Width = BlockData->Width;
- TmpBuffer = (UINT8 *) &(DefaultValueData->Value);
- for (; Width > 0; Width--) {
- StringPtr += UnicodeValueToString (StringPtr, PREFIX_ZERO | RADIX_HEX, TmpBuffer[Width - 1], 2);
- }
- }
- }
- }
- }
- HiiToLower (DefaultAltCfgResp);
//
// 5. Merge string into the input AltCfgResp if the iput *AltCfgResp is not NULL.
@@ -2536,12 +3037,15 @@ Done:
while (!IsListEmpty (&RequestBlockArray->Entry)) {
BlockData = BASE_CR (RequestBlockArray->Entry.ForwardLink, IFR_BLOCK_DATA, Entry);
RemoveEntryList (&BlockData->Entry);
+ if (BlockData->Name != NULL) {
+ FreePool (BlockData->Name);
+ }
FreePool (BlockData);
}
FreePool (RequestBlockArray);
}
-
+
if (VarStorageData != NULL) {
//
// Free link array VarStorageData
@@ -2549,6 +3053,9 @@ Done:
while (!IsListEmpty (&VarStorageData->BlockEntry)) {
BlockData = BASE_CR (VarStorageData->BlockEntry.ForwardLink, IFR_BLOCK_DATA, Entry);
RemoveEntryList (&BlockData->Entry);
+ if (BlockData->Name != NULL) {
+ FreePool (BlockData->Name);
+ }
//
// Free default value link array
//
@@ -2573,19 +3080,10 @@ Done:
}
FreePool (DefaultIdArray);
}
-
+
//
// Free the allocated string
//
- if (GuidStr != NULL) {
- FreePool (GuidStr);
- }
- if (NameStr != NULL) {
- FreePool (NameStr);
- }
- if (PathStr != NULL) {
- FreePool (PathStr);
- }
if (ConfigHdr != NULL) {
FreePool (ConfigHdr);
}
@@ -2601,7 +3099,7 @@ Done:
if (*Request == NULL) {
*PointerProgress = NULL;
} else if (EFI_ERROR (Status)) {
- *PointerProgress = Progress;
+ *PointerProgress = *Request;
} else {
*PointerProgress = *Request + StrLen (*Request);
}
@@ -2773,6 +3271,149 @@ Done:
}
/**
+ Validate the config request elements.
+
+ @param ConfigElements A null-terminated Unicode string in <ConfigRequest> format,
+ without configHdr field.
+
+ @retval CHAR16 * THE first Name/value pair not correct.
+ @retval NULL Success parse the name/value pair
+**/
+CHAR16 *
+OffsetWidthValidate (
+ CHAR16 *ConfigElements
+ )
+{
+ CHAR16 *StringPtr;
+ CHAR16 *RetVal;
+
+ StringPtr = ConfigElements;
+
+ while (1) {
+ RetVal = StringPtr;
+ if (StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) != 0) {
+ return RetVal;
+ }
+
+ while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {
+ StringPtr++;
+ }
+ if (*StringPtr == L'\0') {
+ return RetVal;
+ }
+
+ StringPtr += StrLen (L"&WIDTH=");
+ while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) != 0) {
+ StringPtr ++;
+ }
+
+ if (*StringPtr == L'\0') {
+ return NULL;
+ }
+ }
+}
+
+/**
+ Validate the config request elements.
+
+ @param ConfigElements A null-terminated Unicode string in <ConfigRequest> format,
+ without configHdr field.
+
+ @retval CHAR16 * THE first Name/value pair not correct.
+ @retval NULL Success parse the name/value pair
+
+**/
+CHAR16 *
+NameValueValidate (
+ CHAR16 *ConfigElements
+ )
+{
+ CHAR16 *StringPtr;
+ CHAR16 *RetVal;
+
+ StringPtr = ConfigElements;
+
+ while (1) {
+ RetVal = StringPtr;
+ if (*StringPtr != L'&') {
+ return RetVal;
+ }
+ StringPtr += 1;
+
+ StringPtr = StrStr (StringPtr, L"&");
+
+ if (StringPtr == NULL) {
+ return NULL;
+ }
+ }
+}
+
+/**
+ Validate the config request string.
+
+ @param ConfigRequest A null-terminated Unicode string in <ConfigRequest> format.
+
+ @retval CHAR16 * THE first element not correct.
+ @retval NULL Success parse the name/value pair
+
+**/
+CHAR16 *
+ConfigRequestValidate (
+ CHAR16 *ConfigRequest
+ )
+{
+ BOOLEAN HasNameField;
+ CHAR16 *StringPtr;
+
+ HasNameField = TRUE;
+ StringPtr = ConfigRequest;
+
+ //
+ // Check <ConfigHdr>
+ //
+ if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
+ return ConfigRequest;
+ }
+ StringPtr += StrLen (L"GUID=");
+ while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&NAME=", StrLen (L"&NAME=")) != 0) {
+ StringPtr++;
+ }
+ if (*StringPtr == L'\0') {
+ return ConfigRequest;
+ }
+ StringPtr += StrLen (L"&NAME=");
+ if (*StringPtr == L'&') {
+ HasNameField = FALSE;
+ }
+ while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&PATH=", StrLen (L"&PATH=")) != 0) {
+ StringPtr++;
+ }
+ if (*StringPtr == L'\0') {
+ return ConfigRequest;
+ }
+ StringPtr += StrLen (L"&PATH=");
+ while (*StringPtr != L'\0' && *StringPtr != L'&') {
+ StringPtr ++;
+ }
+
+ if (*StringPtr == L'\0') {
+ return NULL;
+ }
+
+ if (HasNameField) {
+ //
+ // Should be Buffer varstore, config request should be "OFFSET/Width" pairs.
+ //
+ return OffsetWidthValidate(StringPtr);
+ } else {
+ //
+ // Should be Name/Value varstore, config request should be "&name1&name2..." pairs.
+ //
+ return NameValueValidate(StringPtr);
+ }
+}
+
+/**
This function allows a caller to extract the current configuration
for one or more named elements from one or more drivers.
@@ -2807,8 +3448,10 @@ Done:
Progress parameter is set to NULL.
@retval EFI_INVALID_PARAMETER Illegal syntax. Progress set to most recent &
before the error or the beginning of the string.
- @retval EFI_INVALID_PARAMETER Unknown name. Progress points to the & before the
- name in question.
+ @retval EFI_INVALID_PARAMETER The ExtractConfig function of the underlying HII
+ Configuration Access Protocol returned
+ EFI_INVALID_PARAMETER. Progress set to most recent
+ & before the error or the beginning of the string.
**/
EFI_STATUS
@@ -2840,7 +3483,8 @@ HiiConfigRoutingExtractConfig (
BOOLEAN FirstElement;
BOOLEAN IfrDataParsedFlag;
BOOLEAN IsEfiVarStore;
- EFI_IFR_VARSTORE_EFI *EfiVarStoreInfo;
+ EFI_IFR_VARSTORE_EFI *EfiVarStoreInfo;
+ EFI_STRING ErrorPtr;
if (This == NULL || Progress == NULL || Results == NULL) {
return EFI_INVALID_PARAMETER;
@@ -2958,12 +3602,22 @@ HiiConfigRoutingExtractConfig (
goto Done;
}
}
-
+
+ //
+ // Validate ConfigRequest String.
+ //
+ ErrorPtr = ConfigRequestValidate(ConfigRequest);
+ if (ErrorPtr != NULL) {
+ *Progress = StrStr (StringPtr, ErrorPtr);
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+
//
- // Check whether ConfigRequest contains request string OFFSET/WIDTH
+ // Check whether ConfigRequest contains request string.
//
IfrDataParsedFlag = FALSE;
- if ((HiiHandle != NULL) && (StrStr (ConfigRequest, L"&OFFSET=") == NULL)) {
+ if ((HiiHandle != NULL) && !GetElementsFromRequest(ConfigRequest)) {
//
// Get the full request string from IFR when HiiPackage is registered to HiiHandle
//
@@ -2974,13 +3628,14 @@ HiiConfigRoutingExtractConfig (
// AccessProgress indicates the parsing progress on <ConfigRequest>.
// Map it to the progress on <MultiConfigRequest> then return it.
//
+ ASSERT (AccessProgress != NULL);
*Progress = StrStr (StringPtr, AccessProgress);
goto Done;
}
//
// Not any request block is found.
//
- if (StrStr (ConfigRequest, L"&OFFSET=") == NULL) {
+ if (!GetElementsFromRequest(ConfigRequest)) {
AccessResults = AllocateCopyPool (StrSize (ConfigRequest), ConfigRequest);
goto NextConfigString;
}
@@ -2999,7 +3654,7 @@ HiiConfigRoutingExtractConfig (
// Call the GetVariable function to extract settings.
//
Status = GetConfigRespFromEfiVarStore(This, EfiVarStoreInfo, ConfigRequest, &AccessResults, &AccessProgress);
- FreePool (EfiVarStoreInfo);
+ FreePool (EfiVarStoreInfo);
} else {
//
// Call corresponding ConfigAccess protocol to extract settings
@@ -3051,7 +3706,7 @@ HiiConfigRoutingExtractConfig (
DefaultResults = NULL;
}
-NextConfigString:
+NextConfigString:
if (!FirstElement) {
Status = AppendToMultiString (Results, L"&");
ASSERT_EFI_ERROR (Status);
@@ -3114,9 +3769,9 @@ Done:
instance.
@param Results Null-terminated Unicode string in
<MultiConfigAltResp> format which has all values
- filled in for the names in the Request string.
- String to be allocated by the called function.
- De-allocation is up to the caller.
+ filled in for the entirety of the current HII
+ database. String to be allocated by the called
+ function. De-allocation is up to the caller.
@retval EFI_SUCCESS The Results string is filled with the values
corresponding to all requested names.
@@ -3262,7 +3917,7 @@ HiiConfigRoutingExportConfig (
if (StringPtr != NULL) {
*StringPtr = 0;
}
- if (StrStr (AccessResults, L"&OFFSET=") != NULL) {
+ if (GetElementsFromRequest (AccessResults)) {
Status = GetFullStringFromHiiFormPackages (Database, DevicePath, &AccessResults, &DefaultResults, NULL);
ASSERT_EFI_ERROR (Status);
}
@@ -3669,7 +4324,7 @@ HiiBlockToConfig (
//
Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
if (EFI_ERROR (Status)) {
- *Progress = ConfigRequest;
+ *Progress = TmpPtr - 1;
goto Exit;
}
Offset = 0;
@@ -3682,7 +4337,7 @@ HiiBlockToConfig (
StringPtr += Length;
if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {
- *Progress = StringPtr - Length - StrLen (L"OFFSET=") - 1;
+ *Progress = TmpPtr - 1;
Status = EFI_INVALID_PARAMETER;
goto Exit;
}
@@ -3693,7 +4348,7 @@ HiiBlockToConfig (
//
Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
if (EFI_ERROR (Status)) {
- *Progress = ConfigRequest;
+ *Progress = TmpPtr - 1;
goto Exit;
}
Width = 0;
@@ -3706,7 +4361,7 @@ HiiBlockToConfig (
StringPtr += Length;
if (*StringPtr != 0 && *StringPtr != L'&') {
- *Progress = StringPtr - Length - StrLen (L"&WIDTH=");
+ *Progress = TmpPtr - 1;
Status = EFI_INVALID_PARAMETER;
goto Exit;
}
@@ -3829,8 +4484,9 @@ Exit:
(see below) is returned.
@param BlockSize The length of the Block in units of UINT8. On
input, this is the size of the Block. On output,
- if successful, contains the index of the last
- modified byte in the Block.
+ if successful, contains the largest index of the
+ modified byte in the Block, or the required buffer
+ size if the Block is not large enough.
@param Progress On return, points to an element of the ConfigResp
string filled in with the offset of the most
recent '&' before the first failing name / value
@@ -3850,7 +4506,8 @@ Exit:
value pair. Block is left updated and
Progress points at the '&' preceding the first
non-<BlockName>.
- @retval EFI_DEVICE_ERROR Block not large enough. Progress undefined.
+ @retval EFI_BUFFER_TOO_SMALL Block not large enough. Progress undefined.
+ BlockSize is updated with the required buffer size.
@retval EFI_NOT_FOUND Target for the specified routing data was not found.
Progress points to the "G" in "GUID" of the errant
routing data.
@@ -3868,6 +4525,7 @@ HiiConfigToBlock (
{
HII_DATABASE_PRIVATE_DATA *Private;
EFI_STRING StringPtr;
+ EFI_STRING TmpPtr;
UINTN Length;
EFI_STATUS Status;
UINT8 *TmpBuffer;
@@ -3926,13 +4584,14 @@ HiiConfigToBlock (
// <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE='<Number>
//
while (*StringPtr != 0 && StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) == 0) {
+ TmpPtr = StringPtr;
StringPtr += StrLen (L"&OFFSET=");
//
// Get Offset
//
Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
if (EFI_ERROR (Status)) {
- *Progress = ConfigResp;
+ *Progress = TmpPtr;
goto Exit;
}
Offset = 0;
@@ -3945,7 +4604,7 @@ HiiConfigToBlock (
StringPtr += Length;
if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {
- *Progress = StringPtr - Length - StrLen (L"&OFFSET=");
+ *Progress = TmpPtr;
Status = EFI_INVALID_PARAMETER;
goto Exit;
}
@@ -3956,7 +4615,7 @@ HiiConfigToBlock (
//
Status = GetValueOfNumber (StringPtr, &TmpBuffer, &Length);
if (EFI_ERROR (Status)) {
- *Progress = ConfigResp;
+ *Progress = TmpPtr;
goto Exit;
}
Width = 0;
@@ -3969,7 +4628,7 @@ HiiConfigToBlock (
StringPtr += Length;
if (StrnCmp (StringPtr, L"&VALUE=", StrLen (L"&VALUE=")) != 0) {
- *Progress = StringPtr - Length - StrLen (L"&WIDTH=");
+ *Progress = TmpPtr;
Status = EFI_INVALID_PARAMETER;
goto Exit;
}
@@ -3980,13 +4639,13 @@ HiiConfigToBlock (
//
Status = GetValueOfNumber (StringPtr, &Value, &Length);
if (EFI_ERROR (Status)) {
- *Progress = ConfigResp;
+ *Progress = TmpPtr;
goto Exit;
}
StringPtr += Length;
if (*StringPtr != 0 && *StringPtr != L'&') {
- *Progress = StringPtr - Length - StrLen (L"&VALUE=");
+ *Progress = TmpPtr;
Status = EFI_INVALID_PARAMETER;
goto Exit;
}
@@ -4027,7 +4686,7 @@ HiiConfigToBlock (
if (MaxBlockSize > BufferSize) {
*BlockSize = MaxBlockSize;
if (Block != NULL) {
- return EFI_DEVICE_ERROR;
+ return EFI_BUFFER_TOO_SMALL;
}
}
diff --git a/MdeModulePkg/Universal/HiiDatabaseDxe/Database.c b/MdeModulePkg/Universal/HiiDatabaseDxe/Database.c
index 0e16f9850..65334ded5 100644
--- a/MdeModulePkg/Universal/HiiDatabaseDxe/Database.c
+++ b/MdeModulePkg/Universal/HiiDatabaseDxe/Database.c
@@ -3100,17 +3100,18 @@ HiiUpdatePackageList (
@param Handle An array of EFI_HII_HANDLE instances returned.
@retval EFI_SUCCESS The matching handles are outputed successfully.
- HandleBufferLength is updated with the actual length.
+ HandleBufferLength is updated with the actual length.
@retval EFI_BUFFER_TO_SMALL The HandleBufferLength parameter indicates that
Handle is too small to support the number of
handles. HandleBufferLength is updated with a
value that will enable the data to fit.
@retval EFI_NOT_FOUND No matching handle could not be found in database.
- @retval EFI_INVALID_PARAMETER Handle or HandleBufferLength was NULL.
-
+ @retval EFI_INVALID_PARAMETER HandleBufferLength was NULL.
+ @retval EFI_INVALID_PARAMETER The value referenced by HandleBufferLength was not
+ zero and Handle was NULL.
@retval EFI_INVALID_PARAMETER PackageType is not a EFI_HII_PACKAGE_TYPE_GUID but
- PackageGuid is not NULL, PackageType is a EFI_HII_
- PACKAGE_TYPE_GUID but PackageGuid is NULL.
+ PackageGuid is not NULL, PackageType is a EFI_HII_
+ PACKAGE_TYPE_GUID but PackageGuid is NULL.
**/
EFI_STATUS
@@ -3263,7 +3264,9 @@ HiiListPackageLists (
value that will enable the data to fit.
@retval EFI_NOT_FOUND The specifiecd Handle could not be found in the
current database.
- @retval EFI_INVALID_PARAMETER Handle or Buffer or BufferSize was NULL.
+ @retval EFI_INVALID_PARAMETER BufferSize was NULL.
+ @retval EFI_INVALID_PARAMETER The value referenced by BufferSize was not zero
+ and Buffer was NULL.
**/
EFI_STATUS
@@ -3525,7 +3528,9 @@ HiiUnregisterPackageNotify (
number of GUIDs. KeyGuidBufferLength is
updated with a value that will enable the data to
fit.
- @retval EFI_INVALID_PARAMETER The KeyGuidBuffer or KeyGuidBufferLength was NULL.
+ @retval EFI_INVALID_PARAMETER The KeyGuidBufferLength is NULL.
+ @retval EFI_INVALID_PARAMETER The value referenced by KeyGuidBufferLength is not
+ zero and KeyGuidBuffer is NULL.
@retval EFI_NOT_FOUND There was no keyboard layout.
**/
diff --git a/MdeModulePkg/Universal/HiiDatabaseDxe/Font.c b/MdeModulePkg/Universal/HiiDatabaseDxe/Font.c
index f6f784e73..24bb50299 100644
--- a/MdeModulePkg/Universal/HiiDatabaseDxe/Font.c
+++ b/MdeModulePkg/Universal/HiiDatabaseDxe/Font.c
@@ -2679,14 +2679,15 @@ Exit:
with the first font. On return, points to the
returned font handle or points to NULL if there
are no more matching fonts.
- @param StringInfoIn Upon entry, points to the font to return
- information about.
- If NULL, then the information about the system default
- font will be returned.
- @param StringInfoOut Upon return, contains the matching font's
- information. If NULL, then no information is
- returned. It's caller's responsibility to free
- this buffer.
+ @param StringInfoIn Upon entry, points to the font to return information
+ about. If NULL, then the information about the system
+ default font will be returned.
+ @param StringInfoOut Upon return, contains the matching font's information.
+ If NULL, then no information is returned. This buffer
+ is allocated with a call to the Boot Service AllocatePool().
+ It is the caller's responsibility to call the Boot
+ Service FreePool() when the caller no longer requires
+ the contents of StringInfoOut.
@param String Points to the string which will be tested to
determine if all characters are available. If
NULL, then any font is acceptable.
diff --git a/MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabase.h b/MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabase.h
index 455dac353..9046d9057 100644
--- a/MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabase.h
+++ b/MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabase.h
@@ -67,6 +67,7 @@ typedef struct {
CHAR16 *Name;
EFI_VARSTORE_ID VarStoreId;
UINT16 Size;
+ UINT8 Type;
LIST_ENTRY BlockEntry; // Link to its Block array
} IFR_VARSTORAGE_DATA;
@@ -78,6 +79,7 @@ typedef struct {
UINT8 OpCode;
UINT8 Scope;
LIST_ENTRY DefaultValueEntry; // Link to its default value array
+ CHAR16 *Name;
} IFR_BLOCK_DATA;
//
@@ -102,9 +104,10 @@ typedef struct {
//
// Storage types
//
-#define EFI_HII_VARSTORE_BUFFER 0
-#define EFI_HII_VARSTORE_NAME_VALUE 1
-#define EFI_HII_VARSTORE_EFI_VARIABLE 2
+#define EFI_HII_VARSTORE_BUFFER 0
+#define EFI_HII_VARSTORE_NAME_VALUE 1
+#define EFI_HII_VARSTORE_EFI_VARIABLE 2
+#define EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER 3
#define HII_FORMSET_STORAGE_SIGNATURE SIGNATURE_32 ('H', 'S', 'T', 'G')
typedef struct {
@@ -722,13 +725,15 @@ HiiGetGlyph (
with the first font. On return, points to the
returned font handle or points to NULL if there
are no more matching fonts.
- @param StringInfoIn Upon entry, points to the font to return
- information about. If NULL, then the information about the system default
- font will be returned.
- @param StringInfoOut Upon return, contains the matching font's
- information. If NULL, then no information is
- returned. It's caller's responsibility to free
- this buffer.
+ @param StringInfoIn Upon entry, points to the font to return information
+ about. If NULL, then the information about the system
+ default font will be returned.
+ @param StringInfoOut Upon return, contains the matching font's information.
+ If NULL, then no information is returned. This buffer
+ is allocated with a call to the Boot Service AllocatePool().
+ It is the caller's responsibility to call the Boot
+ Service FreePool() when the caller no longer requires
+ the contents of StringInfoOut.
@param String Points to the string which will be tested to
determine if all characters are available. If
NULL, then any font is acceptable.
@@ -736,7 +741,7 @@ HiiGetGlyph (
@retval EFI_SUCCESS Matching font returned successfully.
@retval EFI_NOT_FOUND No matching font was found.
@retval EFI_INVALID_PARAMETER StringInfoIn is NULL.
- @retval EFI_INVALID_PARAMETER StringInfoIn->FontInfoMask is an invalid combination.
+ @retval EFI_INVALID_PARAMETER StringInfoIn->FontInfoMask is an invalid combination.
@retval EFI_OUT_OF_RESOURCES There were insufficient resources to complete the
request.
**/
@@ -1001,13 +1006,14 @@ HiiNewString (
@retval EFI_SUCCESS The string was returned successfully.
@retval EFI_NOT_FOUND The string specified by StringId is not
available.
- @retval EFI_NOT_FOUND The string specified by StringId is available but
- not in the specified language.
- The specified PackageList is not in the database.
- @retval EFI_INVALID_LANGUAGE - The string specified by StringId is available but
+ The specified PackageList is not in the database.
+ @retval EFI_INVALID_LANGUAGE The string specified by StringId is available but
+ not in the specified language.
@retval EFI_BUFFER_TOO_SMALL The buffer specified by StringSize is too small
to hold the string.
- @retval EFI_INVALID_PARAMETER The String or Language or StringSize was NULL.
+ @retval EFI_INVALID_PARAMETER The Language or StringSize was NULL.
+ @retval EFI_INVALID_PARAMETER The value referenced by StringSize was not zero
+ and String was NULL.
@retval EFI_OUT_OF_RESOURCES There were insufficient resources to complete the
request.
@@ -1073,7 +1079,8 @@ HiiSetString (
points to the length of Languages, in bytes.
@retval EFI_SUCCESS The languages were returned successfully.
- @retval EFI_INVALID_PARAMETER The Languages or LanguagesSize was NULL.
+ @retval EFI_INVALID_PARAMETER The LanguagesSize was NULL.
+ @retval EFI_INVALID_PARAMETER The value referenced by LanguagesSize is not zero and Languages is NULL.
@retval EFI_BUFFER_TOO_SMALL The LanguagesSize is too small to hold the list
of supported languages. LanguageSize is updated
to contain the required size.
@@ -1114,15 +1121,16 @@ HiiGetLanguages (
in bytes.
@retval EFI_SUCCESS Secondary languages were correctly returned.
- @retval EFI_INVALID_PARAMETER PrimaryLanguage or SecondaryLanguages or
- SecondaryLanguagesSize was NULL.
+ @retval EFI_INVALID_PARAMETER PrimaryLanguage or SecondaryLanguagesSize was NULL.
+ @retval EFI_INVALID_PARAMETER The value referenced by SecondaryLanguagesSize is not
+ zero and SecondaryLanguages is NULL.
@retval EFI_BUFFER_TOO_SMALL The buffer specified by SecondaryLanguagesSize is
too small to hold the returned information.
SecondaryLanguageSize is updated to hold the size of
the buffer required.
@retval EFI_INVALID_LANGUAGE The language specified by PrimaryLanguage is not
present in the specified package list.
- @retval EFI_NOT_FOUND The specified PackageList is not in the Database.
+ @retval EFI_NOT_FOUND The specified PackageList is not in the Database.
**/
EFI_STATUS
@@ -1241,18 +1249,19 @@ HiiUpdatePackageList (
@param Handle An array of EFI_HII_HANDLE instances returned.
@retval EFI_SUCCESS The matching handles are outputed successfully.
- HandleBufferLength is updated with the actual length.
+ HandleBufferLength is updated with the actual length.
@retval EFI_BUFFER_TO_SMALL The HandleBufferLength parameter indicates that
Handle is too small to support the number of
handles. HandleBufferLength is updated with a
value that will enable the data to fit.
@retval EFI_NOT_FOUND No matching handle could not be found in
database.
- @retval EFI_INVALID_PARAMETER Handle or HandleBufferLength was NULL.
- @retval EFI_INVALID_PARAMETER PackageType is not a EFI_HII_PACKAGE_TYPE_GUID but
- PackageGuid is not NULL, PackageType is a EFI_HII_
- PACKAGE_TYPE_GUID but PackageGuid is NULL.
-
+ @retval EFI_INVALID_PARAMETER HandleBufferLength was NULL.
+ @retval EFI_INVALID_PARAMETER The value referenced by HandleBufferLength was not
+ zero and Handle was NULL.
+ @retval EFI_INVALID_PARAMETER PackageType is not a EFI_HII_PACKAGE_TYPE_GUID but
+ PackageGuid is not NULL, PackageType is a EFI_HII_
+ PACKAGE_TYPE_GUID but PackageGuid is NULL.
**/
EFI_STATUS
@@ -1290,7 +1299,9 @@ HiiListPackageLists (
a value that will enable the data to fit.
@retval EFI_NOT_FOUND The specifiecd Handle could not be found in the
current database.
- @retval EFI_INVALID_PARAMETER Handle or Buffer or BufferSize was NULL.
+ @retval EFI_INVALID_PARAMETER BufferSize was NULL.
+ @retval EFI_INVALID_PARAMETER The value referenced by BufferSize was not zero
+ and Buffer was NULL.
**/
EFI_STATUS
@@ -1390,8 +1401,9 @@ HiiUnregisterPackageNotify (
number of GUIDs. KeyGuidBufferLength is
updated with a value that will enable the data to
fit.
- @retval EFI_INVALID_PARAMETER The KeyGuidBuffer or KeyGuidBufferLength was
- NULL.
+ @retval EFI_INVALID_PARAMETER The KeyGuidBufferLength is NULL.
+ @retval EFI_INVALID_PARAMETER The value referenced by KeyGuidBufferLength is not
+ zero and KeyGuidBuffer is NULL.
@retval EFI_NOT_FOUND There was no keyboard layout.
**/
@@ -1546,9 +1558,9 @@ HiiConfigRoutingExtractConfig (
instance.
@param Results Null-terminated Unicode string in
<MultiConfigAltResp> format which has all values
- filled in for the names in the Request string.
- String to be allocated by the called function.
- De-allocation is up to the caller.
+ filled in for the entirety of the current HII
+ database. String to be allocated by the called
+ function. De-allocation is up to the caller.
@retval EFI_SUCCESS The Results string is filled with the values
corresponding to all requested names.
@@ -1671,8 +1683,9 @@ HiiBlockToConfig (
(see below) is returned.
@param BlockSize The length of the Block in units of UINT8. On
input, this is the size of the Block. On output,
- if successful, contains the index of the last
- modified byte in the Block.
+ if successful, contains the largest index of the
+ modified byte in the Block, or the required buffer
+ size if the Block is not large enough.
@param Progress On return, points to an element of the ConfigResp
string filled in with the offset of the most
recent '&' before the first failing name / value
@@ -1697,6 +1710,8 @@ HiiBlockToConfig (
value pair. Block is left updated and
Progress points at the '&' preceding the first
non-<BlockName>.
+ @retval EFI_BUFFER_TOO_SMALL Block not large enough. Progress undefined.
+ BlockSize is updated with the required buffer size.
**/
EFI_STATUS
diff --git a/MdeModulePkg/Universal/HiiDatabaseDxe/String.c b/MdeModulePkg/Universal/HiiDatabaseDxe/String.c
index c55305886..f3c0555cb 100644
--- a/MdeModulePkg/Universal/HiiDatabaseDxe/String.c
+++ b/MdeModulePkg/Universal/HiiDatabaseDxe/String.c
@@ -1590,7 +1590,8 @@ Done:
@retval EFI_INVALID_LANGUAGE - The string specified by StringId is available but
@retval EFI_BUFFER_TOO_SMALL The buffer specified by StringSize is too small to
hold the string.
- @retval EFI_INVALID_PARAMETER The String or Language or StringSize was NULL.
+ @retval EFI_INVALID_PARAMETER The Language or StringSize was NULL.
+ @retval EFI_INVALID_PARAMETER The value referenced by StringSize was not zero and String was NULL.
@retval EFI_OUT_OF_RESOURCES There were insufficient resources to complete the
request.
@@ -1775,7 +1776,8 @@ HiiSetString (
the length of Languages, in bytes.
@retval EFI_SUCCESS The languages were returned successfully.
- @retval EFI_INVALID_PARAMETER The Languages or LanguagesSize was NULL.
+ @retval EFI_INVALID_PARAMETER The LanguagesSize was NULL.
+ @retval EFI_INVALID_PARAMETER The value referenced by LanguagesSize is not zero and Languages is NULL.
@retval EFI_BUFFER_TOO_SMALL The LanguagesSize is too small to hold the list of
supported languages. LanguageSize is updated to
contain the required size.
@@ -1799,7 +1801,10 @@ HiiGetLanguages (
HII_STRING_PACKAGE_INSTANCE *StringPackage;
UINTN ResultSize;
- if (This == NULL || Languages == NULL || LanguagesSize == NULL || PackageList == NULL) {
+ if (This == NULL || LanguagesSize == NULL || PackageList == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if (*LanguagesSize != 0 && Languages == NULL) {
return EFI_INVALID_PARAMETER;
}
if (!IsHiiHandleValid (PackageList)) {
@@ -1871,15 +1876,16 @@ HiiGetLanguages (
points to the length of SecondaryLanguages in bytes.
@retval EFI_SUCCESS Secondary languages were correctly returned.
- @retval EFI_INVALID_PARAMETER PrimaryLanguage or SecondaryLanguages or
- SecondaryLanguagesSize was NULL.
+ @retval EFI_INVALID_PARAMETER PrimaryLanguage or SecondaryLanguagesSize was NULL.
+ @retval EFI_INVALID_PARAMETER The value referenced by SecondaryLanguagesSize is not
+ zero and SecondaryLanguages is NULL.
@retval EFI_BUFFER_TOO_SMALL The buffer specified by SecondaryLanguagesSize is
too small to hold the returned information.
SecondaryLanguageSize is updated to hold the size of
the buffer required.
@retval EFI_INVALID_LANGUAGE The language specified by PrimaryLanguage is not
present in the specified package list.
- @retval EFI_NOT_FOUND The specified PackageList is not in the Database.
+ @retval EFI_NOT_FOUND The specified PackageList is not in the Database.
**/
EFI_STATUS
@@ -1901,10 +1907,10 @@ HiiGetSecondaryLanguages (
CHAR8 *Languages;
UINTN ResultSize;
- if (This == NULL || PackageList == NULL || PrimaryLanguage == NULL) {
+ if (This == NULL || PackageList == NULL || PrimaryLanguage == NULL || SecondaryLanguagesSize == NULL) {
return EFI_INVALID_PARAMETER;
}
- if (SecondaryLanguages == NULL || SecondaryLanguagesSize == NULL) {
+ if (SecondaryLanguages == NULL && *SecondaryLanguagesSize != 0) {
return EFI_INVALID_PARAMETER;
}
if (!IsHiiHandleValid (PackageList)) {
diff --git a/MdeModulePkg/Universal/Network/IScsiDxe/IScsiProto.c b/MdeModulePkg/Universal/Network/IScsiDxe/IScsiProto.c
index aff036bb7..5a6002e83 100644
--- a/MdeModulePkg/Universal/Network/IScsiDxe/IScsiProto.c
+++ b/MdeModulePkg/Universal/Network/IScsiDxe/IScsiProto.c
@@ -742,7 +742,7 @@ IScsiProcessLoginRsp (
NetbufQueAppend (&Conn->RspQue, Pdu);
Conn->PartialRspRcvd = Continue;
- if ((!Transit) || Continue) {
+ if (Continue) {
//
// It's a partial response, have to wait for another or more Request/Response
// conversations to get the full response.
diff --git a/MdeModulePkg/Universal/Network/SnpDxe/Snp.c b/MdeModulePkg/Universal/Network/SnpDxe/Snp.c
index 177d0a913..ed583b488 100644
--- a/MdeModulePkg/Universal/Network/SnpDxe/Snp.c
+++ b/MdeModulePkg/Universal/Network/SnpDxe/Snp.c
@@ -410,8 +410,13 @@ SimpleNetworkDriverStart (
Snp->TxRxBufferSize = 0;
Snp->TxRxBuffer = NULL;
+
+ if (Nii->Revision >= EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_REVISION) {
+ Snp->IfNum = Nii->IfNum;
- Snp->IfNum = Nii->IfNum;
+ } else {
+ Snp->IfNum = (UINT8) (Nii->IfNum & 0xFF);
+ }
if ((Pxe->hw.Implementation & PXE_ROMID_IMP_HW_UNDI) != 0) {
Snp->IsSwUndi = FALSE;
diff --git a/MdeModulePkg/Universal/PlatformDriOverrideDxe/InternalPlatDriOverrideDxe.h b/MdeModulePkg/Universal/PlatformDriOverrideDxe/InternalPlatDriOverrideDxe.h
index 60113fee1..75af76352 100644
--- a/MdeModulePkg/Universal/PlatformDriOverrideDxe/InternalPlatDriOverrideDxe.h
+++ b/MdeModulePkg/Universal/PlatformDriOverrideDxe/InternalPlatDriOverrideDxe.h
@@ -2,7 +2,7 @@
Ihe internal heder file includes the required Protocol/Guid/Library
and the shared function APIs.
-Copyright (c) 2007 - 2009, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2007 - 2013, Intel Corporation. All rights reserved.<BR>
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
@@ -29,7 +29,6 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include <Protocol/ComponentName2.h>
#include <Protocol/ComponentName.h>
#include <Protocol/DriverBinding.h>
-#include <Protocol/DevicePathToText.h>
#include <Protocol/DevicePath.h>
#include <Protocol/PlatformDriverOverride.h>
#include <Guid/MdeModuleHii.h>
diff --git a/MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatDriOverrideDxe.c b/MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatDriOverrideDxe.c
index 9c0064df2..ab254a0b4 100644
--- a/MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatDriOverrideDxe.c
+++ b/MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatDriOverrideDxe.c
@@ -13,7 +13,7 @@
4. It save all the mapping info in NV variables which will be consumed
by platform override protocol driver to publish the platform override protocol.
-Copyright (c) 2007 - 2012, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2007 - 2013, Intel Corporation. All rights reserved.<BR>
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
@@ -104,45 +104,29 @@ HII_VENDOR_DEVICE_PATH mHiiVendorDevicePath = {
};
/**
- Converting a given device to an unicode string.
-
- This function will dependent on gEfiDevicePathToTextProtocolGuid, if protocol
- does not installed, then return unknown device path L"?" directly.
-
+ Converting a given device to an unicode string.
+
@param DevPath Given device path instance
@return Converted string from given device path.
- @retval L"?" Can not locate gEfiDevicePathToTextProtocolGuid protocol for converting.
+ @retval L"?" Converting failed.
**/
CHAR16 *
DevicePathToStr (
IN EFI_DEVICE_PATH_PROTOCOL *DevPath
)
{
- EFI_STATUS Status;
- EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *DevPathToText;
- CHAR16 *ToText;
-
- if (DevPath == NULL) {
- return L"";
- }
-
- Status = gBS->LocateProtocol (
- &gEfiDevicePathToTextProtocolGuid,
- NULL,
- (VOID **) &DevPathToText
- );
- if (!EFI_ERROR (Status)) {
- ToText = DevPathToText->ConvertDevicePathToText (
- DevPath,
- FALSE,
- TRUE
- );
- ASSERT (ToText != NULL);
- return ToText;
+ CHAR16 *Text;
+ Text = ConvertDevicePathToText (
+ DevPath,
+ FALSE,
+ TRUE
+ );
+ if (Text == NULL) {
+ return AllocateCopyPool (sizeof (L"?"), L"?");
+ } else {
+ return Text;
}
-
- return L"?";
}
/**
diff --git a/MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatformDriOverrideDxe.inf b/MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatformDriOverrideDxe.inf
index bf333d29d..9702f249b 100644
--- a/MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatformDriOverrideDxe.inf
+++ b/MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatformDriOverrideDxe.inf
@@ -16,7 +16,7 @@
# 4. It save all the mapping info in NV variables for the following boot,
# which will be consumed by GetDriver API of the produced the platform override protocol.
#
-# Copyright (c) 2007 - 2011, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2007 - 2013, Intel Corporation. All rights reserved.<BR>
#
# This program and the accompanying materials
# are licensed and made available under the terms and conditions of the BSD License
@@ -95,7 +95,6 @@
gEfiFormBrowser2ProtocolGuid ## CONSUMED
gEfiHiiConfigRoutingProtocolGuid ## CONSUMED
gEfiHiiConfigAccessProtocolGuid ## PRODUCED
- gEfiDevicePathToTextProtocolGuid ## CONSUMED
gEfiPlatformDriverOverrideProtocolGuid ## PRODUCED
[Depex]
diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/Expression.c b/MdeModulePkg/Universal/SetupBrowserDxe/Expression.c
index 29de50341..44dae1ba0 100644
--- a/MdeModulePkg/Universal/SetupBrowserDxe/Expression.c
+++ b/MdeModulePkg/Universal/SetupBrowserDxe/Expression.c
@@ -787,7 +787,7 @@ FORM_BROWSER_FORM *
IdToForm (
IN FORM_BROWSER_FORMSET *FormSet,
IN UINT16 FormId
-)
+ )
{
LIST_ENTRY *Link;
FORM_BROWSER_FORM *Form;
@@ -1511,7 +1511,7 @@ IfrMid (
Result->BufferLen = (UINT16)((BufferLen - Base) < Length ? (BufferLen - Base) : Length);
Result->Buffer = AllocateZeroPool (Result->BufferLen);
ASSERT (Result->Buffer != NULL);
- CopyMem (Result->Buffer, &Buffer[Base], Result->BufferLen);
+ CopyMem (Result->Buffer, &Value[2].Buffer[Base], Result->BufferLen);
}
FreePool (Value[2].Buffer);
@@ -2105,7 +2105,7 @@ GetQuestionValueFromForm (
//
FormSet = AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET));
ASSERT (FormSet != NULL);
- Status = InitializeFormSet(HiiHandle, FormSetGuid, FormSet, FALSE);
+ Status = InitializeFormSet(HiiHandle, FormSetGuid, FormSet);
if (EFI_ERROR (Status)) {
GetTheVal = FALSE;
goto Done;
@@ -2800,7 +2800,7 @@ EvaluateExpression (
for (Index = 0; Index < OpCode->ValueWidth; Index ++, TempBuffer --) {
StrPtr += UnicodeValueToString (StrPtr, PREFIX_ZERO | RADIX_HEX, *TempBuffer, 2);
}
- Status = SetValueByName (OpCode->VarStorage, OpCode->ValueName, NameValue, GetSetValueWithEditBuffer);
+ Status = SetValueByName (OpCode->VarStorage, OpCode->ValueName, NameValue, GetSetValueWithEditBuffer, NULL);
FreePool (NameValue);
if (!EFI_ERROR (Status)) {
Data1.Value.b = TRUE;
diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/Expression.h b/MdeModulePkg/Universal/SetupBrowserDxe/Expression.h
new file mode 100644
index 000000000..5660a997b
--- /dev/null
+++ b/MdeModulePkg/Universal/SetupBrowserDxe/Expression.h
@@ -0,0 +1,265 @@
+/** @file
+Private structure, MACRO and function definitions for User Interface related functionalities.
+
+Copyright (c) 2004 - 2013, Intel Corporation. All rights reserved.<BR>
+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 _EXPRESSION_H_
+#define _EXPRESSION_H_
+
+/**
+ Get the expression list count.
+
+ @param Level Which type this expression belong to. Form,
+ statement or option?
+
+ @retval >=0 The expression count
+ @retval -1 Input parameter error.
+
+**/
+INTN
+GetConditionalExpressionCount (
+ IN EXPRESS_LEVEL Level
+ );
+
+/**
+ Reset stack pointer to begin of the stack.
+
+**/
+VOID
+ResetCurrentExpressionStack (
+ VOID
+ );
+
+/**
+ Reset stack pointer to begin of the stack.
+
+**/
+VOID
+ResetMapExpressionListStack (
+ VOID
+ );
+
+/**
+ Reset stack pointer to begin of the stack.
+
+**/
+VOID
+ResetScopeStack (
+ VOID
+ );
+
+/**
+ Push an Operand onto the Stack
+
+ @param Operand Operand to push.
+
+ @retval EFI_SUCCESS The value was pushed onto the stack.
+ @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the
+ stack.
+
+**/
+EFI_STATUS
+PushScope (
+ IN UINT8 Operand
+ );
+
+/**
+ Get the expression Buffer pointer.
+
+ @param Level Which type this expression belong to. Form,
+ statement or option?
+
+ @retval The start pointer of the expression buffer or NULL.
+
+**/
+FORM_EXPRESSION **
+GetConditionalExpressionList (
+ IN EXPRESS_LEVEL Level
+ );
+
+/**
+ Pop an Operand from the Stack
+
+ @param Operand Operand to pop.
+
+ @retval EFI_SUCCESS The value was pushed onto the stack.
+ @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the
+ stack.
+
+**/
+EFI_STATUS
+PopScope (
+ OUT UINT8 *Operand
+ );
+
+/**
+ Push the list of map expression onto the Stack
+
+ @param Pointer Pointer to the list of map expression to be pushed.
+
+ @retval EFI_SUCCESS The value was pushed onto the stack.
+ @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.
+
+**/
+EFI_STATUS
+PushMapExpressionList (
+ IN VOID *Pointer
+ );
+
+/**
+ Push current expression onto the Stack
+
+ @param Pointer Pointer to current expression.
+
+ @retval EFI_SUCCESS The value was pushed onto the stack.
+ @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.
+
+**/
+EFI_STATUS
+PushCurrentExpression (
+ IN VOID *Pointer
+ );
+
+/**
+ Zero extend integer/boolean/date/time to UINT64 for comparing.
+
+ @param Value HII Value to be converted.
+
+**/
+VOID
+ExtendValueToU64 (
+ IN EFI_HII_VALUE *Value
+ );
+
+/**
+ Push the expression options onto the Stack.
+
+ @param Pointer Pointer to the current expression.
+ @param Level Which type this expression belong to. Form,
+ statement or option?
+
+ @retval EFI_SUCCESS The value was pushed onto the stack.
+ @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.
+
+**/
+EFI_STATUS
+PushConditionalExpression (
+ IN FORM_EXPRESSION *Pointer,
+ IN EXPRESS_LEVEL Level
+ );
+
+/**
+ Pop the expression options from the Stack
+
+ @param Level Which type this expression belong to. Form,
+ statement or option?
+
+ @retval EFI_SUCCESS The value was pushed onto the stack.
+ @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.
+
+**/
+EFI_STATUS
+PopConditionalExpression (
+ IN EXPRESS_LEVEL Level
+ );
+
+/**
+ Pop the list of map expression from the Stack
+
+ @param Pointer Pointer to the list of map expression to be pop.
+
+ @retval EFI_SUCCESS The value was pushed onto the stack.
+ @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.
+
+**/
+EFI_STATUS
+PopMapExpressionList (
+ OUT VOID **Pointer
+ );
+
+/**
+ Pop current expression from the Stack
+
+ @param Pointer Pointer to current expression to be pop.
+
+ @retval EFI_SUCCESS The value was pushed onto the stack.
+ @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.
+
+**/
+EFI_STATUS
+PopCurrentExpression (
+ OUT VOID **Pointer
+ );
+
+/**
+ Evaluate the result of a HII expression.
+
+ If Expression is NULL, then ASSERT.
+
+ @param FormSet FormSet associated with this expression.
+ @param Form Form associated with this expression.
+ @param Expression Expression to be evaluated.
+
+ @retval EFI_SUCCESS The expression evaluated successfuly
+ @retval EFI_NOT_FOUND The Question which referenced by a QuestionId
+ could not be found.
+ @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the
+ stack.
+ @retval EFI_ACCESS_DENIED The pop operation underflowed the stack
+ @retval EFI_INVALID_PARAMETER Syntax error with the Expression
+
+**/
+EFI_STATUS
+EvaluateExpression (
+ IN FORM_BROWSER_FORMSET *FormSet,
+ IN FORM_BROWSER_FORM *Form,
+ IN OUT FORM_EXPRESSION *Expression
+ );
+/**
+ Return the result of the expression list. Check the expression list and
+ return the highest priority express result.
+ Priority: DisableIf > SuppressIf > GrayOutIf > FALSE
+
+ @param ExpList The input expression list.
+ @param Evaluate Whether need to evaluate the expression first.
+ @param FormSet FormSet associated with this expression.
+ @param Form Form associated with this expression.
+
+ @retval EXPRESS_RESULT Return the higher priority express result.
+ DisableIf > SuppressIf > GrayOutIf > FALSE
+
+**/
+EXPRESS_RESULT
+EvaluateExpressionList (
+ IN FORM_EXPRESSION_LIST *ExpList,
+ IN BOOLEAN Evaluate,
+ IN FORM_BROWSER_FORMSET *FormSet, OPTIONAL
+ IN FORM_BROWSER_FORM *Form OPTIONAL
+ );
+
+/**
+ Get Form given its FormId.
+
+ @param FormSet The formset which contains this form.
+ @param FormId Id of this form.
+
+ @retval Pointer The form.
+ @retval NULL Specified Form is not found in the formset.
+
+**/
+FORM_BROWSER_FORM *
+IdToForm (
+ IN FORM_BROWSER_FORMSET *FormSet,
+ IN UINT16 FormId
+ );
+
+#endif // _EXPRESSION_H
diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/IfrParse.c b/MdeModulePkg/Universal/SetupBrowserDxe/IfrParse.c
index 2464aebd0..ac7dce694 100644
--- a/MdeModulePkg/Universal/SetupBrowserDxe/IfrParse.c
+++ b/MdeModulePkg/Universal/SetupBrowserDxe/IfrParse.c
@@ -16,7 +16,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
UINT16 mStatementIndex;
UINT16 mExpressionOpCodeIndex;
-
+EFI_QUESTION_ID mUsedQuestionId;
BOOLEAN mInScopeSubtitle;
extern LIST_ENTRY gBrowserStorageList;
/**
@@ -42,9 +42,9 @@ CreateStatement (
if (Form == NULL) {
//
- // We are currently not in a Form Scope, so just skip this Statement
+ // Only guid op may out side the form level.
//
- return NULL;
+ ASSERT (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_GUID_OP);
}
Statement = &FormSet->StatementBuffer[mStatementIndex];
@@ -54,10 +54,12 @@ CreateStatement (
InitializeListHead (&Statement->OptionListHead);
InitializeListHead (&Statement->InconsistentListHead);
InitializeListHead (&Statement->NoSubmitListHead);
+ InitializeListHead (&Statement->WarningListHead);
Statement->Signature = FORM_BROWSER_STATEMENT_SIGNATURE;
Statement->Operand = ((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode;
+ Statement->OpCode = (EFI_IFR_OP_HEADER *) OpCodeData;
StatementHdr = (EFI_IFR_STATEMENT_HEADER *) (OpCodeData + sizeof (EFI_IFR_OP_HEADER));
CopyMem (&Statement->Prompt, &StatementHdr->Prompt, sizeof (EFI_STRING_ID));
@@ -82,8 +84,11 @@ CreateStatement (
//
// Insert this Statement into current Form
//
- InsertTailList (&Form->StatementListHead, &Statement->Link);
-
+ if (Form == NULL) {
+ InsertTailList (&FormSet->StatementListOSF, &Statement->Link);
+ } else {
+ InsertTailList (&Form->StatementListHead, &Statement->Link);
+ }
return Statement;
}
@@ -812,6 +817,17 @@ DestroyStatement (
DestroyExpression (Expression);
}
+ //
+ // Free WarningIf List
+ //
+ while (!IsListEmpty (&Statement->WarningListHead)) {
+ Link = GetFirstNode (&Statement->WarningListHead);
+ Expression = FORM_EXPRESSION_FROM_LINK (Link);
+ RemoveEntryList (&Expression->Link);
+
+ DestroyExpression (Expression);
+ }
+
if (Statement->Expression != NULL) {
FreePool (Statement->Expression);
}
@@ -1133,6 +1149,7 @@ ParseOpCodes (
CountOpCodes (FormSet, &NumberOfStatement, &NumberOfExpression);
mStatementIndex = 0;
+ mUsedQuestionId = 1;
FormSet->StatementBuffer = AllocateZeroPool (NumberOfStatement * sizeof (FORM_BROWSER_STATEMENT));
if (FormSet->StatementBuffer == NULL) {
return EFI_OUT_OF_RESOURCES;
@@ -1144,6 +1161,7 @@ ParseOpCodes (
return EFI_OUT_OF_RESOURCES;
}
+ InitializeListHead (&FormSet->StatementListOSF);
InitializeListHead (&FormSet->StorageListHead);
InitializeListHead (&FormSet->DefaultStoreListHead);
InitializeListHead (&FormSet->FormListHead);
@@ -1502,7 +1520,6 @@ ParseOpCodes (
InitializeListHead (&CurrentForm->ConfigRequestHead);
CurrentForm->FormType = STANDARD_MAP_FORM_TYPE;
- CurrentForm->NvUpdateRequired = FALSE;
CopyMem (&CurrentForm->FormId, &((EFI_IFR_FORM *) OpCodeData)->FormId, sizeof (UINT16));
CopyMem (&CurrentForm->FormTitle, &((EFI_IFR_FORM *) OpCodeData)->FormTitle, sizeof (EFI_STRING_ID));
@@ -1539,7 +1556,6 @@ ParseOpCodes (
CurrentForm = AllocateZeroPool (sizeof (FORM_BROWSER_FORM));
ASSERT (CurrentForm != NULL);
CurrentForm->Signature = FORM_BROWSER_FORM_SIGNATURE;
- CurrentForm->NvUpdateRequired = FALSE;
InitializeListHead (&CurrentForm->ExpressionListHead);
InitializeListHead (&CurrentForm->StatementListHead);
InitializeListHead (&CurrentForm->ConfigRequestHead);
@@ -1621,8 +1637,14 @@ ParseOpCodes (
// Create a EFI variable Storage for this FormSet
//
if (OpCodeLength < sizeof (EFI_IFR_VARSTORE_EFI)) {
+ //
+ // Create efi varstore with format follow UEFI spec before 2.3.1.
+ //
Storage = CreateStorage (FormSet, EFI_HII_VARSTORE_EFI_VARIABLE, OpCodeData);
} else {
+ //
+ // Create efi varstore with format follow UEFI spec 2.3.1 and later.
+ //
Storage = CreateStorage (FormSet, EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER, OpCodeData);
}
CopyMem (&Storage->VarStoreId, &((EFI_IFR_VARSTORE_EFI *) OpCodeData)->VarStoreId, sizeof (EFI_VARSTORE_ID));
@@ -1653,7 +1675,7 @@ ParseOpCodes (
ASSERT (CurrentStatement != NULL);
CurrentStatement->Flags = ((EFI_IFR_SUBTITLE *) OpCodeData)->Flags;
-
+ CurrentStatement->FakeQuestionId = mUsedQuestionId++;
if (Scope != 0) {
mInScopeSubtitle = TRUE;
}
@@ -1662,13 +1684,14 @@ ParseOpCodes (
case EFI_IFR_TEXT_OP:
CurrentStatement = CreateStatement (OpCodeData, FormSet, CurrentForm);
ASSERT (CurrentStatement != NULL);
-
+ CurrentStatement->FakeQuestionId = mUsedQuestionId++;
CopyMem (&CurrentStatement->TextTwo, &((EFI_IFR_TEXT *) OpCodeData)->TextTwo, sizeof (EFI_STRING_ID));
break;
case EFI_IFR_RESET_BUTTON_OP:
CurrentStatement = CreateStatement (OpCodeData, FormSet, CurrentForm);
ASSERT (CurrentStatement != NULL);
+ CurrentStatement->FakeQuestionId = mUsedQuestionId++;
CopyMem (&CurrentStatement->DefaultId, &((EFI_IFR_RESET_BUTTON *) OpCodeData)->DefaultId, sizeof (EFI_DEFAULT_ID));
break;
@@ -1913,6 +1936,7 @@ ParseOpCodes (
CurrentOption = AllocateZeroPool (sizeof (QUESTION_OPTION));
ASSERT (CurrentOption != NULL);
CurrentOption->Signature = QUESTION_OPTION_SIGNATURE;
+ CurrentOption->OpCode = (EFI_IFR_ONE_OF_OPTION *) OpCodeData;
CurrentOption->Flags = ((EFI_IFR_ONE_OF_OPTION *) OpCodeData)->Flags;
CurrentOption->Value.Type = ((EFI_IFR_ONE_OF_OPTION *) OpCodeData)->Type;
@@ -2008,6 +2032,25 @@ ParseOpCodes (
}
break;
+ case EFI_IFR_WARNING_IF_OP:
+ //
+ // Create an Expression node
+ //
+ CurrentExpression = CreateExpression (CurrentForm);
+ CopyMem (&CurrentExpression->Error, &((EFI_IFR_WARNING_IF *) OpCodeData)->Warning, sizeof (EFI_STRING_ID));
+ CurrentExpression->TimeOut = ((EFI_IFR_WARNING_IF *) OpCodeData)->TimeOut;
+ CurrentExpression->Type = EFI_HII_EXPRESSION_WARNING_IF;
+ InsertTailList (&CurrentStatement->WarningListHead, &CurrentExpression->Link);
+
+ //
+ // Take a look at next OpCode to see whether current expression consists
+ // of single OpCode
+ //
+ if (((EFI_IFR_OP_HEADER *) (OpCodeData + OpCodeLength))->Scope == 0) {
+ SingleOpCodeExpression = TRUE;
+ }
+ break;
+
case EFI_IFR_SUPPRESS_IF_OP:
//
// Question and Option will appear in scope of this OpCode
@@ -2270,45 +2313,8 @@ ParseOpCodes (
//
// Vendor specific
//
- case EFI_IFR_GUID_OP:
- if (CompareGuid (&gEfiIfrTianoGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)))) {
- //
- // Tiano specific GUIDed opcodes
- //
- switch (((EFI_IFR_GUID_LABEL *) OpCodeData)->ExtendOpCode) {
- case EFI_IFR_EXTEND_OP_LABEL:
- //
- // just ignore label
- //
- break;
-
- case EFI_IFR_EXTEND_OP_BANNER:
- //
- // By SubClass to get Banner Data from Front Page
- //
- if (FormSet->SubClass == EFI_FRONT_PAGE_SUBCLASS) {
- CopyMem (
- &gBannerData->Banner[((EFI_IFR_GUID_BANNER *) OpCodeData)->LineNumber][
- ((EFI_IFR_GUID_BANNER *) OpCodeData)->Alignment],
- &((EFI_IFR_GUID_BANNER *) OpCodeData)->Title,
- sizeof (EFI_STRING_ID)
- );
- }
- break;
-
- case EFI_IFR_EXTEND_OP_CLASS:
- CopyMem (&FormSet->Class, &((EFI_IFR_GUID_CLASS *) OpCodeData)->Class, sizeof (UINT16));
- break;
-
- case EFI_IFR_EXTEND_OP_SUBCLASS:
- CopyMem (&FormSet->SubClass, &((EFI_IFR_GUID_SUBCLASS *) OpCodeData)->SubClass, sizeof (UINT16));
- break;
-
- default:
- break;
- }
- }
-
+ case EFI_IFR_GUID_OP:
+ CurrentStatement = CreateStatement (OpCodeData, FormSet, CurrentForm);
break;
//
@@ -2352,6 +2358,7 @@ ParseOpCodes (
case EFI_IFR_NO_SUBMIT_IF_OP:
case EFI_IFR_INCONSISTENT_IF_OP:
+ case EFI_IFR_WARNING_IF_OP:
//
// Ignore end of EFI_IFR_NO_SUBMIT_IF and EFI_IFR_INCONSISTENT_IF
//
diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/Presentation.c b/MdeModulePkg/Universal/SetupBrowserDxe/Presentation.c
index c3854aac2..a5caf4426 100644
--- a/MdeModulePkg/Universal/SetupBrowserDxe/Presentation.c
+++ b/MdeModulePkg/Universal/SetupBrowserDxe/Presentation.c
@@ -19,863 +19,1696 @@ UI_MENU_SELECTION *gCurrentSelection;
EFI_HII_HANDLE mCurrentHiiHandle = NULL;
EFI_GUID mCurrentFormSetGuid = {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}};
UINT16 mCurrentFormId = 0;
+EFI_EVENT mValueChangedEvent = NULL;
+LIST_ENTRY mRefreshEventList = INITIALIZE_LIST_HEAD_VARIABLE (mRefreshEventList);
+UINT32 gBrowserStatus = BROWSER_SUCCESS;
+CHAR16 *gErrorInfo;
+UINT16 mCurFakeQestId;
+FORM_DISPLAY_ENGINE_FORM gDisplayFormData;
/**
- Clear retangle with specified text attribute.
+ Evaluate all expressions in a Form.
+
+ @param FormSet FormSet this Form belongs to.
+ @param Form The Form.
- @param LeftColumn Left column of retangle.
- @param RightColumn Right column of retangle.
- @param TopRow Start row of retangle.
- @param BottomRow End row of retangle.
- @param TextAttribute The character foreground and background.
+ @retval EFI_SUCCESS The expression evaluated successfuly
+
+**/
+EFI_STATUS
+EvaluateFormExpressions (
+ IN FORM_BROWSER_FORMSET *FormSet,
+ IN FORM_BROWSER_FORM *Form
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Link;
+ FORM_EXPRESSION *Expression;
+
+ Link = GetFirstNode (&Form->ExpressionListHead);
+ while (!IsNull (&Form->ExpressionListHead, Link)) {
+ Expression = FORM_EXPRESSION_FROM_LINK (Link);
+ Link = GetNextNode (&Form->ExpressionListHead, Link);
+
+ if (Expression->Type == EFI_HII_EXPRESSION_INCONSISTENT_IF ||
+ Expression->Type == EFI_HII_EXPRESSION_NO_SUBMIT_IF ||
+ Expression->Type == EFI_HII_EXPRESSION_WARNING_IF ||
+ Expression->Type == EFI_HII_EXPRESSION_WRITE ||
+ (Expression->Type == EFI_HII_EXPRESSION_READ && Form->FormType != STANDARD_MAP_FORM_TYPE)) {
+ //
+ // Postpone Form validation to Question editing or Form submitting or Question Write or Question Read for nonstandard form.
+ //
+ continue;
+ }
+
+ Status = EvaluateExpression (FormSet, Form, Expression);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Add empty function for event process function.
+
+ @param Event The Event need to be process
+ @param Context The context of the event.
**/
VOID
-ClearLines (
- IN UINTN LeftColumn,
- IN UINTN RightColumn,
- IN UINTN TopRow,
- IN UINTN BottomRow,
- IN UINTN TextAttribute
+EFIAPI
+SetupBrowserEmptyFunction (
+ IN EFI_EVENT Event,
+ IN VOID *Context
)
{
- CHAR16 *Buffer;
- UINTN Row;
+}
- //
- // For now, allocate an arbitrarily long buffer
- //
- Buffer = AllocateZeroPool (0x10000);
- ASSERT (Buffer != NULL);
+/**
+ Base on the opcode buffer info to get the display statement.
- //
- // Set foreground and background as defined
- //
- gST->ConOut->SetAttribute (gST->ConOut, TextAttribute);
+ @param OpCode The input opcode buffer for this statement.
+
+ @retval Statement The statement use this opcode buffer.
- //
- // Much faster to buffer the long string instead of print it a character at a time
- //
- SetUnicodeMem (Buffer, RightColumn - LeftColumn, L' ');
+**/
+FORM_DISPLAY_ENGINE_STATEMENT *
+GetDisplayStatement (
+ IN EFI_IFR_OP_HEADER *OpCode
+ )
+{
+ FORM_DISPLAY_ENGINE_STATEMENT *DisplayStatement;
+ LIST_ENTRY *Link;
- //
- // Clear the desired area with the appropriate foreground/background
- //
- for (Row = TopRow; Row <= BottomRow; Row++) {
- PrintStringAt (LeftColumn, Row, Buffer);
+ Link = GetFirstNode (&gDisplayFormData.StatementListHead);
+ while (!IsNull (&gDisplayFormData.StatementListHead, Link)) {
+ DisplayStatement = FORM_DISPLAY_ENGINE_STATEMENT_FROM_LINK (Link);
+
+ if (DisplayStatement->OpCode == OpCode) {
+ return DisplayStatement;
+ }
+ Link = GetNextNode (&gDisplayFormData.StatementListHead, Link);
}
- gST->ConOut->SetCursorPosition (gST->ConOut, LeftColumn, TopRow);
+ return NULL;
+}
+
+/**
+ Free the refresh event list.
+
+**/
+VOID
+FreeRefreshEvent (
+ VOID
+ )
+{
+ LIST_ENTRY *Link;
+ FORM_BROWSER_REFRESH_EVENT_NODE *EventNode;
- FreePool (Buffer);
- return ;
+ while (!IsListEmpty (&mRefreshEventList)) {
+ Link = GetFirstNode (&mRefreshEventList);
+ EventNode = FORM_BROWSER_REFRESH_EVENT_FROM_LINK (Link);
+ RemoveEntryList (&EventNode->Link);
+
+ gBS->CloseEvent (EventNode->RefreshEvent);
+
+ FreePool (EventNode);
+ }
}
/**
- Concatenate a narrow string to another string.
+ Check whether this statement value is changed. If yes, update the statement value and return TRUE;
+ else return FALSE.
- @param Destination The destination string.
- @param Source The source string. The string to be concatenated.
- to the end of Destination.
+ @param Statement The statement need to check.
**/
VOID
-NewStrCat (
- IN OUT CHAR16 *Destination,
- IN CHAR16 *Source
+UpdateStatement (
+ IN OUT FORM_BROWSER_STATEMENT *Statement
)
{
- UINTN Length;
-
- for (Length = 0; Destination[Length] != 0; Length++)
- ;
+ GetQuestionValue (gCurrentSelection->FormSet, gCurrentSelection->Form, Statement, GetSetValueWithHiiDriver);
//
- // 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
+ // Reset FormPackage update flag
//
- Destination[Length] = NARROW_CHAR;
- Length++;
+ mHiiPackageListUpdated = FALSE;
- StrCpy (Destination + Length, Source);
+ //
+ // Question value may be changed, need invoke its Callback()
+ //
+ ProcessCallBackFunction (gCurrentSelection, Statement, EFI_BROWSER_ACTION_CHANGING, FALSE);
+
+ if (mHiiPackageListUpdated) {
+ //
+ // Package list is updated, force to reparse IFR binary of target Formset
+ //
+ mHiiPackageListUpdated = FALSE;
+ gCurrentSelection->Action = UI_ACTION_REFRESH_FORMSET;
+ }
}
/**
- Count the storage space of a Unicode string.
+ Refresh the question which has refresh guid event attribute.
+
+ @param Event The event which has this function related.
+ @param Context The input context info related to this event or the status code return to the caller.
+**/
+VOID
+EFIAPI
+RefreshEventNotify(
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ FORM_BROWSER_STATEMENT *Statement;
+
+ Statement = (FORM_BROWSER_STATEMENT *)Context;
+ UpdateStatement(Statement);
+ gBS->SignalEvent (mValueChangedEvent);
+}
+
- This function handles the Unicode string with NARROW_CHAR
- and WIDE_CHAR control characters. NARROW_HCAR and WIDE_CHAR
- does not count in the resultant output. If a WIDE_CHAR is
- hit, then 2 Unicode character will consume an output storage
- space with size of CHAR16 till a NARROW_CHAR is hit.
+/**
+ Create refresh hook event for statement which has refresh event or interval.
- If String is NULL, then ASSERT ().
+ @param Statement The statement need to check.
- @param String The input string to be counted.
+**/
+VOID
+CreateRefreshEvent (
+ IN FORM_BROWSER_STATEMENT *Statement
+ )
+{
+ EFI_STATUS Status;
+ EFI_EVENT RefreshEvent;
+ FORM_BROWSER_REFRESH_EVENT_NODE *EventNode;
- @return Storage space for the input string.
+ //
+ // If question has refresh guid, create the notify function.
+ //
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_CALLBACK,
+ RefreshEventNotify,
+ Statement,
+ &Statement->RefreshGuid,
+ &RefreshEvent);
+ ASSERT_EFI_ERROR (Status);
+
+ EventNode = AllocateZeroPool (sizeof (FORM_BROWSER_REFRESH_EVENT_NODE));
+ ASSERT (EventNode != NULL);
+ EventNode->RefreshEvent = RefreshEvent;
+ InsertTailList(&mRefreshEventList, &EventNode->Link);
+}
+/**
+ Perform value check for a question.
+
+ @param Question The question need to do check.
+ @param Type Condition type need to check.
+ @param ErrorInfo Return info about the error.
+
+ @retval The check result.
**/
-UINTN
-GetStringWidth (
- IN CHAR16 *String
+UINT32
+ConditionCheck (
+ IN FORM_BROWSER_STATEMENT *Question,
+ IN UINT8 Type,
+ OUT STATEMENT_ERROR_INFO *ErrorInfo
)
{
- UINTN Index;
- UINTN Count;
- UINTN IncrementValue;
+ EFI_STATUS Status;
+ LIST_ENTRY *Link;
+ FORM_EXPRESSION *Expression;
+ LIST_ENTRY *ListHead;
+ UINT32 RetVal;
+
+ RetVal = STATEMENT_VALID;
+ ListHead = NULL;
+
+ switch (Type) {
+ case EFI_HII_EXPRESSION_INCONSISTENT_IF:
+ ListHead = &Question->InconsistentListHead;
+ break;
- ASSERT (String != NULL);
- if (String == NULL) {
- return 0;
+ case EFI_HII_EXPRESSION_WARNING_IF:
+ ListHead = &Question->WarningListHead;
+ break;
+
+ default:
+ ASSERT (FALSE);
+ return RetVal;
}
- Index = 0;
- Count = 0;
- IncrementValue = 1;
+ ASSERT (ListHead != NULL);
+ Link = GetFirstNode (ListHead);
+ while (!IsNull (ListHead, Link)) {
+ Expression = FORM_EXPRESSION_FROM_LINK (Link);
+ Link = GetNextNode (ListHead, Link);
- do {
//
- // Advance to the null-terminator or to the first width directive
+ // Evaluate the expression
//
- for (;
- (String[Index] != NARROW_CHAR) && (String[Index] != WIDE_CHAR) && (String[Index] != 0);
- Index++, Count = Count + IncrementValue
- )
- ;
+ Status = EvaluateExpression (gCurrentSelection->FormSet, gCurrentSelection->Form, Expression);
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
- //
- // We hit the null-terminator, we now have a count
- //
- if (String[Index] == 0) {
+ if ((Expression->Result.Type == EFI_IFR_TYPE_BOOLEAN) && Expression->Result.Value.b) {
+ ErrorInfo->StringId = Expression->Error;
+ switch (Type) {
+ case EFI_HII_EXPRESSION_INCONSISTENT_IF:
+ ErrorInfo->TimeOut = 0;
+ RetVal = INCOSISTENT_IF_TRUE;
+ break;
+
+ case EFI_HII_EXPRESSION_WARNING_IF:
+ ErrorInfo->TimeOut = Expression->TimeOut;
+ RetVal = WARNING_IF_TRUE;
+ break;
+
+ default:
+ ASSERT (FALSE);
+ break;
+ }
break;
}
+ }
+
+ return RetVal;
+}
+
+/**
+ Perform value check for a question.
+
+ @param Form Form where Statement is in.
+ @param Statement Value will check for it.
+ @param InputValue New value will be checked.
+ @param ErrorInfo Return the error info for this check.
+
+ @retval TRUE Input Value is valid.
+ @retval FALSE Input Value is invalid.
+**/
+UINT32
+EFIAPI
+QuestionCheck (
+ IN FORM_DISPLAY_ENGINE_FORM *Form,
+ IN FORM_DISPLAY_ENGINE_STATEMENT *Statement,
+ IN EFI_HII_VALUE *InputValue,
+ OUT STATEMENT_ERROR_INFO *ErrorInfo
+ )
+{
+ FORM_BROWSER_STATEMENT *Question;
+ EFI_HII_VALUE BackUpValue;
+ UINT8 *BackUpBuffer;
+ UINT32 RetVal;
+
+ BackUpBuffer = NULL;
+ RetVal = STATEMENT_VALID;
+
+ ASSERT (Form != NULL && Statement != NULL && InputValue != NULL && ErrorInfo != NULL);
+
+ Question = GetBrowserStatement(Statement);
+ ASSERT (Question != NULL);
+
+ //
+ // Back up the quesion value.
+ //
+ switch (Question->Operand) {
+ case EFI_IFR_ORDERED_LIST_OP:
+ BackUpBuffer = AllocateCopyPool (Question->StorageWidth, Question->BufferValue);
+ ASSERT (BackUpBuffer != NULL);
+ CopyMem (Question->BufferValue, InputValue->Buffer, Question->StorageWidth);
+ break;
+
+ default:
+ CopyMem (&BackUpValue, &Question->HiiValue, sizeof (EFI_HII_VALUE));
+ CopyMem (&Question->HiiValue, InputValue, sizeof (EFI_HII_VALUE));
+ break;
+ }
+
+ //
+ // Do the inconsistentif check.
+ //
+ if (!IsListEmpty (&Question->InconsistentListHead)) {
+ RetVal = ConditionCheck(Question, EFI_HII_EXPRESSION_INCONSISTENT_IF, ErrorInfo);
+ }
+
+ //
+ // Do the warningif check.
+ //
+ if (RetVal == STATEMENT_VALID && !IsListEmpty (&Question->WarningListHead)) {
+ RetVal = ConditionCheck(Question, EFI_HII_EXPRESSION_WARNING_IF, ErrorInfo);
+ }
+
+ //
+ // Restore the quesion value.
+ //
+ switch (Question->Operand) {
+ case EFI_IFR_ORDERED_LIST_OP:
+ CopyMem (Question->BufferValue, BackUpBuffer, Question->StorageWidth);
+ break;
+
+ default:
+ CopyMem (&Question->HiiValue, &BackUpValue, sizeof (EFI_HII_VALUE));
+ break;
+ }
+
+ return RetVal;
+}
+
+/**
+
+ Initialize the Display statement structure data.
+
+ @param DisplayStatement Pointer to the display Statement data strucure.
+ @param Statement The statement need to check.
+ @param HostDisplayStatement Pointer to the display Statement data strucure which is an host statement.
+**/
+VOID
+InitializeDisplayStatement (
+ IN OUT FORM_DISPLAY_ENGINE_STATEMENT *DisplayStatement,
+ IN FORM_BROWSER_STATEMENT *Statement,
+ IN FORM_DISPLAY_ENGINE_STATEMENT *HostDisplayStatement
+ )
+{
+ LIST_ENTRY *Link;
+ QUESTION_OPTION *Option;
+ DISPLAY_QUESTION_OPTION *DisplayOption;
+
+ DisplayStatement->Signature = FORM_DISPLAY_ENGINE_STATEMENT_SIGNATURE;
+ DisplayStatement->Version = FORM_DISPLAY_ENGINE_STATEMENT_VERSION_1;
+ DisplayStatement->OpCode = Statement->OpCode;
+ InitializeListHead (&DisplayStatement->NestStatementList);
+ InitializeListHead (&DisplayStatement->OptionListHead);
+
+ if ((EvaluateExpressionList(Statement->Expression, FALSE, NULL, NULL) == ExpressGrayOut) || Statement->Locked) {
+ DisplayStatement->Attribute |= HII_DISPLAY_GRAYOUT;
+ }
+ if ((Statement->ValueExpression != NULL) || ((Statement->QuestionFlags & EFI_IFR_FLAG_READ_ONLY) != 0)) {
+ DisplayStatement->Attribute |= HII_DISPLAY_READONLY;
+ }
+
+ //
+ // Initilize the option list in statement.
+ //
+ Link = GetFirstNode (&Statement->OptionListHead);
+ while (!IsNull (&Statement->OptionListHead, Link)) {
+ Option = QUESTION_OPTION_FROM_LINK (Link);
+ Link = GetNextNode (&Statement->OptionListHead, Link);
+ if ((Option->SuppressExpression != NULL) &&
+ ((EvaluateExpressionList(Option->SuppressExpression, FALSE, NULL, NULL) == ExpressSuppress))) {
+ continue;
+ }
+
+ DisplayOption = AllocateZeroPool (sizeof (DISPLAY_QUESTION_OPTION));
+ ASSERT (DisplayOption != NULL);
+
+ DisplayOption->ImageId = Option->ImageId;
+ DisplayOption->Signature = DISPLAY_QUESTION_OPTION_SIGNATURE;
+ DisplayOption->OptionOpCode = Option->OpCode;
+ InsertTailList(&DisplayStatement->OptionListHead, &DisplayOption->Link);
+ }
+
+ CopyMem (&DisplayStatement->CurrentValue, &Statement->HiiValue, sizeof (EFI_HII_VALUE));
+
+ //
+ // Some special op code need an extra buffer to save the data.
+ // Such as string, password, orderedlist...
+ //
+ if (Statement->BufferValue != NULL) {
//
- // 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)
+ // Ordered list opcode may not initilized, get default value here.
//
- if (String[Index] == NARROW_CHAR) {
- //
- // Skip to the next character
- //
- Index++;
- IncrementValue = 1;
- } else {
- //
- // Skip to the next character
- //
- Index++;
- IncrementValue = 2;
+ if (Statement->OpCode->OpCode == EFI_IFR_ORDERED_LIST_OP && GetArrayData (Statement->BufferValue, Statement->ValueType, 0) == 0) {
+ GetQuestionDefault (gCurrentSelection->FormSet, gCurrentSelection->Form, Statement, 0);
}
- } while (String[Index] != 0);
+
+ DisplayStatement->CurrentValue.Buffer = AllocateCopyPool(Statement->StorageWidth,Statement->BufferValue);
+ DisplayStatement->CurrentValue.BufferLen = Statement->StorageWidth;
+ }
+
+ DisplayStatement->SettingChangedFlag = Statement->ValueChanged;
+
+ //
+ // Get the highlight statement for current form.
+ //
+ if (((gCurrentSelection->QuestionId != 0) && (Statement->QuestionId == gCurrentSelection->QuestionId)) ||
+ ((mCurFakeQestId != 0) && (Statement->FakeQuestionId == mCurFakeQestId))) {
+ gDisplayFormData.HighLightedStatement = DisplayStatement;
+ }
+
+ //
+ // Create the refresh event process function.
+ //
+ if (!CompareGuid (&Statement->RefreshGuid, &gZeroGuid)) {
+ CreateRefreshEvent (Statement);
+ }
+
+ //
+ // For RTC type of date/time, set default refresh interval to be 1 second.
+ //
+ if ((Statement->Operand == EFI_IFR_DATE_OP || Statement->Operand == EFI_IFR_TIME_OP) && Statement->Storage == NULL) {
+ Statement->RefreshInterval = 1;
+ }
+
+ //
+ // Create the refresh guid hook event.
+ // If the statement in this form has refresh event or refresh interval, browser will create this event for display engine.
+ //
+ if ((!CompareGuid (&Statement->RefreshGuid, &gZeroGuid)) || (Statement->RefreshInterval != 0)) {
+ gDisplayFormData.FormRefreshEvent = mValueChangedEvent;
+ }
//
- // Increment by one to include the null-terminator in the size
+ // Save the password check function for later use.
//
- Count++;
+ if (Statement->Operand == EFI_IFR_PASSWORD_OP) {
+ DisplayStatement->PasswordCheck = PasswordCheck;
+ }
+
+ //
+ // Save the validate check question for later use.
+ //
+ if (!IsListEmpty (&Statement->InconsistentListHead) || !IsListEmpty (&Statement->WarningListHead)) {
+ DisplayStatement->ValidateQuestion = QuestionCheck;
+ }
- return Count * sizeof (CHAR16);
+ //
+ // If this statement is nest in the subtitle, insert to the host statement.
+ // else insert to the form it belongs to.
+ //
+ if (Statement->InSubtitle) {
+ InsertTailList(&HostDisplayStatement->NestStatementList, &DisplayStatement->DisplayLink);
+ } else {
+ InsertTailList(&gDisplayFormData.StatementListHead, &DisplayStatement->DisplayLink);
+ }
}
/**
- This function displays the page frame.
+ Process for the refresh interval statement.
+
+ @param Event The Event need to be process
+ @param Context The context of the event.
- @param Selection Selection contains the information about
- the Selection, form and formset to be displayed.
- Selection action may be updated in retrieve callback.
**/
VOID
-DisplayPageFrame (
- IN UI_MENU_SELECTION *Selection
+EFIAPI
+RefreshIntervalProcess (
+ IN EFI_EVENT Event,
+ IN VOID *Context
)
{
- UINTN Index;
- UINT8 Line;
- UINT8 Alignment;
- CHAR16 Character;
- CHAR16 *Buffer;
- CHAR16 *StrFrontPageBanner;
- UINTN Row;
- EFI_SCREEN_DESCRIPTOR LocalScreen;
- UINT8 RowIdx;
- UINT8 ColumnIdx;
-
- 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);
-
- if (Selection->Form->ModalForm) {
- return;
+ FORM_BROWSER_STATEMENT *Statement;
+ LIST_ENTRY *Link;
+
+ Link = GetFirstNode (&gCurrentSelection->Form->StatementListHead);
+ while (!IsNull (&gCurrentSelection->Form->StatementListHead, Link)) {
+ Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link);
+ Link = GetNextNode (&gCurrentSelection->Form->StatementListHead, Link);
+
+ if (Statement->RefreshInterval == 0) {
+ continue;
+ }
+
+ UpdateStatement(Statement);
+ }
+
+ gBS->SignalEvent (mValueChangedEvent);
+}
+
+/**
+
+ Make a copy of the global hotkey info.
+
+**/
+VOID
+UpdateHotkeyList (
+ VOID
+ )
+{
+ BROWSER_HOT_KEY *HotKey;
+ BROWSER_HOT_KEY *CopyKey;
+ LIST_ENTRY *Link;
+
+ Link = GetFirstNode (&gBrowserHotKeyList);
+ while (!IsNull (&gBrowserHotKeyList, Link)) {
+ HotKey = BROWSER_HOT_KEY_FROM_LINK (Link);
+
+ CopyKey = AllocateCopyPool(sizeof (BROWSER_HOT_KEY), HotKey);
+ CopyKey->KeyData = AllocateCopyPool(sizeof (EFI_INPUT_KEY), HotKey->KeyData);
+ CopyKey->HelpString = AllocateCopyPool(StrSize (HotKey->HelpString), HotKey->HelpString);
+
+ InsertTailList(&gDisplayFormData.HotKeyListHead, &CopyKey->Link);
+
+ Link = GetNextNode (&gBrowserHotKeyList, Link);
}
+}
+
+/**
+
+ Enum all statement in current form, find all the statement can be display and
+ add to the display form.
- CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));
+**/
+VOID
+AddStatementToDisplayForm (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Link;
+ FORM_BROWSER_STATEMENT *Statement;
+ FORM_DISPLAY_ENGINE_STATEMENT *DisplayStatement;
+ FORM_DISPLAY_ENGINE_STATEMENT *HostDisplayStatement;
+ UINT8 MinRefreshInterval;
+ EFI_EVENT RefreshIntervalEvent;
+ FORM_BROWSER_REFRESH_EVENT_NODE *EventNode;
+ BOOLEAN FormEditable;
+
+ HostDisplayStatement = NULL;
+ MinRefreshInterval = 0;
+ FormEditable = FALSE;
//
- // For now, allocate an arbitrarily long buffer
+ // Process the statement outside the form, these statements are not recognized
+ // by browser core.
//
- Buffer = AllocateZeroPool (0x10000);
- ASSERT (Buffer != NULL);
+ Link = GetFirstNode (&gCurrentSelection->FormSet->StatementListOSF);
+ while (!IsNull (&gCurrentSelection->FormSet->StatementListOSF, Link)) {
+ Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link);
+ Link = GetNextNode (&gCurrentSelection->FormSet->StatementListOSF, Link);
+
+ DisplayStatement = AllocateZeroPool (sizeof (FORM_DISPLAY_ENGINE_STATEMENT));
+ ASSERT (DisplayStatement != NULL);
+ DisplayStatement->Signature = FORM_DISPLAY_ENGINE_STATEMENT_SIGNATURE;
+ DisplayStatement->Version = FORM_DISPLAY_ENGINE_STATEMENT_VERSION_1;
+ DisplayStatement->OpCode = Statement->OpCode;
- Character = BOXDRAW_HORIZONTAL;
+ InitializeListHead (&DisplayStatement->NestStatementList);
+ InitializeListHead (&DisplayStatement->OptionListHead);
- for (Index = 0; Index + 2 < (LocalScreen.RightColumn - LocalScreen.LeftColumn); Index++) {
- Buffer[Index] = Character;
+ InsertTailList(&gDisplayFormData.StatementListOSF, &DisplayStatement->DisplayLink);
}
- if ((gClassOfVfr & FORMSET_CLASS_FRONT_PAGE) == FORMSET_CLASS_FRONT_PAGE) {
+ //
+ // Process the statement in this form.
+ //
+ Link = GetFirstNode (&gCurrentSelection->Form->StatementListHead);
+ while (!IsNull (&gCurrentSelection->Form->StatementListHead, Link)) {
+ Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link);
+ Link = GetNextNode (&gCurrentSelection->Form->StatementListHead, Link);
+
//
- // ClearLines(0, LocalScreen.RightColumn, 0, BANNER_HEIGHT-1, BANNER_TEXT | BANNER_BACKGROUND);
+ // This statement can't be show, skip it.
//
- ClearLines (
- LocalScreen.LeftColumn,
- LocalScreen.RightColumn,
- LocalScreen.TopRow,
- FRONT_PAGE_HEADER_HEIGHT - 1 + LocalScreen.TopRow,
- BANNER_TEXT | BANNER_BACKGROUND
- );
+ if (EvaluateExpressionList(Statement->Expression, FALSE, NULL, NULL) > ExpressGrayOut) {
+ continue;
+ }
+
+ DisplayStatement = AllocateZeroPool (sizeof (FORM_DISPLAY_ENGINE_STATEMENT));
+ ASSERT (DisplayStatement != NULL);
+
//
- // for (Line = 0; Line < BANNER_HEIGHT; Line++) {
+ // Initialize this statement and add it to the display form.
//
- 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++
- ) {
- RowIdx = (UINT8) (Line - (UINT8) LocalScreen.TopRow);
- ColumnIdx = (UINT8) (Alignment - (UINT8) LocalScreen.LeftColumn);
-
- ASSERT (RowIdx < BANNER_HEIGHT);
- ASSERT (ColumnIdx < BANNER_COLUMNS);
-
- if (gBannerData->Banner[RowIdx][ColumnIdx] != 0x0000) {
- StrFrontPageBanner = GetToken (
- gBannerData->Banner[RowIdx][ColumnIdx],
- gFrontPageHandle
- );
- } else {
- continue;
- }
-
- switch (Alignment - LocalScreen.LeftColumn) {
- case 0:
- //
- // Handle left column
- //
- PrintStringAt (LocalScreen.LeftColumn + BANNER_LEFT_COLUMN_INDENT, Line, StrFrontPageBanner);
- break;
+ InitializeDisplayStatement(DisplayStatement, Statement, HostDisplayStatement);
- case 1:
- //
- // Handle center column
- //
- PrintStringAt (
- LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) / 3,
- Line,
- StrFrontPageBanner
- );
- break;
+ //
+ // Save the Host statement info.
+ // Host statement may has nest statement follow it.
+ //
+ if (!Statement->InSubtitle) {
+ HostDisplayStatement = DisplayStatement;
+ }
- case 2:
- //
- // Handle right column
- //
- PrintStringAt (
- LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) * 2 / 3,
- Line,
- StrFrontPageBanner
- );
- break;
- }
+ if (Statement->Storage != NULL) {
+ FormEditable = TRUE;
+ }
- FreePool (StrFrontPageBanner);
- }
+ //
+ // Get the minimal refresh interval value for later use.
+ //
+ if ((Statement->RefreshInterval != 0) &&
+ (MinRefreshInterval == 0 || Statement->RefreshInterval < MinRefreshInterval)) {
+ MinRefreshInterval = Statement->RefreshInterval;
}
}
- ClearLines (
- LocalScreen.LeftColumn,
- LocalScreen.RightColumn,
- LocalScreen.BottomRow - STATUS_BAR_HEIGHT - gFooterHeight,
- LocalScreen.BottomRow - STATUS_BAR_HEIGHT - 1,
- KEYHELP_TEXT | KEYHELP_BACKGROUND
- );
-
- if ((gClassOfVfr & FORMSET_CLASS_FRONT_PAGE) != FORMSET_CLASS_FRONT_PAGE) {
- ClearLines (
- LocalScreen.LeftColumn,
- LocalScreen.RightColumn,
- LocalScreen.TopRow,
- LocalScreen.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT - 1,
- TITLE_TEXT | TITLE_BACKGROUND
- );
- //
- // Print Top border line
- // +------------------------------------------------------------------------------+
- // ? ?
- // +------------------------------------------------------------------------------+
- //
- Character = BOXDRAW_DOWN_RIGHT;
-
- PrintChar (Character);
- PrintString (Buffer);
-
- Character = BOXDRAW_DOWN_LEFT;
- PrintChar (Character);
-
- Character = 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);
- }
+ //
+ // Create the periodic timer for refresh interval statement.
+ //
+ if (MinRefreshInterval != 0) {
+ Status = gBS->CreateEvent (EVT_TIMER | EVT_NOTIFY_SIGNAL, TPL_CALLBACK, RefreshIntervalProcess, NULL, &RefreshIntervalEvent);
+ ASSERT_EFI_ERROR (Status);
+ Status = gBS->SetTimer (RefreshIntervalEvent, TimerPeriodic, MinRefreshInterval * ONE_SECOND);
+ ASSERT_EFI_ERROR (Status);
+
+ EventNode = AllocateZeroPool (sizeof (FORM_BROWSER_REFRESH_EVENT_NODE));
+ ASSERT (EventNode != NULL);
+ EventNode->RefreshEvent = RefreshIntervalEvent;
+ InsertTailList(&mRefreshEventList, &EventNode->Link);
+ }
- Character = BOXDRAW_UP_RIGHT;
- PrintCharAt (LocalScreen.LeftColumn, LocalScreen.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT - 1, Character);
- PrintString (Buffer);
+ //
+ // Update hotkey list field.
+ //
+ if (gBrowserSettingScope == SystemLevel || FormEditable) {
+ UpdateHotkeyList();
+ }
+}
- Character = BOXDRAW_UP_LEFT;
- PrintChar (Character);
+/**
- if ((gClassOfVfr & FORMSET_CLASS_PLATFORM_SETUP) == FORMSET_CLASS_PLATFORM_SETUP) {
- //
- // Print Bottom border line
- // +------------------------------------------------------------------------------+
- // ? ?
- // +------------------------------------------------------------------------------+
- //
- Character = BOXDRAW_DOWN_RIGHT;
- PrintCharAt (LocalScreen.LeftColumn, LocalScreen.BottomRow - STATUS_BAR_HEIGHT - gFooterHeight, Character);
-
- PrintString (Buffer);
-
- Character = BOXDRAW_DOWN_LEFT;
- PrintChar (Character);
- Character = BOXDRAW_VERTICAL;
- for (Row = LocalScreen.BottomRow - STATUS_BAR_HEIGHT - gFooterHeight + 1;
- Row <= LocalScreen.BottomRow - STATUS_BAR_HEIGHT - 2;
- Row++
- ) {
- PrintCharAt (LocalScreen.LeftColumn, Row, Character);
- PrintCharAt (LocalScreen.RightColumn - 1, Row, Character);
- }
+ Initialize the SettingChangedFlag variable in the display form.
- Character = BOXDRAW_UP_RIGHT;
- PrintCharAt (LocalScreen.LeftColumn, LocalScreen.BottomRow - STATUS_BAR_HEIGHT - 1, Character);
+**/
+VOID
+UpdateDataChangedFlag (
+ VOID
+ )
+{
+ LIST_ENTRY *Link;
+ FORM_BROWSER_FORMSET *LocalFormSet;
- PrintString (Buffer);
+ gDisplayFormData.SettingChangedFlag = FALSE;
- Character = BOXDRAW_UP_LEFT;
- PrintChar (Character);
- }
+ if (IsNvUpdateRequiredForForm (gCurrentSelection->Form)) {
+ gDisplayFormData.SettingChangedFlag = TRUE;
+ return;
}
- FreePool (Buffer);
+ //
+ // Base on the system level to check whether need to show the NV flag.
+ //
+ switch (gBrowserSettingScope) {
+ case SystemLevel:
+ //
+ // Check the maintain list to see whether there is any change.
+ //
+ Link = GetFirstNode (&gBrowserFormSetList);
+ while (!IsNull (&gBrowserFormSetList, Link)) {
+ LocalFormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);
+ if (IsNvUpdateRequiredForFormSet(LocalFormSet)) {
+ gDisplayFormData.SettingChangedFlag = TRUE;
+ return;
+ }
+ Link = GetNextNode (&gBrowserFormSetList, Link);
+ }
+ break;
-}
+ case FormSetLevel:
+ if (IsNvUpdateRequiredForFormSet(gCurrentSelection->FormSet)) {
+ gDisplayFormData.SettingChangedFlag = TRUE;
+ return;
+ }
+ break;
+ default:
+ break;
+ }
+}
/**
- Evaluate all expressions in a Form.
- @param FormSet FormSet this Form belongs to.
- @param Form The Form.
+ Initialize the Display form structure data.
- @retval EFI_SUCCESS The expression evaluated successfuly
+**/
+VOID
+InitializeDisplayFormData (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+
+ gDisplayFormData.Signature = FORM_DISPLAY_ENGINE_FORM_SIGNATURE;
+ gDisplayFormData.Version = FORM_DISPLAY_ENGINE_VERSION_1;
+ gDisplayFormData.ImageId = 0;
+ gDisplayFormData.AnimationId = 0;
+
+ InitializeListHead (&gDisplayFormData.StatementListHead);
+ InitializeListHead (&gDisplayFormData.StatementListOSF);
+ InitializeListHead (&gDisplayFormData.HotKeyListHead);
+
+ Status = gBS->CreateEvent (
+ EVT_NOTIFY_WAIT,
+ TPL_CALLBACK,
+ SetupBrowserEmptyFunction,
+ NULL,
+ &mValueChangedEvent
+ );
+ ASSERT_EFI_ERROR (Status);
+}
+
+/**
+
+ Free the kotkey info saved in form data.
**/
-EFI_STATUS
-EvaluateFormExpressions (
- IN FORM_BROWSER_FORMSET *FormSet,
- IN FORM_BROWSER_FORM *Form
+VOID
+FreeHotkeyList (
+ VOID
)
{
- EFI_STATUS Status;
+ BROWSER_HOT_KEY *HotKey;
LIST_ENTRY *Link;
- FORM_EXPRESSION *Expression;
- Link = GetFirstNode (&Form->ExpressionListHead);
- while (!IsNull (&Form->ExpressionListHead, Link)) {
- Expression = FORM_EXPRESSION_FROM_LINK (Link);
- Link = GetNextNode (&Form->ExpressionListHead, Link);
+ while (!IsListEmpty (&gDisplayFormData.HotKeyListHead)) {
+ Link = GetFirstNode (&gDisplayFormData.HotKeyListHead);
+ HotKey = BROWSER_HOT_KEY_FROM_LINK (Link);
- if (Expression->Type == EFI_HII_EXPRESSION_INCONSISTENT_IF ||
- Expression->Type == EFI_HII_EXPRESSION_NO_SUBMIT_IF ||
- Expression->Type == EFI_HII_EXPRESSION_WRITE ||
- (Expression->Type == EFI_HII_EXPRESSION_READ && Form->FormType != STANDARD_MAP_FORM_TYPE)) {
- //
- // Postpone Form validation to Question editing or Form submitting or Question Write or Question Read for nonstandard form.
- //
- continue;
- }
+ RemoveEntryList (&HotKey->Link);
- Status = EvaluateExpression (FormSet, Form, Expression);
- if (EFI_ERROR (Status)) {
- return Status;
- }
+ FreePool (HotKey->KeyData);
+ FreePool (HotKey->HelpString);
+ FreePool (HotKey);
}
+}
- return EFI_SUCCESS;
+/**
+
+ Update the Display form structure data.
+
+**/
+VOID
+UpdateDisplayFormData (
+ VOID
+ )
+{
+ gDisplayFormData.FormTitle = gCurrentSelection->Form->FormTitle;
+ gDisplayFormData.FormId = gCurrentSelection->FormId;
+ gDisplayFormData.HiiHandle = gCurrentSelection->Handle;
+ CopyGuid (&gDisplayFormData.FormSetGuid, &gCurrentSelection->FormSetGuid);
+
+ gDisplayFormData.Attribute = 0;
+ gDisplayFormData.Attribute |= gCurrentSelection->Form->ModalForm ? HII_DISPLAY_MODAL : 0;
+ gDisplayFormData.Attribute |= gCurrentSelection->Form->Locked ? HII_DISPLAY_LOCK : 0;
+
+ gDisplayFormData.FormRefreshEvent = NULL;
+ gDisplayFormData.HighLightedStatement = NULL;
+
+ gDisplayFormData.BrowserStatus = gBrowserStatus;
+ gDisplayFormData.ErrorString = gErrorInfo;
+
+ gBrowserStatus = BROWSER_SUCCESS;
+ gErrorInfo = NULL;
+
+ UpdateDataChangedFlag ();
+
+ AddStatementToDisplayForm ();
}
-/*
-+------------------------------------------------------------------------------+
-? Setup Page ?
-+------------------------------------------------------------------------------+
+/**
+ Free the Display Statement structure data.
+ @param StatementList Point to the statement list which need to be free.
+**/
+VOID
+FreeStatementData (
+ LIST_ENTRY *StatementList
+ )
+{
+ LIST_ENTRY *Link;
+ LIST_ENTRY *OptionLink;
+ FORM_DISPLAY_ENGINE_STATEMENT *Statement;
+ DISPLAY_QUESTION_OPTION *Option;
+ //
+ // Free Statements/Questions
+ //
+ while (!IsListEmpty (StatementList)) {
+ Link = GetFirstNode (StatementList);
+ Statement = FORM_DISPLAY_ENGINE_STATEMENT_FROM_LINK (Link);
+ //
+ // Free Options List
+ //
+ while (!IsListEmpty (&Statement->OptionListHead)) {
+ OptionLink = GetFirstNode (&Statement->OptionListHead);
+ Option = DISPLAY_QUESTION_OPTION_FROM_LINK (OptionLink);
+ RemoveEntryList (&Option->Link);
+ FreePool (Option);
+ }
+ //
+ // Free nest statement List
+ //
+ if (!IsListEmpty (&Statement->NestStatementList)) {
+ FreeStatementData(&Statement->NestStatementList);
+ }
+ RemoveEntryList (&Statement->DisplayLink);
+ FreePool (Statement);
+ }
+}
+/**
+ Free the Display form structure data.
+**/
+VOID
+FreeDisplayFormData (
+ VOID
+ )
+{
+ FreeStatementData (&gDisplayFormData.StatementListHead);
+ FreeStatementData (&gDisplayFormData.StatementListOSF);
+ FreeRefreshEvent();
+ FreeHotkeyList();
+}
+/**
+ Get FORM_BROWSER_STATEMENT from FORM_DISPLAY_ENGINE_STATEMENT based on the OpCode info.
+ @param DisplayStatement The input FORM_DISPLAY_ENGINE_STATEMENT.
+ @retval FORM_BROWSER_STATEMENT The return FORM_BROWSER_STATEMENT info.
-+------------------------------------------------------------------------------+
-?F1=Scroll Help F9=Reset to Defaults F10=Save and Exit ?
-| ^"=Move Highlight <Spacebar> Toggles Checkbox Esc=Discard Changes |
-+------------------------------------------------------------------------------+
-*/
+**/
+FORM_BROWSER_STATEMENT *
+GetBrowserStatement (
+ IN FORM_DISPLAY_ENGINE_STATEMENT *DisplayStatement
+ )
+{
+ FORM_BROWSER_STATEMENT *Statement;
+ LIST_ENTRY *Link;
+
+ Link = GetFirstNode (&gCurrentSelection->Form->StatementListHead);
+ while (!IsNull (&gCurrentSelection->Form->StatementListHead, Link)) {
+ Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link);
+
+ if (Statement->OpCode == DisplayStatement->OpCode) {
+ return Statement;
+ }
+
+ Link = GetNextNode (&gCurrentSelection->Form->StatementListHead, Link);
+ }
+
+ return NULL;
+}
/**
+ Process the action request in user input.
- Display form and wait for user to select one menu option, then return it.
+ @param Action The user input action request info.
+ @param DefaultId The user input default Id info.
- @param Selection On input, Selection tell setup browser the information
- about the Selection, form and formset to be displayed.
- On output, Selection return the screen item that is selected
- by user.
@retval EFI_SUCESSS This function always return successfully for now.
**/
-EFI_STATUS
-DisplayForm (
- IN OUT UI_MENU_SELECTION *Selection
+EFI_STATUS
+ProcessAction (
+ IN UINT32 Action,
+ IN UINT16 DefaultId
)
{
- CHAR16 *StringPtr;
- UINT16 MenuItemCount;
- EFI_HII_HANDLE Handle;
- EFI_SCREEN_DESCRIPTOR LocalScreen;
- UINT16 Width;
- UINTN ArrayEntry;
- CHAR16 *OutputString;
- LIST_ENTRY *Link;
- FORM_BROWSER_STATEMENT *Statement;
- UINT16 NumberOfLines;
- EFI_STATUS Status;
- UI_MENU_OPTION *MenuOption;
- UINT16 GlyphWidth;
+ EFI_STATUS Status;
- Handle = Selection->Handle;
- MenuItemCount = 0;
- ArrayEntry = 0;
- OutputString = NULL;
+ //
+ // This is caused by use press ESC, and it should not combine with other action type.
+ //
+ if ((Action & BROWSER_ACTION_FORM_EXIT) == BROWSER_ACTION_FORM_EXIT) {
+ FindNextMenu (gCurrentSelection, FormLevel);
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Below is normal hotkey trigged action, these action maybe combine with each other.
+ //
+ if ((Action & BROWSER_ACTION_DISCARD) == BROWSER_ACTION_DISCARD) {
+ DiscardForm (gCurrentSelection->FormSet, gCurrentSelection->Form, gBrowserSettingScope);
+ }
- UiInitMenu ();
+ if ((Action & BROWSER_ACTION_DEFAULT) == BROWSER_ACTION_DEFAULT) {
+ ExtractDefault (gCurrentSelection->FormSet, gCurrentSelection->Form, DefaultId, gBrowserSettingScope, GetDefaultForAll, NULL, FALSE);
+ }
- CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));
+ if ((Action & BROWSER_ACTION_SUBMIT) == BROWSER_ACTION_SUBMIT) {
+ Status = SubmitForm (gCurrentSelection->FormSet, gCurrentSelection->Form, gBrowserSettingScope);
+ if (EFI_ERROR (Status)) {
+ gBrowserStatus = BROWSER_SUBMIT_FAIL;
+ }
+ }
- StringPtr = GetToken (Selection->Form->FormTitle, Handle);
+ if ((Action & BROWSER_ACTION_RESET) == BROWSER_ACTION_RESET) {
+ gResetRequired = TRUE;
+ }
- if ((gClassOfVfr & FORMSET_CLASS_FRONT_PAGE) != FORMSET_CLASS_FRONT_PAGE) {
- if (Selection->Form->ModalForm) {
- gST->ConOut->SetAttribute (gST->ConOut, TITLE_TEXT | EFI_BACKGROUND_BLACK);
- } else {
- gST->ConOut->SetAttribute (gST->ConOut, TITLE_TEXT | TITLE_BACKGROUND);
+ if ((Action & BROWSER_ACTION_EXIT) == BROWSER_ACTION_EXIT) {
+ //
+ // Form Exit without saving, Similar to ESC Key.
+ // FormSet Exit without saving, Exit SendForm.
+ // System Exit without saving, CallExitHandler and Exit SendForm.
+ //
+ DiscardForm (gCurrentSelection->FormSet, gCurrentSelection->Form, gBrowserSettingScope);
+ if (gBrowserSettingScope == FormLevel || gBrowserSettingScope == FormSetLevel) {
+ FindNextMenu (gCurrentSelection, gBrowserSettingScope);
+ } else if (gBrowserSettingScope == SystemLevel) {
+ if (ExitHandlerFunction != NULL) {
+ ExitHandlerFunction ();
+ }
+ gCurrentSelection->Action = UI_ACTION_EXIT;
}
- PrintStringAt (
- (LocalScreen.RightColumn + LocalScreen.LeftColumn - GetStringWidth (StringPtr) / 2) / 2,
- LocalScreen.TopRow + 1,
- StringPtr
- );
}
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Find HII Handle in the HII database associated with given Device Path.
+
+ If DevicePath is NULL, then ASSERT.
+
+ @param DevicePath Device Path associated with the HII package list
+ handle.
+
+ @retval Handle HII package list Handle associated with the Device
+ Path.
+ @retval NULL Hii Package list handle is not found.
+
+**/
+EFI_HII_HANDLE
+EFIAPI
+DevicePathToHiiHandle (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ )
+{
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_PROTOCOL *TmpDevicePath;
+ UINTN BufferSize;
+ UINTN HandleCount;
+ UINTN Index;
+ EFI_HANDLE Handle;
+ EFI_HANDLE DriverHandle;
+ EFI_HII_HANDLE *HiiHandles;
+ EFI_HII_HANDLE HiiHandle;
+
+ ASSERT (DevicePath != NULL);
+
+ TmpDevicePath = DevicePath;
//
- // Remove Buffer allocated for StringPtr after it has been used.
+ // Locate Device Path Protocol handle buffer
//
- FreePool (StringPtr);
+ Status = gBS->LocateDevicePath (
+ &gEfiDevicePathProtocolGuid,
+ &TmpDevicePath,
+ &DriverHandle
+ );
+ if (EFI_ERROR (Status) || !IsDevicePathEnd (TmpDevicePath)) {
+ return NULL;
+ }
//
- // Evaluate all the Expressions in this Form
+ // Retrieve all HII Handles from HII database
//
- Status = EvaluateFormExpressions (Selection->FormSet, Selection->Form);
+ BufferSize = 0x1000;
+ HiiHandles = AllocatePool (BufferSize);
+ ASSERT (HiiHandles != NULL);
+ Status = mHiiDatabase->ListPackageLists (
+ mHiiDatabase,
+ EFI_HII_PACKAGE_TYPE_ALL,
+ NULL,
+ &BufferSize,
+ HiiHandles
+ );
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ FreePool (HiiHandles);
+ HiiHandles = AllocatePool (BufferSize);
+ ASSERT (HiiHandles != NULL);
+
+ Status = mHiiDatabase->ListPackageLists (
+ mHiiDatabase,
+ EFI_HII_PACKAGE_TYPE_ALL,
+ NULL,
+ &BufferSize,
+ HiiHandles
+ );
+ }
+
if (EFI_ERROR (Status)) {
- return Status;
+ FreePool (HiiHandles);
+ return NULL;
}
- Selection->FormEditable = FALSE;
- Link = GetFirstNode (&Selection->Form->StatementListHead);
- while (!IsNull (&Selection->Form->StatementListHead, Link)) {
- Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link);
+ //
+ // Search Hii Handle by Driver Handle
+ //
+ HiiHandle = NULL;
+ HandleCount = BufferSize / sizeof (EFI_HII_HANDLE);
+ for (Index = 0; Index < HandleCount; Index++) {
+ Status = mHiiDatabase->GetPackageListHandle (
+ mHiiDatabase,
+ HiiHandles[Index],
+ &Handle
+ );
+ if (!EFI_ERROR (Status) && (Handle == DriverHandle)) {
+ HiiHandle = HiiHandles[Index];
+ break;
+ }
+ }
- if (EvaluateExpressionList(Statement->Expression, FALSE, NULL, NULL) <= ExpressGrayOut) {
- StringPtr = GetToken (Statement->Prompt, Handle);
- ASSERT (StringPtr != NULL);
+ FreePool (HiiHandles);
+ return HiiHandle;
+}
- Width = GetWidth (Statement, Handle);
+/**
+ Find HII Handle in the HII database associated with given form set guid.
- NumberOfLines = 1;
- ArrayEntry = 0;
- GlyphWidth = 1;
- for (; GetLineByWidth (StringPtr, Width, &GlyphWidth,&ArrayEntry, &OutputString) != 0x0000;) {
- //
- // If there is more string to process print on the next row and increment the Skip value
- //
- if (StrLen (&StringPtr[ArrayEntry]) != 0) {
- NumberOfLines++;
- }
+ If FormSetGuid is NULL, then ASSERT.
- FreePool (OutputString);
- }
+ @param ComparingGuid FormSet Guid associated with the HII package list
+ handle.
- //
- // We are NOT!! removing this StringPtr buffer via FreePool since it is being used in the menuoptions, we will do
- // it in UiFreeMenu.
- //
- MenuOption = UiAddMenuOption (StringPtr, Selection->Handle, Selection->Form, Statement, NumberOfLines, MenuItemCount);
- MenuItemCount++;
+ @retval Handle HII package list Handle associated with the Device
+ Path.
+ @retval NULL Hii Package list handle is not found.
+
+**/
+EFI_HII_HANDLE
+FormSetGuidToHiiHandle (
+ EFI_GUID *ComparingGuid
+ )
+{
+ EFI_HII_HANDLE *HiiHandles;
+ UINTN Index;
+ EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;
+ UINTN BufferSize;
+ UINT32 Offset;
+ UINT32 Offset2;
+ UINT32 PackageListLength;
+ EFI_HII_PACKAGE_HEADER PackageHeader;
+ UINT8 *Package;
+ UINT8 *OpCodeData;
+ EFI_STATUS Status;
+ EFI_HII_HANDLE HiiHandle;
+
+ ASSERT (ComparingGuid != NULL);
+
+ HiiHandle = NULL;
+ //
+ // Get all the Hii handles
+ //
+ HiiHandles = HiiGetHiiHandles (NULL);
+ ASSERT (HiiHandles != NULL);
- if (MenuOption->IsQuestion && !MenuOption->ReadOnly) {
+ //
+ // Search for formset of each class type
+ //
+ for (Index = 0; HiiHandles[Index] != NULL; Index++) {
+ BufferSize = 0;
+ HiiPackageList = NULL;
+ Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, HiiHandles[Index], &BufferSize, HiiPackageList);
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ HiiPackageList = AllocatePool (BufferSize);
+ ASSERT (HiiPackageList != NULL);
+
+ Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, HiiHandles[Index], &BufferSize, HiiPackageList);
+ }
+ if (EFI_ERROR (Status) || HiiPackageList == NULL) {
+ return NULL;
+ }
+
+ //
+ // Get Form package from this HII package List
+ //
+ Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);
+ Offset2 = 0;
+ CopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof (UINT32));
+
+ while (Offset < PackageListLength) {
+ Package = ((UINT8 *) HiiPackageList) + Offset;
+ CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));
+
+ if (PackageHeader.Type == EFI_HII_PACKAGE_FORMS) {
//
- // At least one item is not readonly, this Form is considered as editable
+ // Search FormSet in this Form Package
//
- Selection->FormEditable = TRUE;
+ Offset2 = sizeof (EFI_HII_PACKAGE_HEADER);
+ while (Offset2 < PackageHeader.Length) {
+ OpCodeData = Package + Offset2;
+
+ if (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) {
+ //
+ // Try to compare against formset GUID
+ //
+ if (CompareGuid (ComparingGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)))) {
+ HiiHandle = HiiHandles[Index];
+ break;
+ }
+ }
+
+ Offset2 += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;
+ }
+ }
+ if (HiiHandle != NULL) {
+ break;
}
+ Offset += PackageHeader.Length;
}
-
- Link = GetNextNode (&Selection->Form->StatementListHead, Link);
+
+ FreePool (HiiPackageList);
+ if (HiiHandle != NULL) {
+ break;
+ }
}
- Status = UiDisplayMenu (Selection);
-
- UiFreeMenu ();
+ FreePool (HiiHandles);
- return Status;
+ return HiiHandle;
}
/**
- Initialize the HII String Token to the correct values.
+ check how to process the changed data in current form or form set.
+
+ @param Selection On input, Selection tell setup browser the information
+ about the Selection, form and formset to be displayed.
+ On output, Selection return the screen item that is selected
+ by user.
+
+ @param Scope Data save or discard scope, form or formset.
+ @retval TRUE Success process the changed data, will return to the parent form.
+ @retval FALSE Reject to process the changed data, will stay at current form.
**/
-VOID
-InitializeBrowserStrings (
- VOID
+BOOLEAN
+ProcessChangedData (
+ IN OUT UI_MENU_SELECTION *Selection,
+ IN BROWSER_SETTING_SCOPE Scope
)
{
- gEnterString = GetToken (STRING_TOKEN (ENTER_STRING), gHiiHandle);
- gEnterCommitString = GetToken (STRING_TOKEN (ENTER_COMMIT_STRING), gHiiHandle);
- gEnterEscapeString = GetToken (STRING_TOKEN (ENTER_ESCAPE_STRING), gHiiHandle);
- gEscapeString = GetToken (STRING_TOKEN (ESCAPE_STRING), gHiiHandle);
- gMoveHighlight = GetToken (STRING_TOKEN (MOVE_HIGHLIGHT), gHiiHandle);
- gMakeSelection = GetToken (STRING_TOKEN (MAKE_SELECTION), gHiiHandle);
- gDecNumericInput = GetToken (STRING_TOKEN (DEC_NUMERIC_INPUT), gHiiHandle);
- gHexNumericInput = GetToken (STRING_TOKEN (HEX_NUMERIC_INPUT), gHiiHandle);
- gToggleCheckBox = GetToken (STRING_TOKEN (TOGGLE_CHECK_BOX), gHiiHandle);
- gPromptForData = GetToken (STRING_TOKEN (PROMPT_FOR_DATA), 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);
- gPassowordInvalid = GetToken (STRING_TOKEN (PASSWORD_INVALID), 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);
- gSaveChanges = GetToken (STRING_TOKEN (SAVE_CHANGES), gHiiHandle);
- gOptionMismatch = GetToken (STRING_TOKEN (OPTION_MISMATCH), gHiiHandle);
- gFormSuppress = GetToken (STRING_TOKEN (FORM_SUPPRESSED), gHiiHandle);
- gProtocolNotFound = GetToken (STRING_TOKEN (PROTOCOL_NOT_FOUND), gHiiHandle);
- return ;
+ BOOLEAN RetValue;
+
+ RetValue = TRUE;
+ switch (mFormDisplay->ConfirmDataChange()) {
+ case BROWSER_ACTION_DISCARD:
+ DiscardForm (Selection->FormSet, Selection->Form, Scope);
+ break;
+
+ case BROWSER_ACTION_SUBMIT:
+ SubmitForm (Selection->FormSet, Selection->Form, Scope);
+ break;
+
+ case BROWSER_ACTION_NONE:
+ RetValue = FALSE;
+ break;
+
+ default:
+ //
+ // if Invalid value return, process same as BROWSER_ACTION_NONE.
+ //
+ RetValue = FALSE;
+ break;
+ }
+
+ return RetValue;
}
/**
- Free up the resource allocated for all strings required
- by Setup Browser.
+ Find parent formset menu(the first menu which has different formset) for current menu.
+ If not find, just return to the first menu.
+
+ @param Selection The selection info.
**/
VOID
-FreeBrowserStrings (
- VOID
+FindParentFormSet (
+ IN OUT UI_MENU_SELECTION *Selection
)
{
- FreePool (gEnterString);
- FreePool (gEnterCommitString);
- FreePool (gEnterEscapeString);
- FreePool (gEscapeString);
- FreePool (gMoveHighlight);
- FreePool (gMakeSelection);
- FreePool (gDecNumericInput);
- FreePool (gHexNumericInput);
- FreePool (gToggleCheckBox);
- FreePool (gPromptForData);
- FreePool (gPromptForPassword);
- FreePool (gPromptForNewPassword);
- FreePool (gConfirmPassword);
- FreePool (gPassowordInvalid);
- FreePool (gConfirmError);
- FreePool (gPressEnter);
- FreePool (gEmptyString);
- FreePool (gAreYouSure);
- FreePool (gYesResponse);
- FreePool (gNoResponse);
- FreePool (gMiniString);
- FreePool (gPlusString);
- FreePool (gMinusString);
- FreePool (gAdjustNumber);
- FreePool (gSaveChanges);
- FreePool (gOptionMismatch);
- FreePool (gFormSuppress);
- FreePool (gProtocolNotFound);
- return ;
+ FORM_ENTRY_INFO *CurrentMenu;
+ FORM_ENTRY_INFO *ParentMenu;
+
+ CurrentMenu = Selection->CurrentMenu;
+ ParentMenu = UiFindParentMenu(CurrentMenu);
+
+ //
+ // Find a menu which has different formset guid with current.
+ //
+ while (ParentMenu != NULL && CompareGuid (&CurrentMenu->FormSetGuid, &ParentMenu->FormSetGuid)) {
+ CurrentMenu = ParentMenu;
+ ParentMenu = UiFindParentMenu(CurrentMenu);
+ }
+
+ if (ParentMenu != NULL) {
+ CopyMem (&Selection->FormSetGuid, &ParentMenu->FormSetGuid, sizeof (EFI_GUID));
+ Selection->Handle = ParentMenu->HiiHandle;
+ Selection->FormId = ParentMenu->FormId;
+ Selection->QuestionId = ParentMenu->QuestionId;
+ } else {
+ Selection->FormId = CurrentMenu->FormId;
+ Selection->QuestionId = CurrentMenu->QuestionId;
+ }
+
+ Selection->Statement = NULL;
}
/**
- Show all registered HotKey help strings on bottom Rows.
+ Process the goto op code, update the info in the selection structure.
+
+ @param Statement The statement belong to goto op code.
+ @param Selection The selection info.
+ @retval EFI_SUCCESS The menu process successfully.
+ @return Other value if the process failed.
**/
-VOID
-PrintHotKeyHelpString (
- VOID
+EFI_STATUS
+ProcessGotoOpCode (
+ IN OUT FORM_BROWSER_STATEMENT *Statement,
+ IN OUT UI_MENU_SELECTION *Selection
)
{
- UINTN CurrentCol;
- UINTN CurrentRow;
- UINTN BottomRowOfHotKeyHelp;
- UINTN ColumnWidth;
- UINTN Index;
- EFI_SCREEN_DESCRIPTOR LocalScreen;
- LIST_ENTRY *Link;
- BROWSER_HOT_KEY *HotKey;
+ CHAR16 *StringPtr;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ FORM_BROWSER_FORM *RefForm;
+ EFI_STATUS Status;
+ EFI_HII_HANDLE HiiHandle;
+
+ Status = EFI_SUCCESS;
+ StringPtr = NULL;
+ HiiHandle = NULL;
- CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));
- ColumnWidth = (LocalScreen.RightColumn - LocalScreen.LeftColumn) / 3;
- BottomRowOfHotKeyHelp = LocalScreen.BottomRow - STATUS_BAR_HEIGHT - 3;
+ //
+ // Prepare the device path check, get the device path info first.
+ //
+ if (Statement->HiiValue.Value.ref.DevicePath != 0) {
+ StringPtr = GetToken (Statement->HiiValue.Value.ref.DevicePath, Selection->FormSet->HiiHandle);
+ }
//
- // Calculate total number of Register HotKeys.
+ // Check whether the device path string is a valid string.
//
- Index = 0;
- Link = GetFirstNode (&gBrowserHotKeyList);
- while (!IsNull (&gBrowserHotKeyList, Link)) {
- HotKey = BROWSER_HOT_KEY_FROM_LINK (Link);
- //
- // Help string can't exceed ColumnWidth. One Row will show three Help information.
- //
- if (StrLen (HotKey->HelpString) > ColumnWidth) {
- HotKey->HelpString[ColumnWidth] = L'\0';
+ if (Statement->HiiValue.Value.ref.DevicePath != 0 && StringPtr != NULL) {
+ if (Selection->Form->ModalForm) {
+ return Status;
}
+
//
- // Calculate help information Column and Row.
+ // Goto another Hii Package list
//
- if ((Index % 3) != 2) {
- CurrentCol = LocalScreen.LeftColumn + (2 - Index % 3) * ColumnWidth;
+ if (mPathFromText != NULL) {
+ DevicePath = mPathFromText->ConvertTextToDevicePath(StringPtr);
+ if (DevicePath != NULL) {
+ HiiHandle = DevicePathToHiiHandle (DevicePath);
+ FreePool (DevicePath);
+ }
+ FreePool (StringPtr);
} else {
- CurrentCol = LocalScreen.LeftColumn + 2;
+ //
+ // Not found the EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL protocol.
+ //
+ gBrowserStatus = BROWSER_PROTOCOL_NOT_FOUND;
+ FreePool (StringPtr);
+ return Status;
+ }
+
+ if (HiiHandle != Selection->Handle) {
+ //
+ // Goto another Formset, check for uncommitted data
+ //
+ if ((gBrowserSettingScope == FormLevel || gBrowserSettingScope == FormSetLevel) &&
+ IsNvUpdateRequiredForFormSet(Selection->FormSet)) {
+ if (!ProcessChangedData(Selection, FormSetLevel)) {
+ return EFI_SUCCESS;
+ }
+ }
+ }
+
+ Selection->Action = UI_ACTION_REFRESH_FORMSET;
+ Selection->Handle = HiiHandle;
+ if (Selection->Handle == NULL) {
+ //
+ // If target Hii Handle not found, exit current formset.
+ //
+ FindParentFormSet(Selection);
+ return EFI_SUCCESS;
}
- CurrentRow = BottomRowOfHotKeyHelp - Index / 3;
- //
- // Print HotKey help string on bottom Row.
- //
- PrintStringAt (CurrentCol, CurrentRow, HotKey->HelpString);
+ CopyMem (&Selection->FormSetGuid,&Statement->HiiValue.Value.ref.FormSetGuid, sizeof (EFI_GUID));
+ Selection->FormId = Statement->HiiValue.Value.ref.FormId;
+ Selection->QuestionId = Statement->HiiValue.Value.ref.QuestionId;
+ } else if (!CompareGuid (&Statement->HiiValue.Value.ref.FormSetGuid, &gZeroGuid)) {
+ if (Selection->Form->ModalForm) {
+ return Status;
+ }
+ if (!CompareGuid (&Statement->HiiValue.Value.ref.FormSetGuid, &Selection->FormSetGuid)) {
+ //
+ // Goto another Formset, check for uncommitted data
+ //
+ if ((gBrowserSettingScope == FormLevel || gBrowserSettingScope == FormSetLevel) &&
+ IsNvUpdateRequiredForFormSet(Selection->FormSet)) {
+ if (!ProcessChangedData(Selection, FormSetLevel)) {
+ return EFI_SUCCESS;
+ }
+ }
+ }
+
+ Selection->Action = UI_ACTION_REFRESH_FORMSET;
+ Selection->Handle = FormSetGuidToHiiHandle(&Statement->HiiValue.Value.ref.FormSetGuid);
+ if (Selection->Handle == NULL) {
+ //
+ // If target Hii Handle not found, exit current formset.
+ //
+ FindParentFormSet(Selection);
+ return EFI_SUCCESS;
+ }
+
+ CopyMem (&Selection->FormSetGuid, &Statement->HiiValue.Value.ref.FormSetGuid, sizeof (EFI_GUID));
+ Selection->FormId = Statement->HiiValue.Value.ref.FormId;
+ Selection->QuestionId = Statement->HiiValue.Value.ref.QuestionId;
+ } else if (Statement->HiiValue.Value.ref.FormId != 0) {
//
- // Get Next Hot Key.
+ // Goto another Form, check for uncommitted data
//
- Link = GetNextNode (&gBrowserHotKeyList, Link);
- Index ++;
+ if (Statement->HiiValue.Value.ref.FormId != Selection->FormId) {
+ if ((gBrowserSettingScope == FormLevel && IsNvUpdateRequiredForForm(Selection->Form))) {
+ if (!ProcessChangedData (Selection, FormLevel)) {
+ return EFI_SUCCESS;
+ }
+ }
+ }
+
+ RefForm = IdToForm (Selection->FormSet, Statement->HiiValue.Value.ref.FormId);
+ if ((RefForm != NULL) && (RefForm->SuppressExpression != NULL)) {
+ if (EvaluateExpressionList(RefForm->SuppressExpression, TRUE, Selection->FormSet, RefForm) != ExpressFalse) {
+ //
+ // Form is suppressed.
+ //
+ gBrowserStatus = BROWSER_FORM_SUPPRESS;
+ return EFI_SUCCESS;
+ }
+ }
+
+ Selection->FormId = Statement->HiiValue.Value.ref.FormId;
+ Selection->QuestionId = Statement->HiiValue.Value.ref.QuestionId;
+ } else if (Statement->HiiValue.Value.ref.QuestionId != 0) {
+ Selection->QuestionId = Statement->HiiValue.Value.ref.QuestionId;
}
-
- return;
+
+ return Status;
}
+
/**
- Update key's help imformation.
+ Process Question Config.
- @param Selection Tell setup browser the information about the Selection
- @param MenuOption The Menu option
- @param Selected Whether or not a tag be selected
+ @param Selection The UI menu selection.
+ @param Question The Question to be peocessed.
+
+ @retval EFI_SUCCESS Question Config process success.
+ @retval Other Question Config process fail.
**/
-VOID
-UpdateKeyHelp (
- IN UI_MENU_SELECTION *Selection,
- IN UI_MENU_OPTION *MenuOption,
- IN BOOLEAN Selected
+EFI_STATUS
+ProcessQuestionConfig (
+ IN UI_MENU_SELECTION *Selection,
+ IN FORM_BROWSER_STATEMENT *Question
)
{
- UINTN SecCol;
- UINTN ThdCol;
- UINTN LeftColumnOfHelp;
- UINTN RightColumnOfHelp;
- UINTN TopRowOfHelp;
- UINTN BottomRowOfHelp;
- UINTN StartColumnOfHelp;
- EFI_SCREEN_DESCRIPTOR LocalScreen;
- FORM_BROWSER_STATEMENT *Statement;
+ EFI_STATUS Status;
+ CHAR16 *ConfigResp;
+ CHAR16 *Progress;
+ EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;
- gST->ConOut->SetAttribute (gST->ConOut, KEYHELP_TEXT | KEYHELP_BACKGROUND);
+ if (Question->QuestionConfig == 0) {
+ return EFI_SUCCESS;
+ }
- if (Selection->Form->ModalForm) {
- return;
+ //
+ // Get <ConfigResp>
+ //
+ ConfigResp = GetToken (Question->QuestionConfig, Selection->FormSet->HiiHandle);
+ if (ConfigResp == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Send config to Configuration Driver
+ //
+ ConfigAccess = Selection->FormSet->ConfigAccess;
+ if (ConfigAccess == NULL) {
+ return EFI_UNSUPPORTED;
}
+ Status = ConfigAccess->RouteConfig (
+ ConfigAccess,
+ ConfigResp,
+ &Progress
+ );
- CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));
+ return Status;
+}
- SecCol = LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) / 3;
- ThdCol = LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) / 3 * 2;
+/**
- StartColumnOfHelp = LocalScreen.LeftColumn + 2;
- LeftColumnOfHelp = LocalScreen.LeftColumn + 1;
- RightColumnOfHelp = LocalScreen.RightColumn - 2;
- TopRowOfHelp = LocalScreen.BottomRow - STATUS_BAR_HEIGHT - gFooterHeight + 1;
- BottomRowOfHelp = LocalScreen.BottomRow - STATUS_BAR_HEIGHT - 2;
+ Process the user input data.
- Statement = MenuOption->ThisTag;
- switch (Statement->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);
+ @param UserInput The user input data.
+ @param ChangeHighlight Whether need to change the highlight statement.
+
+ @retval EFI_SUCESSS This function always return successfully for now.
- if (!Selected) {
+**/
+EFI_STATUS
+ProcessUserInput (
+ IN USER_INPUT *UserInput,
+ IN BOOLEAN ChangeHighlight
+ )
+{
+ EFI_STATUS Status;
+ FORM_BROWSER_STATEMENT *Statement;
+
+ Status = EFI_SUCCESS;
+
+ //
+ // When Exit from FormDisplay function, one of the below two cases must be true.
+ //
+ ASSERT (UserInput->Action != 0 || UserInput->SelectedStatement != NULL);
+
+ //
+ // Remove the last highligh question id, this id will update when show next form.
+ //
+ gCurrentSelection->QuestionId = 0;
+
+ //
+ // First process the Action field in USER_INPUT.
+ //
+ if (UserInput->Action != 0) {
+ Status = ProcessAction (UserInput->Action, UserInput->DefaultId);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Clear the highlight info.
+ //
+ gCurrentSelection->Statement = NULL;
+
+ if (UserInput->SelectedStatement != NULL) {
+ Statement = GetBrowserStatement(UserInput->SelectedStatement);
+ ASSERT (Statement != NULL);
//
- // On system setting, HotKey will show on every form.
+ // Save the current highlight menu in the menu history data.
+ // which will be used when later browse back to this form.
//
- if (gBrowserSettingScope == SystemLevel ||
- (Selection->FormEditable && gFunctionKeySetting != NONE_FUNCTION_KEY_SETTING)) {
- PrintHotKeyHelpString ();
+ gCurrentSelection->CurrentMenu->QuestionId = Statement->QuestionId;
+ //
+ // For statement like text, actio, it not has question id.
+ // So use FakeQuestionId to save the question.
+ //
+ if (gCurrentSelection->CurrentMenu->QuestionId == 0) {
+ mCurFakeQestId = Statement->FakeQuestionId;
+ } else {
+ mCurFakeQestId = 0;
}
+ }
+ } else {
+ Statement = GetBrowserStatement(UserInput->SelectedStatement);
+ ASSERT (Statement != NULL);
- if ((gClassOfVfr & FORMSET_CLASS_PLATFORM_SETUP) == FORMSET_CLASS_PLATFORM_SETUP) {
- PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString);
- }
+ gCurrentSelection->Statement = Statement;
- if ((Statement->Operand == EFI_IFR_DATE_OP) ||
- (Statement->Operand == EFI_IFR_TIME_OP)) {
- PrintAt (
- StartColumnOfHelp,
- BottomRowOfHelp,
- L"%c%c%c%c%s",
- ARROW_UP,
- ARROW_DOWN,
- ARROW_RIGHT,
- ARROW_LEFT,
- gMoveHighlight
- );
- PrintStringAt (SecCol, BottomRowOfHelp, gEnterString);
- PrintStringAt (StartColumnOfHelp, TopRowOfHelp, gAdjustNumber);
+ if (ChangeHighlight) {
+ //
+ // This question is the current user select one,record it and later
+ // show it as the highlight question.
+ //
+ gCurrentSelection->CurrentMenu->QuestionId = Statement->QuestionId;
+ //
+ // For statement like text, actio, it not has question id.
+ // So use FakeQuestionId to save the question.
+ //
+ if (gCurrentSelection->CurrentMenu->QuestionId == 0) {
+ mCurFakeQestId = Statement->FakeQuestionId;
} else {
- PrintAt (StartColumnOfHelp, BottomRowOfHelp, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);
- if (Statement->Operand == EFI_IFR_NUMERIC_OP && Statement->Step != 0) {
- PrintStringAt (StartColumnOfHelp, TopRowOfHelp, gAdjustNumber);
- }
- PrintStringAt (SecCol, BottomRowOfHelp, gEnterString);
+ mCurFakeQestId = 0;
}
- } else {
- PrintStringAt (SecCol, BottomRowOfHelp, gEnterCommitString);
+ }
+ switch (Statement->Operand) {
+ case EFI_IFR_REF_OP:
+ Status = ProcessGotoOpCode(Statement, gCurrentSelection);
+ break;
+
+ case EFI_IFR_ACTION_OP:
//
- // If it is a selected numeric with manual input, display different message
+ // Process the Config string <ConfigResp>
//
- if ((Statement->Operand == EFI_IFR_NUMERIC_OP) ||
- (Statement->Operand == EFI_IFR_DATE_OP) ||
- (Statement->Operand == EFI_IFR_TIME_OP)) {
- PrintStringAt (
- SecCol,
- TopRowOfHelp,
- ((Statement->Flags & EFI_IFR_DISPLAY_UINT_HEX) == EFI_IFR_DISPLAY_UINT_HEX) ? gHexNumericInput : gDecNumericInput
- );
- } else if (Statement->Operand != EFI_IFR_ORDERED_LIST_OP) {
- PrintAt (StartColumnOfHelp, BottomRowOfHelp, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);
- }
+ Status = ProcessQuestionConfig (gCurrentSelection, Statement);
+ break;
+
+ case EFI_IFR_RESET_BUTTON_OP:
+ //
+ // Reset Question to default value specified by DefaultId
+ //
+ Status = ExtractDefault (gCurrentSelection->FormSet, NULL, Statement->DefaultId, FormSetLevel, GetDefaultForAll, NULL, FALSE);
+ break;
- if (Statement->Operand == EFI_IFR_ORDERED_LIST_OP) {
- PrintStringAt (StartColumnOfHelp, TopRowOfHelp, gPlusString);
- PrintStringAt (ThdCol, TopRowOfHelp, gMinusString);
- }
+ default:
+ switch (Statement->Operand) {
+ case EFI_IFR_STRING_OP:
+ DeleteString(Statement->HiiValue.Value.string, gCurrentSelection->FormSet->HiiHandle);
+ Statement->HiiValue.Value.string = UserInput->InputValue.Value.string;
+ CopyMem (Statement->BufferValue, UserInput->InputValue.Buffer, (UINTN) UserInput->InputValue.BufferLen);
+ FreePool (UserInput->InputValue.Buffer);
+ break;
+
+ case EFI_IFR_PASSWORD_OP:
+ if (UserInput->InputValue.Buffer == NULL) {
+ //
+ // User not input new password, just return.
+ //
+ break;
+ }
+
+ DeleteString(Statement->HiiValue.Value.string, gCurrentSelection->FormSet->HiiHandle);
+ Statement->HiiValue.Value.string = UserInput->InputValue.Value.string;
+ CopyMem (Statement->BufferValue, UserInput->InputValue.Buffer, (UINTN) UserInput->InputValue.BufferLen);
+ FreePool (UserInput->InputValue.Buffer);
+ //
+ // Two password match, send it to Configuration Driver
+ //
+ if ((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) {
+ PasswordCheck (NULL, UserInput->SelectedStatement, (CHAR16 *) Statement->BufferValue);
+ //
+ // Clean the value after saved it.
+ //
+ ZeroMem (Statement->BufferValue, (UINTN) UserInput->InputValue.BufferLen);
+ HiiSetString (gCurrentSelection->FormSet->HiiHandle, Statement->HiiValue.Value.string, (CHAR16*)Statement->BufferValue, NULL);
+ } else {
+ SetQuestionValue (gCurrentSelection->FormSet, gCurrentSelection->Form, Statement, GetSetValueWithHiiDriver);
+ }
+ break;
+
+ case EFI_IFR_ORDERED_LIST_OP:
+ CopyMem (Statement->BufferValue, UserInput->InputValue.Buffer, UserInput->InputValue.BufferLen);
+ break;
- PrintStringAt (ThdCol, BottomRowOfHelp, gEnterEscapeString);
+ default:
+ CopyMem (&Statement->HiiValue, &UserInput->InputValue, sizeof (EFI_HII_VALUE));
+ break;
+ }
+ if (Statement->Operand != EFI_IFR_PASSWORD_OP) {
+ SetQuestionValue (gCurrentSelection->FormSet, gCurrentSelection->Form, Statement, GetSetValueWithEditBuffer);
+ }
+ break;
}
- break;
+ }
- case EFI_IFR_CHECKBOX_OP:
- ClearLines (LeftColumnOfHelp, RightColumnOfHelp, TopRowOfHelp, BottomRowOfHelp, KEYHELP_TEXT | KEYHELP_BACKGROUND);
+ return Status;
+}
+
+/**
+
+ Display form and wait for user to select one menu option, then return it.
+
+ @retval EFI_SUCESSS This function always return successfully for now.
+**/
+EFI_STATUS
+DisplayForm (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ USER_INPUT UserInput;
+ FORM_ENTRY_INFO *CurrentMenu;
+ BOOLEAN ChangeHighlight;
+
+ ZeroMem (&UserInput, sizeof (USER_INPUT));
+
+ //
+ // Update the menu history data.
+ //
+ CurrentMenu = UiFindMenuList (gCurrentSelection->Handle, &gCurrentSelection->FormSetGuid, gCurrentSelection->FormId);
+ if (CurrentMenu == NULL) {
//
- // On system setting, HotKey will show on every form.
+ // Current menu not found, add it to the menu tree
//
- if (gBrowserSettingScope == SystemLevel ||
- (Selection->FormEditable && gFunctionKeySetting != NONE_FUNCTION_KEY_SETTING)) {
- PrintHotKeyHelpString ();
- }
- if ((gClassOfVfr & FORMSET_CLASS_PLATFORM_SETUP) == FORMSET_CLASS_PLATFORM_SETUP) {
- PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString);
- }
-
- PrintAt (StartColumnOfHelp, BottomRowOfHelp, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);
- PrintStringAt (SecCol, BottomRowOfHelp, gToggleCheckBox);
- break;
+ CurrentMenu = UiAddMenuList (gCurrentSelection->Handle, &gCurrentSelection->FormSetGuid,
+ gCurrentSelection->FormId, gCurrentSelection->QuestionId);
+ ASSERT (CurrentMenu != NULL);
+ }
+ gCurrentSelection->CurrentMenu = CurrentMenu;
- case EFI_IFR_REF_OP:
- case EFI_IFR_PASSWORD_OP:
- case EFI_IFR_STRING_OP:
- case EFI_IFR_TEXT_OP:
- case EFI_IFR_ACTION_OP:
- case EFI_IFR_RESET_BUTTON_OP:
- case EFI_IFR_SUBTITLE_OP:
- ClearLines (LeftColumnOfHelp, RightColumnOfHelp, TopRowOfHelp, BottomRowOfHelp, KEYHELP_TEXT | KEYHELP_BACKGROUND);
+ //
+ // Find currrent highlight statement.
+ //
+ if (gCurrentSelection->QuestionId == 0) {
+ //
+ // Highlight not specified, fetch it from cached menu
+ //
+ gCurrentSelection->QuestionId = CurrentMenu->QuestionId;
+ }
- if (!Selected) {
- //
- // On system setting, HotKey will show on every form.
- //
- if (gBrowserSettingScope == SystemLevel ||
- (Selection->FormEditable && gFunctionKeySetting != NONE_FUNCTION_KEY_SETTING)) {
- PrintHotKeyHelpString ();
- }
- if ((gClassOfVfr & FORMSET_CLASS_PLATFORM_SETUP) == FORMSET_CLASS_PLATFORM_SETUP) {
- PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString);
- }
+ //
+ // Evaluate all the Expressions in this Form
+ //
+ Status = EvaluateFormExpressions (gCurrentSelection->FormSet, gCurrentSelection->Form);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
- PrintAt (StartColumnOfHelp, BottomRowOfHelp, L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight);
- if (Statement->Operand != EFI_IFR_TEXT_OP && Statement->Operand != EFI_IFR_SUBTITLE_OP) {
- PrintStringAt (SecCol, BottomRowOfHelp, gEnterString);
- }
- } else {
- if (Statement->Operand != EFI_IFR_REF_OP) {
- PrintStringAt (
- (LocalScreen.RightColumn - GetStringWidth (gEnterCommitString) / 2) / 2,
- BottomRowOfHelp,
- gEnterCommitString
- );
- PrintStringAt (ThdCol, BottomRowOfHelp, gEnterEscapeString);
- }
- }
- break;
+ UpdateDisplayFormData ();
- default:
- break;
+ //
+ // Three possible status maybe return.
+ //
+ // EFI_INVALID_PARAMETER: The input dimension info is not valid.
+ // EFI_NOT_FOUND: The input value for oneof/orderedlist opcode is not valid
+ // and an valid value has return.
+ // EFI_SUCCESS: Success shows form and get user input in UserInput paramenter.
+ //
+ Status = mFormDisplay->FormDisplay (&gDisplayFormData, &UserInput);
+ if (EFI_ERROR (Status) && Status != EFI_NOT_FOUND) {
+ FreeDisplayFormData();
+ return Status;
}
+
+ //
+ // If status is EFI_SUCCESS, means user has change the highlight menu and new user input return.
+ // in this case, browser need to change the highlight menu.
+ // If status is EFI_NOT_FOUND, means the input DisplayFormData has error for oneof/orderedlist
+ // opcode and new valid value has return, browser core need to adjust
+ // value for this opcode and shows this form again.
+ //
+ ChangeHighlight = (Status == EFI_SUCCESS ? TRUE :FALSE);
+
+ Status = ProcessUserInput (&UserInput, ChangeHighlight);
+
+ FreeDisplayFormData();
+
+ return Status;
}
/**
@@ -920,60 +1753,136 @@ FormUpdateNotify (
}
/**
- check whether the formset need to update the NV.
+ Update the NV flag info for this form set.
@param FormSet FormSet data structure.
- @retval TRUE Need to update the NV.
- @retval FALSE No need to update the NV.
**/
-BOOLEAN
-IsNvUpdateRequired (
+BOOLEAN
+IsNvUpdateRequiredForFormSet (
IN FORM_BROWSER_FORMSET *FormSet
)
{
LIST_ENTRY *Link;
FORM_BROWSER_FORM *Form;
+ BOOLEAN RetVal;
+
+ //
+ // Not finished question initialization, return FALSE.
+ //
+ if (!FormSet->QuestionInited) {
+ return FALSE;
+ }
+
+ RetVal = FALSE;
Link = GetFirstNode (&FormSet->FormListHead);
while (!IsNull (&FormSet->FormListHead, Link)) {
Form = FORM_BROWSER_FORM_FROM_LINK (Link);
- if (Form->NvUpdateRequired ) {
- return TRUE;
+ RetVal = IsNvUpdateRequiredForForm(Form);
+ if (RetVal) {
+ break;
}
Link = GetNextNode (&FormSet->FormListHead, Link);
}
+ return RetVal;
+}
+
+/**
+ Update the NvUpdateRequired flag for a form.
+
+ @param Form Form data structure.
+
+**/
+BOOLEAN
+IsNvUpdateRequiredForForm (
+ IN FORM_BROWSER_FORM *Form
+ )
+{
+ LIST_ENTRY *Link;
+ FORM_BROWSER_STATEMENT *Statement;
+
+ Link = GetFirstNode (&Form->StatementListHead);
+ while (!IsNull (&Form->StatementListHead, Link)) {
+ Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link);
+
+ if (Statement->ValueChanged) {
+ return TRUE;
+ }
+
+ Link = GetNextNode (&Form->StatementListHead, Link);
+ }
+
return FALSE;
}
/**
- check whether the formset need to update the NV.
+ Check whether the storage data for current form set is changed.
- @param FormSet FormSet data structure.
- @param SetValue Whether set new value or clear old value.
+ @param FormSet FormSet data structure.
+ @retval TRUE Data is changed.
+ @retval FALSE Data is not changed.
**/
-VOID
-UpdateNvInfoInForm (
- IN FORM_BROWSER_FORMSET *FormSet,
- IN BOOLEAN SetValue
+BOOLEAN
+IsStorageDataChangedForFormSet (
+ IN FORM_BROWSER_FORMSET *FormSet
)
{
LIST_ENTRY *Link;
- FORM_BROWSER_FORM *Form;
-
- Link = GetFirstNode (&FormSet->FormListHead);
- while (!IsNull (&FormSet->FormListHead, Link)) {
- Form = FORM_BROWSER_FORM_FROM_LINK (Link);
+ FORMSET_STORAGE *Storage;
+ BROWSER_STORAGE *BrowserStorage;
+ CHAR16 *ConfigRespNew;
+ CHAR16 *ConfigRespOld;
+ BOOLEAN RetVal;
- Form->NvUpdateRequired = SetValue;
+ RetVal = FALSE;
+ ConfigRespNew = NULL;
+ ConfigRespOld = NULL;
- Link = GetNextNode (&FormSet->FormListHead, Link);
+ //
+ // Request current settings from Configuration Driver
+ //
+ Link = GetFirstNode (&FormSet->StorageListHead);
+ while (!IsNull (&FormSet->StorageListHead, Link)) {
+ Storage = FORMSET_STORAGE_FROM_LINK (Link);
+ Link = GetNextNode (&FormSet->StorageListHead, Link);
+
+ BrowserStorage = Storage->BrowserStorage;
+
+ if (BrowserStorage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {
+ continue;
+ }
+
+ if (Storage->ElementCount == 0) {
+ continue;
+ }
+
+ StorageToConfigResp (BrowserStorage, &ConfigRespNew, Storage->ConfigRequest, TRUE);
+ StorageToConfigResp (BrowserStorage, &ConfigRespOld, Storage->ConfigRequest, FALSE);
+ ASSERT (ConfigRespNew != NULL && ConfigRespOld != NULL);
+
+ if (StrCmp (ConfigRespNew, ConfigRespOld) != 0) {
+ RetVal = TRUE;
+ }
+
+ FreePool (ConfigRespNew);
+ ConfigRespNew = NULL;
+
+ FreePool (ConfigRespOld);
+ ConfigRespOld = NULL;
+
+ if (RetVal) {
+ break;
+ }
}
+
+ return RetVal;
}
+
/**
Find menu which will show next time.
@@ -981,170 +1890,92 @@ UpdateNvInfoInForm (
about the Selection, form and formset to be displayed.
On output, Selection return the screen item that is selected
by user.
- @param Repaint Whether need to repaint the menu.
- @param NewLine Whether need to show at new line.
+ @param SettingLevel Input Settting level, if it is FormLevel, just exit current form.
+ else, we need to exit current formset.
- @retval TRUE Need return.
- @retval FALSE No need to return.
+ @retval TRUE Exit current form.
+ @retval FALSE User press ESC and keep in current form.
**/
BOOLEAN
FindNextMenu (
- IN OUT UI_MENU_SELECTION *Selection,
- IN BOOLEAN *Repaint,
- IN BOOLEAN *NewLine
+ IN OUT UI_MENU_SELECTION *Selection,
+ IN BROWSER_SETTING_SCOPE SettingLevel
)
{
- UI_MENU_LIST *CurrentMenu;
- CHAR16 YesResponse;
- CHAR16 NoResponse;
- EFI_INPUT_KEY Key;
- BROWSER_SETTING_SCOPE Scope;
+ FORM_ENTRY_INFO *CurrentMenu;
+ FORM_ENTRY_INFO *ParentMenu;
+ BROWSER_SETTING_SCOPE Scope;
CurrentMenu = Selection->CurrentMenu;
+ ParentMenu = NULL;
+ Scope = FormSetLevel;
- if (CurrentMenu != NULL && CurrentMenu->Parent != NULL) {
+ if (CurrentMenu != NULL && (ParentMenu = UiFindParentMenu(CurrentMenu)) != NULL) {
//
// we have a parent, so go to the parent menu
//
- if (CompareGuid (&CurrentMenu->FormSetGuid, &CurrentMenu->Parent->FormSetGuid)) {
- //
- // The parent menu and current menu are in the same formset
- //
- Selection->Action = UI_ACTION_REFRESH_FORM;
- Scope = FormLevel;
- } else {
- Selection->Action = UI_ACTION_REFRESH_FORMSET;
- CopyMem (&Selection->FormSetGuid, &CurrentMenu->Parent->FormSetGuid, sizeof (EFI_GUID));
- Selection->Handle = CurrentMenu->Parent->HiiHandle;
- Scope = FormSetLevel;
- }
-
- //
- // Form Level Check whether the data is changed.
- //
- if ((gBrowserSettingScope == FormLevel && Selection->Form->NvUpdateRequired) ||
- (gBrowserSettingScope == FormSetLevel && IsNvUpdateRequired(Selection->FormSet) && Scope == FormSetLevel)) {
- gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
-
- YesResponse = gYesResponse[0];
- NoResponse = gNoResponse[0];
-
- //
- // If NV flag is up, prompt user
- //
- do {
- CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, gSaveChanges, 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 (Key.ScanCode == SCAN_ESC) {
+ if (CompareGuid (&CurrentMenu->FormSetGuid, &ParentMenu->FormSetGuid)) {
+ if (SettingLevel == FormSetLevel) {
//
- // User hits the ESC key, Ingore.
+ // Find a menu which has different formset guid with current.
//
- if (Repaint != NULL) {
- *Repaint = TRUE;
- }
- if (NewLine != NULL) {
- *NewLine = TRUE;
+ while (CompareGuid (&CurrentMenu->FormSetGuid, &ParentMenu->FormSetGuid)) {
+ CurrentMenu = ParentMenu;
+ if ((ParentMenu = UiFindParentMenu(CurrentMenu)) == NULL) {
+ break;
+ }
}
- Selection->Action = UI_ACTION_NONE;
- return FALSE;
- }
-
- if ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) == (YesResponse | UPPER_LOWER_CASE_OFFSET)) {
- //
- // If the user hits the YesResponse key
- //
- SubmitForm (Selection->FormSet, Selection->Form, Scope);
+ if (ParentMenu != NULL) {
+ Scope = FormSetLevel;
+ }
} else {
- //
- // If the user hits the NoResponse key
- //
- DiscardForm (Selection->FormSet, Selection->Form, Scope);
+ Scope = FormLevel;
}
+ } else {
+ Scope = FormSetLevel;
}
-
- Selection->Statement = NULL;
-
- Selection->FormId = CurrentMenu->Parent->FormId;
- Selection->QuestionId = CurrentMenu->Parent->QuestionId;
-
- //
- // Clear highlight record for this menu
- //
- CurrentMenu->QuestionId = 0;
- return FALSE;
- }
-
- if ((gClassOfVfr & FORMSET_CLASS_FRONT_PAGE) == FORMSET_CLASS_FRONT_PAGE) {
- //
- // We never exit FrontPage, so skip the ESC
- //
- Selection->Action = UI_ACTION_NONE;
- return FALSE;
}
//
- // We are going to leave current FormSet, so check uncommited data in this FormSet
+ // Form Level Check whether the data is changed.
//
- if (gBrowserSettingScope != SystemLevel && IsNvUpdateRequired(Selection->FormSet)) {
- gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
-
- YesResponse = gYesResponse[0];
- NoResponse = gNoResponse[0];
-
- //
- // If NV flag is up, prompt user
- //
- do {
- CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, gSaveChanges, 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 (Key.ScanCode == SCAN_ESC) {
- //
- // User hits the ESC key
- //
- if (Repaint != NULL) {
- *Repaint = TRUE;
- }
-
- if (NewLine != NULL) {
- *NewLine = TRUE;
- }
-
- Selection->Action = UI_ACTION_NONE;
+ if ((gBrowserSettingScope == FormLevel && IsNvUpdateRequiredForForm (Selection->Form)) ||
+ (gBrowserSettingScope == FormSetLevel && IsNvUpdateRequiredForFormSet(Selection->FormSet) && Scope == FormSetLevel)) {
+ if (!ProcessChangedData(Selection, Scope)) {
return FALSE;
}
+ }
- if ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) == (YesResponse | UPPER_LOWER_CASE_OFFSET)) {
- //
- // If the user hits the YesResponse key
- //
- SubmitForm (Selection->FormSet, Selection->Form, FormSetLevel);
+ if (ParentMenu != NULL) {
+ //
+ // ParentMenu is found. Then, go to it.
+ //
+ if (Scope == FormLevel) {
+ Selection->Action = UI_ACTION_REFRESH_FORM;
} else {
- //
- // If the user hits the NoResponse key
- //
- DiscardForm (Selection->FormSet, Selection->Form, FormSetLevel);
+ Selection->Action = UI_ACTION_REFRESH_FORMSET;
+ CopyMem (&Selection->FormSetGuid, &ParentMenu->FormSetGuid, sizeof (EFI_GUID));
+ Selection->Handle = ParentMenu->HiiHandle;
}
- }
- Selection->Statement = NULL;
- if (CurrentMenu != NULL) {
+ Selection->Statement = NULL;
+
+ Selection->FormId = ParentMenu->FormId;
+ Selection->QuestionId = ParentMenu->QuestionId;
+
+ //
+ // Clear highlight record for this menu
+ //
CurrentMenu->QuestionId = 0;
+ return FALSE;
}
+ //
+ // Current in root page, exit the SendForm
+ //
Selection->Action = UI_ACTION_EXIT;
+
return TRUE;
}
@@ -1244,18 +2075,19 @@ ProcessCallBackFunction (
if (Action == EFI_BROWSER_ACTION_CHANGED) {
switch (ActionRequest) {
case EFI_BROWSER_ACTION_REQUEST_RESET:
+ DiscardFormIsRequired = TRUE;
gResetRequired = TRUE;
- Selection->Action = UI_ACTION_EXIT;
+ NeedExit = TRUE;
break;
case EFI_BROWSER_ACTION_REQUEST_SUBMIT:
SubmitFormIsRequired = TRUE;
- Selection->Action = UI_ACTION_EXIT;
+ NeedExit = TRUE;
break;
case EFI_BROWSER_ACTION_REQUEST_EXIT:
DiscardFormIsRequired = TRUE;
- Selection->Action = UI_ACTION_EXIT;
+ NeedExit = TRUE;
break;
case EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT:
@@ -1266,7 +2098,7 @@ ProcessCallBackFunction (
case EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT:
DiscardFormIsRequired = TRUE;
- SettingLevel = FormLevel;
+ SettingLevel = FormLevel;
NeedExit = TRUE;
break;
@@ -1319,7 +2151,7 @@ ProcessCallBackFunction (
}
if (NeedExit) {
- FindNextMenu (Selection, NULL, NULL);
+ FindNextMenu (Selection, SettingLevel);
}
return Status;
@@ -1399,9 +2231,7 @@ SetupBrowser (
EFI_HANDLE NotifyHandle;
FORM_BROWSER_STATEMENT *Statement;
EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;
- EFI_INPUT_KEY Key;
- gMenuRefreshHead = NULL;
ConfigAccess = Selection->FormSet->ConfigAccess;
//
@@ -1422,21 +2252,17 @@ SetupBrowser (
//
// Initialize current settings of Questions in this FormSet
//
- Status = InitializeCurrentSetting (Selection->FormSet);
- if (EFI_ERROR (Status)) {
- goto Done;
- }
+ InitializeCurrentSetting (Selection->FormSet);
//
- // Update gOldFormSet on maintain back up FormSet list.
- // And, make gOldFormSet point to current FormSet.
+ // Initilize Action field.
//
- if (gOldFormSet != NULL) {
- RemoveEntryList (&gOldFormSet->Link);
- DestroyFormSet (gOldFormSet);
- }
- gOldFormSet = Selection->FormSet;
- InsertTailList (&gBrowserFormSetList, &gOldFormSet->Link);
+ Selection->Action = UI_ACTION_REFRESH_FORM;
+
+ //
+ // Clean the mCurFakeQestId value is formset refreshed.
+ //
+ mCurFakeQestId = 0;
do {
//
@@ -1479,10 +2305,7 @@ SetupBrowser (
//
// Form is suppressed.
//
- do {
- CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, gFormSuppress, gPressEnter, gEmptyString);
- } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
-
+ gBrowserStatus = BROWSER_FORM_SUPPRESS;
Status = EFI_NOT_FOUND;
goto Done;
}
@@ -1497,7 +2320,6 @@ SetupBrowser (
((Selection->Handle != mCurrentHiiHandle) ||
(!CompareGuid (&Selection->FormSetGuid, &mCurrentFormSetGuid)) ||
(Selection->FormId != mCurrentFormId))) {
-
//
// Keep current form information
//
@@ -1511,12 +2333,6 @@ SetupBrowser (
}
//
- // EXIT requests to close form.
- //
- if (Selection->Action == UI_ACTION_EXIT) {
- goto Done;
- }
- //
// IFR is updated during callback of open form, force to reparse the IFR binary
//
if (mHiiPackageListUpdated) {
@@ -1535,12 +2351,6 @@ SetupBrowser (
}
//
- // EXIT requests to close form.
- //
- if (Selection->Action == UI_ACTION_EXIT) {
- goto Done;
- }
- //
// IFR is updated during callback of read value, force to reparse the IFR binary
//
if (mHiiPackageListUpdated) {
@@ -1550,14 +2360,9 @@ SetupBrowser (
}
//
- // Displays the Header and Footer borders
- //
- DisplayPageFrame (Selection);
-
- //
// Display form
//
- Status = DisplayForm (Selection);
+ Status = DisplayForm ();
if (EFI_ERROR (Status)) {
goto Done;
}
@@ -1567,20 +2372,16 @@ SetupBrowser (
//
Statement = Selection->Statement;
if (Statement != NULL) {
- if ((Statement->QuestionFlags & EFI_IFR_FLAG_RESET_REQUIRED) == EFI_IFR_FLAG_RESET_REQUIRED) {
- gResetRequired = TRUE;
- }
-
if ((ConfigAccess != NULL) &&
((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) == EFI_IFR_FLAG_CALLBACK) &&
(Statement->Operand != EFI_IFR_PASSWORD_OP)) {
- Status = ProcessCallBackFunction(Selection, Statement, EFI_BROWSER_ACTION_CHANGING, FALSE);
- if (Statement->Operand == EFI_IFR_REF_OP && Selection->Action != UI_ACTION_EXIT) {
+ Status = ProcessCallBackFunction(Selection, Statement, EFI_BROWSER_ACTION_CHANGING, FALSE);
+ if (Statement->Operand == EFI_IFR_REF_OP) {
//
// Process dynamic update ref opcode.
//
if (!EFI_ERROR (Status)) {
- Status = ProcessGotoOpCode(Statement, Selection, NULL, NULL);
+ Status = ProcessGotoOpCode(Statement, Selection);
}
//
@@ -1602,6 +2403,27 @@ SetupBrowser (
}
//
+ // Check whether Exit flag is TRUE.
+ //
+ if (gExitRequired) {
+ switch (gBrowserSettingScope) {
+ case SystemLevel:
+ Selection->Action = UI_ACTION_EXIT;
+ break;
+
+ case FormSetLevel:
+ case FormLevel:
+ FindNextMenu (Selection, gBrowserSettingScope);
+ break;
+
+ default:
+ break;
+ }
+
+ gExitRequired = FALSE;
+ }
+
+ //
// Before exit the form, invoke ConfigAccess.Callback() with EFI_BROWSER_ACTION_FORM_CLOSE
// for each question with callback flag.
//
diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/Print.c b/MdeModulePkg/Universal/SetupBrowserDxe/Print.c
deleted file mode 100644
index eeadf2494..000000000
--- a/MdeModulePkg/Universal/SetupBrowserDxe/Print.c
+++ /dev/null
@@ -1,272 +0,0 @@
-/** @file
-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 %
-
-
-Copyright (c) 2004 - 2012, Intel Corporation. All rights reserved.<BR>
-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 "Setup.h"
-
-/**
- The internal function prints to the EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
- protocol instance.
-
- @param Column The position of the output string.
- @param Row The position of the output string.
- @param Out The EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL instance.
- @param Fmt The format string.
- @param Args The additional argument for the variables in the format string.
-
- @return Number of Unicode character printed.
-
-**/
-UINTN
-PrintInternal (
- IN UINTN Column,
- IN UINTN Row,
- IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *Out,
- IN CHAR16 *Fmt,
- IN VA_LIST Args
- )
-{
- CHAR16 *Buffer;
- CHAR16 *BackupBuffer;
- UINTN Index;
- UINTN PreviousIndex;
- UINTN Count;
-
- //
- // 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;
- Count = 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]);
- Count += StrLen (&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]);
- Count += StrLen (&BackupBuffer[PreviousIndex]);
-
- FreePool (Buffer);
- FreePool (BackupBuffer);
- return Count;
-}
-
-
-/**
- Prints a formatted unicode string to the default console.
-
- @param Fmt Format string
- @param ... Variable argument list for format string.
-
- @return Length of string printed to the console.
-
-**/
-UINTN
-EFIAPI
-ConsolePrint (
- IN CHAR16 *Fmt,
- ...
- )
-{
- VA_LIST Args;
- UINTN LengthOfPrinted;
-
- VA_START (Args, Fmt);
- LengthOfPrinted = PrintInternal ((UINTN) -1, (UINTN) -1, gST->ConOut, Fmt, Args);
- VA_END (Args);
- return LengthOfPrinted;
-}
-
-
-/**
- Prints a unicode string to the default console,
- using L"%s" format.
-
- @param String String pointer.
-
- @return Length of string printed to the console
-
-**/
-UINTN
-PrintString (
- IN CHAR16 *String
- )
-{
- return ConsolePrint (L"%s", String);
-}
-
-
-/**
- Prints a chracter to the default console,
- using L"%c" format.
-
- @param Character Character to print.
-
- @return Length of string printed to the console.
-
-**/
-UINTN
-PrintChar (
- CHAR16 Character
- )
-{
- return ConsolePrint (L"%c", Character);
-}
-
-
-/**
- Prints a formatted unicode string to the default console, at
- the supplied cursor position.
-
- @param Column The cursor position to print the string at.
- @param Row The cursor position to print the string at.
- @param Fmt Format string.
- @param ... Variable argument list for format string.
-
- @return Length of string printed to the console
-
-**/
-UINTN
-EFIAPI
-PrintAt (
- IN UINTN Column,
- IN UINTN Row,
- IN CHAR16 *Fmt,
- ...
- )
-{
- VA_LIST Args;
- UINTN LengthOfPrinted;
-
- VA_START (Args, Fmt);
- LengthOfPrinted = PrintInternal (Column, Row, gST->ConOut, Fmt, Args);
- VA_END (Args);
- return LengthOfPrinted;
-}
-
-
-/**
- Prints a unicode string to the default console, at
- the supplied cursor position, using L"%s" format.
-
- @param Column The cursor position to print the string at.
- @param Row The cursor position to print the string at
- @param String String pointer.
-
- @return Length of string printed to the console
-
-**/
-UINTN
-PrintStringAt (
- IN UINTN Column,
- IN UINTN Row,
- IN CHAR16 *String
- )
-{
- return PrintAt (Column, Row, L"%s", String);
-}
-
-
-/**
- Prints a chracter to the default console, at
- the supplied cursor position, using L"%c" format.
-
- @param Column The cursor position to print the string at.
- @param Row The cursor position to print the string at.
- @param Character Character to print.
-
- @return Length of string printed to the console.
-
-**/
-UINTN
-PrintCharAt (
- IN UINTN Column,
- IN UINTN Row,
- CHAR16 Character
- )
-{
- return PrintAt (Column, Row, L"%c", Character);
-}
diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/ProcessOptions.c b/MdeModulePkg/Universal/SetupBrowserDxe/ProcessOptions.c
deleted file mode 100644
index fecb98e8b..000000000
--- a/MdeModulePkg/Universal/SetupBrowserDxe/ProcessOptions.c
+++ /dev/null
@@ -1,1075 +0,0 @@
-/** @file
-Implementation for handling the User Interface option processing.
-
-
-Copyright (c) 2004 - 2012, Intel Corporation. All rights reserved.<BR>
-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 "Setup.h"
-
-
-/**
- Process Question Config.
-
- @param Selection The UI menu selection.
- @param Question The Question to be peocessed.
-
- @retval EFI_SUCCESS Question Config process success.
- @retval Other Question Config process fail.
-
-**/
-EFI_STATUS
-ProcessQuestionConfig (
- IN UI_MENU_SELECTION *Selection,
- IN FORM_BROWSER_STATEMENT *Question
- )
-{
- EFI_STATUS Status;
- CHAR16 *ConfigResp;
- CHAR16 *Progress;
- EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;
-
- if (Question->QuestionConfig == 0) {
- return EFI_SUCCESS;
- }
-
- //
- // Get <ConfigResp>
- //
- ConfigResp = GetToken (Question->QuestionConfig, Selection->FormSet->HiiHandle);
- if (ConfigResp == NULL) {
- return EFI_NOT_FOUND;
- }
-
- //
- // Send config to Configuration Driver
- //
- ConfigAccess = Selection->FormSet->ConfigAccess;
- if (ConfigAccess == NULL) {
- return EFI_UNSUPPORTED;
- }
- Status = ConfigAccess->RouteConfig (
- ConfigAccess,
- ConfigResp,
- &Progress
- );
-
- return Status;
-}
-
-
-/**
- Search an Option of a Question by its value.
-
- @param Question The Question
- @param OptionValue Value for Option to be searched.
-
- @retval Pointer Pointer to the found Option.
- @retval NULL Option not found.
-
-**/
-QUESTION_OPTION *
-ValueToOption (
- IN FORM_BROWSER_STATEMENT *Question,
- IN EFI_HII_VALUE *OptionValue
- )
-{
- LIST_ENTRY *Link;
- QUESTION_OPTION *Option;
- INTN Result;
-
- Link = GetFirstNode (&Question->OptionListHead);
- while (!IsNull (&Question->OptionListHead, Link)) {
- Option = QUESTION_OPTION_FROM_LINK (Link);
-
- if ((CompareHiiValue (&Option->Value, OptionValue, &Result, NULL) == EFI_SUCCESS) && (Result == 0)) {
- //
- // Check the suppressif condition, only a valid option can be return.
- //
- if ((Option->SuppressExpression == NULL) ||
- ((EvaluateExpressionList(Option->SuppressExpression, FALSE, NULL, NULL) == ExpressFalse))) {
- return Option;
- }
- }
-
- Link = GetNextNode (&Question->OptionListHead, Link);
- }
-
- return NULL;
-}
-
-
-/**
- Return data element in an Array by its Index.
-
- @param Array The data array.
- @param Type Type of the data in this array.
- @param Index Zero based index for data in this array.
-
- @retval Value The data to be returned
-
-**/
-UINT64
-GetArrayData (
- IN VOID *Array,
- IN UINT8 Type,
- IN UINTN Index
- )
-{
- UINT64 Data;
-
- ASSERT (Array != NULL);
-
- Data = 0;
- switch (Type) {
- case EFI_IFR_TYPE_NUM_SIZE_8:
- Data = (UINT64) *(((UINT8 *) Array) + Index);
- break;
-
- case EFI_IFR_TYPE_NUM_SIZE_16:
- Data = (UINT64) *(((UINT16 *) Array) + Index);
- break;
-
- case EFI_IFR_TYPE_NUM_SIZE_32:
- Data = (UINT64) *(((UINT32 *) Array) + Index);
- break;
-
- case EFI_IFR_TYPE_NUM_SIZE_64:
- Data = (UINT64) *(((UINT64 *) Array) + Index);
- break;
-
- default:
- break;
- }
-
- return Data;
-}
-
-
-/**
- Set value of a data element in an Array by its Index.
-
- @param Array The data array.
- @param Type Type of the data in this array.
- @param Index Zero based index for data in this array.
- @param Value The value to be set.
-
-**/
-VOID
-SetArrayData (
- IN VOID *Array,
- IN UINT8 Type,
- IN UINTN Index,
- IN UINT64 Value
- )
-{
-
- ASSERT (Array != NULL);
-
- switch (Type) {
- case EFI_IFR_TYPE_NUM_SIZE_8:
- *(((UINT8 *) Array) + Index) = (UINT8) Value;
- break;
-
- case EFI_IFR_TYPE_NUM_SIZE_16:
- *(((UINT16 *) Array) + Index) = (UINT16) Value;
- break;
-
- case EFI_IFR_TYPE_NUM_SIZE_32:
- *(((UINT32 *) Array) + Index) = (UINT32) Value;
- break;
-
- case EFI_IFR_TYPE_NUM_SIZE_64:
- *(((UINT64 *) Array) + Index) = (UINT64) Value;
- break;
-
- default:
- break;
- }
-}
-
-/**
- Check whether this value already in the array, if yes, return the index.
-
- @param Array The data array.
- @param Type Type of the data in this array.
- @param Value The value to be find.
- @param Index The index in the array which has same value with Value.
-
- @retval TRUE Found the value in the array.
- @retval FALSE Not found the value.
-
-**/
-BOOLEAN
-FindArrayData (
- IN VOID *Array,
- IN UINT8 Type,
- IN UINT64 Value,
- OUT UINTN *Index OPTIONAL
- )
-{
- UINTN Count;
- UINT64 TmpValue;
-
- ASSERT (Array != NULL);
-
- Count = 0;
- TmpValue = 0;
-
- while ((TmpValue = GetArrayData (Array, Type, Count)) != 0) {
- if (Value == TmpValue) {
- if (Index != NULL) {
- *Index = Count;
- }
- return TRUE;
- }
-
- Count ++;
- }
-
- return FALSE;
-}
-
-/**
- Print Question Value according to it's storage width and display attributes.
-
- @param Question The Question to be printed.
- @param FormattedNumber Buffer for output string.
- @param BufferSize The FormattedNumber buffer size in bytes.
-
- @retval EFI_SUCCESS Print success.
- @retval EFI_BUFFER_TOO_SMALL Buffer size is not enough for formatted number.
-
-**/
-EFI_STATUS
-PrintFormattedNumber (
- IN FORM_BROWSER_STATEMENT *Question,
- IN OUT CHAR16 *FormattedNumber,
- IN UINTN BufferSize
- )
-{
- INT64 Value;
- CHAR16 *Format;
- EFI_HII_VALUE *QuestionValue;
-
- if (BufferSize < (21 * sizeof (CHAR16))) {
- return EFI_BUFFER_TOO_SMALL;
- }
-
- QuestionValue = &Question->HiiValue;
-
- Value = (INT64) QuestionValue->Value.u64;
- switch (Question->Flags & EFI_IFR_DISPLAY) {
- case EFI_IFR_DISPLAY_INT_DEC:
- switch (QuestionValue->Type) {
- case EFI_IFR_NUMERIC_SIZE_1:
- Value = (INT64) ((INT8) QuestionValue->Value.u8);
- break;
-
- case EFI_IFR_NUMERIC_SIZE_2:
- Value = (INT64) ((INT16) QuestionValue->Value.u16);
- break;
-
- case EFI_IFR_NUMERIC_SIZE_4:
- Value = (INT64) ((INT32) QuestionValue->Value.u32);
- break;
-
- case EFI_IFR_NUMERIC_SIZE_8:
- default:
- break;
- }
-
- if (Value < 0) {
- Value = -Value;
- Format = L"-%ld";
- } else {
- Format = L"%ld";
- }
- break;
-
- case EFI_IFR_DISPLAY_UINT_DEC:
- Format = L"%ld";
- break;
-
- case EFI_IFR_DISPLAY_UINT_HEX:
- Format = L"%lx";
- break;
-
- default:
- return EFI_UNSUPPORTED;
- break;
- }
-
- UnicodeSPrint (FormattedNumber, BufferSize, Format, Value);
-
- return EFI_SUCCESS;
-}
-
-
-/**
- Password may be stored as encrypted by Configuration Driver. When change a
- password, user will be challenged with old password. To validate user input old
- password, we will send the clear text to Configuration Driver via Callback().
- Configuration driver is responsible to check the passed in password and return
- the validation result. If validation pass, state machine in password Callback()
- will transit from BROWSER_STATE_VALIDATE_PASSWORD to BROWSER_STATE_SET_PASSWORD.
- After user type in new password twice, Callback() will be invoked to send the
- new password to Configuration Driver.
-
- @param Selection Pointer to UI_MENU_SELECTION.
- @param MenuOption The MenuOption for this password Question.
- @param String The clear text of password.
-
- @retval EFI_NOT_AVAILABLE_YET Callback() request to terminate password input.
- @return In state of BROWSER_STATE_VALIDATE_PASSWORD:
- @retval EFI_SUCCESS Password correct, Browser will prompt for new
- password.
- @retval EFI_NOT_READY Password incorrect, Browser will show error
- message.
- @retval Other Browser will do nothing.
- @return In state of BROWSER_STATE_SET_PASSWORD:
- @retval EFI_SUCCESS Set password success.
- @retval Other Set password failed.
-
-**/
-EFI_STATUS
-PasswordCallback (
- IN UI_MENU_SELECTION *Selection,
- IN UI_MENU_OPTION *MenuOption,
- IN CHAR16 *String
- )
-{
- EFI_STATUS Status;
- EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;
- EFI_BROWSER_ACTION_REQUEST ActionRequest;
- EFI_IFR_TYPE_VALUE IfrTypeValue;
-
- ConfigAccess = Selection->FormSet->ConfigAccess;
- if (ConfigAccess == NULL) {
- return EFI_UNSUPPORTED;
- }
-
- //
- // Prepare password string in HII database
- //
- if (String != NULL) {
- IfrTypeValue.string = NewString (String, Selection->FormSet->HiiHandle);
- } else {
- IfrTypeValue.string = 0;
- }
-
- //
- // Send password to Configuration Driver for validation
- //
- Status = ConfigAccess->Callback (
- ConfigAccess,
- EFI_BROWSER_ACTION_CHANGING,
- MenuOption->ThisTag->QuestionId,
- MenuOption->ThisTag->HiiValue.Type,
- &IfrTypeValue,
- &ActionRequest
- );
-
- //
- // Remove password string from HII database
- //
- if (String != NULL) {
- DeleteString (IfrTypeValue.string, Selection->FormSet->HiiHandle);
- }
-
- return Status;
-}
-
-
-/**
- Display error message for invalid password.
-
-**/
-VOID
-PasswordInvalid (
- VOID
- )
-{
- EFI_INPUT_KEY Key;
-
- //
- // Invalid password, prompt error message
- //
- do {
- CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, gPassowordInvalid, gPressEnter, gEmptyString);
- } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
-}
-
-
-/**
- Process a Question's Option (whether selected or un-selected).
-
- @param Selection Pointer to UI_MENU_SELECTION.
- @param MenuOption The MenuOption for this Question.
- @param Selected TRUE: if Question is selected.
- @param OptionString Pointer of the Option String to be displayed.
-
- @retval EFI_SUCCESS Question Option process success.
- @retval Other Question Option process fail.
-
-**/
-EFI_STATUS
-ProcessOptions (
- IN UI_MENU_SELECTION *Selection,
- IN UI_MENU_OPTION *MenuOption,
- IN BOOLEAN Selected,
- OUT CHAR16 **OptionString
- )
-{
- EFI_STATUS Status;
- CHAR16 *StringPtr;
- CHAR16 *TempString;
- UINTN Index;
- FORM_BROWSER_STATEMENT *Question;
- CHAR16 FormattedNumber[21];
- UINT16 Number;
- CHAR16 Character[2];
- EFI_INPUT_KEY Key;
- UINTN BufferSize;
- QUESTION_OPTION *OneOfOption;
- LIST_ENTRY *Link;
- EFI_HII_VALUE HiiValue;
- EFI_HII_VALUE *QuestionValue;
- UINT16 Maximum;
- QUESTION_OPTION *Option;
- UINTN Index2;
- UINT8 *ValueArray;
- UINT8 ValueType;
- EFI_STRING_ID StringId;
-
- Status = EFI_SUCCESS;
-
- StringPtr = NULL;
- Character[1] = L'\0';
- *OptionString = NULL;
- StringId = 0;
-
- ZeroMem (FormattedNumber, 21 * sizeof (CHAR16));
- BufferSize = (gOptionBlockWidth + 1) * 2 * gScreenDimensions.BottomRow;
-
- Question = MenuOption->ThisTag;
- QuestionValue = &Question->HiiValue;
- Maximum = (UINT16) Question->Maximum;
-
- ValueArray = Question->BufferValue;
- ValueType = Question->ValueType;
-
- switch (Question->Operand) {
- case EFI_IFR_ORDERED_LIST_OP:
- //
- // Check whether there are Options of this OrderedList
- //
- if (IsListEmpty (&Question->OptionListHead)) {
- break;
- }
- //
- // Initialize Option value array
- //
- if (GetArrayData (ValueArray, ValueType, 0) == 0) {
- GetQuestionDefault (Selection->FormSet, Selection->Form, Question, 0);
- }
-
- if (Selected) {
- //
- // Go ask for input
- //
- Status = GetSelectionInputPopUp (Selection, MenuOption);
- } else {
- //
- // We now know how many strings we will have, so we can allocate the
- // space required for the array or strings.
- //
- *OptionString = AllocateZeroPool (Question->MaxContainers * BufferSize);
- ASSERT (*OptionString);
-
- HiiValue.Type = ValueType;
- HiiValue.Value.u64 = 0;
- for (Index = 0; Index < Question->MaxContainers; Index++) {
- HiiValue.Value.u64 = GetArrayData (ValueArray, ValueType, Index);
- if (HiiValue.Value.u64 == 0) {
- //
- // Values for the options in ordered lists should never be a 0
- //
- break;
- }
-
- OneOfOption = ValueToOption (Question, &HiiValue);
- if (OneOfOption == NULL) {
- //
- // Show error message
- //
- do {
- CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, gOptionMismatch, gPressEnter, gEmptyString);
- } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
-
- //
- // The initial value of the orderedlist is invalid, force to be valid value
- //
- Link = GetFirstNode (&Question->OptionListHead);
- Index2 = 0;
- while (!IsNull (&Question->OptionListHead, Link) && Index2 < Question->MaxContainers) {
- Option = QUESTION_OPTION_FROM_LINK (Link);
- Link = GetNextNode (&Question->OptionListHead, Link);
- if ((Option->SuppressExpression != NULL) &&
- ((EvaluateExpressionList(Option->SuppressExpression, FALSE, NULL, NULL) == ExpressSuppress))) {
- continue;
- }
- SetArrayData (ValueArray, ValueType, Index2, Option->Value.Value.u64);
- Index2++;
- }
- SetArrayData (ValueArray, ValueType, Index2, 0);
-
- Status = SetQuestionValue (Selection->FormSet, Selection->Form, Question, GetSetValueWithEditBuffer);
- UpdateStatusBar (Selection, NV_UPDATE_REQUIRED, Question->QuestionFlags, TRUE);
-
- FreePool (*OptionString);
- *OptionString = NULL;
- return EFI_NOT_FOUND;
- }
-
- Character[0] = LEFT_ONEOF_DELIMITER;
- NewStrCat (OptionString[0], Character);
- StringPtr = GetToken (OneOfOption->Text, Selection->Handle);
- ASSERT (StringPtr != NULL);
- NewStrCat (OptionString[0], StringPtr);
- Character[0] = RIGHT_ONEOF_DELIMITER;
- NewStrCat (OptionString[0], Character);
- Character[0] = CHAR_CARRIAGE_RETURN;
- NewStrCat (OptionString[0], Character);
- FreePool (StringPtr);
- }
-
- //
- // Search the other options, try to find the one not in the container.
- //
- Link = GetFirstNode (&Question->OptionListHead);
- while (!IsNull (&Question->OptionListHead, Link)) {
- OneOfOption = QUESTION_OPTION_FROM_LINK (Link);
- Link = GetNextNode (&Question->OptionListHead, Link);
- if ((OneOfOption->SuppressExpression != NULL) &&
- ((EvaluateExpressionList(OneOfOption->SuppressExpression, FALSE, NULL, NULL) == ExpressSuppress))) {
- continue;
- }
-
- if (FindArrayData (ValueArray, ValueType, OneOfOption->Value.Value.u64, NULL)) {
- continue;
- }
-
- SetArrayData (ValueArray, ValueType, Index++, OneOfOption->Value.Value.u64);
-
- Character[0] = LEFT_ONEOF_DELIMITER;
- NewStrCat (OptionString[0], Character);
- StringPtr = GetToken (OneOfOption->Text, Selection->Handle);
- ASSERT (StringPtr != NULL);
- NewStrCat (OptionString[0], StringPtr);
- Character[0] = RIGHT_ONEOF_DELIMITER;
- NewStrCat (OptionString[0], Character);
- Character[0] = CHAR_CARRIAGE_RETURN;
- NewStrCat (OptionString[0], Character);
- FreePool (StringPtr);
- }
- }
- break;
-
- case EFI_IFR_ONE_OF_OP:
- //
- // Check whether there are Options of this OneOf
- //
- if (IsListEmpty (&Question->OptionListHead)) {
- break;
- }
- if (Selected) {
- //
- // Go ask for input
- //
- Status = GetSelectionInputPopUp (Selection, MenuOption);
- } else {
- *OptionString = AllocateZeroPool (BufferSize);
- ASSERT (*OptionString);
-
- OneOfOption = ValueToOption (Question, QuestionValue);
- if (OneOfOption == NULL) {
- //
- // Show error message
- //
- do {
- CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, gOptionMismatch, gPressEnter, gEmptyString);
- } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
-
- //
- // Force the Question value to be valid
- //
- Link = GetFirstNode (&Question->OptionListHead);
- while (!IsNull (&Question->OptionListHead, Link)) {
- Option = QUESTION_OPTION_FROM_LINK (Link);
-
- if ((Option->SuppressExpression == NULL) ||
- (EvaluateExpressionList(Option->SuppressExpression, FALSE, NULL, NULL) == ExpressFalse)) {
- CopyMem (QuestionValue, &Option->Value, sizeof (EFI_HII_VALUE));
- SetQuestionValue (Selection->FormSet, Selection->Form, Question, GetSetValueWithEditBuffer);
- UpdateStatusBar (Selection, NV_UPDATE_REQUIRED, Question->QuestionFlags, TRUE);
- break;
- }
-
- Link = GetNextNode (&Question->OptionListHead, Link);
- }
-
- FreePool (*OptionString);
- *OptionString = NULL;
- return EFI_NOT_FOUND;
- }
-
- Character[0] = LEFT_ONEOF_DELIMITER;
- NewStrCat (OptionString[0], Character);
- StringPtr = GetToken (OneOfOption->Text, Selection->Handle);
- ASSERT (StringPtr != NULL);
- NewStrCat (OptionString[0], StringPtr);
- Character[0] = RIGHT_ONEOF_DELIMITER;
- NewStrCat (OptionString[0], Character);
-
- FreePool (StringPtr);
- }
- break;
-
- case EFI_IFR_CHECKBOX_OP:
- *OptionString = AllocateZeroPool (BufferSize);
- ASSERT (*OptionString);
-
- *OptionString[0] = LEFT_CHECKBOX_DELIMITER;
-
- if (Selected) {
- //
- // Since this is a BOOLEAN operation, flip it upon selection
- //
- QuestionValue->Value.b = (BOOLEAN) (QuestionValue->Value.b ? FALSE : TRUE);
-
- //
- // Perform inconsistent check
- //
- Status = ValidateQuestion (Selection->FormSet, Selection->Form, Question, EFI_HII_EXPRESSION_INCONSISTENT_IF);
- if (EFI_ERROR (Status)) {
- //
- // Inconsistent check fail, restore Question Value
- //
- QuestionValue->Value.b = (BOOLEAN) (QuestionValue->Value.b ? FALSE : TRUE);
- FreePool (*OptionString);
- *OptionString = NULL;
- return Status;
- }
-
- //
- // Save Question value
- //
- Status = SetQuestionValue (Selection->FormSet, Selection->Form, Question, GetSetValueWithEditBuffer);
- UpdateStatusBar (Selection, NV_UPDATE_REQUIRED, Question->QuestionFlags, TRUE);
- }
-
- if (QuestionValue->Value.b) {
- *(OptionString[0] + 1) = CHECK_ON;
- } else {
- *(OptionString[0] + 1) = CHECK_OFF;
- }
- *(OptionString[0] + 2) = RIGHT_CHECKBOX_DELIMITER;
- break;
-
- case EFI_IFR_NUMERIC_OP:
- if (Selected) {
- //
- // Go ask for input
- //
- Status = GetNumericInput (Selection, MenuOption);
- } else {
- *OptionString = AllocateZeroPool (BufferSize);
- ASSERT (*OptionString);
-
- *OptionString[0] = LEFT_NUMERIC_DELIMITER;
-
- //
- // Formatted print
- //
- PrintFormattedNumber (Question, FormattedNumber, 21 * sizeof (CHAR16));
- Number = (UINT16) GetStringWidth (FormattedNumber);
- CopyMem (OptionString[0] + 1, FormattedNumber, Number);
-
- *(OptionString[0] + Number / 2) = RIGHT_NUMERIC_DELIMITER;
- }
- break;
-
- case EFI_IFR_DATE_OP:
- if (Selected) {
- //
- // This is similar to numerics
- //
- Status = GetNumericInput (Selection, MenuOption);
- } else {
- *OptionString = AllocateZeroPool (BufferSize);
- ASSERT (*OptionString);
-
- switch (MenuOption->Sequence) {
- case 0:
- *OptionString[0] = LEFT_NUMERIC_DELIMITER;
- UnicodeSPrint (OptionString[0] + 1, 21 * sizeof (CHAR16), L"%02d", QuestionValue->Value.date.Month);
- *(OptionString[0] + 3) = DATE_SEPARATOR;
- break;
-
- case 1:
- SetUnicodeMem (OptionString[0], 4, L' ');
- UnicodeSPrint (OptionString[0] + 4, 21 * sizeof (CHAR16), L"%02d", QuestionValue->Value.date.Day);
- *(OptionString[0] + 6) = DATE_SEPARATOR;
- break;
-
- case 2:
- SetUnicodeMem (OptionString[0], 7, L' ');
- UnicodeSPrint (OptionString[0] + 7, 21 * sizeof (CHAR16), L"%04d", QuestionValue->Value.date.Year);
- *(OptionString[0] + 11) = RIGHT_NUMERIC_DELIMITER;
- break;
- }
- }
- break;
-
- case EFI_IFR_TIME_OP:
- if (Selected) {
- //
- // This is similar to numerics
- //
- Status = GetNumericInput (Selection, MenuOption);
- } else {
- *OptionString = AllocateZeroPool (BufferSize);
- ASSERT (*OptionString);
-
- switch (MenuOption->Sequence) {
- case 0:
- *OptionString[0] = LEFT_NUMERIC_DELIMITER;
- UnicodeSPrint (OptionString[0] + 1, 21 * sizeof (CHAR16), L"%02d", QuestionValue->Value.time.Hour);
- *(OptionString[0] + 3) = TIME_SEPARATOR;
- break;
-
- case 1:
- SetUnicodeMem (OptionString[0], 4, L' ');
- UnicodeSPrint (OptionString[0] + 4, 21 * sizeof (CHAR16), L"%02d", QuestionValue->Value.time.Minute);
- *(OptionString[0] + 6) = TIME_SEPARATOR;
- break;
-
- case 2:
- SetUnicodeMem (OptionString[0], 7, L' ');
- UnicodeSPrint (OptionString[0] + 7, 21 * sizeof (CHAR16), L"%02d", QuestionValue->Value.time.Second);
- *(OptionString[0] + 9) = RIGHT_NUMERIC_DELIMITER;
- break;
- }
- }
- break;
-
- case EFI_IFR_STRING_OP:
- if (Selected) {
- StringPtr = AllocateZeroPool ((Maximum + 1) * sizeof (CHAR16));
- ASSERT (StringPtr);
- CopyMem(StringPtr, Question->BufferValue, Maximum * sizeof (CHAR16));
-
- Status = ReadString (MenuOption, gPromptForData, StringPtr);
- if (!EFI_ERROR (Status)) {
- HiiSetString(Selection->FormSet->HiiHandle, Question->HiiValue.Value.string, StringPtr, NULL);
- Status = ValidateQuestion(Selection->FormSet, Selection->Form, Question, EFI_HII_EXPRESSION_INCONSISTENT_IF);
- if (EFI_ERROR (Status)) {
- HiiSetString(Selection->FormSet->HiiHandle, Question->HiiValue.Value.string, (CHAR16*)Question->BufferValue, NULL);
- } else {
- CopyMem (Question->BufferValue, StringPtr, Maximum * sizeof (CHAR16));
- SetQuestionValue (Selection->FormSet, Selection->Form, Question, GetSetValueWithEditBuffer);
-
- UpdateStatusBar (Selection, NV_UPDATE_REQUIRED, Question->QuestionFlags, TRUE);
- }
- }
-
- FreePool (StringPtr);
- } else {
- *OptionString = AllocateZeroPool (BufferSize);
- ASSERT (*OptionString);
-
- if (((CHAR16 *) Question->BufferValue)[0] == 0x0000) {
- *(OptionString[0]) = '_';
- } else {
- if ((Maximum * sizeof (CHAR16)) < BufferSize) {
- BufferSize = Maximum * sizeof (CHAR16);
- }
- CopyMem (OptionString[0], (CHAR16 *) Question->BufferValue, BufferSize);
- }
- }
- break;
-
- case EFI_IFR_PASSWORD_OP:
- if (Selected) {
- StringPtr = AllocateZeroPool ((Maximum + 1) * sizeof (CHAR16));
- ASSERT (StringPtr);
-
- //
- // For interactive passwords, old password is validated by callback
- //
- if ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) {
- //
- // Use a NULL password to test whether old password is required
- //
- *StringPtr = 0;
- Status = PasswordCallback (Selection, MenuOption, StringPtr);
- if (Status == EFI_NOT_AVAILABLE_YET || Status == EFI_UNSUPPORTED) {
- //
- // Callback is not supported, or
- // Callback request to terminate password input
- //
- FreePool (StringPtr);
- return EFI_SUCCESS;
- }
-
- if (EFI_ERROR (Status)) {
- //
- // Old password exist, ask user for the old password
- //
- Status = ReadString (MenuOption, gPromptForPassword, StringPtr);
- if (EFI_ERROR (Status)) {
- FreePool (StringPtr);
- return Status;
- }
-
- //
- // Check user input old password
- //
- Status = PasswordCallback (Selection, MenuOption, StringPtr);
- if (EFI_ERROR (Status)) {
- if (Status == EFI_NOT_READY) {
- //
- // Typed in old password incorrect
- //
- PasswordInvalid ();
- } else {
- Status = EFI_SUCCESS;
- }
-
- FreePool (StringPtr);
- return Status;
- }
- }
- } else {
- //
- // For non-interactive password, validate old password in local
- //
- if (*((CHAR16 *) Question->BufferValue) != 0) {
- //
- // There is something there! Prompt for password
- //
- Status = ReadString (MenuOption, gPromptForPassword, StringPtr);
- if (EFI_ERROR (Status)) {
- FreePool (StringPtr);
- return Status;
- }
-
- TempString = AllocateCopyPool ((Maximum + 1) * sizeof (CHAR16), Question->BufferValue);
- ASSERT (TempString != NULL);
-
- TempString[Maximum] = L'\0';
-
- if (StrCmp (StringPtr, TempString) != 0) {
- //
- // Typed in old password incorrect
- //
- PasswordInvalid ();
-
- FreePool (StringPtr);
- FreePool (TempString);
- return Status;
- }
-
- FreePool (TempString);
- }
- }
-
- //
- // Ask for new password
- //
- ZeroMem (StringPtr, (Maximum + 1) * sizeof (CHAR16));
- Status = ReadString (MenuOption, gPromptForNewPassword, StringPtr);
- if (EFI_ERROR (Status)) {
- //
- // Reset state machine for interactive password
- //
- if ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) {
- PasswordCallback (Selection, MenuOption, NULL);
- }
-
- FreePool (StringPtr);
- return Status;
- }
-
- //
- // Confirm new password
- //
- TempString = AllocateZeroPool ((Maximum + 1) * sizeof (CHAR16));
- ASSERT (TempString);
- Status = ReadString (MenuOption, gConfirmPassword, TempString);
- if (EFI_ERROR (Status)) {
- //
- // Reset state machine for interactive password
- //
- if ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) {
- PasswordCallback (Selection, MenuOption, NULL);
- }
-
- FreePool (StringPtr);
- FreePool (TempString);
- return Status;
- }
-
- //
- // Compare two typed-in new passwords
- //
- if (StrCmp (StringPtr, TempString) == 0) {
- //
- // Prepare the Question->HiiValue.Value.string for ValidateQuestion use.
- //
- if((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) {
- StringId = Question->HiiValue.Value.string;
- Question->HiiValue.Value.string = NewString (StringPtr, Selection->FormSet->HiiHandle);
- } else {
- HiiSetString(Selection->FormSet->HiiHandle, Question->HiiValue.Value.string, StringPtr, NULL);
- }
-
- Status = ValidateQuestion(Selection->FormSet, Selection->Form, Question, EFI_HII_EXPRESSION_INCONSISTENT_IF);
-
- //
- // Researve the Question->HiiValue.Value.string.
- //
- if((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) {
- DeleteString(Question->HiiValue.Value.string, Selection->FormSet->HiiHandle);
- Question->HiiValue.Value.string = StringId;
- }
-
- if (EFI_ERROR (Status)) {
- //
- // Reset state machine for interactive password
- //
- if ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) {
- PasswordCallback (Selection, MenuOption, NULL);
- } else {
- //
- // Researve the Question->HiiValue.Value.string.
- //
- HiiSetString(Selection->FormSet->HiiHandle, Question->HiiValue.Value.string, (CHAR16*)Question->BufferValue, NULL);
- }
- } else {
- //
- // Two password match, send it to Configuration Driver
- //
- if ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) {
- PasswordCallback (Selection, MenuOption, StringPtr);
- } else {
- CopyMem (Question->BufferValue, StringPtr, Maximum * sizeof (CHAR16));
- SetQuestionValue (Selection->FormSet, Selection->Form, Question, GetSetValueWithHiiDriver);
- }
- }
- } else {
- //
- // Reset state machine for interactive password
- //
- if ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) {
- PasswordCallback (Selection, MenuOption, NULL);
- }
-
- //
- // Two password mismatch, prompt error message
- //
- do {
- CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, gConfirmError, gPressEnter, gEmptyString);
- } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
- }
-
- FreePool (TempString);
- FreePool (StringPtr);
- }
- break;
-
- default:
- break;
- }
-
- return Status;
-}
-
-
-/**
- Process the help string: Split StringPtr to several lines of strings stored in
- FormattedString and the glyph width of each line cannot exceed gHelpBlockWidth.
-
- @param StringPtr The entire help string.
- @param FormattedString The oupput formatted string.
- @param EachLineWidth The max string length of each line in the formatted string.
- @param RowCount TRUE: if Question is selected.
-
-**/
-UINTN
-ProcessHelpString (
- IN CHAR16 *StringPtr,
- OUT CHAR16 **FormattedString,
- OUT UINT16 *EachLineWidth,
- IN UINTN RowCount
- )
-{
- UINTN Index;
- CHAR16 *OutputString;
- UINTN TotalRowNum;
- UINTN CheckedNum;
- UINT16 GlyphWidth;
- UINT16 LineWidth;
- UINT16 MaxStringLen;
- UINT16 StringLen;
-
- TotalRowNum = 0;
- CheckedNum = 0;
- GlyphWidth = 1;
- Index = 0;
- MaxStringLen = 0;
- StringLen = 0;
-
- //
- // Set default help string width.
- //
- LineWidth = (UINT16) (gHelpBlockWidth - 1);
-
- //
- // Get row number of the String.
- //
- while ((StringLen = GetLineByWidth (StringPtr, LineWidth, &GlyphWidth, &Index, &OutputString)) != 0) {
- if (StringLen > MaxStringLen) {
- MaxStringLen = StringLen;
- }
-
- TotalRowNum ++;
- FreePool (OutputString);
- }
- *EachLineWidth = MaxStringLen;
-
- *FormattedString = AllocateZeroPool (TotalRowNum * MaxStringLen * sizeof (CHAR16));
- ASSERT (*FormattedString != NULL);
-
- //
- // Generate formatted help string array.
- //
- GlyphWidth = 1;
- Index = 0;
- while((StringLen = GetLineByWidth (StringPtr, LineWidth, &GlyphWidth, &Index, &OutputString)) != 0) {
- CopyMem (*FormattedString + CheckedNum * MaxStringLen, OutputString, StringLen * sizeof (CHAR16));
- CheckedNum ++;
- FreePool (OutputString);
- }
-
- return TotalRowNum;
-}
diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/Setup.c b/MdeModulePkg/Universal/SetupBrowserDxe/Setup.c
index ed904161b..6dcb4aa77 100644
--- a/MdeModulePkg/Universal/SetupBrowserDxe/Setup.c
+++ b/MdeModulePkg/Universal/SetupBrowserDxe/Setup.c
@@ -26,167 +26,281 @@ SETUP_DRIVER_PRIVATE_DATA mPrivateData = {
RegisterHotKey,
RegiserExitHandler,
SaveReminder
+ },
+ {
+ BROWSER_EXTENSION2_VERSION_1,
+ SetScope,
+ RegisterHotKey,
+ RegiserExitHandler,
+ IsBrowserDataModified,
+ ExecuteAction,
}
};
EFI_HII_DATABASE_PROTOCOL *mHiiDatabase;
-EFI_HII_STRING_PROTOCOL *mHiiString;
EFI_HII_CONFIG_ROUTING_PROTOCOL *mHiiConfigRouting;
EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL *mPathFromText;
+EDKII_FORM_DISPLAY_ENGINE_PROTOCOL *mFormDisplay;
UINTN gBrowserContextCount = 0;
LIST_ENTRY gBrowserContextList = INITIALIZE_LIST_HEAD_VARIABLE (gBrowserContextList);
LIST_ENTRY gBrowserFormSetList = INITIALIZE_LIST_HEAD_VARIABLE (gBrowserFormSetList);
LIST_ENTRY gBrowserHotKeyList = INITIALIZE_LIST_HEAD_VARIABLE (gBrowserHotKeyList);
-LIST_ENTRY gBrowserStorageList = INITIALIZE_LIST_HEAD_VARIABLE (gBrowserStorageList);
+LIST_ENTRY gBrowserStorageList = INITIALIZE_LIST_HEAD_VARIABLE (gBrowserStorageList);
-BANNER_DATA *gBannerData;
-EFI_HII_HANDLE gFrontPageHandle;
-UINTN gClassOfVfr;
-UINTN gFunctionKeySetting;
BOOLEAN gResetRequired;
-EFI_HII_HANDLE gHiiHandle;
-UINT16 gDirection;
-EFI_SCREEN_DESCRIPTOR gScreenDimensions;
+BOOLEAN gExitRequired;
BROWSER_SETTING_SCOPE gBrowserSettingScope = FormSetLevel;
BOOLEAN mBrowserScopeFirstSet = TRUE;
EXIT_HANDLER ExitHandlerFunction = NULL;
-UINTN gFooterHeight;
//
// Browser Global Strings
//
-CHAR16 *gSaveFailed;
-CHAR16 *gDiscardFailed;
-CHAR16 *gDefaultFailed;
-CHAR16 *gEnterString;
-CHAR16 *gEnterCommitString;
-CHAR16 *gEnterEscapeString;
-CHAR16 *gEscapeString;
-CHAR16 *gMoveHighlight;
-CHAR16 *gMakeSelection;
-CHAR16 *gDecNumericInput;
-CHAR16 *gHexNumericInput;
-CHAR16 *gToggleCheckBox;
-CHAR16 *gPromptForData;
-CHAR16 *gPromptForPassword;
-CHAR16 *gPromptForNewPassword;
-CHAR16 *gConfirmPassword;
-CHAR16 *gConfirmError;
-CHAR16 *gPassowordInvalid;
-CHAR16 *gPressEnter;
CHAR16 *gEmptyString;
-CHAR16 *gAreYouSure;
-CHAR16 *gYesResponse;
-CHAR16 *gNoResponse;
-CHAR16 *gMiniString;
-CHAR16 *gPlusString;
-CHAR16 *gMinusString;
-CHAR16 *gAdjustNumber;
-CHAR16 *gSaveChanges;
-CHAR16 *gOptionMismatch;
-CHAR16 *gFormSuppress;
-CHAR16 *gProtocolNotFound;
-
CHAR16 *mUnknownString = L"!";
-CHAR16 gPromptBlockWidth;
-CHAR16 gOptionBlockWidth;
-CHAR16 gHelpBlockWidth;
-
EFI_GUID gZeroGuid = {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}};
-EFI_GUID gSetupBrowserGuid = {
- 0xab368524, 0xb60c, 0x495b, {0xa0, 0x9, 0x12, 0xe8, 0x5b, 0x1a, 0xea, 0x32}
-};
-FORM_BROWSER_FORMSET *gOldFormSet = NULL;
+extern UINT32 gBrowserStatus;
+extern CHAR16 *gErrorInfo;
+extern EFI_GUID mCurrentFormSetGuid;
+extern EFI_HII_HANDLE mCurrentHiiHandle;
+extern UINT16 mCurrentFormId;
+extern FORM_DISPLAY_ENGINE_FORM gDisplayFormData;
+
+/**
+ Create a menu with specified formset GUID and form ID, and add it as a child
+ of the given parent menu.
+
+ @param HiiHandle Hii handle related to this formset.
+ @param FormSetGuid The Formset Guid of menu to be added.
+ @param FormId The Form ID of menu to be added.
+ @param QuestionId The question id of this menu to be added.
+
+ @return A pointer to the newly added menu or NULL if memory is insufficient.
+
+**/
+FORM_ENTRY_INFO *
+UiAddMenuList (
+ IN EFI_HII_HANDLE HiiHandle,
+ IN EFI_GUID *FormSetGuid,
+ IN UINT16 FormId,
+ IN UINT16 QuestionId
+ )
+{
+ FORM_ENTRY_INFO *MenuList;
+
+ MenuList = AllocateZeroPool (sizeof (FORM_ENTRY_INFO));
+ if (MenuList == NULL) {
+ return NULL;
+ }
+
+ MenuList->Signature = FORM_ENTRY_INFO_SIGNATURE;
+
+ MenuList->HiiHandle = HiiHandle;
+ CopyMem (&MenuList->FormSetGuid, FormSetGuid, sizeof (EFI_GUID));
+ MenuList->FormId = FormId;
+ MenuList->QuestionId = QuestionId;
-FUNCTIION_KEY_SETTING gFunctionKeySettingTable[] = {
//
- // Boot Manager
+ // If parent is not specified, it is the root Form of a Formset
//
- {
- {
- 0x847bc3fe,
- 0xb974,
- 0x446d,
- {
- 0x94,
- 0x49,
- 0x5a,
- 0xd5,
- 0x41,
- 0x2e,
- 0x99,
- 0x3b
+ InsertTailList (&mPrivateData.FormBrowserEx2.FormViewHistoryHead, &MenuList->Link);
+
+ return MenuList;
+}
+
+/**
+ Return the form id for the input hiihandle and formset.
+
+ @param HiiHandle HiiHandle for FormSet.
+ @param FormSetGuid The Formset GUID of the menu to search.
+
+ @return First form's id for this form set.
+
+**/
+EFI_FORM_ID
+GetFirstFormId (
+ IN EFI_HII_HANDLE HiiHandle,
+ IN EFI_GUID *FormSetGuid
+ )
+{
+ LIST_ENTRY *Link;
+ FORM_BROWSER_FORM *Form;
+
+ Link = GetFirstNode (&gCurrentSelection->FormSet->FormListHead);
+ Form = FORM_BROWSER_FORM_FROM_LINK (Link);
+
+ return Form->FormId;
+}
+
+/**
+ Search Menu with given FormSetGuid and FormId in all cached menu list.
+
+ @param HiiHandle HiiHandle for FormSet.
+ @param FormSetGuid The Formset GUID of the menu to search.
+ @param FormId The Form ID of menu to search.
+
+ @return A pointer to menu found or NULL if not found.
+
+**/
+FORM_ENTRY_INFO *
+UiFindMenuList (
+ IN EFI_HII_HANDLE HiiHandle,
+ IN EFI_GUID *FormSetGuid,
+ IN UINT16 FormId
+ )
+{
+ LIST_ENTRY *Link;
+ FORM_ENTRY_INFO *MenuList;
+ FORM_ENTRY_INFO *RetMenu;
+ EFI_FORM_ID FirstFormId;
+
+ RetMenu = NULL;
+
+ Link = GetFirstNode (&mPrivateData.FormBrowserEx2.FormViewHistoryHead);
+ while (!IsNull (&mPrivateData.FormBrowserEx2.FormViewHistoryHead, Link)) {
+ MenuList = FORM_ENTRY_INFO_FROM_LINK (Link);
+ Link = GetNextNode (&mPrivateData.FormBrowserEx2.FormViewHistoryHead, Link);
+
+ //
+ // If already find the menu, free the menus behind it.
+ //
+ if (RetMenu != NULL) {
+ RemoveEntryList (&MenuList->Link);
+ FreePool (MenuList);
+ continue;
+ }
+
+ //
+ // Find the same FromSet.
+ //
+ if (MenuList->HiiHandle == HiiHandle) {
+ if (CompareGuid (&MenuList->FormSetGuid, &gZeroGuid)) {
+ //
+ // FormSetGuid is not specified.
+ //
+ RetMenu = MenuList;
+ } else if (CompareGuid (&MenuList->FormSetGuid, FormSetGuid)) {
+ if (MenuList->FormId == FormId) {
+ RetMenu = MenuList;
+ } else if (FormId == 0 || MenuList->FormId == 0 ) {
+ FirstFormId = GetFirstFormId (HiiHandle, FormSetGuid);
+ if ((FormId == 0 && FirstFormId == MenuList->FormId) || (MenuList->FormId ==0 && FirstFormId == FormId)) {
+ RetMenu = MenuList;
+ }
+ }
}
- },
- NONE_FUNCTION_KEY_SETTING
- },
+ }
+ }
+
+ return RetMenu;
+}
+
+/**
+ Find parent menu for current menu.
+
+ @param CurrentMenu Current Menu
+
+ @retval The parent menu for current menu.
+**/
+FORM_ENTRY_INFO *
+UiFindParentMenu (
+ IN FORM_ENTRY_INFO *CurrentMenu
+ )
+{
+ FORM_ENTRY_INFO *ParentMenu;
+
+ ParentMenu = NULL;
+ if (CurrentMenu->Link.BackLink != &mPrivateData.FormBrowserEx2.FormViewHistoryHead) {
+ ParentMenu = FORM_ENTRY_INFO_FROM_LINK (CurrentMenu->Link.BackLink);
+ }
+
+ return ParentMenu;
+}
+
+/**
+ Free Menu list linked list.
+
+ @param MenuListHead One Menu list point in the menu list.
+
+**/
+VOID
+UiFreeMenuList (
+ LIST_ENTRY *MenuListHead
+ )
+{
+ FORM_ENTRY_INFO *MenuList;
+
+ while (!IsListEmpty (MenuListHead)) {
+ MenuList = FORM_ENTRY_INFO_FROM_LINK (MenuListHead->ForwardLink);
+ RemoveEntryList (&MenuList->Link);
+
+ FreePool (MenuList);
+ }
+}
+
+/**
+ Load all hii formset to the browser.
+
+**/
+VOID
+LoadAllHiiFormset (
+ VOID
+ )
+{
+ FORM_BROWSER_FORMSET *LocalFormSet;
+ EFI_HII_HANDLE *HiiHandles;
+ UINTN Index;
+ EFI_GUID ZeroGuid;
+ EFI_STATUS Status;
+
//
- // Device Manager
+ // Get all the Hii handles
//
- {
- {
- 0x3ebfa8e6,
- 0x511d,
- 0x4b5b,
- {
- 0xa9,
- 0x5f,
- 0xfb,
- 0x38,
- 0x26,
- 0xf,
- 0x1c,
- 0x27
- }
- },
- NONE_FUNCTION_KEY_SETTING
- },
+ HiiHandles = HiiGetHiiHandles (NULL);
+ ASSERT (HiiHandles != NULL);
+
//
- // BMM FormSet.
+ // Search for formset of each class type
//
- {
- {
- 0x642237c7,
- 0x35d4,
- 0x472d,
- {
- 0x83,
- 0x65,
- 0x12,
- 0xe0,
- 0xcc,
- 0xf2,
- 0x7a,
- 0x22
- }
- },
- NONE_FUNCTION_KEY_SETTING
- },
+ for (Index = 0; HiiHandles[Index] != NULL; Index++) {
+ //
+ // Check HiiHandles[Index] does exist in global maintain list.
+ //
+ if (GetFormSetFromHiiHandle (HiiHandles[Index]) != NULL) {
+ continue;
+ }
+
+ //
+ // Initilize FormSet Setting
+ //
+ LocalFormSet = AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET));
+ ASSERT (LocalFormSet != NULL);
+ ZeroMem (&ZeroGuid, sizeof (ZeroGuid));
+ Status = InitializeFormSet (HiiHandles[Index], &ZeroGuid, LocalFormSet);
+ if (EFI_ERROR (Status) || IsListEmpty (&LocalFormSet->FormListHead)) {
+ DestroyFormSet (LocalFormSet);
+ continue;
+ }
+ InitializeCurrentSetting (LocalFormSet);
+
+ //
+ // Initilize Questions' Value
+ //
+ Status = LoadFormSetConfig (NULL, LocalFormSet);
+ if (EFI_ERROR (Status)) {
+ DestroyFormSet (LocalFormSet);
+ continue;
+ }
+ }
+
//
- // BMM File Explorer FormSet.
+ // Free resources, and restore gOldFormSet and gClassOfVfr
//
- {
- {
- 0x1f2d63e1,
- 0xfebd,
- 0x4dc7,
- {
- 0x9c,
- 0xc5,
- 0xba,
- 0x2b,
- 0x1c,
- 0xef,
- 0x9c,
- 0x5b
- }
- },
- NONE_FUNCTION_KEY_SETTING
- },
-};
+ FreePool (HiiHandles);
+}
/**
This is the routine which an external caller uses to direct the browser
@@ -229,26 +343,14 @@ SendForm (
UI_MENU_SELECTION *Selection;
UINTN Index;
FORM_BROWSER_FORMSET *FormSet;
- LIST_ENTRY *Link;
+ FORM_ENTRY_INFO *MenuList;
//
- // Calculate total number of Register HotKeys.
+ // If EDKII_FORM_DISPLAY_ENGINE_PROTOCOL not found, return EFI_UNSUPPORTED.
//
- Index = 0;
- Link = GetFirstNode (&gBrowserHotKeyList);
- while (!IsNull (&gBrowserHotKeyList, Link)) {
- Link = GetNextNode (&gBrowserHotKeyList, Link);
- Index ++;
+ if (mFormDisplay == NULL) {
+ return EFI_UNSUPPORTED;
}
- //
- // Show three HotKeys help information on one ROW.
- //
- gFooterHeight = FOOTER_HEIGHT + (Index / 3);
-
- //
- // Clean the history menu list.
- //
- InitializeListHead (&gMenuList);
//
// Save globals used by SendForm()
@@ -256,65 +358,10 @@ SendForm (
SaveBrowserContext ();
gResetRequired = FALSE;
- Status = EFI_SUCCESS;
- ZeroMem (&gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));
-
- //
- // 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)
- ) {
- Status = EFI_INVALID_PARAMETER;
- goto Done;
- } 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 +
- gFooterHeight +
- 1
- )
- ) {
- CopyMem (&gScreenDimensions, (VOID *) ScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));
- } else {
- Status = EFI_INVALID_PARAMETER;
- goto Done;
- }
- }
- }
-
- gOptionBlockWidth = (CHAR16) ((gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn) / 3);
- gPromptBlockWidth = (CHAR16) (gOptionBlockWidth + LEFT_SKIPPED_COLUMNS);
- gHelpBlockWidth = (CHAR16) (gOptionBlockWidth - LEFT_SKIPPED_COLUMNS);
-
- //
- // Initialize the strings for the browser, upon exit of the browser, the strings will be freed
- //
- InitializeBrowserStrings ();
-
- //
- // Ensure we are in Text mode
- //
- gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));
+ gExitRequired = FALSE;
+ Status = EFI_SUCCESS;
+ gEmptyString = L"";
+ gDisplayFormData.ScreenDimensions = (EFI_SCREEN_DESCRIPTOR *) ScreenDimensions;
for (Index = 0; Index < HandleCount; Index++) {
Selection = AllocateZeroPool (sizeof (UI_MENU_SELECTION));
@@ -335,7 +382,7 @@ SendForm (
//
// Initialize internal data structures of FormSet
//
- Status = InitializeFormSet (Selection->Handle, &Selection->FormSetGuid, FormSet, TRUE);
+ Status = InitializeFormSet (Selection->Handle, &Selection->FormSetGuid, FormSet);
if (EFI_ERROR (Status) || IsListEmpty (&FormSet->FormListHead)) {
DestroyFormSet (FormSet);
break;
@@ -343,11 +390,6 @@ SendForm (
Selection->FormSet = FormSet;
//
- // Try to find pre FormSet in the maintain backup list.
- //
- gOldFormSet = GetFormSetFromHiiHandle (Selection->Handle);
-
- //
// Display this formset
//
gCurrentSelection = Selection;
@@ -356,27 +398,36 @@ SendForm (
gCurrentSelection = NULL;
- if (EFI_ERROR (Status)) {
- break;
- }
-
- } while (Selection->Action == UI_ACTION_REFRESH_FORMSET);
-
- if (gOldFormSet != NULL) {
//
// If no data is changed, don't need to save current FormSet into the maintain list.
//
- if (!IsNvUpdateRequired (gOldFormSet)) {
- CleanBrowserStorage(gOldFormSet);
- RemoveEntryList (&gOldFormSet->Link);
- DestroyFormSet (gOldFormSet);
+ if (!IsNvUpdateRequiredForFormSet (FormSet) && !IsStorageDataChangedForFormSet(FormSet)) {
+ CleanBrowserStorage(FormSet);
+ RemoveEntryList (&FormSet->Link);
+ DestroyFormSet (FormSet);
}
- gOldFormSet = NULL;
- }
+
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+ } while (Selection->Action == UI_ACTION_REFRESH_FORMSET);
FreePool (Selection);
}
+ //
+ // Still has error info, pop up a message.
+ //
+ if (gBrowserStatus != BROWSER_SUCCESS) {
+ gDisplayFormData.BrowserStatus = gBrowserStatus;
+ gDisplayFormData.ErrorString = gErrorInfo;
+
+ gBrowserStatus = BROWSER_SUCCESS;
+ gErrorInfo = NULL;
+
+ mFormDisplay->FormDisplay (&gDisplayFormData, NULL);
+ }
+
if (ActionRequest != NULL) {
*ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;
if (gResetRequired) {
@@ -384,13 +435,17 @@ SendForm (
}
}
- FreeBrowserStrings ();
- UiFreeMenuList(&gMenuList);
+ mFormDisplay->ExitDisplay();
- gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));
- gST->ConOut->ClearScreen (gST->ConOut);
+ //
+ // Clear the menu history data.
+ //
+ while (!IsListEmpty (&mPrivateData.FormBrowserEx2.FormViewHistoryHead)) {
+ MenuList = FORM_ENTRY_INFO_FROM_LINK (mPrivateData.FormBrowserEx2.FormViewHistoryHead.ForwardLink);
+ RemoveEntryList (&MenuList->Link);
+ FreePool (MenuList);
+ }
-Done:
//
// Restore globals used by SendForm()
//
@@ -399,10 +454,93 @@ Done:
return Status;
}
+/**
+ Get or set data to the storage.
+
+ @param ResultsDataSize The size of the buffer associatedwith ResultsData.
+ @param ResultsData A string returned from an IFR browser or
+ equivalent. The results string will have no
+ routing information in them.
+ @param RetrieveData A BOOLEAN field which allows an agent to retrieve
+ (if RetrieveData = TRUE) data from the uncommitted
+ browser state information or set (if RetrieveData
+ = FALSE) data in the uncommitted browser state
+ information.
+ @param Storage The pointer to the storage.
+
+ @retval EFI_SUCCESS The results have been distributed or are awaiting
+ distribution.
+
+**/
+EFI_STATUS
+ProcessStorage (
+ IN OUT UINTN *ResultsDataSize,
+ IN OUT EFI_STRING *ResultsData,
+ IN BOOLEAN RetrieveData,
+ IN BROWSER_STORAGE *Storage
+ )
+{
+ CHAR16 *ConfigResp;
+ EFI_STATUS Status;
+ CHAR16 *StrPtr;
+ UINTN BufferSize;
+ UINTN TmpSize;
+
+ if (RetrieveData) {
+ //
+ // Generate <ConfigResp>
+ //
+ Status = StorageToConfigResp (Storage, &ConfigResp, Storage->ConfigRequest, TRUE);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Skip <ConfigHdr> and '&' to point to <ConfigBody> when first copy the configbody.
+ // Also need to consider add "\0" at first time.
+ //
+ StrPtr = ConfigResp + StrLen (Storage->ConfigHdr) + 1;
+ BufferSize = StrSize (StrPtr);
+
+
+ //
+ // Copy the data if the input buffer is bigger enough.
+ //
+ if (*ResultsDataSize >= BufferSize) {
+ StrCpy (*ResultsData, StrPtr);
+ }
+
+ *ResultsDataSize = BufferSize;
+ FreePool (ConfigResp);
+ } else {
+ //
+ // Prepare <ConfigResp>
+ //
+ TmpSize = StrLen (*ResultsData);
+ BufferSize = (TmpSize + StrLen (Storage->ConfigHdr) + 2) * sizeof (CHAR16);
+ ConfigResp = AllocateZeroPool (BufferSize);
+ ASSERT (ConfigResp != NULL);
+
+ StrCpy (ConfigResp, Storage->ConfigHdr);
+ StrCat (ConfigResp, L"&");
+ StrCat (ConfigResp, *ResultsData);
+
+ //
+ // Update Browser uncommited data
+ //
+ Status = ConfigRespToStorage (Storage, ConfigResp);
+ FreePool (ConfigResp);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
/**
- This function is called by a callback handler to retrieve uncommitted state
- data from the browser.
+ This routine called this service in the browser to retrieve or set certain uncommitted
+ state information that resides in the open formsets.
@param This A pointer to the EFI_FORM_BROWSER2_PROTOCOL
instance.
@@ -440,60 +578,69 @@ BrowserCallback (
{
EFI_STATUS Status;
LIST_ENTRY *Link;
- FORMSET_STORAGE *Storage;
+ BROWSER_STORAGE *Storage;
+ FORMSET_STORAGE *FormsetStorage;
FORM_BROWSER_FORMSET *FormSet;
+ UINTN TotalSize;
BOOLEAN Found;
- CHAR16 *ConfigResp;
- CHAR16 *StrPtr;
- UINTN BufferSize;
- UINTN TmpSize;
if (ResultsDataSize == NULL || ResultsData == NULL) {
return EFI_INVALID_PARAMETER;
}
- if (gCurrentSelection == NULL) {
- return EFI_NOT_READY;
- }
-
- Storage = NULL;
- ConfigResp = NULL;
- FormSet = gCurrentSelection->FormSet;
+ TotalSize = *ResultsDataSize;
+ Storage = NULL;
+ Found = FALSE;
+ Status = EFI_SUCCESS;
//
- // Find target storage
+ // If set browser data, pre load all hii formset to avoid set the varstore which is not
+ // saved in browser.
//
- Link = GetFirstNode (&FormSet->StorageListHead);
- if (IsNull (&FormSet->StorageListHead, Link)) {
- return EFI_UNSUPPORTED;
+ if (!RetrieveData && (gBrowserSettingScope == SystemLevel)) {
+ LoadAllHiiFormset();
}
if (VariableGuid != NULL) {
//
- // Try to find target storage
+ // Try to find target storage in the current formset.
//
- Found = FALSE;
- while (!IsNull (&FormSet->StorageListHead, Link)) {
- Storage = FORMSET_STORAGE_FROM_LINK (Link);
- Link = GetNextNode (&FormSet->StorageListHead, Link);
+ Link = GetFirstNode (&gBrowserStorageList);
+ while (!IsNull (&gBrowserStorageList, Link)) {
+ Storage = BROWSER_STORAGE_FROM_LINK (Link);
+ Link = GetNextNode (&gBrowserStorageList, Link);
+ //
+ // Check the current storage.
+ //
+ if (!CompareGuid (&Storage->Guid, (EFI_GUID *) VariableGuid)) {
+ continue;
+ }
- if (CompareGuid (&Storage->BrowserStorage->Guid, (EFI_GUID *) VariableGuid)) {
- if (Storage->BrowserStorage->Type == EFI_HII_VARSTORE_BUFFER ||
- Storage->BrowserStorage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) {
- //
- // Buffer storage require both GUID and Name
- //
- if (VariableName == NULL) {
- return EFI_NOT_FOUND;
- }
+ if (Storage->Type == EFI_HII_VARSTORE_BUFFER ||
+ Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) {
+ //
+ // Buffer storage require both GUID and Name
+ //
+ if (VariableName == NULL) {
+ return EFI_NOT_FOUND;
+ }
- if (StrCmp (Storage->BrowserStorage->Name, (CHAR16 *) VariableName) != 0) {
- continue;
- }
+ if (StrCmp (Storage->Name, (CHAR16 *) VariableName) != 0) {
+ continue;
}
- Found = TRUE;
- break;
}
+
+ Status = ProcessStorage (&TotalSize, &ResultsData, RetrieveData, Storage);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Different formsets may have same varstore, so here just set the flag
+ // not exit the circle.
+ //
+ Found = TRUE;
+ break;
}
if (!Found) {
@@ -503,65 +650,62 @@ BrowserCallback (
//
// GUID/Name is not specified, take the first storage in FormSet
//
- Storage = FORMSET_STORAGE_FROM_LINK (Link);
- }
-
- if (RetrieveData) {
- //
- // Skip if there is no RequestElement
- //
- if (Storage->ElementCount == 0) {
- return EFI_SUCCESS;
+ if (gCurrentSelection == NULL) {
+ return EFI_NOT_READY;
}
//
// Generate <ConfigResp>
//
- Status = StorageToConfigResp (Storage->BrowserStorage, &ConfigResp, Storage->ConfigRequest);
+ FormSet = gCurrentSelection->FormSet;
+ Link = GetFirstNode (&FormSet->StorageListHead);
+ if (IsNull (&FormSet->StorageListHead, Link)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ FormsetStorage = FORMSET_STORAGE_FROM_LINK (Link);
+
+ Status = ProcessStorage (&TotalSize, &ResultsData, RetrieveData, FormsetStorage->BrowserStorage);
if (EFI_ERROR (Status)) {
return Status;
}
+ }
- //
- // Skip <ConfigHdr> and '&' to point to <ConfigBody>
- //
- StrPtr = ConfigResp + StrLen (Storage->BrowserStorage->ConfigHdr) + 1;
+ if (RetrieveData) {
+ Status = TotalSize <= *ResultsDataSize ? EFI_SUCCESS : EFI_BUFFER_TOO_SMALL;
+ *ResultsDataSize = TotalSize;
+ }
+
+ return Status;
- BufferSize = StrSize (StrPtr);
- if (*ResultsDataSize < BufferSize) {
- *ResultsDataSize = BufferSize;
+}
- FreePool (ConfigResp);
- return EFI_BUFFER_TOO_SMALL;
- }
- *ResultsDataSize = BufferSize;
- CopyMem (ResultsData, StrPtr, BufferSize);
+/**
+ Callback function for SimpleTextInEx protocol install events
- FreePool (ConfigResp);
- } else {
- //
- // Prepare <ConfigResp>
- //
- TmpSize = StrLen (ResultsData);
- BufferSize = (TmpSize + StrLen (Storage->BrowserStorage->ConfigHdr) + 2) * sizeof (CHAR16);
- ConfigResp = AllocateZeroPool (BufferSize);
- ASSERT (ConfigResp != NULL);
+ @param Event the event that is signaled.
+ @param Context not used here.
- StrCpy (ConfigResp, Storage->BrowserStorage->ConfigHdr);
- StrCat (ConfigResp, L"&");
- StrCat (ConfigResp, ResultsData);
+**/
+VOID
+EFIAPI
+FormDisplayCallback (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
- //
- // Update Browser uncommited data
- //
- Status = ConfigRespToStorage (Storage->BrowserStorage, ConfigResp);
- if (EFI_ERROR (Status)) {
- return Status;
- }
+ if (mFormDisplay != NULL) {
+ return;
}
- return EFI_SUCCESS;
+ Status = gBS->LocateProtocol (
+ &gEdkiiFormDisplayEngineProtocolGuid,
+ NULL,
+ (VOID **) &mFormDisplay
+ );
}
/**
@@ -582,8 +726,7 @@ InitializeSetup (
)
{
EFI_STATUS Status;
- EFI_INPUT_KEY DefaultHotKey;
- EFI_STRING HelpString;
+ VOID *Registration;
//
// Locate required Hii relative protocols
@@ -596,13 +739,6 @@ InitializeSetup (
ASSERT_EFI_ERROR (Status);
Status = gBS->LocateProtocol (
- &gEfiHiiStringProtocolGuid,
- NULL,
- (VOID **) &mHiiString
- );
- ASSERT_EFI_ERROR (Status);
-
- Status = gBS->LocateProtocol (
&gEfiHiiConfigRoutingProtocolGuid,
NULL,
(VOID **) &mHiiConfigRouting
@@ -616,30 +752,6 @@ InitializeSetup (
);
//
- // Publish our HII data
- //
- gHiiHandle = HiiAddPackages (
- &gSetupBrowserGuid,
- ImageHandle,
- SetupBrowserStrings,
- NULL
- );
- ASSERT (gHiiHandle != NULL);
-
- //
- // Initialize Driver private data
- //
- gBannerData = AllocateZeroPool (sizeof (BANNER_DATA));
- ASSERT (gBannerData != NULL);
-
- //
- // Initialize generic help strings.
- //
- gSaveFailed = GetToken (STRING_TOKEN (SAVE_FAILED), gHiiHandle);
- gDiscardFailed = GetToken (STRING_TOKEN (DISCARD_FAILED), gHiiHandle);
- gDefaultFailed = GetToken (STRING_TOKEN (DEFAULT_FAILED), gHiiHandle);
-
- //
// Install FormBrowser2 protocol
//
mPrivateData.Handle = NULL;
@@ -652,34 +764,45 @@ InitializeSetup (
ASSERT_EFI_ERROR (Status);
//
- // Install default HotKey F10 for Save
- //
- DefaultHotKey.UnicodeChar = CHAR_NULL;
- HelpString = GetToken (STRING_TOKEN (FUNCTION_TEN_STRING), gHiiHandle);
- DefaultHotKey.ScanCode = SCAN_F10;
- RegisterHotKey (&DefaultHotKey, BROWSER_ACTION_SUBMIT, 0, HelpString);
- FreePool (HelpString);
- //
- // Install default HotKey F9 for Reset To Defaults
- //
- DefaultHotKey.ScanCode = SCAN_F9;
- HelpString = GetToken (STRING_TOKEN (FUNCTION_NINE_STRING), gHiiHandle);
- RegisterHotKey (&DefaultHotKey, BROWSER_ACTION_DEFAULT, EFI_HII_DEFAULT_CLASS_STANDARD, HelpString);
- FreePool (HelpString);
-
- //
- // Install FormBrowserEx protocol
+ // Install FormBrowserEx2 protocol
//
+ InitializeListHead (&mPrivateData.FormBrowserEx2.FormViewHistoryHead);
mPrivateData.Handle = NULL;
Status = gBS->InstallProtocolInterface (
&mPrivateData.Handle,
+ &gEdkiiFormBrowserEx2ProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &mPrivateData.FormBrowserEx2
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = gBS->InstallProtocolInterface (
+ &mPrivateData.Handle,
&gEfiFormBrowserExProtocolGuid,
EFI_NATIVE_INTERFACE,
&mPrivateData.FormBrowserEx
);
ASSERT_EFI_ERROR (Status);
- return Status;
+ InitializeDisplayFormData ();
+
+ Status = gBS->LocateProtocol (
+ &gEdkiiFormDisplayEngineProtocolGuid,
+ NULL,
+ (VOID **) &mFormDisplay
+ );
+
+ if (EFI_ERROR (Status)) {
+ EfiCreateProtocolNotifyEvent (
+ &gEdkiiFormDisplayEngineProtocolGuid,
+ TPL_CALLBACK,
+ FormDisplayCallback,
+ NULL,
+ &Registration
+ );
+ }
+
+ return EFI_SUCCESS;
}
@@ -815,58 +938,6 @@ NewStringCat (
*Dest = NewString;
}
-
-/**
- Synchronize or restore Storage's Edit copy and Shadow copy.
-
- @param Storage The Storage to be synchronized.
- @param SyncOrRestore Sync the buffer to editbuffer or Restore the
- editbuffer to buffer
- if TRUE, copy the editbuffer to the buffer.
- if FALSE, copy the buffer to the editbuffer.
-
-**/
-VOID
-SynchronizeStorage (
- IN BROWSER_STORAGE *Storage,
- IN BOOLEAN SyncOrRestore
- )
-{
- LIST_ENTRY *Link;
- NAME_VALUE_NODE *Node;
-
- switch (Storage->Type) {
- case EFI_HII_VARSTORE_BUFFER:
- case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:
- if (SyncOrRestore) {
- CopyMem (Storage->Buffer, Storage->EditBuffer, Storage->Size);
- } else {
- CopyMem (Storage->EditBuffer, Storage->Buffer, Storage->Size);
- }
- break;
-
- case EFI_HII_VARSTORE_NAME_VALUE:
- Link = GetFirstNode (&Storage->NameValueListHead);
- while (!IsNull (&Storage->NameValueListHead, Link)) {
- Node = NAME_VALUE_NODE_FROM_LINK (Link);
-
- if (SyncOrRestore) {
- NewStringCpy (&Node->Value, Node->EditValue);
- } else {
- NewStringCpy (&Node->EditValue, Node->Value);
- }
-
- Link = GetNextNode (&Storage->NameValueListHead, Link);
- }
- break;
-
- case EFI_HII_VARSTORE_EFI_VARIABLE:
- default:
- break;
- }
-}
-
-
/**
Get Value for given Name from a NameValue Storage.
@@ -923,6 +994,7 @@ GetValueByName (
@param Name The Name.
@param Value The Value to set.
@param SetValueTo Whether update editValue or Value.
+ @param ReturnNode The node use the input name.
@retval EFI_SUCCESS Value found for given Name.
@retval EFI_NOT_FOUND No such Name found in NameValue storage.
@@ -930,10 +1002,11 @@ GetValueByName (
**/
EFI_STATUS
SetValueByName (
- IN BROWSER_STORAGE *Storage,
- IN CHAR16 *Name,
- IN CHAR16 *Value,
- IN GET_SET_QUESTION_VALUE_WITH SetValueTo
+ IN BROWSER_STORAGE *Storage,
+ IN CHAR16 *Name,
+ IN CHAR16 *Value,
+ IN GET_SET_QUESTION_VALUE_WITH SetValueTo,
+ OUT NAME_VALUE_NODE **ReturnNode
)
{
LIST_ENTRY *Link;
@@ -964,6 +1037,11 @@ SetValueByName (
} else {
Node->Value = Buffer;
}
+
+ if (ReturnNode != NULL) {
+ *ReturnNode = Node;
+ }
+
return EFI_SUCCESS;
}
@@ -980,6 +1058,7 @@ SetValueByName (
@param Storage The Storage to be conveted.
@param ConfigResp The returned <ConfigResp>.
@param ConfigRequest The ConfigRequest string.
+ @param GetEditBuf Get the data from editbuffer or buffer.
@retval EFI_SUCCESS Convert success.
@retval EFI_INVALID_PARAMETER Incorrect storage type.
@@ -989,23 +1068,26 @@ EFI_STATUS
StorageToConfigResp (
IN BROWSER_STORAGE *Storage,
IN CHAR16 **ConfigResp,
- IN CHAR16 *ConfigRequest
+ IN CHAR16 *ConfigRequest,
+ IN BOOLEAN GetEditBuf
)
{
EFI_STATUS Status;
EFI_STRING Progress;
LIST_ENTRY *Link;
NAME_VALUE_NODE *Node;
+ UINT8 *SourceBuf;
Status = EFI_SUCCESS;
switch (Storage->Type) {
case EFI_HII_VARSTORE_BUFFER:
case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:
+ SourceBuf = GetEditBuf ? Storage->EditBuffer : Storage->Buffer;
Status = mHiiConfigRouting->BlockToConfig (
mHiiConfigRouting,
ConfigRequest,
- Storage->EditBuffer,
+ SourceBuf,
Storage->Size,
ConfigResp,
&Progress
@@ -1024,7 +1106,11 @@ StorageToConfigResp (
NewStringCat (ConfigResp, L"&");
NewStringCat (ConfigResp, Node->Name);
NewStringCat (ConfigResp, L"=");
- NewStringCat (ConfigResp, Node->EditValue);
+ if (GetEditBuf) {
+ NewStringCat (ConfigResp, Node->EditValue);
+ } else {
+ NewStringCat (ConfigResp, Node->Value);
+ }
}
Link = GetNextNode (&Storage->NameValueListHead, Link);
}
@@ -1105,7 +1191,7 @@ ConfigRespToStorage (
if (StrPtr != NULL) {
*StrPtr = 0;
}
- SetValueByName (Storage, Name, Value, GetSetValueWithEditBuffer);
+ SetValueByName (Storage, Name, Value, GetSetValueWithEditBuffer, NULL);
}
break;
@@ -1169,13 +1255,6 @@ GetQuestionValue (
}
//
- // Statement don't have storage, skip them
- //
- if (Question->QuestionId == 0) {
- return Status;
- }
-
- //
// Question value is provided by an Expression, evaluate it
//
if (Question->ValueExpression != NULL) {
@@ -1531,7 +1610,7 @@ GetQuestionValue (
if (IsBufferStorage) {
CopyMem (Storage->EditBuffer + Question->VarStoreInfo.VarOffset, Dst, StorageWidth);
} else {
- SetValueByName (Storage, Question->VariableName, Value, GetSetValueWithEditBuffer);
+ SetValueByName (Storage, Question->VariableName, Value, GetSetValueWithEditBuffer, NULL);
}
if (Result != NULL) {
@@ -1581,21 +1660,16 @@ SetQuestionValue (
CHAR16 *TemName;
CHAR16 *TemString;
UINTN Index;
+ NAME_VALUE_NODE *Node;
Status = EFI_SUCCESS;
+ Node = NULL;
if (SetValueTo >= GetSetValueWithMax) {
return EFI_INVALID_PARAMETER;
}
//
- // Statement don't have storage, skip them
- //
- if (Question->QuestionId == 0) {
- return Status;
- }
-
- //
// If Question value is provided by an Expression, then it is read only
//
if (Question->ValueExpression != NULL) {
@@ -1717,6 +1791,14 @@ SetQuestionValue (
//
CopyMem (Storage->Buffer + Question->VarStoreInfo.VarOffset, Src, StorageWidth);
}
+ //
+ // Check whether question value has been changed.
+ //
+ if (CompareMem (Storage->Buffer + Question->VarStoreInfo.VarOffset, Storage->EditBuffer + Question->VarStoreInfo.VarOffset, StorageWidth) != 0) {
+ Question->ValueChanged = TRUE;
+ } else {
+ Question->ValueChanged = FALSE;
+ }
} else {
if (IsString) {
//
@@ -1748,8 +1830,19 @@ SetQuestionValue (
}
}
- Status = SetValueByName (Storage, Question->VariableName, Value, SetValueTo);
+ Status = SetValueByName (Storage, Question->VariableName, Value, SetValueTo, &Node);
FreePool (Value);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Check whether question value has been changed.
+ //
+ if (StrCmp (Node->Value, Node->EditValue) != 0) {
+ Question->ValueChanged = TRUE;
+ } else {
+ Question->ValueChanged = FALSE;
+ }
}
} else if (SetValueTo == GetSetValueWithHiiDriver) {
if (Storage->Type == EFI_HII_VARSTORE_BUFFER || Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {
@@ -1868,12 +1961,12 @@ SetQuestionValue (
/**
- Perform inconsistent check for a Form.
+ Perform nosubmitif check for a Form.
@param FormSet FormSet data structure.
@param Form Form data structure.
@param Question The Question to be validated.
- @param Type Validation type: InConsistent or NoSubmit
+ @param Type Validation type: NoSubmit
@retval EFI_SUCCESS Form validation pass.
@retval other Form validation failed.
@@ -1891,12 +1984,9 @@ ValidateQuestion (
LIST_ENTRY *Link;
LIST_ENTRY *ListHead;
EFI_STRING PopUp;
- EFI_INPUT_KEY Key;
FORM_EXPRESSION *Expression;
- if (Type == EFI_HII_EXPRESSION_INCONSISTENT_IF) {
- ListHead = &Question->InconsistentListHead;
- } else if (Type == EFI_HII_EXPRESSION_NO_SUBMIT_IF) {
+ if (Type == EFI_HII_EXPRESSION_NO_SUBMIT_IF) {
ListHead = &Question->NoSubmitListHead;
} else {
return EFI_UNSUPPORTED;
@@ -1920,10 +2010,10 @@ ValidateQuestion (
//
if (Expression->Error != 0) {
PopUp = GetToken (Expression->Error, FormSet->HiiHandle);
- do {
- CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, PopUp, gPressEnter, gEmptyString);
- } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
- FreePool (PopUp);
+ if (Type == EFI_HII_EXPRESSION_NO_SUBMIT_IF) {
+ gBrowserStatus = BROWSER_NO_SUBMIT_IF;
+ gErrorInfo = PopUp;
+ }
}
return EFI_NOT_READY;
@@ -1987,7 +2077,8 @@ NoSubmitCheck (
Fill storage's edit copy with settings requested from Configuration Driver.
@param FormSet FormSet data structure.
- @param ConfigInfo The config info related to this form.
+ @param Storage The storage which need to sync.
+ @param ConfigRequest The config request string which used to sync storage.
@param SyncOrRestore Sync the buffer to editbuffer or Restore the
editbuffer to buffer
if TRUE, copy the editbuffer to the buffer.
@@ -1997,10 +2088,11 @@ NoSubmitCheck (
**/
EFI_STATUS
-SynchronizeStorageForForm (
- IN FORM_BROWSER_FORMSET *FormSet,
- IN FORM_BROWSER_CONFIG_REQUEST *ConfigInfo,
- IN BOOLEAN SyncOrRestore
+SynchronizeStorage (
+ IN FORM_BROWSER_FORMSET *FormSet,
+ OUT BROWSER_STORAGE *Storage,
+ IN CHAR16 *ConfigRequest,
+ IN BOOLEAN SyncOrRestore
)
{
EFI_STATUS Status;
@@ -2014,57 +2106,52 @@ SynchronizeStorageForForm (
Status = EFI_SUCCESS;
Result = NULL;
- if (FormSet->ConfigAccess == NULL && ConfigInfo->Storage->Type != EFI_HII_VARSTORE_NAME_VALUE) {
- return EFI_NOT_FOUND;
- }
-
- if (ConfigInfo->ElementCount == 0) {
- //
- // Skip if there is no RequestElement
- //
- return EFI_SUCCESS;
- }
- if (ConfigInfo->Storage->Type == EFI_HII_VARSTORE_BUFFER ||
- (ConfigInfo->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) {
- BufferSize = ConfigInfo->Storage->Size;
+ if (Storage->Type == EFI_HII_VARSTORE_BUFFER ||
+ (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) {
+ BufferSize = Storage->Size;
if (SyncOrRestore) {
- Src = ConfigInfo->Storage->EditBuffer;
- Dst = ConfigInfo->Storage->Buffer;
+ Src = Storage->EditBuffer;
+ Dst = Storage->Buffer;
} else {
- Src = ConfigInfo->Storage->Buffer;
- Dst = ConfigInfo->Storage->EditBuffer;
+ Src = Storage->Buffer;
+ Dst = Storage->EditBuffer;
}
- Status = mHiiConfigRouting->BlockToConfig(
- mHiiConfigRouting,
- ConfigInfo->ConfigRequest,
- Src,
- BufferSize,
- &Result,
- &Progress
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
+ if (ConfigRequest != NULL) {
+ Status = mHiiConfigRouting->BlockToConfig(
+ mHiiConfigRouting,
+ ConfigRequest,
+ Src,
+ BufferSize,
+ &Result,
+ &Progress
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
- Status = mHiiConfigRouting->ConfigToBlock (
- mHiiConfigRouting,
- Result,
- Dst,
- &BufferSize,
- &Progress
- );
- if (Result != NULL) {
- FreePool (Result);
+ Status = mHiiConfigRouting->ConfigToBlock (
+ mHiiConfigRouting,
+ Result,
+ Dst,
+ &BufferSize,
+ &Progress
+ );
+ if (Result != NULL) {
+ FreePool (Result);
+ }
+ } else {
+ CopyMem (Dst, Src, BufferSize);
}
- } else if (ConfigInfo->Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {
- Link = GetFirstNode (&ConfigInfo->Storage->NameValueListHead);
- while (!IsNull (&ConfigInfo->Storage->NameValueListHead, Link)) {
+ } else if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {
+ Link = GetFirstNode (&Storage->NameValueListHead);
+ while (!IsNull (&Storage->NameValueListHead, Link)) {
Node = NAME_VALUE_NODE_FROM_LINK (Link);
- if (StrStr (ConfigInfo->ConfigRequest, Node->Name) != NULL) {
+ if ((ConfigRequest != NULL && StrStr (ConfigRequest, Node->Name) != NULL) ||
+ (ConfigRequest == NULL)) {
if (SyncOrRestore) {
NewStringCpy (&Node->Value, Node->EditValue);
} else {
@@ -2072,7 +2159,7 @@ SynchronizeStorageForForm (
}
}
- Link = GetNextNode (&ConfigInfo->Storage->NameValueListHead, Link);
+ Link = GetNextNode (&Storage->NameValueListHead, Link);
}
}
@@ -2095,20 +2182,9 @@ SendDiscardInfoToDriver (
{
LIST_ENTRY *Link;
FORM_BROWSER_STATEMENT *Question;
- EFI_STATUS Status;
- EFI_HII_VALUE HiiValue;
- UINT8 *BufferValue;
- BOOLEAN ValueChanged;
EFI_IFR_TYPE_VALUE *TypeValue;
EFI_BROWSER_ACTION_REQUEST ActionRequest;
- ValueChanged = FALSE;
- BufferValue = NULL;
-
- if(!Form->NvUpdateRequired) {
- return;
- }
-
Link = GetFirstNode (&Form->StatementListHead);
while (!IsNull (&Form->StatementListHead, Link)) {
Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);
@@ -2122,45 +2198,10 @@ SendDiscardInfoToDriver (
continue;
}
- if (Question->BufferValue != NULL) {
- BufferValue = AllocateZeroPool (Question->StorageWidth);
- ASSERT (BufferValue != NULL);
- CopyMem (BufferValue, Question->BufferValue, Question->StorageWidth);
- } else {
- HiiValue.Type = Question->HiiValue.Type;
- CopyMem (&HiiValue.Value, &Question->HiiValue.Value, sizeof (EFI_IFR_TYPE_VALUE));
- }
-
- Status = GetQuestionValue (FormSet, Form, Question, GetSetValueWithBuffer);
- if (EFI_ERROR (Status)) {
- if (BufferValue != NULL) {
- FreePool (BufferValue);
- BufferValue = NULL;
- }
+ if (!Question->ValueChanged) {
continue;
}
- if (Question->BufferValue != NULL) {
- if (CompareMem (BufferValue, Question->BufferValue, Question->StorageWidth)) {
- ValueChanged = TRUE;
- }
- } else {
- if (CompareMem (&HiiValue.Value, &Question->HiiValue.Value, sizeof (EFI_IFR_TYPE_VALUE))) {
- ValueChanged = TRUE;
- }
- }
-
- if (BufferValue != NULL) {
- FreePool (BufferValue);
- BufferValue = NULL;
- }
-
- if (!ValueChanged) {
- continue;
- }
-
- ValueChanged = FALSE;
-
if (Question->HiiValue.Type == EFI_IFR_TYPE_BUFFER) {
TypeValue = (EFI_IFR_TYPE_VALUE *) Question->BufferValue;
} else {
@@ -2225,6 +2266,78 @@ ValidateFormSet (
return Find;
}
+/**
+ Check whether need to enable the reset flag in form level.
+ Also clean all ValueChanged flag in question.
+
+ @param SetFlag Whether need to set the Reset Flag.
+ @param Form Form data structure.
+
+**/
+VOID
+UpdateFlagForForm (
+ IN BOOLEAN SetFlag,
+ IN FORM_BROWSER_FORM *Form
+ )
+{
+ LIST_ENTRY *Link;
+ FORM_BROWSER_STATEMENT *Question;
+ BOOLEAN FindOne;
+
+ FindOne = FALSE;
+ Link = GetFirstNode (&Form->StatementListHead);
+ while (!IsNull (&Form->StatementListHead, Link)) {
+ Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);
+
+ if (SetFlag && Question->ValueChanged && ((Question->QuestionFlags & EFI_IFR_FLAG_RESET_REQUIRED) != 0)) {
+ gResetRequired = TRUE;
+ }
+
+ if (Question->ValueChanged) {
+ Question->ValueChanged = FALSE;
+ }
+
+ Link = GetNextNode (&Form->StatementListHead, Link);
+ }
+}
+
+/**
+ Check whether need to enable the reset flag.
+ Also clean ValueChanged flag for all statements.
+
+ Form level or formset level, only one.
+
+ @param SetFlag Whether need to set the Reset Flag.
+ @param FormSet FormSet data structure.
+ @param Form Form data structure.
+
+**/
+VOID
+ValueChangeResetFlagUpdate (
+ IN BOOLEAN SetFlag,
+ IN FORM_BROWSER_FORMSET *FormSet,
+ IN FORM_BROWSER_FORM *Form
+ )
+{
+ FORM_BROWSER_FORM *CurrentForm;
+ LIST_ENTRY *Link;
+
+ //
+ // Form != NULL means only check form level.
+ //
+ if (Form != NULL) {
+ UpdateFlagForForm(SetFlag, Form);
+ return;
+ }
+
+ Link = GetFirstNode (&FormSet->FormListHead);
+ while (!IsNull (&FormSet->FormListHead, Link)) {
+ CurrentForm = FORM_BROWSER_FORM_FROM_LINK (Link);
+ Link = GetNextNode (&FormSet->FormListHead, Link);
+
+ UpdateFlagForForm(SetFlag, CurrentForm);
+ }
+}
/**
Discard data based on the input setting scope (Form, FormSet or System).
@@ -2256,7 +2369,7 @@ DiscardForm (
return EFI_UNSUPPORTED;
}
- if (SettingScope == FormLevel && Form->NvUpdateRequired) {
+ if (SettingScope == FormLevel && IsNvUpdateRequiredForForm (Form)) {
ConfigInfo = NULL;
Link = GetFirstNode (&Form->ConfigRequestHead);
while (!IsNull (&Form->ConfigRequestHead, Link)) {
@@ -2277,7 +2390,7 @@ DiscardForm (
//
// Prepare <ConfigResp>
//
- SynchronizeStorageForForm(FormSet, ConfigInfo, FALSE);
+ SynchronizeStorage(FormSet, ConfigInfo->Storage, ConfigInfo->ConfigRequest, FALSE);
//
// Call callback with Changed type to inform the driver.
@@ -2285,8 +2398,8 @@ DiscardForm (
SendDiscardInfoToDriver (FormSet, Form);
}
- Form->NvUpdateRequired = FALSE;
- } else if (SettingScope == FormSetLevel && IsNvUpdateRequired(FormSet)) {
+ ValueChangeResetFlagUpdate (FALSE, NULL, Form);
+ } else if (SettingScope == FormSetLevel && IsNvUpdateRequiredForFormSet (FormSet)) {
//
// Discard Buffer storage or Name/Value storage
@@ -2307,7 +2420,7 @@ DiscardForm (
continue;
}
- SynchronizeStorage(Storage->BrowserStorage, FALSE);
+ SynchronizeStorage(FormSet, Storage->BrowserStorage, Storage->ConfigRequest, FALSE);
}
Link = GetFirstNode (&FormSet->FormListHead);
@@ -2321,7 +2434,7 @@ DiscardForm (
SendDiscardInfoToDriver (FormSet, Form);
}
- UpdateNvInfoInForm (FormSet, FALSE);
+ ValueChangeResetFlagUpdate(FALSE, FormSet, NULL);
} else if (SettingScope == SystemLevel) {
//
// System Level Discard.
@@ -2401,7 +2514,7 @@ SubmitForm (
return Status;
}
- if (SettingScope == FormLevel && Form->NvUpdateRequired) {
+ if (SettingScope == FormLevel && IsNvUpdateRequiredForForm (Form)) {
ConfigInfo = NULL;
Link = GetFirstNode (&Form->ConfigRequestHead);
while (!IsNull (&Form->ConfigRequestHead, Link)) {
@@ -2423,7 +2536,7 @@ SubmitForm (
//
// 1. Prepare <ConfigResp>
//
- Status = StorageToConfigResp (ConfigInfo->Storage, &ConfigResp, ConfigInfo->ConfigRequest);
+ Status = StorageToConfigResp (ConfigInfo->Storage, &ConfigResp, ConfigInfo->ConfigRequest, TRUE);
if (EFI_ERROR (Status)) {
return Status;
}
@@ -2499,14 +2612,14 @@ SubmitForm (
//
// 3. Config success, update storage shadow Buffer, only update the data belong to this form.
//
- SynchronizeStorageForForm(FormSet, ConfigInfo, TRUE);
+ SynchronizeStorage (FormSet, ConfigInfo->Storage, ConfigInfo->ConfigRequest, TRUE);
}
//
// 4. Update the NV flag.
//
- Form->NvUpdateRequired = FALSE;
- } else if (SettingScope == FormSetLevel && IsNvUpdateRequired(FormSet)) {
+ ValueChangeResetFlagUpdate(TRUE, NULL, Form);
+ } else if (SettingScope == FormSetLevel && IsNvUpdateRequiredForFormSet (FormSet)) {
//
// Submit Buffer storage or Name/Value storage
//
@@ -2530,7 +2643,7 @@ SubmitForm (
//
// 1. Prepare <ConfigResp>
//
- Status = StorageToConfigResp (Storage, &ConfigResp, FormSetStorage->ConfigRequest);
+ Status = StorageToConfigResp (Storage, &ConfigResp, FormSetStorage->ConfigRequest, TRUE);
if (EFI_ERROR (Status)) {
return Status;
}
@@ -2602,13 +2715,13 @@ SubmitForm (
//
// 3. Config success, update storage shadow Buffer
//
- SynchronizeStorage (Storage, TRUE);
+ SynchronizeStorage (FormSet, Storage, FormSetStorage->ConfigRequest, TRUE);
}
//
// 4. Update the NV flag.
//
- UpdateNvInfoInForm (FormSet, FALSE);
+ ValueChangeResetFlagUpdate(TRUE, FormSet, NULL);
} else if (SettingScope == SystemLevel) {
//
// System Level Save.
@@ -2864,6 +2977,138 @@ GetDefaultIdForCallBack (
}
}
+
+
+/**
+ Return data element in an Array by its Index.
+
+ @param Array The data array.
+ @param Type Type of the data in this array.
+ @param Index Zero based index for data in this array.
+
+ @retval Value The data to be returned
+
+**/
+UINT64
+GetArrayData (
+ IN VOID *Array,
+ IN UINT8 Type,
+ IN UINTN Index
+ )
+{
+ UINT64 Data;
+
+ ASSERT (Array != NULL);
+
+ Data = 0;
+ switch (Type) {
+ case EFI_IFR_TYPE_NUM_SIZE_8:
+ Data = (UINT64) *(((UINT8 *) Array) + Index);
+ break;
+
+ case EFI_IFR_TYPE_NUM_SIZE_16:
+ Data = (UINT64) *(((UINT16 *) Array) + Index);
+ break;
+
+ case EFI_IFR_TYPE_NUM_SIZE_32:
+ Data = (UINT64) *(((UINT32 *) Array) + Index);
+ break;
+
+ case EFI_IFR_TYPE_NUM_SIZE_64:
+ Data = (UINT64) *(((UINT64 *) Array) + Index);
+ break;
+
+ default:
+ break;
+ }
+
+ return Data;
+}
+
+
+/**
+ Set value of a data element in an Array by its Index.
+
+ @param Array The data array.
+ @param Type Type of the data in this array.
+ @param Index Zero based index for data in this array.
+ @param Value The value to be set.
+
+**/
+VOID
+SetArrayData (
+ IN VOID *Array,
+ IN UINT8 Type,
+ IN UINTN Index,
+ IN UINT64 Value
+ )
+{
+
+ ASSERT (Array != NULL);
+
+ switch (Type) {
+ case EFI_IFR_TYPE_NUM_SIZE_8:
+ *(((UINT8 *) Array) + Index) = (UINT8) Value;
+ break;
+
+ case EFI_IFR_TYPE_NUM_SIZE_16:
+ *(((UINT16 *) Array) + Index) = (UINT16) Value;
+ break;
+
+ case EFI_IFR_TYPE_NUM_SIZE_32:
+ *(((UINT32 *) Array) + Index) = (UINT32) Value;
+ break;
+
+ case EFI_IFR_TYPE_NUM_SIZE_64:
+ *(((UINT64 *) Array) + Index) = (UINT64) Value;
+ break;
+
+ default:
+ break;
+ }
+}
+
+/**
+ Search an Option of a Question by its value.
+
+ @param Question The Question
+ @param OptionValue Value for Option to be searched.
+
+ @retval Pointer Pointer to the found Option.
+ @retval NULL Option not found.
+
+**/
+QUESTION_OPTION *
+ValueToOption (
+ IN FORM_BROWSER_STATEMENT *Question,
+ IN EFI_HII_VALUE *OptionValue
+ )
+{
+ LIST_ENTRY *Link;
+ QUESTION_OPTION *Option;
+ INTN Result;
+
+ Link = GetFirstNode (&Question->OptionListHead);
+ while (!IsNull (&Question->OptionListHead, Link)) {
+ Option = QUESTION_OPTION_FROM_LINK (Link);
+
+ if ((CompareHiiValue (&Option->Value, OptionValue, &Result, NULL) == EFI_SUCCESS) && (Result == 0)) {
+ //
+ // Check the suppressif condition, only a valid option can be return.
+ //
+ if ((Option->SuppressExpression == NULL) ||
+ ((EvaluateExpressionList(Option->SuppressExpression, FALSE, NULL, NULL) == ExpressFalse))) {
+ return Option;
+ }
+ }
+
+ Link = GetNextNode (&Question->OptionListHead, Link);
+ }
+
+ return NULL;
+}
+
+
/**
Reset Question to its default value.
@@ -3155,11 +3400,7 @@ ExtractDefault (
LIST_ENTRY *FormLink;
LIST_ENTRY *Link;
FORM_BROWSER_STATEMENT *Question;
- FORM_BROWSER_FORMSET *BackUpFormSet;
FORM_BROWSER_FORMSET *LocalFormSet;
- EFI_HII_HANDLE *HiiHandles;
- UINTN Index;
- EFI_GUID ZeroGuid;
Status = EFI_SUCCESS;
@@ -3229,10 +3470,6 @@ ExtractDefault (
if ((Question->Storage != NULL) &&
(Question->Storage->Type != EFI_HII_VARSTORE_EFI_VARIABLE)) {
SetQuestionValue (FormSet, Form, Question, GetSetValueWithEditBuffer);
- //
- // Update Form NV flag.
- //
- Form->NvUpdateRequired = TRUE;
}
}
} else if (SettingScope == FormSetLevel) {
@@ -3244,65 +3481,9 @@ ExtractDefault (
}
} else if (SettingScope == SystemLevel) {
//
- // Open all FormSet by locate HII packages.
- // Initiliaze the maintain FormSet to store default data as back up data.
+ // Preload all Hii formset.
//
- BackUpFormSet = gOldFormSet;
- gOldFormSet = NULL;
-
- //
- // Get all the Hii handles
- //
- HiiHandles = HiiGetHiiHandles (NULL);
- ASSERT (HiiHandles != NULL);
-
- //
- // Search for formset of each class type
- //
- for (Index = 0; HiiHandles[Index] != NULL; Index++) {
- //
- // Check HiiHandles[Index] does exist in global maintain list.
- //
- if (GetFormSetFromHiiHandle (HiiHandles[Index]) != NULL) {
- continue;
- }
-
- //
- // Initilize FormSet Setting
- //
- LocalFormSet = AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET));
- ASSERT (LocalFormSet != NULL);
- ZeroMem (&ZeroGuid, sizeof (ZeroGuid));
- Status = InitializeFormSet (HiiHandles[Index], &ZeroGuid, LocalFormSet, FALSE);
- if (EFI_ERROR (Status) || IsListEmpty (&LocalFormSet->FormListHead)) {
- DestroyFormSet (LocalFormSet);
- continue;
- }
- Status = InitializeCurrentSetting (LocalFormSet);
- if (EFI_ERROR (Status)) {
- DestroyFormSet (LocalFormSet);
- continue;
- }
- //
- // Initilize Questions' Value
- //
- Status = LoadFormSetConfig (NULL, LocalFormSet);
- if (EFI_ERROR (Status)) {
- DestroyFormSet (LocalFormSet);
- continue;
- }
-
- //
- // Add FormSet into the maintain list.
- //
- InsertTailList (&gBrowserFormSetList, &LocalFormSet->Link);
- }
-
- //
- // Free resources, and restore gOldFormSet and gClassOfVfr
- //
- FreePool (HiiHandles);
- gOldFormSet = BackUpFormSet;
+ LoadAllHiiFormset();
//
// Set Default Value for each FormSet in the maintain list.
@@ -3321,6 +3502,81 @@ ExtractDefault (
return EFI_SUCCESS;
}
+
+/**
+ Validate whether this question's value has changed.
+
+ @param FormSet FormSet data structure.
+ @param Form Form data structure.
+ @param Question Question to be initialized.
+ @param GetValueFrom Where to get value, may from editbuffer, buffer or hii driver.
+
+ @retval TRUE Question's value has changed.
+ @retval FALSE Question's value has not changed
+
+**/
+BOOLEAN
+IsQuestionValueChanged (
+ IN FORM_BROWSER_FORMSET *FormSet,
+ IN FORM_BROWSER_FORM *Form,
+ IN OUT FORM_BROWSER_STATEMENT *Question,
+ IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
+ )
+{
+ EFI_HII_VALUE BackUpValue;
+ CHAR8 *BackUpBuffer;
+ EFI_STATUS Status;
+ BOOLEAN ValueChanged;
+ UINTN BufferWidth;
+
+ //
+ // For quetion without storage, always mark it as data not changed.
+ //
+ if (Question->Storage == NULL && Question->Operand != EFI_IFR_TIME_OP && Question->Operand != EFI_IFR_DATE_OP) {
+ return FALSE;
+ }
+
+ BackUpBuffer = NULL;
+ ValueChanged = FALSE;
+
+ switch (Question->Operand) {
+ case EFI_IFR_ORDERED_LIST_OP:
+ BufferWidth = Question->StorageWidth;
+ BackUpBuffer = AllocateCopyPool (BufferWidth, Question->BufferValue);
+ ASSERT (BackUpBuffer != NULL);
+ break;
+
+ case EFI_IFR_STRING_OP:
+ case EFI_IFR_PASSWORD_OP:
+ BufferWidth = (UINTN) Question->Maximum * sizeof (CHAR16);
+ BackUpBuffer = AllocateCopyPool (BufferWidth, Question->BufferValue);
+ ASSERT (BackUpBuffer != NULL);
+ break;
+
+ default:
+ BufferWidth = 0;
+ break;
+ }
+ CopyMem (&BackUpValue, &Question->HiiValue, sizeof (EFI_HII_VALUE));
+
+ Status = GetQuestionValue (FormSet, Form, Question, GetValueFrom);
+ ASSERT_EFI_ERROR(Status);
+
+ if (CompareMem (&BackUpValue, &Question->HiiValue, sizeof (EFI_HII_VALUE)) != 0 ||
+ CompareMem (BackUpBuffer, Question->BufferValue, BufferWidth) != 0) {
+ ValueChanged = TRUE;
+ }
+
+ CopyMem (&Question->HiiValue, &BackUpValue, sizeof (EFI_HII_VALUE));
+ CopyMem (Question->BufferValue, BackUpBuffer, BufferWidth);
+
+ if (BackUpBuffer != NULL) {
+ FreePool (BackUpBuffer);
+ }
+
+ return ValueChanged;
+}
+
/**
Initialize Question's Edit copy from Storage.
@@ -3354,7 +3610,11 @@ LoadFormConfig (
//
// Initialize local copy of Value for each Question
//
- Status = GetQuestionValue (FormSet, Form, Question, GetSetValueWithEditBuffer);
+ if (Question->Operand == EFI_IFR_PASSWORD_OP && (Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK)== 0) {
+ Status = GetQuestionValue (FormSet, Form, Question, GetSetValueWithHiiDriver);
+ } else {
+ Status = GetQuestionValue (FormSet, Form, Question, GetSetValueWithEditBuffer);
+ }
if (EFI_ERROR (Status)) {
return Status;
}
@@ -3394,6 +3654,11 @@ LoadFormConfig (
Status = ProcessCallBackFunction(Selection, Question, EFI_BROWSER_ACTION_RETRIEVE, TRUE);
}
+ //
+ // Update Question Value changed flag.
+ //
+ Question->ValueChanged = IsQuestionValueChanged(FormSet, Form, Question, GetSetValueWithBuffer);
+
Link = GetNextNode (&Form->StatementListHead, Link);
}
@@ -3437,6 +3702,11 @@ LoadFormSetConfig (
Link = GetNextNode (&FormSet->FormListHead, Link);
}
+ //
+ // Finished question initialization.
+ //
+ FormSet->QuestionInited = TRUE;
+
return EFI_SUCCESS;
}
@@ -3491,6 +3761,13 @@ RemoveConfigRequest (
CHAR16 *NextRequestElement;
CHAR16 *SearchKey;
+ //
+ // No request element in it, just return.
+ //
+ if (ConfigRequest == NULL) {
+ return;
+ }
+
if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {
//
// "&Name1&Name2" section for EFI_HII_VARSTORE_NAME_VALUE storage
@@ -3565,6 +3842,7 @@ CleanBrowserStorage (
{
LIST_ENTRY *Link;
FORMSET_STORAGE *Storage;
+ CHAR16 *ConfigRequest;
Link = GetFirstNode (&FormSet->StorageListHead);
while (!IsNull (&FormSet->StorageListHead, Link)) {
@@ -3572,7 +3850,8 @@ CleanBrowserStorage (
Link = GetNextNode (&FormSet->StorageListHead, Link);
if ((Storage->BrowserStorage->Type != EFI_HII_VARSTORE_BUFFER) &&
- (Storage->BrowserStorage->Type != EFI_HII_VARSTORE_NAME_VALUE)) {
+ (Storage->BrowserStorage->Type != EFI_HII_VARSTORE_NAME_VALUE) &&
+ (Storage->BrowserStorage->Type != EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) {
continue;
}
@@ -3580,7 +3859,8 @@ CleanBrowserStorage (
continue;
}
- RemoveConfigRequest (Storage->BrowserStorage, Storage->ConfigRequest);
+ ConfigRequest = FormSet->QuestionInited ? Storage->ConfigRequest : Storage->ConfigElements;
+ RemoveConfigRequest (Storage->BrowserStorage, ConfigRequest);
}
}
@@ -3651,7 +3931,6 @@ AppendConfigRequest (
Adjust the config request info, remove the request elements which already in AllConfigRequest string.
@param Storage Form set Storage.
- @param ConfigRequest Return the ConfigRequest info.
@retval TRUE Has element not covered by current used elements, need to continue to call ExtractConfig
@retval FALSE All elements covered by current used elements.
@@ -3659,8 +3938,7 @@ AppendConfigRequest (
**/
BOOLEAN
ConfigRequestAdjust (
- IN FORMSET_STORAGE *Storage,
- OUT CHAR16 **ConfigRequest
+ IN FORMSET_STORAGE *Storage
)
{
CHAR16 *RequestElement;
@@ -3676,7 +3954,10 @@ ConfigRequestAdjust (
if (Storage->BrowserStorage->ConfigRequest == NULL) {
Storage->BrowserStorage->ConfigRequest = AllocateCopyPool (StrSize (Storage->ConfigRequest), Storage->ConfigRequest);
- *ConfigRequest = AllocateCopyPool (StrSize (Storage->ConfigRequest), Storage->ConfigRequest);
+ if (Storage->ConfigElements != NULL) {
+ FreePool (Storage->ConfigElements);
+ }
+ Storage->ConfigElements = AllocateCopyPool (StrSize (Storage->ConfigRequest), Storage->ConfigRequest);
return TRUE;
}
@@ -3745,7 +4026,10 @@ ConfigRequestAdjust (
}
if (RetVal) {
- *ConfigRequest = RetBuf;
+ if (Storage->ConfigElements != NULL) {
+ FreePool (Storage->ConfigElements);
+ }
+ Storage->ConfigElements = RetBuf;
} else {
FreePool (RetBuf);
}
@@ -3754,15 +4038,162 @@ ConfigRequestAdjust (
}
/**
+
+ Base on ConfigRequest info to get default value for current formset.
+
+ ConfigRequest info include the info about which questions in current formset need to
+ get default value. This function only get these questions default value.
+
+ @param FormSet FormSet data structure.
+ @param Storage Storage need to update value.
+ @param ConfigRequest The config request string.
+
+**/
+VOID
+GetDefaultForFormset (
+ IN FORM_BROWSER_FORMSET *FormSet,
+ IN BROWSER_STORAGE *Storage,
+ IN CHAR16 *ConfigRequest
+ )
+{
+ UINT8 *BackUpBuf;
+ UINTN BufferSize;
+ LIST_ENTRY BackUpList;
+ NAME_VALUE_NODE *Node;
+ LIST_ENTRY *Link;
+ LIST_ENTRY *NodeLink;
+ NAME_VALUE_NODE *TmpNode;
+ EFI_STATUS Status;
+ EFI_STRING Progress;
+ EFI_STRING Result;
+
+ BackUpBuf = NULL;
+ InitializeListHead(&BackUpList);
+
+ //
+ // Back update the edit buffer.
+ //
+ if (Storage->Type == EFI_HII_VARSTORE_BUFFER ||
+ (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) {
+ BackUpBuf = AllocateCopyPool (Storage->Size, Storage->EditBuffer);
+ ASSERT (BackUpBuf != NULL);
+ } else if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {
+ Link = GetFirstNode (&Storage->NameValueListHead);
+ while (!IsNull (&Storage->NameValueListHead, Link)) {
+ Node = NAME_VALUE_NODE_FROM_LINK (Link);
+ Link = GetNextNode (&Storage->NameValueListHead, Link);
+
+ //
+ // Only back Node belong to this formset.
+ //
+ if (StrStr (Storage->ConfigRequest, Node->Name) == NULL) {
+ continue;
+ }
+
+ TmpNode = AllocateCopyPool (sizeof (NAME_VALUE_NODE), Node);
+ TmpNode->Name = AllocateCopyPool (StrSize(Node->Name) * sizeof (CHAR16), Node->Name);
+ TmpNode->EditValue = AllocateCopyPool (StrSize(Node->EditValue) * sizeof (CHAR16), Node->EditValue);
+
+ InsertTailList(&BackUpList, &TmpNode->Link);
+ }
+ }
+
+ //
+ // Get default value.
+ //
+ ExtractDefault (FormSet, NULL, EFI_HII_DEFAULT_CLASS_STANDARD, FormSetLevel, GetDefaultForStorage, Storage, TRUE);
+
+ //
+ // Update the question value based on the input ConfigRequest.
+ //
+ if (Storage->Type == EFI_HII_VARSTORE_BUFFER ||
+ (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) {
+ ASSERT (BackUpBuf != NULL);
+ BufferSize = Storage->Size;
+ Status = mHiiConfigRouting->BlockToConfig(
+ mHiiConfigRouting,
+ ConfigRequest,
+ Storage->EditBuffer,
+ BufferSize,
+ &Result,
+ &Progress
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = mHiiConfigRouting->ConfigToBlock (
+ mHiiConfigRouting,
+ Result,
+ BackUpBuf,
+ &BufferSize,
+ &Progress
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ if (Result != NULL) {
+ FreePool (Result);
+ }
+
+ CopyMem (Storage->EditBuffer, BackUpBuf, Storage->Size);
+ FreePool (BackUpBuf);
+ } else if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {
+ //
+ // Update question value, only element in ConfigReqeust will be update.
+ //
+ Link = GetFirstNode (&BackUpList);
+ while (!IsNull (&BackUpList, Link)) {
+ Node = NAME_VALUE_NODE_FROM_LINK (Link);
+ Link = GetNextNode (&BackUpList, Link);
+
+ if (StrStr (ConfigRequest, Node->Name) != NULL) {
+ continue;
+ }
+
+ NodeLink = GetFirstNode (&Storage->NameValueListHead);
+ while (!IsNull (&Storage->NameValueListHead, NodeLink)) {
+ TmpNode = NAME_VALUE_NODE_FROM_LINK (NodeLink);
+ NodeLink = GetNextNode (&Storage->NameValueListHead, NodeLink);
+
+ if (StrCmp (Node->Name, TmpNode->Name) != 0) {
+ continue;
+ }
+
+ FreePool (TmpNode->EditValue);
+ TmpNode->EditValue = AllocateCopyPool (StrSize(Node->EditValue) * sizeof (CHAR16), Node->EditValue);
+
+ RemoveEntryList (&Node->Link);
+ FreePool (Node->EditValue);
+ FreePool (Node->Name);
+ FreePool (Node);
+ }
+ }
+
+ //
+ // Restore the Name/Value node.
+ //
+ Link = GetFirstNode (&BackUpList);
+ while (!IsNull (&BackUpList, Link)) {
+ Node = NAME_VALUE_NODE_FROM_LINK (Link);
+ Link = GetNextNode (&BackUpList, Link);
+
+ //
+ // Free this node.
+ //
+ RemoveEntryList (&Node->Link);
+ FreePool (Node->EditValue);
+ FreePool (Node->Name);
+ FreePool (Node);
+ }
+ }
+}
+
+/**
Fill storage's edit copy with settings requested from Configuration Driver.
@param FormSet FormSet data structure.
@param Storage Buffer Storage.
- @retval EFI_SUCCESS The function completed successfully.
-
**/
-EFI_STATUS
+VOID
LoadStorage (
IN FORM_BROWSER_FORMSET *FormSet,
IN FORMSET_STORAGE *Storage
@@ -3772,18 +4203,17 @@ LoadStorage (
EFI_STRING Progress;
EFI_STRING Result;
CHAR16 *StrPtr;
- CHAR16 *ConfigRequest;
- if (Storage->BrowserStorage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {
- return EFI_SUCCESS;
- }
+ switch (Storage->BrowserStorage->Type) {
+ case EFI_HII_VARSTORE_EFI_VARIABLE:
+ return;
+
+ case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:
+ if (Storage->BrowserStorage->ReferenceCount > 1) {
+ ConfigRequestAdjust(Storage);
+ return;
+ }
- if (Storage->BrowserStorage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) {
- Status = EFI_SUCCESS;
- //
- // EFI varstore data all get from variable, so no need to get again.
- //
- if (Storage->BrowserStorage->ReferenceCount == 1) {
Status = gRT->GetVariable (
Storage->BrowserStorage->Name,
&Storage->BrowserStorage->Guid,
@@ -3791,55 +4221,78 @@ LoadStorage (
(UINTN*)&Storage->BrowserStorage->Size,
Storage->BrowserStorage->EditBuffer
);
- }
- return Status;
- }
+ //
+ // If get variable fail, extract default from IFR binary
+ //
+ if (EFI_ERROR (Status)) {
+ ExtractDefault (FormSet, NULL, EFI_HII_DEFAULT_CLASS_STANDARD, FormSetLevel, GetDefaultForStorage, Storage->BrowserStorage, TRUE);
+ }
- if (FormSet->ConfigAccess == NULL) {
- return EFI_NOT_FOUND;
- }
+ Storage->BrowserStorage->ConfigRequest = AllocateCopyPool (StrSize (Storage->ConfigRequest), Storage->ConfigRequest);
+ //
+ // Input NULL for ConfigRequest field means sync all fields from editbuffer to buffer.
+ //
+ SynchronizeStorage(FormSet, Storage->BrowserStorage, NULL, TRUE);
+ break;
- if (Storage->ElementCount == 0) {
- //
- // Skip if there is no RequestElement
- //
- return EFI_SUCCESS;
- }
+ case EFI_HII_VARSTORE_BUFFER:
+ case EFI_HII_VARSTORE_NAME_VALUE:
+ //
+ // Skip if there is no RequestElement
+ //
+ if (Storage->ElementCount == 0) {
+ return;
+ }
- //
- // Adjust the ConfigRequest string, only the field not saved in BrowserStorage->AllConfig
- // will used to call ExtractConfig.
- //
- if (!ConfigRequestAdjust(Storage, &ConfigRequest)) {
- return EFI_SUCCESS;
- }
+ //
+ // Adjust the ConfigRequest string, only the field not saved in BrowserStorage->AllConfig
+ // will used to call ExtractConfig.
+ // If not elements need to udpate, return.
+ //
+ if (!ConfigRequestAdjust(Storage)) {
+ return;
+ }
+ ASSERT (Storage->ConfigElements != NULL);
- //
- // Request current settings from Configuration Driver
- //
- Status = FormSet->ConfigAccess->ExtractConfig (
- FormSet->ConfigAccess,
- ConfigRequest,
- &Progress,
- &Result
- );
- FreePool (ConfigRequest);
+ Status = EFI_NOT_FOUND;
+ if (FormSet->ConfigAccess != NULL) {
+ //
+ // Request current settings from Configuration Driver
+ //
+ Status = FormSet->ConfigAccess->ExtractConfig (
+ FormSet->ConfigAccess,
+ Storage->ConfigElements,
+ &Progress,
+ &Result
+ );
+
+ if (!EFI_ERROR (Status)) {
+ //
+ // Convert Result from <ConfigAltResp> to <ConfigResp>
+ //
+ StrPtr = StrStr (Result, L"&GUID=");
+ if (StrPtr != NULL) {
+ *StrPtr = L'\0';
+ }
+
+ Status = ConfigRespToStorage (Storage->BrowserStorage, Result);
+ FreePool (Result);
+ }
+ }
- if (EFI_ERROR (Status)) {
- return Status;
- }
+ if (EFI_ERROR (Status)) {
+ //
+ // Base on the configRequest string to get default value.
+ //
+ GetDefaultForFormset (FormSet, Storage->BrowserStorage, Storage->ConfigElements);
+ }
- //
- // Convert Result from <ConfigAltResp> to <ConfigResp>
- //
- StrPtr = StrStr (Result, L"&GUID=");
- if (StrPtr != NULL) {
- *StrPtr = L'\0';
- }
+ SynchronizeStorage(FormSet, Storage->BrowserStorage, Storage->ConfigElements, TRUE);
+ break;
- Status = ConfigRespToStorage (Storage->BrowserStorage, Result);
- FreePool (Result);
- return Status;
+ default:
+ break;
+ }
}
/**
@@ -3847,22 +4300,15 @@ LoadStorage (
@param FormSet FormSet data structure.
- @retval EFI_SUCCESS The function completed successfully.
-
**/
-EFI_STATUS
+VOID
InitializeCurrentSetting (
IN OUT FORM_BROWSER_FORMSET *FormSet
)
{
LIST_ENTRY *Link;
- LIST_ENTRY *Link2;
FORMSET_STORAGE *Storage;
- FORMSET_STORAGE *StorageSrc;
- FORMSET_STORAGE *OldStorage;
- FORM_BROWSER_FORM *Form;
- FORM_BROWSER_FORM *Form2;
- EFI_STATUS Status;
+ FORM_BROWSER_FORMSET *OldFormSet;
//
// Extract default from IFR binary for no storage questions.
@@ -3876,77 +4322,21 @@ InitializeCurrentSetting (
while (!IsNull (&FormSet->StorageListHead, Link)) {
Storage = FORMSET_STORAGE_FROM_LINK (Link);
- OldStorage = NULL;
- if (gOldFormSet != NULL) {
- //
- // Try to find the Storage in backup formset gOldFormSet
- //
- Link2 = GetFirstNode (&gOldFormSet->StorageListHead);
- while (!IsNull (&gOldFormSet->StorageListHead, Link2)) {
- StorageSrc = FORMSET_STORAGE_FROM_LINK (Link2);
-
- if (StorageSrc->VarStoreId == Storage->VarStoreId) {
- OldStorage = StorageSrc;
- break;
- }
-
- Link2 = GetNextNode (&gOldFormSet->StorageListHead, Link2);
- }
- }
-
- //
- // Storage is not found in backup formset and current global storage not has other driver used,
- // request it from ConfigDriver
- //
- if (OldStorage == NULL) {
- Status = LoadStorage (FormSet, Storage);
-
- if (EFI_ERROR (Status)) {
- //
- // If get last time changed value failed, extract default from IFR binary
- //
- ExtractDefault (FormSet, NULL, EFI_HII_DEFAULT_CLASS_STANDARD, FormSetLevel, GetDefaultForStorage, Storage->BrowserStorage, TRUE);
- //
- // ExtractDefault will set the NV flag to TRUE, so need this function to clean the flag
- // in current situation.
- //
- UpdateNvInfoInForm (FormSet, FALSE);
- }
-
- //
- // Now Edit Buffer is filled with default values(lower priority) or current
- // settings(higher priority), sychronize it to shadow Buffer
- //
- SynchronizeStorage (Storage->BrowserStorage, TRUE);
- }
+ LoadStorage (FormSet, Storage);
Link = GetNextNode (&FormSet->StorageListHead, Link);
}
//
- // If has old formset, get the old nv update status.
+ // Try to find pre FormSet in the maintain backup list.
+ // If old formset != NULL, destroy this formset. Add new formset to gBrowserFormSetList.
//
- if (gOldFormSet != NULL) {
- Link = GetFirstNode (&FormSet->FormListHead);
- while (!IsNull (&FormSet->FormListHead, Link)) {
- Form = FORM_BROWSER_FORM_FROM_LINK (Link);
-
- Link2 = GetFirstNode (&gOldFormSet->FormListHead);
- while (!IsNull (&gOldFormSet->FormListHead, Link2)) {
- Form2 = FORM_BROWSER_FORM_FROM_LINK (Link2);
-
- if (Form->FormId == Form2->FormId) {
- Form->NvUpdateRequired = Form2->NvUpdateRequired;
- break;
- }
-
- Link2 = GetNextNode (&gOldFormSet->FormListHead, Link2);
- }
- Link = GetNextNode (&FormSet->FormListHead, Link);
- }
+ OldFormSet = GetFormSetFromHiiHandle (FormSet->HiiHandle);
+ if (OldFormSet != NULL) {
+ RemoveEntryList (&OldFormSet->Link);
+ DestroyFormSet (OldFormSet);
}
-
- return EFI_SUCCESS;
+ InsertTailList (&gBrowserFormSetList, &FormSet->Link);
}
@@ -4129,7 +4519,6 @@ GetIfrBinaryData (
found in package list.
On output, GUID of the formset found(if not NULL).
@param FormSet FormSet data structure.
- @param UpdateGlobalVar Whether need to update the global variable.
@retval EFI_SUCCESS The function completed successfully.
@retval EFI_NOT_FOUND The specified FormSet could not be found.
@@ -4139,13 +4528,11 @@ EFI_STATUS
InitializeFormSet (
IN EFI_HII_HANDLE Handle,
IN OUT EFI_GUID *FormSetGuid,
- OUT FORM_BROWSER_FORMSET *FormSet,
- IN BOOLEAN UpdateGlobalVar
+ OUT FORM_BROWSER_FORMSET *FormSet
)
{
EFI_STATUS Status;
EFI_HANDLE DriverHandle;
- UINT16 Index;
Status = GetIfrBinaryData (Handle, FormSetGuid, &FormSet->IfrBinaryLength, &FormSet->IfrBinaryData);
if (EFI_ERROR (Status)) {
@@ -4155,6 +4542,7 @@ InitializeFormSet (
FormSet->Signature = FORM_BROWSER_FORMSET_SIGNATURE;
FormSet->HiiHandle = Handle;
CopyMem (&FormSet->Guid, FormSetGuid, sizeof (EFI_GUID));
+ FormSet->QuestionInited = FALSE;
//
// Retrieve ConfigAccess Protocol associated with this HiiPackageList
@@ -4181,55 +4569,8 @@ InitializeFormSet (
// Parse the IFR binary OpCodes
//
Status = ParseOpCodes (FormSet);
- if (EFI_ERROR (Status)) {
- return Status;
- }
- //
- // If not need to update the global variable, just return.
- //
- if (!UpdateGlobalVar) {
- return Status;
- }
-
- //
- // Set VFR type by FormSet SubClass field
- //
- gClassOfVfr = FORMSET_CLASS_PLATFORM_SETUP;
- if (FormSet->SubClass == EFI_FRONT_PAGE_SUBCLASS) {
- gClassOfVfr = FORMSET_CLASS_FRONT_PAGE;
- }
-
- //
- // Set VFR type by FormSet class guid
- //
- for (Index = 0; Index < 3; Index ++) {
- if (CompareGuid (&FormSet->ClassGuid[Index], &gEfiHiiPlatformSetupFormsetGuid)) {
- gClassOfVfr |= FORMSET_CLASS_PLATFORM_SETUP;
- break;
- }
- }
-
- gFunctionKeySetting = ENABLE_FUNCTION_KEY_SETTING;
-
- if ((gClassOfVfr & FORMSET_CLASS_FRONT_PAGE) == FORMSET_CLASS_FRONT_PAGE) {
- gFrontPageHandle = FormSet->HiiHandle;
- gFunctionKeySetting = NONE_FUNCTION_KEY_SETTING;
- }
-
- //
- // Match GUID to find out the function key setting. If match fail, use the default setting.
- //
- for (Index = 0; Index < sizeof (gFunctionKeySettingTable) / sizeof (FUNCTIION_KEY_SETTING); Index++) {
- if (CompareGuid (&FormSet->Guid, &(gFunctionKeySettingTable[Index].FormSetGuid))) {
- //
- // Update the function key setting.
- //
- gFunctionKeySetting = gFunctionKeySettingTable[Index].KeySetting;
- }
- }
-
- return EFI_SUCCESS;
+ return Status;
}
@@ -4245,6 +4586,7 @@ SaveBrowserContext (
)
{
BROWSER_CONTEXT *Context;
+ FORM_ENTRY_INFO *MenuList;
gBrowserContextCount++;
if (gBrowserContextCount == 1) {
@@ -4262,47 +4604,23 @@ SaveBrowserContext (
//
// Save FormBrowser context
//
- Context->BannerData = gBannerData;
- Context->ClassOfVfr = gClassOfVfr;
- Context->FunctionKeySetting = gFunctionKeySetting;
+ Context->Selection = gCurrentSelection;
Context->ResetRequired = gResetRequired;
- Context->Direction = gDirection;
- Context->EnterString = gEnterString;
- Context->EnterCommitString = gEnterCommitString;
- Context->EnterEscapeString = gEnterEscapeString;
- Context->EscapeString = gEscapeString;
- Context->MoveHighlight = gMoveHighlight;
- Context->MakeSelection = gMakeSelection;
- Context->DecNumericInput = gDecNumericInput;
- Context->HexNumericInput = gHexNumericInput;
- Context->ToggleCheckBox = gToggleCheckBox;
- Context->PromptForData = gPromptForData;
- Context->PromptForPassword = gPromptForPassword;
- Context->PromptForNewPassword = gPromptForNewPassword;
- Context->ConfirmPassword = gConfirmPassword;
- Context->ConfirmError = gConfirmError;
- Context->PassowordInvalid = gPassowordInvalid;
- Context->PressEnter = gPressEnter;
- Context->EmptyString = gEmptyString;
- Context->AreYouSure = gAreYouSure;
- Context->YesResponse = gYesResponse;
- Context->NoResponse = gNoResponse;
- Context->MiniString = gMiniString;
- Context->PlusString = gPlusString;
- Context->MinusString = gMinusString;
- Context->AdjustNumber = gAdjustNumber;
- Context->SaveChanges = gSaveChanges;
- Context->OptionMismatch = gOptionMismatch;
- Context->FormSuppress = gFormSuppress;
- Context->PromptBlockWidth = gPromptBlockWidth;
- Context->OptionBlockWidth = gOptionBlockWidth;
- Context->HelpBlockWidth = gHelpBlockWidth;
- Context->OldFormSet = gOldFormSet;
- Context->MenuRefreshHead = gMenuRefreshHead;
- Context->ProtocolNotFound = gProtocolNotFound;
-
- CopyMem (&Context->ScreenDimensions, &gScreenDimensions, sizeof (gScreenDimensions));
- CopyMem (&Context->MenuOption, &gMenuOption, sizeof (gMenuOption));
+ Context->ExitRequired = gExitRequired;
+ Context->HiiHandle = mCurrentHiiHandle;
+ Context->FormId = mCurrentFormId;
+ CopyGuid (&Context->FormSetGuid, &mCurrentFormSetGuid);
+
+ //
+ // Save the menu history data.
+ //
+ InitializeListHead(&Context->FormHistoryList);
+ while (!IsListEmpty (&mPrivateData.FormBrowserEx2.FormViewHistoryHead)) {
+ MenuList = FORM_ENTRY_INFO_FROM_LINK (mPrivateData.FormBrowserEx2.FormViewHistoryHead.ForwardLink);
+ RemoveEntryList (&MenuList->Link);
+
+ InsertTailList(&Context->FormHistoryList, &MenuList->Link);
+ }
//
// Insert to FormBrowser context list
@@ -4322,6 +4640,7 @@ RestoreBrowserContext (
{
LIST_ENTRY *Link;
BROWSER_CONTEXT *Context;
+ FORM_ENTRY_INFO *MenuList;
ASSERT (gBrowserContextCount != 0);
gBrowserContextCount--;
@@ -4340,47 +4659,22 @@ RestoreBrowserContext (
//
// Restore FormBrowser context
//
- gBannerData = Context->BannerData;
- gClassOfVfr = Context->ClassOfVfr;
- gFunctionKeySetting = Context->FunctionKeySetting;
+ gCurrentSelection = Context->Selection;
gResetRequired = Context->ResetRequired;
- gDirection = Context->Direction;
- gEnterString = Context->EnterString;
- gEnterCommitString = Context->EnterCommitString;
- gEnterEscapeString = Context->EnterEscapeString;
- gEscapeString = Context->EscapeString;
- gMoveHighlight = Context->MoveHighlight;
- gMakeSelection = Context->MakeSelection;
- gDecNumericInput = Context->DecNumericInput;
- gHexNumericInput = Context->HexNumericInput;
- gToggleCheckBox = Context->ToggleCheckBox;
- gPromptForData = Context->PromptForData;
- gPromptForPassword = Context->PromptForPassword;
- gPromptForNewPassword = Context->PromptForNewPassword;
- gConfirmPassword = Context->ConfirmPassword;
- gConfirmError = Context->ConfirmError;
- gPassowordInvalid = Context->PassowordInvalid;
- gPressEnter = Context->PressEnter;
- gEmptyString = Context->EmptyString;
- gAreYouSure = Context->AreYouSure;
- gYesResponse = Context->YesResponse;
- gNoResponse = Context->NoResponse;
- gMiniString = Context->MiniString;
- gPlusString = Context->PlusString;
- gMinusString = Context->MinusString;
- gAdjustNumber = Context->AdjustNumber;
- gSaveChanges = Context->SaveChanges;
- gOptionMismatch = Context->OptionMismatch;
- gFormSuppress = Context->FormSuppress;
- gPromptBlockWidth = Context->PromptBlockWidth;
- gOptionBlockWidth = Context->OptionBlockWidth;
- gHelpBlockWidth = Context->HelpBlockWidth;
- gOldFormSet = Context->OldFormSet;
- gMenuRefreshHead = Context->MenuRefreshHead;
- gProtocolNotFound = Context->ProtocolNotFound;
-
- CopyMem (&gScreenDimensions, &Context->ScreenDimensions, sizeof (gScreenDimensions));
- CopyMem (&gMenuOption, &Context->MenuOption, sizeof (gMenuOption));
+ gExitRequired = Context->ExitRequired;
+ mCurrentHiiHandle = Context->HiiHandle;
+ mCurrentFormId = Context->FormId;
+ CopyGuid (&mCurrentFormSetGuid, &Context->FormSetGuid);
+
+ //
+ // Restore the menu history data.
+ //
+ while (!IsListEmpty (&Context->FormHistoryList)) {
+ MenuList = FORM_ENTRY_INFO_FROM_LINK (Context->FormHistoryList.ForwardLink);
+ RemoveEntryList (&MenuList->Link);
+
+ InsertTailList(&mPrivateData.FormBrowserEx2.FormViewHistoryHead, &MenuList->Link);
+ }
//
// Remove from FormBrowser context list
@@ -4440,7 +4734,7 @@ IsHiiHandleInBrowserContext (
//
// HiiHandle is Current FormSet.
//
- if ((gOldFormSet != NULL) && (gOldFormSet->HiiHandle == Handle)) {
+ if (mCurrentHiiHandle == Handle) {
return TRUE;
}
@@ -4450,7 +4744,7 @@ IsHiiHandleInBrowserContext (
Link = GetFirstNode (&gBrowserContextList);
while (!IsNull (&gBrowserContextList, Link)) {
Context = BROWSER_CONTEXT_FROM_LINK (Link);
- if (Context->OldFormSet->HiiHandle == Handle) {
+ if (Context->HiiHandle == Handle) {
//
// HiiHandle is in BrowserContext
//
@@ -4463,6 +4757,83 @@ IsHiiHandleInBrowserContext (
}
/**
+ Perform Password check.
+ Passwork may be encrypted by driver that requires the specific check.
+
+ @param Form Form where Password Statement is in.
+ @param Statement Password statement
+ @param PasswordString Password string to be checked. It may be NULL.
+ NULL means to restore password.
+ "" string can be used to checked whether old password does exist.
+
+ @return Status Status of Password check.
+**/
+EFI_STATUS
+EFIAPI
+PasswordCheck (
+ IN FORM_DISPLAY_ENGINE_FORM *Form,
+ IN FORM_DISPLAY_ENGINE_STATEMENT *Statement,
+ IN EFI_STRING PasswordString OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;
+ EFI_BROWSER_ACTION_REQUEST ActionRequest;
+ EFI_IFR_TYPE_VALUE IfrTypeValue;
+ FORM_BROWSER_STATEMENT *Question;
+
+ ConfigAccess = gCurrentSelection->FormSet->ConfigAccess;
+ Question = GetBrowserStatement(Statement);
+ ASSERT (Question != NULL);
+
+ if ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) == EFI_IFR_FLAG_CALLBACK) {
+ if (ConfigAccess == NULL) {
+ return EFI_UNSUPPORTED;
+ }
+ } else {
+ if (PasswordString == NULL) {
+ return EFI_SUCCESS;
+ }
+
+ if (StrnCmp (PasswordString, (CHAR16 *) Question->BufferValue, Question->StorageWidth/sizeof (CHAR16)) == 0) {
+ return EFI_SUCCESS;
+ } else {
+ return EFI_NOT_READY;
+ }
+ }
+
+ //
+ // Prepare password string in HII database
+ //
+ if (PasswordString != NULL) {
+ IfrTypeValue.string = NewString (PasswordString, gCurrentSelection->FormSet->HiiHandle);
+ } else {
+ IfrTypeValue.string = 0;
+ }
+
+ //
+ // Send password to Configuration Driver for validation
+ //
+ Status = ConfigAccess->Callback (
+ ConfigAccess,
+ EFI_BROWSER_ACTION_CHANGING,
+ Question->QuestionId,
+ Question->HiiValue.Type,
+ &IfrTypeValue,
+ &ActionRequest
+ );
+
+ //
+ // Remove password string from HII database
+ //
+ if (PasswordString != NULL) {
+ DeleteString (IfrTypeValue.string, gCurrentSelection->FormSet->HiiHandle);
+ }
+
+ return Status;
+}
+
+/**
Find the registered HotKey based on KeyData.
@param[in] KeyData A pointer to a buffer that describes the keystroke
@@ -4512,7 +4883,7 @@ SetScope (
if (Scope >= MaxLevel) {
return EFI_INVALID_PARAMETER;
}
-
+
//
// When no hot key registered in system or on the first setting,
// Scope can be set.
@@ -4637,6 +5008,128 @@ RegiserExitHandler (
}
/**
+ Check whether the browser data has been modified.
+
+ @retval TRUE Browser data is modified.
+ @retval FALSE No browser data is modified.
+
+**/
+BOOLEAN
+EFIAPI
+IsBrowserDataModified (
+ VOID
+ )
+{
+ LIST_ENTRY *Link;
+ FORM_BROWSER_FORMSET *FormSet;
+
+ if (gCurrentSelection == NULL) {
+ return FALSE;
+ }
+
+ switch (gBrowserSettingScope) {
+ case FormLevel:
+ return IsNvUpdateRequiredForForm (gCurrentSelection->Form);
+
+ case FormSetLevel:
+ return IsNvUpdateRequiredForFormSet (gCurrentSelection->FormSet);
+
+ case SystemLevel:
+ Link = GetFirstNode (&gBrowserFormSetList);
+ while (!IsNull (&gBrowserFormSetList, Link)) {
+ FormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);
+ if (IsNvUpdateRequiredForFormSet (FormSet)) {
+ return TRUE;
+ }
+ Link = GetNextNode (&gBrowserFormSetList, Link);
+ }
+ return FALSE;
+
+ default:
+ return FALSE;
+ }
+}
+
+/**
+ Execute the action requested by the Action parameter.
+
+ @param[in] Action Execute the request action.
+ @param[in] DefaultId The default Id info when need to load default value. Only used when Action is BROWSER_ACTION_DEFAULT.
+
+ @retval EFI_SUCCESS Execute the request action succss.
+ @retval EFI_INVALID_PARAMETER The input action value is invalid.
+
+**/
+EFI_STATUS
+EFIAPI
+ExecuteAction (
+ IN UINT32 Action,
+ IN UINT16 DefaultId
+ )
+{
+ EFI_STATUS Status;
+
+ if (gCurrentSelection == NULL) {
+ return EFI_NOT_READY;
+ }
+
+ Status = EFI_SUCCESS;
+
+ //
+ // Executet the discard action.
+ //
+ if ((Action & BROWSER_ACTION_DISCARD) != 0) {
+ Status = DiscardForm (gCurrentSelection->FormSet, gCurrentSelection->Form, gBrowserSettingScope);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ //
+ // Executet the difault action.
+ //
+ if ((Action & BROWSER_ACTION_DEFAULT) != 0) {
+ Status = ExtractDefault (gCurrentSelection->FormSet, gCurrentSelection->Form, DefaultId, gBrowserSettingScope, GetDefaultForAll, NULL, FALSE);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ //
+ // Executet the submit action.
+ //
+ if ((Action & BROWSER_ACTION_SUBMIT) != 0) {
+ Status = SubmitForm (gCurrentSelection->FormSet, gCurrentSelection->Form, gBrowserSettingScope);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ //
+ // Executet the reset action.
+ //
+ if ((Action & BROWSER_ACTION_RESET) != 0) {
+ gResetRequired = TRUE;
+ }
+
+ //
+ // Executet the exit action.
+ //
+ if ((Action & BROWSER_ACTION_EXIT) != 0) {
+ DiscardForm (gCurrentSelection->FormSet, gCurrentSelection->Form, gBrowserSettingScope);
+ if (gBrowserSettingScope == SystemLevel) {
+ if (ExitHandlerFunction != NULL) {
+ ExitHandlerFunction ();
+ }
+ }
+
+ gExitRequired = TRUE;
+ }
+
+ return Status;
+}
+
+/**
Create reminder to let user to choose save or discard the changed browser data.
Caller can use it to actively check the changed browser data.
@@ -4655,12 +5148,6 @@ SaveReminder (
FORM_BROWSER_FORMSET *FormSet;
BOOLEAN IsDataChanged;
UINT32 DataSavedAction;
- CHAR16 *YesResponse;
- CHAR16 *NoResponse;
- CHAR16 *EmptyString;
- CHAR16 *ChangeReminderString;
- CHAR16 *SaveConfirmString;
- EFI_INPUT_KEY Key;
DataSavedAction = BROWSER_NO_CHANGES;
IsDataChanged = FALSE;
@@ -4671,7 +5158,7 @@ SaveReminder (
if (!ValidateFormSet(FormSet)) {
continue;
}
- if (IsNvUpdateRequired (FormSet)) {
+ if (IsNvUpdateRequiredForFormSet (FormSet)) {
IsDataChanged = TRUE;
break;
}
@@ -4685,42 +5172,19 @@ SaveReminder (
}
//
- // If data is changed, prompt user
+ // If data is changed, prompt user to save or discard it.
//
- gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
-
- YesResponse = GetToken (STRING_TOKEN (ARE_YOU_SURE_YES), gHiiHandle);
- ASSERT (YesResponse != NULL);
- NoResponse = GetToken (STRING_TOKEN (ARE_YOU_SURE_NO), gHiiHandle);
- ASSERT (NoResponse != NULL);
- EmptyString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);
- ChangeReminderString = GetToken (STRING_TOKEN (CHANGE_REMINDER), gHiiHandle);
- SaveConfirmString = GetToken (STRING_TOKEN (SAVE_CONFIRM), gHiiHandle);
-
do {
- CreateDialog (4, TRUE, 0, NULL, &Key, EmptyString, ChangeReminderString, SaveConfirmString, EmptyString);
- } while
- (((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (NoResponse[0] | UPPER_LOWER_CASE_OFFSET)) &&
- ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (YesResponse[0] | UPPER_LOWER_CASE_OFFSET))
- );
+ DataSavedAction = (UINT32) mFormDisplay->ConfirmDataChange();
- //
- // If the user hits the YesResponse key
- //
- if ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) == (YesResponse[0] | UPPER_LOWER_CASE_OFFSET)) {
- SubmitForm (NULL, NULL, SystemLevel);
- DataSavedAction = BROWSER_SAVE_CHANGES;
- } else {
- DiscardForm (NULL, NULL, SystemLevel);
- DataSavedAction = BROWSER_DISCARD_CHANGES;
- gResetRequired = FALSE;
- }
-
- FreePool (YesResponse);
- FreePool (NoResponse);
- FreePool (EmptyString);
- FreePool (SaveConfirmString);
- FreePool (ChangeReminderString);
+ if (DataSavedAction == BROWSER_SAVE_CHANGES) {
+ SubmitForm (NULL, NULL, SystemLevel);
+ break;
+ } else if (DataSavedAction == BROWSER_DISCARD_CHANGES) {
+ DiscardForm (NULL, NULL, SystemLevel);
+ break;
+ }
+ } while (1);
return DataSavedAction;
}
diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/Setup.h b/MdeModulePkg/Universal/SetupBrowserDxe/Setup.h
index 9a0c73909..99418543d 100644
--- a/MdeModulePkg/Universal/SetupBrowserDxe/Setup.h
+++ b/MdeModulePkg/Universal/SetupBrowserDxe/Setup.h
@@ -22,7 +22,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include <Protocol/SimpleTextOut.h>
#include <Protocol/SimpleTextIn.h>
#include <Protocol/FormBrowser2.h>
-#include <Protocol/FormBrowserEx.h>
+#include <Protocol/FormBrowserEx2.h>
+#include <Protocol/DisplayProtocol.h>
#include <Protocol/DevicePath.h>
#include <Protocol/UnicodeCollation.h>
#include <Protocol/HiiConfigAccess.h>
@@ -47,106 +48,29 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include <Library/HiiLib.h>
#include <Library/PcdLib.h>
#include <Library/DevicePathLib.h>
+#include <Library/UefiLib.h>
-#include "Colors.h"
//
// This is the generated header file which includes whatever needs to be exported (strings + IFR)
//
-extern UINT8 SetupBrowserStrings[];
+#define UI_ACTION_NONE 0
+#define UI_ACTION_REFRESH_FORM 1
+#define UI_ACTION_REFRESH_FORMSET 2
+#define UI_ACTION_EXIT 3
//
-// Screen definitions
-//
-#define BANNER_HEIGHT 6
-#define BANNER_COLUMNS 3
-#define BANNER_LEFT_COLUMN_INDENT 1
-
-#define FRONT_PAGE_HEADER_HEIGHT 6
-#define NONE_FRONT_PAGE_HEADER_HEIGHT 3
-#define LEFT_SKIPPED_COLUMNS 3
-#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
-
-//
-// Definition for function key setting
-//
-#define NONE_FUNCTION_KEY_SETTING 0
-#define ENABLE_FUNCTION_KEY_SETTING 1
-
-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'
-
-//
-// 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
-
-//
// Incremental string lenght of ConfigRequest
//
#define CONFIG_REQUEST_STRING_INCREMENTAL 1024
//
-// HII value compare result
-//
-#define HII_VALUE_UNDEFINED 0
-#define HII_VALUE_EQUAL 1
-#define HII_VALUE_LESS_THAN 2
-#define HII_VALUE_GREATER_THAN 3
-
-//
// Incremental size of stack for expression
//
#define EXPRESSION_STACK_SIZE_INCREMENT 0x100
@@ -163,15 +87,12 @@ typedef struct {
//
// Produced protocol
//
- EFI_FORM_BROWSER2_PROTOCOL FormBrowser2;
-
- EFI_FORM_BROWSER_EXTENSION_PROTOCOL FormBrowserEx;
+ EFI_FORM_BROWSER2_PROTOCOL FormBrowser2;
+ EFI_FORM_BROWSER_EXTENSION_PROTOCOL FormBrowserEx;
-} SETUP_DRIVER_PRIVATE_DATA;
+ EDKII_FORM_BROWSER_EXTENSION2_PROTOCOL FormBrowserEx2;
-typedef struct {
- EFI_STRING_ID Banner[BANNER_HEIGHT][BANNER_COLUMNS];
-} BANNER_DATA;
+} SETUP_DRIVER_PRIVATE_DATA;
//
// IFR relative definition
@@ -185,25 +106,16 @@ typedef struct {
#define EFI_HII_EXPRESSION_RULE 6
#define EFI_HII_EXPRESSION_READ 7
#define EFI_HII_EXPRESSION_WRITE 8
+#define EFI_HII_EXPRESSION_WARNING_IF 9
#define EFI_HII_VARSTORE_BUFFER 0
#define EFI_HII_VARSTORE_NAME_VALUE 1
-#define EFI_HII_VARSTORE_EFI_VARIABLE 2
-#define EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER 3
+#define EFI_HII_VARSTORE_EFI_VARIABLE 2 // EFI Varstore type follow UEFI spec before 2.3.1.
+#define EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER 3 // EFI varstore type follow UEFI spec 2.3.1 and later.
#define FORM_INCONSISTENT_VALIDATION 0
#define FORM_NO_SUBMIT_VALIDATION 1
-#define FORMSET_CLASS_PLATFORM_SETUP 0x0001
-#define FORMSET_CLASS_FRONT_PAGE 0x0002
-
-typedef struct {
- UINT8 Type;
- UINT8 *Buffer;
- UINT16 BufferLen;
- EFI_IFR_TYPE_VALUE Value;
-} EFI_HII_VALUE;
-
#define NAME_VALUE_NODE_SIGNATURE SIGNATURE_32 ('N', 'V', 'S', 'T')
typedef struct {
@@ -255,6 +167,7 @@ typedef struct {
BROWSER_STORAGE *BrowserStorage;
CHAR16 *ConfigRequest; // <ConfigRequest> = <ConfigHdr> + <RequestElement>
+ CHAR16 *ConfigElements;// Elements need to load initial data.
UINTN ElementCount; // Number of <RequestElement> in the <ConfigRequest>
UINTN SpareStrLen; // Spare length of ConfigRequest string buffer
} FORMSET_STORAGE;
@@ -312,6 +225,8 @@ typedef struct {
EFI_HII_VALUE Result; // Expression evaluation result
+ UINT8 TimeOut; // For EFI_IFR_WARNING_IF
+
LIST_ENTRY OpCodeListHead; // OpCodes consist of this expression (EXPRESSION_OPCODE)
} FORM_EXPRESSION;
@@ -344,6 +259,8 @@ typedef struct {
typedef struct {
UINTN Signature;
LIST_ENTRY Link;
+
+ EFI_IFR_ONE_OF_OPTION *OpCode; // OneOfOption Data
EFI_STRING_ID Text;
UINT8 Flags;
@@ -376,6 +293,7 @@ typedef struct {
LIST_ENTRY Link;
UINT8 Operand; // The operand (first byte) of this Statement or Question
+ EFI_IFR_OP_HEADER *OpCode;
//
// Statement Header
@@ -385,6 +303,11 @@ typedef struct {
EFI_STRING_ID TextTwo; // For EFI_IFR_TEXT
//
+ // Fake Question Id, used for statement not has true QuestionId.
+ //
+ EFI_QUESTION_ID FakeQuestionId;
+
+ //
// Question Header
//
EFI_QUESTION_ID QuestionId; // The value of zero is reserved
@@ -417,6 +340,7 @@ typedef struct {
EFI_DEFAULT_ID DefaultId; // for EFI_IFR_RESET_BUTTON
EFI_GUID RefreshGuid; // for EFI_IFR_REFRESH_ID
BOOLEAN Locked; // Whether this statement is locked.
+ BOOLEAN ValueChanged; // Whether this statement's value is changed.
//
// Get from IFR parsing
//
@@ -430,6 +354,7 @@ typedef struct {
LIST_ENTRY InconsistentListHead;// nested inconsistent expression list (FORM_EXPRESSION)
LIST_ENTRY NoSubmitListHead; // nested nosubmit expression list (FORM_EXPRESSION)
+ LIST_ENTRY WarningListHead; // nested warning expression list (FORM_EXPRESSION)
FORM_EXPRESSION_LIST *Expression; // nesting inside of GrayOutIf/DisableIf/SuppressIf
FORM_EXPRESSION *ReadExpression; // nested EFI_IFR_READ, provide this question value by read expression.
@@ -467,8 +392,6 @@ typedef struct {
BOOLEAN ModalForm; // Whether this is a modal form.
BOOLEAN Locked; // Whether this form is locked.
- BOOLEAN NvUpdateRequired; // Whether this form has NV update request.
-
LIST_ENTRY ExpressionListHead; // List of Expressions (FORM_EXPRESSION)
LIST_ENTRY StatementListHead; // List of Statements and Questions (FORM_BROWSER_STATEMENT)
LIST_ENTRY ConfigRequestHead; // List of configreques for all storage.
@@ -502,6 +425,7 @@ typedef struct {
UINTN IfrBinaryLength;
UINT8 *IfrBinaryData;
+ BOOLEAN QuestionInited; // Have finished question initilization?
EFI_GUID Guid;
EFI_STRING_ID FormSetTitle;
EFI_STRING_ID Help;
@@ -514,84 +438,82 @@ typedef struct {
FORM_BROWSER_STATEMENT *StatementBuffer; // Buffer for all Statements and Questions
EXPRESSION_OPCODE *ExpressionBuffer; // Buffer for all Expression OpCode
+ LIST_ENTRY StatementListOSF; // Statement list out side of the form.
LIST_ENTRY StorageListHead; // Storage list (FORMSET_STORAGE)
LIST_ENTRY DefaultStoreListHead; // DefaultStore list (FORMSET_DEFAULTSTORE)
LIST_ENTRY FormListHead; // Form list (FORM_BROWSER_FORM)
LIST_ENTRY ExpressionListHead; // List of Expressions (FORM_EXPRESSION)
} FORM_BROWSER_FORMSET;
-
#define FORM_BROWSER_FORMSET_FROM_LINK(a) CR (a, FORM_BROWSER_FORMSET, Link, FORM_BROWSER_FORMSET_SIGNATURE)
-#define BROWSER_CONTEXT_SIGNATURE SIGNATURE_32 ('B', 'C', 'T', 'X')
+typedef struct {
+ LIST_ENTRY Link;
+ EFI_EVENT RefreshEvent;
+} FORM_BROWSER_REFRESH_EVENT_NODE;
+
+#define FORM_BROWSER_REFRESH_EVENT_FROM_LINK(a) BASE_CR (a, FORM_BROWSER_REFRESH_EVENT_NODE, Link)
+
typedef struct {
- UINTN Signature;
- LIST_ENTRY Link;
+ EFI_HII_HANDLE Handle;
//
- // Globals defined in Setup.c
+ // Target formset/form/Question information
//
- BANNER_DATA *BannerData;
- UINTN ClassOfVfr;
- UINTN FunctionKeySetting;
- BOOLEAN ResetRequired;
- UINT16 Direction;
- EFI_SCREEN_DESCRIPTOR ScreenDimensions;
- CHAR16 *EnterString;
- CHAR16 *EnterCommitString;
- CHAR16 *EnterEscapeString;
- CHAR16 *EscapeString;
- CHAR16 *MoveHighlight;
- CHAR16 *MakeSelection;
- CHAR16 *DecNumericInput;
- CHAR16 *HexNumericInput;
- CHAR16 *ToggleCheckBox;
- CHAR16 *PromptForData;
- CHAR16 *PromptForPassword;
- CHAR16 *PromptForNewPassword;
- CHAR16 *ConfirmPassword;
- CHAR16 *ConfirmError;
- CHAR16 *PassowordInvalid;
- CHAR16 *PressEnter;
- CHAR16 *EmptyString;
- CHAR16 *AreYouSure;
- CHAR16 *YesResponse;
- CHAR16 *NoResponse;
- CHAR16 *MiniString;
- CHAR16 *PlusString;
- CHAR16 *MinusString;
- CHAR16 *AdjustNumber;
- CHAR16 *SaveChanges;
- CHAR16 *OptionMismatch;
- CHAR16 *FormSuppress;
- CHAR16 *ProtocolNotFound;
- CHAR16 PromptBlockWidth;
- CHAR16 OptionBlockWidth;
- CHAR16 HelpBlockWidth;
- FORM_BROWSER_FORMSET *OldFormSet;
+ EFI_GUID FormSetGuid;
+ UINT16 FormId;
+ UINT16 QuestionId;
+ UINTN Sequence; // used for time/date only.
+
+ UINTN TopRow;
+ UINTN BottomRow;
+ UINTN PromptCol;
+ UINTN OptionCol;
+ UINTN CurrentRow;
//
- // Globals defined in Ui.c
+ // Ation for Browser to taken:
+ // UI_ACTION_NONE - navigation inside a form
+ // UI_ACTION_REFRESH_FORM - re-evaluate expressions and repaint form
+ // UI_ACTION_REFRESH_FORMSET - re-parse formset IFR binary
//
- LIST_ENTRY MenuOption;
- VOID *MenuRefreshHead;
-} BROWSER_CONTEXT;
+ UINTN Action;
-#define BROWSER_CONTEXT_FROM_LINK(a) CR (a, BROWSER_CONTEXT, Link, BROWSER_CONTEXT_SIGNATURE)
+ //
+ // Current selected fomset/form/Question
+ //
+ FORM_BROWSER_FORMSET *FormSet;
+ FORM_BROWSER_FORM *Form;
+ FORM_BROWSER_STATEMENT *Statement;
-#define BROWSER_HOT_KEY_SIGNATURE SIGNATURE_32 ('B', 'H', 'K', 'S')
+ //
+ // Whether the Form is editable
+ //
+ BOOLEAN FormEditable;
+
+ FORM_ENTRY_INFO *CurrentMenu;
+} UI_MENU_SELECTION;
+
+#define BROWSER_CONTEXT_SIGNATURE SIGNATURE_32 ('B', 'C', 'T', 'X')
typedef struct {
UINTN Signature;
LIST_ENTRY Link;
-
- EFI_INPUT_KEY *KeyData;
- IN UINT32 Action;
- IN UINT16 DefaultId;
- IN EFI_STRING HelpString;
-} BROWSER_HOT_KEY;
-#define BROWSER_HOT_KEY_FROM_LINK(a) CR (a, BROWSER_HOT_KEY, Link, BROWSER_HOT_KEY_SIGNATURE)
+ //
+ // Globals defined in Setup.c
+ //
+ BOOLEAN ResetRequired;
+ BOOLEAN ExitRequired;
+ EFI_HII_HANDLE HiiHandle;
+ EFI_GUID FormSetGuid;
+ EFI_FORM_ID FormId;
+ UI_MENU_SELECTION *Selection;
+
+ LIST_ENTRY FormHistoryList;
+} BROWSER_CONTEXT;
+
+#define BROWSER_CONTEXT_FROM_LINK(a) CR (a, BROWSER_CONTEXT, Link, BROWSER_CONTEXT_SIGNATURE)
//
// Scope for get defaut value. It may be GetDefaultForNoStorage, GetDefaultForStorage or GetDefaultForAll.
@@ -614,72 +536,31 @@ typedef enum {
} GET_SET_QUESTION_VALUE_WITH;
extern EFI_HII_DATABASE_PROTOCOL *mHiiDatabase;
-extern EFI_HII_STRING_PROTOCOL *mHiiString;
extern EFI_HII_CONFIG_ROUTING_PROTOCOL *mHiiConfigRouting;
extern EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL *mPathFromText;
+extern EDKII_FORM_DISPLAY_ENGINE_PROTOCOL *mFormDisplay;
-extern BANNER_DATA *gBannerData;
-extern EFI_HII_HANDLE gFrontPageHandle;
-extern UINTN gClassOfVfr;
-extern UINTN gFunctionKeySetting;
extern BOOLEAN gResetRequired;
-extern EFI_HII_HANDLE gHiiHandle;
-extern UINT16 gDirection;
-extern EFI_SCREEN_DESCRIPTOR gScreenDimensions;
+extern BOOLEAN gExitRequired;
-extern FORM_BROWSER_FORMSET *gOldFormSet;
extern LIST_ENTRY gBrowserFormSetList;
extern LIST_ENTRY gBrowserHotKeyList;
extern BROWSER_SETTING_SCOPE gBrowserSettingScope;
extern EXIT_HANDLER ExitHandlerFunction;
-extern UINTN gFooterHeight;
-
+extern EFI_HII_HANDLE mCurrentHiiHandle;
//
// Browser Global Strings
//
-extern CHAR16 *gDiscardFailed;
-extern CHAR16 *gDefaultFailed;
-extern CHAR16 *gEnterString;
-extern CHAR16 *gEnterCommitString;
-extern CHAR16 *gEnterEscapeString;
-extern CHAR16 *gEscapeString;
-extern CHAR16 *gSaveFailed;
-extern CHAR16 *gMoveHighlight;
-extern CHAR16 *gMakeSelection;
-extern CHAR16 *gDecNumericInput;
-extern CHAR16 *gHexNumericInput;
-extern CHAR16 *gToggleCheckBox;
-extern CHAR16 *gPromptForData;
-extern CHAR16 *gPromptForPassword;
-extern CHAR16 *gPromptForNewPassword;
-extern CHAR16 *gConfirmPassword;
-extern CHAR16 *gConfirmError;
-extern CHAR16 *gPassowordInvalid;
-extern CHAR16 *gPressEnter;
extern CHAR16 *gEmptyString;
-extern CHAR16 *gAreYouSure;
-extern CHAR16 *gYesResponse;
-extern CHAR16 *gNoResponse;
-extern CHAR16 *gMiniString;
-extern CHAR16 *gPlusString;
-extern CHAR16 *gMinusString;
-extern CHAR16 *gAdjustNumber;
-extern CHAR16 *gSaveChanges;
-extern CHAR16 *gOptionMismatch;
-extern CHAR16 *gFormSuppress;
-extern CHAR16 *gProtocolNotFound;
-
-extern CHAR16 gPromptBlockWidth;
-extern CHAR16 gOptionBlockWidth;
-extern CHAR16 gHelpBlockWidth;
extern EFI_GUID gZeroGuid;
-extern EFI_GUID gTianoHiiIfrGuid;
-#include "Ui.h"
+extern UI_MENU_SELECTION *gCurrentSelection;
+
//
// Global Procedure Defines
//
+#include "Expression.h"
/**
Initialize the HII String Token to the correct values.
@@ -691,91 +572,6 @@ InitializeBrowserStrings (
);
/**
- Prints a unicode string to the default console,
- using L"%s" format.
-
- @param String String pointer.
-
- @return Length of string printed to the console
-
-**/
-UINTN
-PrintString (
- IN CHAR16 *String
- );
-
-/**
- Prints a chracter to the default console,
- using L"%c" format.
-
- @param Character Character to print.
-
- @return Length of string printed to the console.
-
-**/
-UINTN
-PrintChar (
- CHAR16 Character
- );
-
-/**
- Prints a formatted unicode string to the default console, at
- the supplied cursor position.
-
- @param Column The cursor position to print the string at.
- @param Row The cursor position to print the string at
- @param Fmt Format string
- @param ... Variable argument list for formating string.
-
- @return Length of string printed to the console
-
-**/
-UINTN
-EFIAPI
-PrintAt (
- IN UINTN Column,
- IN UINTN Row,
- IN CHAR16 *Fmt,
- ...
- );
-
-/**
- Prints a unicode string to the default console, at
- the supplied cursor position, using L"%s" format.
-
- @param Column The cursor position to print the string at.
- @param Row The cursor position to print the string at
- @param String String pointer.
-
- @return Length of string printed to the console
-
-**/
-UINTN
-PrintStringAt (
- IN UINTN Column,
- IN UINTN Row,
- IN CHAR16 *String
- );
-
-/**
- Prints a chracter to the default console, at
- the supplied cursor position, using L"%c" format.
-
- @param Column The cursor position to print the string at.
- @param Row The cursor position to print the string at.
- @param Character Character to print.
-
- @return Length of string printed to the console.
-
-**/
-UINTN
-PrintCharAt (
- IN UINTN Column,
- IN UINTN Row,
- CHAR16 Character
- );
-
-/**
Parse opcodes in the formset IFR binary.
@param FormSet Pointer of the FormSet data structure.
@@ -800,17 +596,6 @@ DestroyFormSet (
IN OUT FORM_BROWSER_FORMSET *FormSet
);
-/**
- This function displays the page frame.
-
- @param Selection Selection contains the information about
- the Selection, form and formset to be displayed.
- Selection action may be updated in retrieve callback.
-**/
-VOID
-DisplayPageFrame (
- IN UI_MENU_SELECTION *Selection
- );
/**
Create a new string in HII Package List.
@@ -860,59 +645,6 @@ GetToken (
);
/**
- Draw a pop up windows based on the dimension, number of lines and
- strings specified.
-
- @param RequestedWidth The width of the pop-up.
- @param NumberOfLines The number of lines.
- @param Marker The variable argument list for the list of string to be printed.
-
-**/
-VOID
-CreateSharedPopUp (
- IN UINTN RequestedWidth,
- IN UINTN NumberOfLines,
- IN VA_LIST Marker
- );
-
-/**
- Routine used to abstract a generic dialog interface and return the selected key or string
-
- @param NumberOfLines The number of lines for the dialog box
- @param 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
- @param MaximumStringSize The maximum size in bytes of a typed in string
- (each character is a CHAR16) and the minimum
- string returned is two bytes
- @param StringBuffer The passed in pointer to the buffer which will
- hold the typed in string if HotKey is FALSE
- @param KeyValue The EFI_KEY value returned if HotKey is TRUE..
- @param ... A series of (quantity == NumberOfLines) text
- strings which will be used to construct the dialog
- box
-
- @retval EFI_SUCCESS Displayed dialog and received user interaction
- @retval EFI_INVALID_PARAMETER One of the parameters was invalid (e.g.
- (StringBuffer == NULL) && (HotKey == FALSE))
- @retval EFI_DEVICE_ERROR User typed in an ESC character to exit the routine
-
-**/
-EFI_STATUS
-EFIAPI
-CreateDialog (
- IN UINTN NumberOfLines,
- IN BOOLEAN HotKey,
- IN UINTN MaximumStringSize,
- OUT CHAR16 *StringBuffer,
- OUT EFI_INPUT_KEY *KeyValue,
- ...
- );
-
-/**
Get Value for given Name from a NameValue Storage.
@param Storage The NameValue Storage.
@@ -939,6 +671,7 @@ GetValueByName (
@param Name The Name.
@param Value The Value to set.
@param SetValueTo Whether update editValue or Value.
+ @param ReturnNode The node use the input name.
@retval EFI_SUCCESS Value found for given Name.
@retval EFI_NOT_FOUND No such Name found in NameValue storage.
@@ -946,10 +679,31 @@ GetValueByName (
**/
EFI_STATUS
SetValueByName (
- IN BROWSER_STORAGE *Storage,
- IN CHAR16 *Name,
- IN CHAR16 *Value,
- IN GET_SET_QUESTION_VALUE_WITH SetValueTo
+ IN BROWSER_STORAGE *Storage,
+ IN CHAR16 *Name,
+ IN CHAR16 *Value,
+ IN GET_SET_QUESTION_VALUE_WITH SetValueTo,
+ OUT NAME_VALUE_NODE **ReturnNode
+ );
+
+/**
+ Validate whether this question's value has changed.
+
+ @param FormSet FormSet data structure.
+ @param Form Form data structure.
+ @param Question Question to be initialized.
+ @param GetValueFrom Where to get value, may from editbuffer, buffer or hii driver.
+
+ @retval TRUE Question's value has changed.
+ @retval FALSE Question's value has not changed
+
+**/
+BOOLEAN
+IsQuestionValueChanged (
+ IN FORM_BROWSER_FORMSET *FormSet,
+ IN FORM_BROWSER_FORM *Form,
+ IN OUT FORM_BROWSER_STATEMENT *Question,
+ IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
);
/**
@@ -1071,10 +825,8 @@ GetQuestionDefault (
@param FormSet FormSet data structure.
- @retval EFI_SUCCESS The function completed successfully.
-
**/
-EFI_STATUS
+VOID
InitializeCurrentSetting (
IN OUT FORM_BROWSER_FORMSET *FormSet
);
@@ -1087,7 +839,6 @@ InitializeCurrentSetting (
GUID), take the first FormSet found in package
list.
@param FormSet FormSet data structure.
- @param UpdateGlobalVar Whether need to update the global variable.
@retval EFI_SUCCESS The function completed successfully.
@retval EFI_NOT_FOUND The specified FormSet could not be found.
@@ -1097,8 +848,7 @@ EFI_STATUS
InitializeFormSet (
IN EFI_HII_HANDLE Handle,
IN OUT EFI_GUID *FormSetGuid,
- OUT FORM_BROWSER_FORMSET *FormSet,
- IN BOOLEAN UpdateGlobalVar
+ OUT FORM_BROWSER_FORMSET *FormSet
);
/**
@@ -1176,6 +926,7 @@ LoadFormSetConfig (
@param Storage The Storage to be conveted.
@param ConfigResp The returned <ConfigResp>.
@param ConfigRequest The ConfigRequest string.
+ @param GetEditBuf Get the data from editbuffer or buffer.
@retval EFI_SUCCESS Convert success.
@retval EFI_INVALID_PARAMETER Incorrect storage type.
@@ -1185,7 +936,8 @@ EFI_STATUS
StorageToConfigResp (
IN BROWSER_STORAGE *Storage,
IN CHAR16 **ConfigResp,
- IN CHAR16 *ConfigRequest
+ IN CHAR16 *ConfigRequest,
+ IN BOOLEAN GetEditBuf
);
/**
@@ -1210,10 +962,8 @@ ConfigRespToStorage (
@param FormSet FormSet data structure.
@param Storage Buffer Storage.
- @retval EFI_SUCCESS The function completed successfully.
-
**/
-EFI_STATUS
+VOID
LoadStorage (
IN FORM_BROWSER_FORMSET *FormSet,
IN FORMSET_STORAGE *Storage
@@ -1349,30 +1099,29 @@ BrowserCallback (
about the Selection, form and formset to be displayed.
On output, Selection return the screen item that is selected
by user.
- @param Repaint Whether need to repaint the menu.
- @param NewLine Whether need to show at new line.
+ @param SettingLevel Input Settting level, if it is FormLevel, just exit current form.
+ else, we need to exit current formset.
- @retval TRUE Need return.
- @retval FALSE No need to return.
+ @retval TRUE Exit current form.
+ @retval FALSE User press ESC and keep in current form.
**/
BOOLEAN
FindNextMenu (
- IN OUT UI_MENU_SELECTION *Selection,
- IN BOOLEAN *Repaint,
- IN BOOLEAN *NewLine
+ IN OUT UI_MENU_SELECTION *Selection,
+ IN BROWSER_SETTING_SCOPE SettingLevel
);
/**
- check whether the formset need to update the NV.
+ check whether the form need to update the NV.
- @param FormSet FormSet data structure.
- @param SetValue Whether set new value or clear old value.
+ @param Form Form data structure.
+ @retval TRUE Need to update the NV.
+ @retval FALSE No need to update the NV.
**/
-VOID
-UpdateNvInfoInForm (
- IN FORM_BROWSER_FORMSET *FormSet,
- IN BOOLEAN SetValue
+BOOLEAN
+IsNvUpdateRequiredForForm (
+ IN FORM_BROWSER_FORM *Form
);
/**
@@ -1383,12 +1132,25 @@ UpdateNvInfoInForm (
@retval TRUE Need to update the NV.
@retval FALSE No need to update the NV.
**/
-BOOLEAN
-IsNvUpdateRequired (
+BOOLEAN
+IsNvUpdateRequiredForFormSet (
IN FORM_BROWSER_FORMSET *FormSet
);
/**
+ Check whether the storage data for current form set is changed.
+
+ @param FormSet FormSet data structure.
+
+ @retval TRUE Data is changed.
+ @retval FALSE Data is not changed.
+**/
+BOOLEAN
+IsStorageDataChangedForFormSet (
+ IN FORM_BROWSER_FORMSET *FormSet
+ );
+
+/**
Call the call back function for the question and process the return action.
@param Selection On input, Selection tell setup browser the information
@@ -1517,6 +1279,38 @@ RegiserExitHandler (
);
/**
+
+ Check whether the browser data has been modified.
+
+ @retval TRUE Browser data is changed.
+ @retval FALSE No browser data is changed.
+
+**/
+BOOLEAN
+EFIAPI
+IsBrowserDataModified (
+ VOID
+ );
+
+/**
+
+ Execute the action requested by the Action parameter.
+
+ @param[in] Action Execute the request action.
+ @param[in] DefaultId The default Id info when need to load default value.
+
+ @retval EFI_SUCCESS Execute the request action succss.
+ @retval EFI_INVALID_PARAMETER The input action value is invalid.
+
+**/
+EFI_STATUS
+EFIAPI
+ExecuteAction (
+ IN UINT32 Action,
+ IN UINT16 DefaultId
+ );
+
+/**
Create reminder to let user to choose save or discard the changed browser data.
Caller can use it to actively check the changed browser data.
@@ -1545,6 +1339,267 @@ GetHotKeyFromRegisterList (
);
/**
+
+ Get FORM_BROWSER_STATEMENT from FORM_DISPLAY_ENGINE_STATEMENT based on the OpCode info.
+
+ @param DisplayStatement The input FORM_DISPLAY_ENGINE_STATEMENT.
+
+ @retval FORM_BROWSER_STATEMENT The return FORM_BROWSER_STATEMENT info.
+
+**/
+FORM_BROWSER_STATEMENT *
+GetBrowserStatement (
+ IN FORM_DISPLAY_ENGINE_STATEMENT *DisplayStatement
+ );
+
+/**
+ Password may be stored as encrypted by Configuration Driver. When change a
+ password, user will be challenged with old password. To validate user input old
+ password, we will send the clear text to Configuration Driver via Callback().
+ Configuration driver is responsible to check the passed in password and return
+ the validation result. If validation pass, state machine in password Callback()
+ will transit from BROWSER_STATE_VALIDATE_PASSWORD to BROWSER_STATE_SET_PASSWORD.
+ After user type in new password twice, Callback() will be invoked to send the
+ new password to Configuration Driver.
+
+ @param Selection Pointer to UI_MENU_SELECTION.
+ @param MenuOption The MenuOption for this password Question.
+ @param String The clear text of password.
+
+ @retval EFI_NOT_AVAILABLE_YET Callback() request to terminate password input.
+ @return In state of BROWSER_STATE_VALIDATE_PASSWORD:
+ @retval EFI_SUCCESS Password correct, Browser will prompt for new
+ password.
+ @retval EFI_NOT_READY Password incorrect, Browser will show error
+ message.
+ @retval Other Browser will do nothing.
+ @return In state of BROWSER_STATE_SET_PASSWORD:
+ @retval EFI_SUCCESS Set password success.
+ @retval Other Set password failed.
+
+**/
+EFI_STATUS
+PasswordCallback (
+ IN UI_MENU_SELECTION *Selection,
+ IN FORM_BROWSER_STATEMENT *Question,
+ IN CHAR16 *String
+ );
+
+/**
+ Display error message for invalid password.
+
+**/
+VOID
+PasswordInvalid (
+ VOID
+ );
+
+/**
+ The worker function that send the displays to the screen. On output,
+ the selection made by user is returned.
+
+ @param Selection On input, Selection tell setup browser the information
+ about the Selection, form and formset to be displayed.
+ On output, Selection return the screen item that is selected
+ by user.
+
+ @retval EFI_SUCCESS The page is displayed successfully.
+ @return Other value if the page failed to be diplayed.
+
+**/
+EFI_STATUS
+SetupBrowser (
+ IN OUT UI_MENU_SELECTION *Selection
+ );
+
+/**
+ Free up the resource allocated for all strings required
+ by Setup Browser.
+
+**/
+VOID
+FreeBrowserStrings (
+ VOID
+ );
+
+/**
+ Create a menu with specified formset GUID and form ID, and add it as a child
+ of the given parent menu.
+
+ @param HiiHandle Hii handle related to this formset.
+ @param FormSetGuid The Formset Guid of menu to be added.
+ @param FormId The Form ID of menu to be added.
+ @param QuestionId The question id of this menu to be added.
+
+ @return A pointer to the newly added menu or NULL if memory is insufficient.
+
+**/
+FORM_ENTRY_INFO *
+UiAddMenuList (
+ IN EFI_HII_HANDLE HiiHandle,
+ IN EFI_GUID *FormSetGuid,
+ IN UINT16 FormId,
+ IN UINT16 QuestionId
+ );
+
+/**
+ Search Menu with given FormSetGuid and FormId in all cached menu list.
+
+ @param HiiHandle HiiHandle for FormSet.
+ @param FormSetGuid The Formset GUID of the menu to search.
+ @param FormId The Form ID of menu to search.
+
+ @return A pointer to menu found or NULL if not found.
+
+**/
+FORM_ENTRY_INFO *
+UiFindMenuList (
+ IN EFI_HII_HANDLE HiiHandle,
+ IN EFI_GUID *FormSetGuid,
+ IN UINT16 FormId
+ );
+
+/**
+ Free Menu list linked list.
+
+ @param MenuListHead One Menu list point in the menu list.
+
+**/
+VOID
+UiFreeMenuList (
+ LIST_ENTRY *MenuListHead
+ );
+
+/**
+ Find parent menu for current menu.
+
+ @param CurrentMenu Current Menu
+
+ @retval The parent menu for current menu.
+**/
+FORM_ENTRY_INFO *
+UiFindParentMenu (
+ IN FORM_ENTRY_INFO *CurrentMenu
+ );
+
+/**
+ Search an Option of a Question by its value.
+
+ @param Question The Question
+ @param OptionValue Value for Option to be searched.
+
+ @retval Pointer Pointer to the found Option.
+ @retval NULL Option not found.
+
+**/
+QUESTION_OPTION *
+ValueToOption (
+ IN FORM_BROWSER_STATEMENT *Question,
+ IN EFI_HII_VALUE *OptionValue
+ );
+/**
+ Return data element in an Array by its Index.
+
+ @param Array The data array.
+ @param Type Type of the data in this array.
+ @param Index Zero based index for data in this array.
+
+ @retval Value The data to be returned
+
+**/
+UINT64
+GetArrayData (
+ IN VOID *Array,
+ IN UINT8 Type,
+ IN UINTN Index
+ );
+
+/**
+ Set value of a data element in an Array by its Index.
+
+ @param Array The data array.
+ @param Type Type of the data in this array.
+ @param Index Zero based index for data in this array.
+ @param Value The value to be set.
+
+**/
+VOID
+SetArrayData (
+ IN VOID *Array,
+ IN UINT8 Type,
+ IN UINTN Index,
+ IN UINT64 Value
+ );
+
+/**
+ Compare two Hii value.
+
+ @param Value1 Expression value to compare on left-hand.
+ @param Value2 Expression value to compare on right-hand.
+ @param Result Return value after compare.
+ retval 0 Two operators equal.
+ return Positive value if Value1 is greater than Value2.
+ retval Negative value if Value1 is less than Value2.
+ @param HiiHandle Only required for string compare.
+
+ @retval other Could not perform compare on two values.
+ @retval EFI_SUCCESS Compare the value success.
+
+**/
+EFI_STATUS
+CompareHiiValue (
+ IN EFI_HII_VALUE *Value1,
+ IN EFI_HII_VALUE *Value2,
+ OUT INTN *Result,
+ IN EFI_HII_HANDLE HiiHandle OPTIONAL
+ );
+
+/**
+ Perform Password check.
+ Passwork may be encrypted by driver that requires the specific check.
+
+ @param Form Form where Password Statement is in.
+ @param Statement Password statement
+ @param PasswordString Password string to be checked. It may be NULL.
+ NULL means to restore password.
+ "" string can be used to checked whether old password does exist.
+
+ @return Status Status of Password check.
+**/
+EFI_STATUS
+EFIAPI
+PasswordCheck (
+ IN FORM_DISPLAY_ENGINE_FORM *Form,
+ IN FORM_DISPLAY_ENGINE_STATEMENT *Statement,
+ IN EFI_STRING PasswordString OPTIONAL
+ );
+
+/**
+
+ Get FORM_BROWSER_STATEMENT from FORM_DISPLAY_ENGINE_STATEMENT based on the OpCode info.
+
+ @param DisplayStatement The input FORM_DISPLAY_ENGINE_STATEMENT.
+
+ @retval FORM_BROWSER_STATEMENT The return FORM_BROWSER_STATEMENT info.
+
+**/
+FORM_BROWSER_STATEMENT *
+GetBrowserStatement (
+ IN FORM_DISPLAY_ENGINE_STATEMENT *DisplayStatement
+ );
+
+/**
+
+ Initialize the Display form structure data.
+
+**/
+VOID
+InitializeDisplayFormData (
+ VOID
+ );
+
+
+/**
Base on the current formset info, clean the ConfigRequest string in browser storage.
@param FormSet Pointer of the FormSet
@@ -1554,5 +1609,5 @@ VOID
CleanBrowserStorage (
IN OUT FORM_BROWSER_FORMSET *FormSet
);
-
+
#endif
diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf b/MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf
index 7e740bc09..a3f3a6fc2 100644
--- a/MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf
+++ b/MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf
@@ -19,7 +19,7 @@
BASE_NAME = SetupBrowser
FILE_GUID = EBf342FE-B1D3-4EF8-957C-8048606FF671
MODULE_TYPE = DXE_DRIVER
- VERSION_STRING = 1.0
+ VERSION_STRING = 2.0
ENTRY_POINT = InitializeSetup
#
@@ -29,19 +29,12 @@
#
[Sources]
- SetupBrowserStr.uni
Setup.c
Setup.h
IfrParse.c
Expression.c
- InputHandler.c
- Print.c
Presentation.c
- ProcessOptions.c
- Ui.c
- Ui.h
- Colors.h
-
+ Expression.h
[Packages]
MdePkg/MdePkg.dec
@@ -59,34 +52,27 @@
HiiLib
DevicePathLib
PcdLib
+ UefiLib
[Guids]
- gEfiIfrTianoGuid ## CONSUMES ## GUID
gEfiIfrFrameworkGuid ## CONSUMES ## GUID
gEfiHiiPlatformSetupFormsetGuid
gEfiHiiStandardFormGuid ## SOMETIMES_CONSUMES ## GUID
[Protocols]
gEfiHiiConfigAccessProtocolGuid ## CONSUMES
- gEfiHiiStringProtocolGuid ## CONSUMES
gEfiFormBrowser2ProtocolGuid ## PRODUCES
- gEfiFormBrowserExProtocolGuid ## PRODUCES
+ gEdkiiFormBrowserEx2ProtocolGuid ## PRODUCES
gEfiHiiConfigRoutingProtocolGuid ## CONSUMES
gEfiHiiDatabaseProtocolGuid ## CONSUMES
gEfiUnicodeCollation2ProtocolGuid ## CONSUMES
gEfiUserManagerProtocolGuid ## SOMETIMES_CONSUMES
gEfiDevicePathFromTextProtocolGuid ## SOMETIMES_CONSUMES
+ gEdkiiFormDisplayEngineProtocolGuid ## PRODUCE
+ gEfiFormBrowserExProtocolGuid ## PRODUCE
[FeaturePcd]
gEfiMdeModulePkgTokenSpaceGuid.PcdFrameworkCompatibilitySupport ## CONSUMES
- gEfiMdeModulePkgTokenSpaceGuid.PcdBrowserGrayOutTextStatement ## CONSUMES
- gEfiMdeModulePkgTokenSpaceGuid.PcdBrowerGrayOutReadOnlyMenu ## CONSUMES
-
-[Pcd]
- gEfiMdeModulePkgTokenSpaceGuid.PcdBrowserSubtitleTextColor ## CONSUMES
- gEfiMdeModulePkgTokenSpaceGuid.PcdBrowserFieldTextColor ## CONSUMES
- gEfiMdeModulePkgTokenSpaceGuid.PcdBrowserFieldTextHighlightColor ## CONSUMES
- gEfiMdeModulePkgTokenSpaceGuid.PcdBrowserFieldBackgroundHighlightColor ## CONSUMES
[Depex]
gEfiHiiDatabaseProtocolGuid AND gEfiHiiConfigRoutingProtocolGuid
diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/Ui.c b/MdeModulePkg/Universal/SetupBrowserDxe/Ui.c
deleted file mode 100644
index 7c246b60e..000000000
--- a/MdeModulePkg/Universal/SetupBrowserDxe/Ui.c
+++ /dev/null
@@ -1,4027 +0,0 @@
-/** @file
-Utility functions for User Interface functions.
-
-Copyright (c) 2004 - 2013, Intel Corporation. All rights reserved.<BR>
-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 "Setup.h"
-
-LIST_ENTRY gMenuOption;
-LIST_ENTRY gMenuList;
-MENU_REFRESH_ENTRY *gMenuRefreshHead; // Menu list used for refresh timer opcode.
-MENU_REFRESH_ENTRY *gMenuEventGuidRefreshHead; // Menu list used for refresh event guid opcode.
-
-//
-// 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_LEFT,
- UiLeft,
- },
- {
- SCAN_RIGHT,
- UiRight,
- }
-};
-
-UINTN mScanCodeNumber = sizeof (gScanCodeToOperation) / sizeof (gScanCodeToOperation[0]);
-
-SCREEN_OPERATION_T0_CONTROL_FLAG gScreenOperationToControlFlag[] = {
- {
- UiNoOperation,
- CfUiNoOperation,
- },
- {
- UiSelect,
- CfUiSelect,
- },
- {
- UiUp,
- CfUiUp,
- },
- {
- UiDown,
- CfUiDown,
- },
- {
- UiLeft,
- CfUiLeft,
- },
- {
- UiRight,
- CfUiRight,
- },
- {
- UiReset,
- CfUiReset,
- },
- {
- UiPageUp,
- CfUiPageUp,
- },
- {
- UiPageDown,
- CfUiPageDown
- },
- {
- UiHotKey,
- CfUiHotKey
- }
-};
-
-BOOLEAN mInputError;
-BOOLEAN GetLineByWidthFinished = FALSE;
-
-
-/**
- Set Buffer to Value for Size bytes.
-
- @param Buffer Memory to set.
- @param Size Number of bytes to set
- @param Value Value of the set operation.
-
-**/
-VOID
-SetUnicodeMem (
- IN VOID *Buffer,
- IN UINTN Size,
- IN CHAR16 Value
- )
-{
- CHAR16 *Ptr;
-
- Ptr = Buffer;
- while ((Size--) != 0) {
- *(Ptr++) = Value;
- }
-}
-
-
-/**
- Initialize Menu option list.
-
-**/
-VOID
-UiInitMenu (
- VOID
- )
-{
- InitializeListHead (&gMenuOption);
-}
-
-
-/**
- Free Menu option linked list.
-
-**/
-VOID
-UiFreeMenu (
- VOID
- )
-{
- UI_MENU_OPTION *MenuOption;
-
- while (!IsListEmpty (&gMenuOption)) {
- MenuOption = MENU_OPTION_FROM_LINK (gMenuOption.ForwardLink);
- RemoveEntryList (&MenuOption->Link);
-
- //
- // We allocated space for this description when we did a GetToken, free it here
- //
- if (MenuOption->Skip != 0) {
- //
- // For date/time, MenuOption->Description is shared by three Menu Options
- // Data format : [01/02/2004] [11:22:33]
- // Line number : 0 0 1 0 0 1
- //
- FreePool (MenuOption->Description);
- }
- FreePool (MenuOption);
- }
-}
-
-
-/**
- Create a menu with specified formset GUID and form ID, and add it as a child
- of the given parent menu.
-
- @param Parent The parent of menu to be added.
- @param HiiHandle Hii handle related to this formset.
- @param FormSetGuid The Formset Guid of menu to be added.
- @param FormId The Form ID of menu to be added.
-
- @return A pointer to the newly added menu or NULL if memory is insufficient.
-
-**/
-UI_MENU_LIST *
-UiAddMenuList (
- IN OUT UI_MENU_LIST *Parent,
- IN EFI_HII_HANDLE HiiHandle,
- IN EFI_GUID *FormSetGuid,
- IN UINT16 FormId
- )
-{
- UI_MENU_LIST *MenuList;
-
- MenuList = AllocateZeroPool (sizeof (UI_MENU_LIST));
- if (MenuList == NULL) {
- return NULL;
- }
-
- MenuList->Signature = UI_MENU_LIST_SIGNATURE;
- InitializeListHead (&MenuList->ChildListHead);
-
- MenuList->HiiHandle = HiiHandle;
- CopyMem (&MenuList->FormSetGuid, FormSetGuid, sizeof (EFI_GUID));
- MenuList->FormId = FormId;
- MenuList->Parent = Parent;
-
- if (Parent == NULL) {
- //
- // If parent is not specified, it is the root Form of a Formset
- //
- InsertTailList (&gMenuList, &MenuList->Link);
- } else {
- InsertTailList (&Parent->ChildListHead, &MenuList->Link);
- }
-
- return MenuList;
-}
-
-
-/**
- Search Menu with given FormId, FormSetGuid and Handle in all cached menu list.
-
- @param Parent The parent of menu to search.
- @param Handle Hii handle related to this formset.
- @param FormSetGuid The Formset GUID of the menu to search.
- @param FormId The Form ID of menu to search.
-
- @return A pointer to menu found or NULL if not found.
-
-**/
-UI_MENU_LIST *
-UiFindChildMenuList (
- IN UI_MENU_LIST *Parent,
- IN EFI_HII_HANDLE Handle,
- IN EFI_GUID *FormSetGuid,
- IN UINT16 FormId
- )
-{
- LIST_ENTRY *Link;
- UI_MENU_LIST *Child;
- UI_MENU_LIST *MenuList;
-
- ASSERT (Parent != NULL);
-
- if (Parent->FormId == FormId && CompareGuid (FormSetGuid, &Parent->FormSetGuid) && Parent->HiiHandle == Handle) {
- return Parent;
- }
-
- Link = GetFirstNode (&Parent->ChildListHead);
- while (!IsNull (&Parent->ChildListHead, Link)) {
- Child = UI_MENU_LIST_FROM_LINK (Link);
-
- MenuList = UiFindChildMenuList (Child, Handle, FormSetGuid, FormId);
- if (MenuList != NULL) {
- return MenuList;
- }
-
- Link = GetNextNode (&Parent->ChildListHead, Link);
- }
-
- return NULL;
-}
-
-
-/**
- Search Menu with given Handle, FormSetGuid and FormId in all cached menu list.
-
- @param Handle Hii handle related to this formset.
- @param FormSetGuid The Formset GUID of the menu to search.
- @param FormId The Form ID of menu to search.
-
- @return A pointer to menu found or NULL if not found.
-
-**/
-UI_MENU_LIST *
-UiFindMenuList (
- IN EFI_HII_HANDLE Handle,
- IN EFI_GUID *FormSetGuid,
- IN UINT16 FormId
- )
-{
- LIST_ENTRY *Link;
- UI_MENU_LIST *MenuList;
- UI_MENU_LIST *Child;
-
- Link = GetFirstNode (&gMenuList);
- while (!IsNull (&gMenuList, Link)) {
- MenuList = UI_MENU_LIST_FROM_LINK (Link);
-
- Child = UiFindChildMenuList(MenuList, Handle, FormSetGuid, FormId);
- if (Child != NULL) {
-
- //
- // If this form already in the menu history list,
- // just free the list between old this form.
- //
- UiFreeMenuList(&Child->ChildListHead);
- return Child;
- }
-
- Link = GetNextNode (&gMenuList, Link);
- }
-
- return NULL;
-}
-
-/**
- Free Menu list linked list.
-
- @param MenuListHead One Menu list point in the menu list.
-
-**/
-VOID
-UiFreeMenuList (
- LIST_ENTRY *MenuListHead
- )
-{
- UI_MENU_LIST *MenuList;
-
- while (!IsListEmpty (MenuListHead)) {
- MenuList = UI_MENU_LIST_FROM_LINK (MenuListHead->ForwardLink);
- RemoveEntryList (&MenuList->Link);
-
- UiFreeMenuList(&MenuList->ChildListHead);
- FreePool (MenuList);
- }
-
-}
-
-/**
- Free Menu option linked list.
-
-**/
-VOID
-UiFreeRefreshList (
- VOID
- )
-{
- MENU_REFRESH_ENTRY *OldMenuRefreshEntry;
-
- while (gMenuRefreshHead != NULL) {
- OldMenuRefreshEntry = gMenuRefreshHead->Next;
- FreePool (gMenuRefreshHead);
- gMenuRefreshHead = OldMenuRefreshEntry;
- }
-
- while (gMenuEventGuidRefreshHead != NULL) {
- OldMenuRefreshEntry = gMenuEventGuidRefreshHead->Next;
- if (gMenuEventGuidRefreshHead != NULL) {
- gBS->CloseEvent(gMenuEventGuidRefreshHead->Event);
- }
- FreePool (gMenuEventGuidRefreshHead);
- gMenuEventGuidRefreshHead = OldMenuRefreshEntry;
- }
-}
-
-
-/**
- Process option string for date/time opcode.
-
- @param MenuOption Menu option point to date/time.
- @param OptionString Option string input for process.
- @param AddOptCol Whether need to update MenuOption->OptCol.
-
-**/
-VOID
-ProcessStringForDateTime (
- UI_MENU_OPTION *MenuOption,
- CHAR16 *OptionString,
- BOOLEAN AddOptCol
- )
-{
- UINTN Index;
- UINTN Count;
- FORM_BROWSER_STATEMENT *Statement;
-
- ASSERT (MenuOption != NULL && OptionString != NULL);
-
- Statement = MenuOption->ThisTag;
-
- //
- // If leading spaces on OptionString - remove the spaces
- //
- for (Index = 0; OptionString[Index] == L' '; Index++) {
- //
- // Base on the blockspace to get the option column info.
- //
- if (AddOptCol) {
- MenuOption->OptCol++;
- }
- }
-
- for (Count = 0; OptionString[Index] != CHAR_NULL; Index++) {
- OptionString[Count] = OptionString[Index];
- Count++;
- }
- OptionString[Count] = CHAR_NULL;
-
- //
- // Enable to suppress field in the opcode base on the flag.
- //
- if (Statement->Operand == EFI_IFR_DATE_OP) {
- //
- // OptionString format is: <**: **: ****>
- // |month|day|year|
- // 4 3 5
- //
- if ((Statement->Flags & EFI_QF_DATE_MONTH_SUPPRESS) && (MenuOption->Sequence == 0)) {
- //
- // At this point, only "<**:" in the optionstring.
- // Clean the day's ** field, after clean, the format is "< :"
- //
- SetUnicodeMem (&OptionString[1], 2, L' ');
- } else if ((Statement->Flags & EFI_QF_DATE_DAY_SUPPRESS) && (MenuOption->Sequence == 1)) {
- //
- // At this point, only "**:" in the optionstring.
- // Clean the month's "**" field, after clean, the format is " :"
- //
- SetUnicodeMem (&OptionString[0], 2, L' ');
- } else if ((Statement->Flags & EFI_QF_DATE_YEAR_SUPPRESS) && (MenuOption->Sequence == 2)) {
- //
- // At this point, only "****>" in the optionstring.
- // Clean the year's "****" field, after clean, the format is " >"
- //
- SetUnicodeMem (&OptionString[0], 4, L' ');
- }
- } else if (Statement->Operand == EFI_IFR_TIME_OP) {
- //
- // OptionString format is: <**: **: **>
- // |hour|minute|second|
- // 4 3 3
- //
- if ((Statement->Flags & QF_TIME_HOUR_SUPPRESS) && (MenuOption->Sequence == 0)) {
- //
- // At this point, only "<**:" in the optionstring.
- // Clean the hour's ** field, after clean, the format is "< :"
- //
- SetUnicodeMem (&OptionString[1], 2, L' ');
- } else if ((Statement->Flags & QF_TIME_MINUTE_SUPPRESS) && (MenuOption->Sequence == 1)) {
- //
- // At this point, only "**:" in the optionstring.
- // Clean the minute's "**" field, after clean, the format is " :"
- //
- SetUnicodeMem (&OptionString[0], 2, L' ');
- } else if ((Statement->Flags & QF_TIME_SECOND_SUPPRESS) && (MenuOption->Sequence == 2)) {
- //
- // At this point, only "**>" in the optionstring.
- // Clean the second's "**" field, after clean, the format is " >"
- //
- SetUnicodeMem (&OptionString[0], 2, L' ');
- }
- }
-}
-
-/**
- Refresh question.
-
- @param MenuRefreshEntry Menu refresh structure which has info about the refresh question.
-**/
-EFI_STATUS
-RefreshQuestion (
- IN MENU_REFRESH_ENTRY *MenuRefreshEntry
- )
-{
- CHAR16 *OptionString;
- EFI_STATUS Status;
- UI_MENU_SELECTION *Selection;
- FORM_BROWSER_STATEMENT *Question;
-
- Selection = MenuRefreshEntry->Selection;
- Question = MenuRefreshEntry->MenuOption->ThisTag;
-
- Status = GetQuestionValue (Selection->FormSet, Selection->Form, Question, GetSetValueWithHiiDriver);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- OptionString = NULL;
- ProcessOptions (Selection, MenuRefreshEntry->MenuOption, FALSE, &OptionString);
-
- if (OptionString != NULL) {
- //
- // If old Text is longer than new string, need to clean the old string before paint the newer.
- // This option is no need for time/date opcode, because time/data opcode has fixed string length.
- //
- if ((MenuRefreshEntry->MenuOption->ThisTag->Operand != EFI_IFR_DATE_OP) &&
- (MenuRefreshEntry->MenuOption->ThisTag->Operand != EFI_IFR_TIME_OP)) {
- ClearLines (
- MenuRefreshEntry->CurrentColumn,
- MenuRefreshEntry->CurrentColumn + gOptionBlockWidth - 1,
- MenuRefreshEntry->CurrentRow,
- MenuRefreshEntry->CurrentRow,
- PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND
- );
- }
-
- gST->ConOut->SetAttribute (gST->ConOut, MenuRefreshEntry->CurrentAttribute);
- ProcessStringForDateTime(MenuRefreshEntry->MenuOption, OptionString, FALSE);
- PrintStringAt (MenuRefreshEntry->CurrentColumn, MenuRefreshEntry->CurrentRow, OptionString);
- FreePool (OptionString);
- }
-
- //
- // Question value may be changed, need invoke its Callback()
- //
- Status = ProcessCallBackFunction (Selection, Question, EFI_BROWSER_ACTION_CHANGING, FALSE);
-
- return Status;
-}
-
-/**
- Refresh the question which has refresh guid event attribute.
-
- @param Event The event which has this function related.
- @param Context The input context info related to this event or the status code return to the caller.
-**/
-VOID
-EFIAPI
-RefreshQuestionNotify(
- IN EFI_EVENT Event,
- IN VOID *Context
- )
-{
- MENU_REFRESH_ENTRY *MenuRefreshEntry;
- UI_MENU_SELECTION *Selection;
-
- //
- // Reset FormPackage update flag
- //
- mHiiPackageListUpdated = FALSE;
-
- MenuRefreshEntry = (MENU_REFRESH_ENTRY *)Context;
- ASSERT (MenuRefreshEntry != NULL);
- Selection = MenuRefreshEntry->Selection;
-
- RefreshQuestion (MenuRefreshEntry);
-
- if (mHiiPackageListUpdated) {
- //
- // Package list is updated, force to reparse IFR binary of target Formset
- //
- mHiiPackageListUpdated = FALSE;
- Selection->Action = UI_ACTION_REFRESH_FORMSET;
- }
-}
-
-
-/**
- Refresh screen.
-
-**/
-EFI_STATUS
-RefreshForm (
- VOID
- )
-{
- MENU_REFRESH_ENTRY *MenuRefreshEntry;
- EFI_STATUS Status;
- UI_MENU_SELECTION *Selection;
-
- if (gMenuRefreshHead != NULL) {
- //
- // call from refresh interval process.
- //
- MenuRefreshEntry = gMenuRefreshHead;
- Selection = MenuRefreshEntry->Selection;
- //
- // Reset FormPackage update flag
- //
- mHiiPackageListUpdated = FALSE;
-
- do {
- Status = RefreshQuestion (MenuRefreshEntry);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- MenuRefreshEntry = MenuRefreshEntry->Next;
-
- } while (MenuRefreshEntry != NULL);
-
- if (mHiiPackageListUpdated) {
- //
- // Package list is updated, force to reparse IFR binary of target Formset
- //
- mHiiPackageListUpdated = FALSE;
- Selection->Action = UI_ACTION_REFRESH_FORMSET;
- return EFI_SUCCESS;
- }
- }
-
- return EFI_TIMEOUT;
-}
-
-
-/**
- Wait for a given event to fire, or for an optional timeout to expire.
-
- @param Event The event to wait for
- @param Timeout An optional timeout value in 100 ns units.
- @param RefreshInterval Menu refresh interval (in seconds).
-
- @retval EFI_SUCCESS Event fired before Timeout expired.
- @retval EFI_TIME_OUT Timout expired before Event fired.
-
-**/
-EFI_STATUS
-UiWaitForSingleEvent (
- IN EFI_EVENT Event,
- IN UINT64 Timeout, OPTIONAL
- IN UINT8 RefreshInterval OPTIONAL
- )
-{
- EFI_STATUS Status;
- UINTN Index;
- EFI_EVENT TimerEvent;
- EFI_EVENT WaitList[2];
-
- if (Timeout != 0) {
- //
- // 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
- //
- if (RefreshInterval == 0) {
- Timeout = ONE_SECOND;
- } else {
- Timeout = RefreshInterval * 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;
- if (RefreshInterval != 0) {
- Status = RefreshForm ();
- }
- }
-
- gBS->CloseEvent (TimerEvent);
- } while (Status == EFI_TIMEOUT);
- }
-
- return Status;
-}
-
-
-/**
- Add one menu option by specified description and context.
-
- @param String String description for this option.
- @param Handle Hii handle for the package list.
- @param Form The form this statement belong to.
- @param Statement Statement of this Menu Option.
- @param NumberOfLines Display lines for this Menu Option.
- @param MenuItemCount The index for this Option in the Menu.
-
- @retval Pointer Pointer to the added Menu Option.
-
-**/
-UI_MENU_OPTION *
-UiAddMenuOption (
- IN CHAR16 *String,
- IN EFI_HII_HANDLE Handle,
- IN FORM_BROWSER_FORM *Form,
- IN FORM_BROWSER_STATEMENT *Statement,
- IN UINT16 NumberOfLines,
- IN UINT16 MenuItemCount
- )
-{
- UI_MENU_OPTION *MenuOption;
- UINTN Index;
- UINTN Count;
-
- Count = 1;
- MenuOption = NULL;
-
- if (Statement->Operand == EFI_IFR_DATE_OP || Statement->Operand == EFI_IFR_TIME_OP) {
- //
- // Add three MenuOptions for Date/Time
- // Data format : [01/02/2004] [11:22:33]
- // Line number : 0 0 1 0 0 1
- //
- NumberOfLines = 0;
- Count = 3;
-
- if (Statement->Storage == NULL) {
- //
- // For RTC type of date/time, set default refresh interval to be 1 second
- //
- if (Statement->RefreshInterval == 0) {
- Statement->RefreshInterval = 1;
- }
- }
- }
-
- for (Index = 0; Index < Count; Index++) {
- MenuOption = AllocateZeroPool (sizeof (UI_MENU_OPTION));
- ASSERT (MenuOption);
-
- MenuOption->Signature = UI_MENU_OPTION_SIGNATURE;
- MenuOption->Description = String;
- MenuOption->Handle = Handle;
- MenuOption->ThisTag = Statement;
- MenuOption->EntryNumber = MenuItemCount;
-
- if (Index == 2) {
- //
- // Override LineNumber for the MenuOption in Date/Time sequence
- //
- MenuOption->Skip = 1;
- } else {
- MenuOption->Skip = NumberOfLines;
- }
- MenuOption->Sequence = Index;
-
- if (EvaluateExpressionList(Statement->Expression, FALSE, NULL, NULL) == ExpressGrayOut ) {
- MenuOption->GrayOut = TRUE;
- } else {
- MenuOption->GrayOut = FALSE;
- }
-
- //
- // If the form or the question has the lock attribute, deal same as grayout.
- //
- if (Form->Locked || Statement->Locked) {
- MenuOption->GrayOut = TRUE;
- }
-
- switch (Statement->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:
- case EFI_IFR_CHECKBOX_OP:
- case EFI_IFR_PASSWORD_OP:
- case EFI_IFR_STRING_OP:
- //
- // User could change the value of these items
- //
- MenuOption->IsQuestion = TRUE;
- break;
-
- case EFI_IFR_TEXT_OP:
- if (FeaturePcdGet (PcdBrowserGrayOutTextStatement)) {
- //
- // Initializing GrayOut option as TRUE for Text setup options
- // so that those options will be Gray in colour and un selectable.
- //
- MenuOption->GrayOut = TRUE;
- }
- //
- // break skipped on purpose
- //
- default:
- MenuOption->IsQuestion = FALSE;
- break;
- }
-
- if ((Statement->ValueExpression != NULL) ||
- ((Statement->QuestionFlags & EFI_IFR_FLAG_READ_ONLY) != 0)) {
- MenuOption->ReadOnly = TRUE;
- if (FeaturePcdGet (PcdBrowerGrayOutReadOnlyMenu)) {
- MenuOption->GrayOut = TRUE;
- }
- }
-
- InsertTailList (&gMenuOption, &MenuOption->Link);
- }
-
- return MenuOption;
-}
-
-
-/**
- Routine used to abstract a generic dialog interface and return the selected key or string
-
- @param NumberOfLines The number of lines for the dialog box
- @param 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
- @param MaximumStringSize The maximum size in bytes of a typed in string
- (each character is a CHAR16) and the minimum
- string returned is two bytes
- @param StringBuffer The passed in pointer to the buffer which will
- hold the typed in string if HotKey is FALSE
- @param KeyValue The EFI_KEY value returned if HotKey is TRUE..
- @param ... A series of (quantity == NumberOfLines) text
- strings which will be used to construct the dialog
- box
-
- @retval EFI_SUCCESS Displayed dialog and received user interaction
- @retval EFI_INVALID_PARAMETER One of the parameters was invalid (e.g.
- (StringBuffer == NULL) && (HotKey == FALSE))
- @retval EFI_DEVICE_ERROR User typed in an ESC character to exit the routine
-
-**/
-EFI_STATUS
-EFIAPI
-CreateDialog (
- IN UINTN NumberOfLines,
- IN BOOLEAN HotKey,
- IN UINTN MaximumStringSize,
- OUT CHAR16 *StringBuffer,
- OUT EFI_INPUT_KEY *KeyValue,
- ...
- )
-{
- 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;
- EFI_STATUS Status;
- 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);
-
- //
- // 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 = 0;
-
- VA_START (Marker, KeyValue);
-
- //
- // Determine the largest string in the dialog box
- // Notice we are starting with 1 since String is the first string
- //
- for (Count = 0; 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);
- }
- }
- VA_END (Marker);
-
- Start = (DimensionsWidth - LargestString - 2) / 2 + gScreenDimensions.LeftColumn + 1;
- Top = ((DimensionsHeight - NumberOfLines - 2) / 2) + gScreenDimensions.TopRow - 1;
-
- Count = 0;
-
- //
- // Display the Popup
- //
- VA_START (Marker, KeyValue);
- CreateSharedPopUp (LargestString, NumberOfLines, Marker);
- VA_END (Marker);
-
- //
- // Take the first key typed and report it back?
- //
- if (HotKey) {
- Status = WaitForKeyStroke (&Key);
- ASSERT_EFI_ERROR (Status);
- CopyMem (KeyValue, &Key, sizeof (EFI_INPUT_KEY));
-
- } else {
- do {
- Status = 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);
- }
- //
- // break skipped on purpose
- //
-
- 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;
-}
-
-/**
- Draw a pop up windows based on the dimension, number of lines and
- strings specified.
-
- @param RequestedWidth The width of the pop-up.
- @param NumberOfLines The number of lines.
- @param Marker The variable argument list for the list of string to be printed.
-
-**/
-VOID
-CreateSharedPopUp (
- IN UINTN RequestedWidth,
- IN UINTN NumberOfLines,
- IN VA_LIST Marker
- )
-{
- 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;
-
- 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 = BOXDRAW_DOWN_RIGHT;
- PrintCharAt (Start, Top, Character);
- Character = BOXDRAW_HORIZONTAL;
- for (Index = Start; Index + 2 < End; Index++) {
- PrintChar (Character);
- }
-
- Character = BOXDRAW_DOWN_LEFT;
- PrintChar (Character);
- Character = BOXDRAW_VERTICAL;
-
- Count = 0;
- for (Index = Top; Index + 2 < Bottom; Index++, Count++) {
- String = VA_ARG (Marker, CHAR16*);
-
- //
- // 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 = BOXDRAW_UP_RIGHT;
- PrintCharAt (Start, Bottom - 1, Character);
- Character = BOXDRAW_HORIZONTAL;
- for (Index = Start; Index + 2 < End; Index++) {
- PrintChar (Character);
- }
-
- Character = BOXDRAW_UP_LEFT;
- PrintChar (Character);
-}
-
-/**
- Draw a pop up windows based on the dimension, number of lines and
- strings specified.
-
- @param RequestedWidth The width of the pop-up.
- @param NumberOfLines The number of lines.
- @param ... A series of text strings that displayed in the pop-up.
-
-**/
-VOID
-EFIAPI
-CreateMultiStringPopUp (
- IN UINTN RequestedWidth,
- IN UINTN NumberOfLines,
- ...
- )
-{
- VA_LIST Marker;
-
- VA_START (Marker, NumberOfLines);
-
- CreateSharedPopUp (RequestedWidth, NumberOfLines, Marker);
-
- VA_END (Marker);
-}
-
-
-/**
- Update status bar on the bottom of menu.
-
- @param Selection Current Selction info.
- @param MessageType The type of message to be shown.
- @param Flags The flags in Question header.
- @param State Set or clear.
-
-**/
-VOID
-UpdateStatusBar (
- IN UI_MENU_SELECTION *Selection,
- IN UINTN MessageType,
- IN UINT8 Flags,
- IN BOOLEAN State
- )
-{
- UINTN Index;
- CHAR16 *NvUpdateMessage;
- CHAR16 *InputErrorMessage;
- LIST_ENTRY *Link;
- FORM_BROWSER_FORMSET *LocalFormSet;
- FORM_BROWSER_STATEMENT *Question;
-
- 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
- );
- mInputError = TRUE;
- } else {
- gST->ConOut->SetAttribute (gST->ConOut, PcdGet8 (PcdBrowserFieldTextHighlightColor));
- for (Index = 0; Index < (GetStringWidth (InputErrorMessage) - 2) / 2; Index++) {
- PrintAt (gScreenDimensions.LeftColumn + gPromptBlockWidth + Index, gScreenDimensions.BottomRow - 1, L" ");
- }
-
- mInputError = FALSE;
- }
- break;
-
- case NV_UPDATE_REQUIRED:
- //
- // Global setting support. Show configuration change on every form.
- //
- if (State) {
- gResetRequired = (BOOLEAN) (gResetRequired | ((Flags & EFI_IFR_FLAG_RESET_REQUIRED) == EFI_IFR_FLAG_RESET_REQUIRED));
-
- if (Selection != NULL && Selection->Statement != NULL) {
- Question = Selection->Statement;
- if (Question->Storage != NULL || Question->Operand == EFI_IFR_DATE_OP || Question->Operand == EFI_IFR_TIME_OP) {
- //
- // Update only for Question value that need to be saved into Storage.
- //
- Selection->Form->NvUpdateRequired = TRUE;
- }
- }
-
- if (Selection == NULL || IsNvUpdateRequired (Selection->FormSet)) {
- gST->ConOut->SetAttribute (gST->ConOut, INFO_TEXT);
- PrintStringAt (
- gScreenDimensions.LeftColumn + gPromptBlockWidth + gOptionBlockWidth,
- gScreenDimensions.BottomRow - 1,
- NvUpdateMessage
- );
- }
- } else {
- gST->ConOut->SetAttribute (gST->ConOut, PcdGet8 (PcdBrowserFieldTextHighlightColor));
- for (Index = 0; Index < (GetStringWidth (NvUpdateMessage) - 2) / 2; Index++) {
- PrintAt (
- (gScreenDimensions.LeftColumn + gPromptBlockWidth + gOptionBlockWidth + Index),
- gScreenDimensions.BottomRow - 1,
- L" "
- );
- }
- }
- break;
-
- case REFRESH_STATUS_BAR:
- if (mInputError) {
- UpdateStatusBar (Selection, INPUT_ERROR, Flags, TRUE);
- }
-
- switch (gBrowserSettingScope) {
- case SystemLevel:
- //
- // Check the maintain list to see whether there is any change.
- //
- Link = GetFirstNode (&gBrowserFormSetList);
- while (!IsNull (&gBrowserFormSetList, Link)) {
- LocalFormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);
- if (IsNvUpdateRequired(LocalFormSet)) {
- UpdateStatusBar (NULL, NV_UPDATE_REQUIRED, Flags, TRUE);
- break;
- }
- Link = GetNextNode (&gBrowserFormSetList, Link);
- }
- break;
- case FormSetLevel:
- case FormLevel:
- UpdateStatusBar (Selection, NV_UPDATE_REQUIRED, Flags, TRUE);
- default:
- break;
- }
-
- break;
-
- default:
- break;
- }
-
- FreePool (InputErrorMessage);
- FreePool (NvUpdateMessage);
- return ;
-}
-
-
-/**
- Get the supported width for a particular op-code
-
- @param Statement The FORM_BROWSER_STATEMENT structure passed in.
- @param Handle The handle in the HII database being used
-
- @return Returns the number of CHAR16 characters that is support.
-
-**/
-UINT16
-GetWidth (
- IN FORM_BROWSER_STATEMENT *Statement,
- IN EFI_HII_HANDLE Handle
- )
-{
- CHAR16 *String;
- UINTN Size;
- UINT16 Width;
-
- Size = 0;
-
- //
- // See if the second text parameter is really NULL
- //
- if ((Statement->Operand == EFI_IFR_TEXT_OP) && (Statement->TextTwo != 0)) {
- String = GetToken (Statement->TextTwo, Handle);
- Size = StrLen (String);
- FreePool (String);
- }
-
- if ((Statement->Operand == EFI_IFR_SUBTITLE_OP) ||
- (Statement->Operand == EFI_IFR_REF_OP) ||
- (Statement->Operand == EFI_IFR_PASSWORD_OP) ||
- (Statement->Operand == EFI_IFR_ACTION_OP) ||
- (Statement->Operand == EFI_IFR_RESET_BUTTON_OP) ||
- //
- // Allow a wide display if text op-code and no secondary text op-code
- //
- ((Statement->Operand == EFI_IFR_TEXT_OP) && (Size == 0))
- ) {
- Width = (UINT16) (gPromptBlockWidth + gOptionBlockWidth);
- } else {
- Width = (UINT16) gPromptBlockWidth;
- }
-
- if (Statement->InSubtitle) {
- Width -= SUBTITLE_INDENT;
- }
-
- return (UINT16) (Width - LEFT_SKIPPED_COLUMNS);
-}
-
-/**
- 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.
- The output string format is:
- Glyph Info + String info + '\0'.
-
- In the code, it deals \r,\n,\r\n same as \n\r, also it not process the \r or \g.
-
- @param InputString String description for this option.
- @param LineWidth Width of the desired string to extract in CHAR16
- characters
- @param GlyphWidth The glyph width of the begin of the char in the string.
- @param Index Where in InputString to start the copy process
- @param OutputString Buffer to copy the string into
-
- @return Returns the number of CHAR16 characters that were copied into the OutputString
- buffer, include extra glyph info and '\0' info.
-
-**/
-UINT16
-GetLineByWidth (
- IN CHAR16 *InputString,
- IN UINT16 LineWidth,
- IN OUT UINT16 *GlyphWidth,
- IN OUT UINTN *Index,
- OUT CHAR16 **OutputString
- )
-{
- UINT16 StrOffset;
- UINT16 GlyphOffset;
- UINT16 OriginalGlyphWidth;
- BOOLEAN ReturnFlag;
- UINT16 LastSpaceOffset;
- UINT16 LastGlyphWidth;
-
- if (InputString == NULL || Index == NULL || OutputString == NULL) {
- return 0;
- }
-
- if (LineWidth == 0 || *GlyphWidth == 0) {
- return 0;
- }
-
- //
- // Save original glyph width.
- //
- OriginalGlyphWidth = *GlyphWidth;
- LastGlyphWidth = OriginalGlyphWidth;
- ReturnFlag = FALSE;
- LastSpaceOffset = 0;
-
- //
- // 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 (StrOffset = 0, GlyphOffset = 0; GlyphOffset <= LineWidth; StrOffset++) {
- switch (InputString[*Index + StrOffset]) {
- case NARROW_CHAR:
- *GlyphWidth = 1;
- break;
-
- case WIDE_CHAR:
- *GlyphWidth = 2;
- break;
-
- case CHAR_CARRIAGE_RETURN:
- case CHAR_LINEFEED:
- case CHAR_NULL:
- ReturnFlag = TRUE;
- break;
-
- default:
- GlyphOffset = GlyphOffset + *GlyphWidth;
-
- //
- // Record the last space info in this line. Will be used in rewind.
- //
- if ((InputString[*Index + StrOffset] == CHAR_SPACE) && (GlyphOffset <= LineWidth)) {
- LastSpaceOffset = StrOffset;
- LastGlyphWidth = *GlyphWidth;
- }
- break;
- }
-
- if (ReturnFlag) {
- break;
- }
- }
-
- //
- // Rewind the string from the maximum size until we see a space to break the line
- //
- if (GlyphOffset > LineWidth) {
- //
- // Rewind the string to last space char in this line.
- //
- if (LastSpaceOffset != 0) {
- StrOffset = LastSpaceOffset;
- *GlyphWidth = LastGlyphWidth;
- } else {
- //
- // Roll back to last char in the line width.
- //
- StrOffset--;
- }
- }
-
- //
- // The CHAR_NULL has process last time, this time just return 0 to stand for the end.
- //
- if (StrOffset == 0 && (InputString[*Index + StrOffset] == CHAR_NULL)) {
- return 0;
- }
-
- //
- // Need extra glyph info and '\0' info, so +2.
- //
- *OutputString = AllocateZeroPool (((UINTN) (StrOffset + 2) * sizeof(CHAR16)));
- if (*OutputString == NULL) {
- return 0;
- }
-
- //
- // Save the glyph info at the begin of the string, will used by Print function.
- //
- if (OriginalGlyphWidth == 1) {
- *(*OutputString) = NARROW_CHAR;
- } else {
- *(*OutputString) = WIDE_CHAR;
- }
-
- CopyMem ((*OutputString) + 1, &InputString[*Index], StrOffset * sizeof(CHAR16));
-
- if (InputString[*Index + StrOffset] == CHAR_SPACE) {
- //
- // Skip the space info at the begin of next line.
- //
- *Index = (UINT16) (*Index + StrOffset + 1);
- } else if (InputString[*Index + StrOffset] == CHAR_LINEFEED) {
- //
- // Skip the /n or /n/r info.
- //
- if (InputString[*Index + StrOffset + 1] == CHAR_CARRIAGE_RETURN) {
- *Index = (UINT16) (*Index + StrOffset + 2);
- } else {
- *Index = (UINT16) (*Index + StrOffset + 1);
- }
- } else if (InputString[*Index + StrOffset] == CHAR_CARRIAGE_RETURN) {
- //
- // Skip the /r or /r/n info.
- //
- if (InputString[*Index + StrOffset + 1] == CHAR_LINEFEED) {
- *Index = (UINT16) (*Index + StrOffset + 2);
- } else {
- *Index = (UINT16) (*Index + StrOffset + 1);
- }
- } else {
- *Index = (UINT16) (*Index + StrOffset);
- }
-
- //
- // Include extra glyph info and '\0' info, so +2.
- //
- return StrOffset + 2;
-}
-
-
-/**
- Update display lines for a Menu Option.
-
- @param Selection The user's selection.
- @param MenuOption The MenuOption to be checked.
-
-**/
-VOID
-UpdateOptionSkipLines (
- IN UI_MENU_SELECTION *Selection,
- IN UI_MENU_OPTION *MenuOption
- )
-{
- UINTN Index;
- UINT16 Width;
- UINTN Row;
- UINTN OriginalRow;
- CHAR16 *OutputString;
- CHAR16 *OptionString;
- UINT16 GlyphWidth;
-
- Row = 0;
- OptionString = NULL;
- Width = (UINT16) gOptionBlockWidth;
- OriginalRow = 0;
- GlyphWidth = 1;
-
- ProcessOptions (Selection, MenuOption, FALSE, &OptionString);
- if (OptionString == NULL) {
- return;
- }
-
- for (Index = 0; GetLineByWidth (OptionString, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {
- //
- // If there is more string to process print on the next row and increment the Skip value
- //
- if (StrLen (&OptionString[Index]) != 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 (OptionString != NULL) {
- FreePool (OptionString);
- }
-}
-
-
-/**
- Check whether this Menu Option could be highlighted.
-
- This is an internal function.
-
- @param MenuOption The MenuOption to be checked.
-
- @retval TRUE This Menu Option is selectable.
- @retval FALSE This Menu Option could not be selected.
-
-**/
-BOOLEAN
-IsSelectable (
- UI_MENU_OPTION *MenuOption
- )
-{
- if ((MenuOption->ThisTag->Operand == EFI_IFR_SUBTITLE_OP) ||
- MenuOption->GrayOut || MenuOption->ReadOnly) {
- return FALSE;
- } else {
- return TRUE;
- }
-}
-
-
-/**
- Determine if the menu is the last menu that can be selected.
-
- This is an internal function.
-
- @param Direction The scroll direction. False is down. True is up.
- @param CurrentPos The current focus.
-
- @return FALSE -- the menu isn't the last menu that can be selected.
- @return TRUE -- the menu is the last menu that can be selected.
-
-**/
-BOOLEAN
-ValueIsScroll (
- IN BOOLEAN Direction,
- IN LIST_ENTRY *CurrentPos
- )
-{
- LIST_ENTRY *Temp;
-
- Temp = Direction ? CurrentPos->BackLink : CurrentPos->ForwardLink;
-
- if (Temp == &gMenuOption) {
- return TRUE;
- }
-
- return FALSE;
-}
-
-
-/**
- Move to next selectable statement.
-
- This is an internal function.
-
- @param Selection Menu selection.
- @param GoUp The navigation direction. TRUE: up, FALSE: down.
- @param CurrentPosition Current position.
- @param GapToTop Gap position to top or bottom.
-
- @return The row distance from current MenuOption to next selectable MenuOption.
-
- @retval -1 Reach the begin of the menu, still can't find the selectable menu.
- @retval Value Find the selectable menu, maybe the truly selectable, maybe the l
- last menu showing at current form.
-
-**/
-INTN
-MoveToNextStatement (
- IN UI_MENU_SELECTION *Selection,
- IN BOOLEAN GoUp,
- IN OUT LIST_ENTRY **CurrentPosition,
- IN UINTN GapToTop
- )
-{
- INTN Distance;
- LIST_ENTRY *Pos;
- UI_MENU_OPTION *NextMenuOption;
- UI_MENU_OPTION *PreMenuOption;
-
- Distance = 0;
- Pos = *CurrentPosition;
- PreMenuOption = MENU_OPTION_FROM_LINK (Pos);
-
- while (TRUE) {
- NextMenuOption = MENU_OPTION_FROM_LINK (Pos);
- //
- // NextMenuOption->Row == 0 means this menu has not calculate
- // the NextMenuOption->Skip value yet, just calculate here.
- //
- if (NextMenuOption->Row == 0) {
- UpdateOptionSkipLines (Selection, NextMenuOption);
- }
-
- if (GoUp && (PreMenuOption != NextMenuOption)) {
- //
- // In this case, still can't find the selectable menu,
- // return the last one in the showing form.
- //
- if ((UINTN) Distance + NextMenuOption->Skip > GapToTop) {
- NextMenuOption = PreMenuOption;
- break;
- }
-
- //
- // Current Position doesn't need to be caculated when go up.
- // Caculate distanct at first when go up
- //
- Distance += NextMenuOption->Skip;
- }
-
- if (IsSelectable (NextMenuOption)) {
- break;
- }
-
- //
- // Arrive at begin of the menu list.
- //
- if ((GoUp ? Pos->BackLink : Pos->ForwardLink) == &gMenuOption) {
- Distance = -1;
- break;
- }
-
- if (!GoUp) {
- //
- // In this case, still can't find the selectable menu,
- // return the last one in the showing form.
- //
- if ((UINTN) Distance + NextMenuOption->Skip > GapToTop) {
- NextMenuOption = PreMenuOption;
- break;
- }
-
- Distance += NextMenuOption->Skip;
- }
-
- PreMenuOption = NextMenuOption;
- Pos = (GoUp ? Pos->BackLink : Pos->ForwardLink);
- }
-
- *CurrentPosition = &NextMenuOption->Link;
- return Distance;
-}
-
-
-/**
- Adjust Data and Time position accordingly.
- Data format : [01/02/2004] [11:22:33]
- Line number : 0 0 1 0 0 1
-
- This is an internal function.
-
- @param DirectionUp the up or down direction. False is down. True is
- up.
- @param CurrentPosition Current position. On return: Point to the last
- Option (Year or Second) if up; Point to the first
- Option (Month or Hour) if down.
-
- @return Return line number to pad. It is possible that we stand on a zero-advance
- @return data or time opcode, so pad one line when we judge if we are going to scroll outside.
-
-**/
-UINTN
-AdjustDateAndTimePosition (
- IN BOOLEAN DirectionUp,
- IN OUT LIST_ENTRY **CurrentPosition
- )
-{
- UINTN Count;
- LIST_ENTRY *NewPosition;
- UI_MENU_OPTION *MenuOption;
- UINTN PadLineNumber;
-
- PadLineNumber = 0;
- NewPosition = *CurrentPosition;
- MenuOption = MENU_OPTION_FROM_LINK (NewPosition);
-
- 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 MenuOption
- //
- Count = 0;
- while (MenuOption->Skip == 0) {
- Count++;
- NewPosition = NewPosition->ForwardLink;
- MenuOption = MENU_OPTION_FROM_LINK (NewPosition);
- PadLineNumber = 1;
- }
-
- NewPosition = *CurrentPosition;
- if (DirectionUp) {
- //
- // Since the behavior of hitting the up arrow on a Date/Time MenuOption is intended
- // to be one that back to the previous set of MenuOptions, we need to advance to the first
- // Date/Time MenuOption 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 MenuOption is intended
- // to be one that progresses to the next set of MenuOptions, we need to advance to the last
- // Date/Time MenuOption 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;
-}
-
-/**
- Find HII Handle in the HII database associated with given Device Path.
-
- If DevicePath is NULL, then ASSERT.
-
- @param DevicePath Device Path associated with the HII package list
- handle.
-
- @retval Handle HII package list Handle associated with the Device
- Path.
- @retval NULL Hii Package list handle is not found.
-
-**/
-EFI_HII_HANDLE
-EFIAPI
-DevicePathToHiiHandle (
- IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
- )
-{
- EFI_STATUS Status;
- EFI_DEVICE_PATH_PROTOCOL *TmpDevicePath;
- UINTN BufferSize;
- UINTN HandleCount;
- UINTN Index;
- EFI_HANDLE Handle;
- EFI_HANDLE DriverHandle;
- EFI_HII_HANDLE *HiiHandles;
- EFI_HII_HANDLE HiiHandle;
-
- ASSERT (DevicePath != NULL);
-
- TmpDevicePath = DevicePath;
- //
- // Locate Device Path Protocol handle buffer
- //
- Status = gBS->LocateDevicePath (
- &gEfiDevicePathProtocolGuid,
- &TmpDevicePath,
- &DriverHandle
- );
- if (EFI_ERROR (Status) || !IsDevicePathEnd (TmpDevicePath)) {
- return NULL;
- }
-
- //
- // Retrieve all HII Handles from HII database
- //
- BufferSize = 0x1000;
- HiiHandles = AllocatePool (BufferSize);
- ASSERT (HiiHandles != NULL);
- Status = mHiiDatabase->ListPackageLists (
- mHiiDatabase,
- EFI_HII_PACKAGE_TYPE_ALL,
- NULL,
- &BufferSize,
- HiiHandles
- );
- if (Status == EFI_BUFFER_TOO_SMALL) {
- FreePool (HiiHandles);
- HiiHandles = AllocatePool (BufferSize);
- ASSERT (HiiHandles != NULL);
-
- Status = mHiiDatabase->ListPackageLists (
- mHiiDatabase,
- EFI_HII_PACKAGE_TYPE_ALL,
- NULL,
- &BufferSize,
- HiiHandles
- );
- }
-
- if (EFI_ERROR (Status)) {
- FreePool (HiiHandles);
- return NULL;
- }
-
- //
- // Search Hii Handle by Driver Handle
- //
- HiiHandle = NULL;
- HandleCount = BufferSize / sizeof (EFI_HII_HANDLE);
- for (Index = 0; Index < HandleCount; Index++) {
- Status = mHiiDatabase->GetPackageListHandle (
- mHiiDatabase,
- HiiHandles[Index],
- &Handle
- );
- if (!EFI_ERROR (Status) && (Handle == DriverHandle)) {
- HiiHandle = HiiHandles[Index];
- break;
- }
- }
-
- FreePool (HiiHandles);
- return HiiHandle;
-}
-
-/**
- Find HII Handle in the HII database associated with given form set guid.
-
- If FormSetGuid is NULL, then ASSERT.
-
- @param ComparingGuid FormSet Guid associated with the HII package list
- handle.
-
- @retval Handle HII package list Handle associated with the Device
- Path.
- @retval NULL Hii Package list handle is not found.
-
-**/
-EFI_HII_HANDLE
-FormSetGuidToHiiHandle (
- EFI_GUID *ComparingGuid
- )
-{
- EFI_HII_HANDLE *HiiHandles;
- UINTN Index;
- EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;
- UINTN BufferSize;
- UINT32 Offset;
- UINT32 Offset2;
- UINT32 PackageListLength;
- EFI_HII_PACKAGE_HEADER PackageHeader;
- UINT8 *Package;
- UINT8 *OpCodeData;
- EFI_STATUS Status;
- EFI_HII_HANDLE HiiHandle;
-
- ASSERT (ComparingGuid != NULL);
-
- HiiHandle = NULL;
- //
- // Get all the Hii handles
- //
- HiiHandles = HiiGetHiiHandles (NULL);
- ASSERT (HiiHandles != NULL);
-
- //
- // Search for formset of each class type
- //
- for (Index = 0; HiiHandles[Index] != NULL; Index++) {
- BufferSize = 0;
- HiiPackageList = NULL;
- Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, HiiHandles[Index], &BufferSize, HiiPackageList);
- if (Status == EFI_BUFFER_TOO_SMALL) {
- HiiPackageList = AllocatePool (BufferSize);
- ASSERT (HiiPackageList != NULL);
-
- Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, HiiHandles[Index], &BufferSize, HiiPackageList);
- }
- if (EFI_ERROR (Status) || HiiPackageList == NULL) {
- return NULL;
- }
-
- //
- // Get Form package from this HII package List
- //
- Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);
- Offset2 = 0;
- CopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof (UINT32));
-
- while (Offset < PackageListLength) {
- Package = ((UINT8 *) HiiPackageList) + Offset;
- CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));
-
- if (PackageHeader.Type == EFI_HII_PACKAGE_FORMS) {
- //
- // Search FormSet in this Form Package
- //
- Offset2 = sizeof (EFI_HII_PACKAGE_HEADER);
- while (Offset2 < PackageHeader.Length) {
- OpCodeData = Package + Offset2;
-
- if (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) {
- //
- // Try to compare against formset GUID
- //
- if (CompareGuid (ComparingGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)))) {
- HiiHandle = HiiHandles[Index];
- break;
- }
- }
-
- Offset2 += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;
- }
- }
- if (HiiHandle != NULL) {
- break;
- }
- Offset += PackageHeader.Length;
- }
-
- FreePool (HiiPackageList);
- if (HiiHandle != NULL) {
- break;
- }
- }
-
- FreePool (HiiHandles);
-
- return HiiHandle;
-}
-
-/**
- Process the goto op code, update the info in the selection structure.
-
- @param Statement The statement belong to goto op code.
- @param Selection The selection info.
- @param Repaint Whether need to repaint the menu.
- @param NewLine Whether need to create new line.
-
- @retval EFI_SUCCESS The menu process successfully.
- @return Other value if the process failed.
-**/
-EFI_STATUS
-ProcessGotoOpCode (
- IN OUT FORM_BROWSER_STATEMENT *Statement,
- IN OUT UI_MENU_SELECTION *Selection,
- OUT BOOLEAN *Repaint,
- OUT BOOLEAN *NewLine
- )
-{
- CHAR16 *StringPtr;
- EFI_DEVICE_PATH_PROTOCOL *DevicePath;
- FORM_BROWSER_FORM *RefForm;
- EFI_INPUT_KEY Key;
- EFI_STATUS Status;
-
- Status = EFI_SUCCESS;
- StringPtr = NULL;
-
- //
- // Prepare the device path check, get the device path info first.
- //
- if (Statement->HiiValue.Value.ref.DevicePath != 0) {
- StringPtr = GetToken (Statement->HiiValue.Value.ref.DevicePath, Selection->FormSet->HiiHandle);
- }
-
- //
- // Check whether the device path string is a valid string.
- //
- if (Statement->HiiValue.Value.ref.DevicePath != 0 && StringPtr != NULL) {
- if (Selection->Form->ModalForm) {
- return Status;
- }
-
- //
- // Goto another Hii Package list
- //
- if (mPathFromText != NULL) {
- DevicePath = mPathFromText->ConvertTextToDevicePath(StringPtr);
- if (DevicePath != NULL) {
- Selection->Handle = DevicePathToHiiHandle (DevicePath);
- FreePool (DevicePath);
- }
- FreePool (StringPtr);
- } else {
- //
- // Not found the EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL protocol.
- //
- do {
- CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, gProtocolNotFound, gPressEnter, gEmptyString);
- } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
- if (Repaint != NULL) {
- *Repaint = TRUE;
- }
- FreePool (StringPtr);
- return Status;
- }
-
- Selection->Action = UI_ACTION_REFRESH_FORMSET;
- if (Selection->Handle == NULL) {
- //
- // If target Hii Handle not found, exit
- //
- Selection->Action = UI_ACTION_EXIT;
- Selection->Statement = NULL;
- return Status;
- }
-
- CopyMem (&Selection->FormSetGuid,&Statement->HiiValue.Value.ref.FormSetGuid, sizeof (EFI_GUID));
- Selection->FormId = Statement->HiiValue.Value.ref.FormId;
- Selection->QuestionId = Statement->HiiValue.Value.ref.QuestionId;
- } else if (!CompareGuid (&Statement->HiiValue.Value.ref.FormSetGuid, &gZeroGuid)) {
- if (Selection->Form->ModalForm) {
- return Status;
- }
- //
- // Goto another Formset, check for uncommitted data
- //
- Selection->Action = UI_ACTION_REFRESH_FORMSET;
-
- Selection->Handle = FormSetGuidToHiiHandle(&Statement->HiiValue.Value.ref.FormSetGuid);
- if (Selection->Handle == NULL) {
- //
- // If target Hii Handle not found, exit
- //
- Selection->Action = UI_ACTION_EXIT;
- Selection->Statement = NULL;
- return Status;
- }
-
- CopyMem (&Selection->FormSetGuid, &Statement->HiiValue.Value.ref.FormSetGuid, sizeof (EFI_GUID));
- Selection->FormId = Statement->HiiValue.Value.ref.FormId;
- Selection->QuestionId = Statement->HiiValue.Value.ref.QuestionId;
- } else if (Statement->HiiValue.Value.ref.FormId != 0) {
- //
- // Check whether target From is suppressed.
- //
- RefForm = IdToForm (Selection->FormSet, Statement->HiiValue.Value.ref.FormId);
-
- if ((RefForm != NULL) && (RefForm->SuppressExpression != NULL)) {
- if (EvaluateExpressionList(RefForm->SuppressExpression, TRUE, Selection->FormSet, RefForm) != ExpressFalse) {
- //
- // Form is suppressed.
- //
- do {
- CreateDialog (4, TRUE, 0, NULL, &Key, gEmptyString, gFormSuppress, gPressEnter, gEmptyString);
- } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
- if (Repaint != NULL) {
- *Repaint = TRUE;
- }
- return Status;
- }
- }
-
- //
- // Goto another form inside this formset,
- //
- Selection->Action = UI_ACTION_REFRESH_FORM;
-
- Selection->FormId = Statement->HiiValue.Value.ref.FormId;
- Selection->QuestionId = Statement->HiiValue.Value.ref.QuestionId;
- } else if (Statement->HiiValue.Value.ref.QuestionId != 0) {
- //
- // Goto another Question
- //
- Selection->QuestionId = Statement->HiiValue.Value.ref.QuestionId;
-
- if ((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) {
- Selection->Action = UI_ACTION_REFRESH_FORM;
- } else {
- if (Repaint != NULL) {
- *Repaint = TRUE;
- }
- if (NewLine != NULL) {
- *NewLine = TRUE;
- }
- }
- } else {
- if ((Statement->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) {
- Selection->Action = UI_ACTION_REFRESH_FORM;
- }
- }
-
- return Status;
-}
-
-/**
- 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.
-
- @param Selection Menu selection.
-
- @retval EFI_SUCESSS This function always return successfully for now.
-
-**/
-EFI_STATUS
-UiDisplayMenu (
- IN OUT UI_MENU_SELECTION *Selection
- )
-{
- INTN SkipValue;
- INTN Difference;
- UINTN DistanceValue;
- UINTN Row;
- UINTN Col;
- UINTN Temp;
- UINTN Temp2;
- UINTN TopRow;
- UINTN BottomRow;
- UINTN OriginalRow;
- UINTN Index;
- UINT16 Width;
- CHAR16 *StringPtr;
- CHAR16 *OptionString;
- CHAR16 *OutputString;
- CHAR16 *HelpString;
- CHAR16 *HelpHeaderString;
- CHAR16 *HelpBottomString;
- BOOLEAN NewLine;
- BOOLEAN Repaint;
- BOOLEAN SavedValue;
- BOOLEAN UpArrow;
- BOOLEAN DownArrow;
- BOOLEAN InitializedFlag;
- EFI_STATUS Status;
- EFI_INPUT_KEY Key;
- LIST_ENTRY *Link;
- LIST_ENTRY *NewPos;
- LIST_ENTRY *TopOfScreen;
- LIST_ENTRY *SavedListEntry;
- UI_MENU_OPTION *MenuOption;
- UI_MENU_OPTION *NextMenuOption;
- UI_MENU_OPTION *SavedMenuOption;
- UI_MENU_OPTION *PreviousMenuOption;
- UI_CONTROL_FLAG ControlFlag;
- EFI_SCREEN_DESCRIPTOR LocalScreen;
- MENU_REFRESH_ENTRY *MenuRefreshEntry;
- MENU_REFRESH_ENTRY *MenuUpdateEntry;
- UI_SCREEN_OPERATION ScreenOperation;
- UINT8 MinRefreshInterval;
- UINT16 DefaultId;
- FORM_BROWSER_STATEMENT *Statement;
- UI_MENU_LIST *CurrentMenu;
- UINTN ModalSkipColumn;
- BROWSER_HOT_KEY *HotKey;
- UINTN HelpPageIndex;
- UINTN HelpPageCount;
- UINTN RowCount;
- UINTN HelpLine;
- UINTN HelpHeaderLine;
- UINTN HelpBottomLine;
- BOOLEAN MultiHelpPage;
- UINT16 GlyphWidth;
- UINT16 EachLineWidth;
- UINT16 HeaderLineWidth;
- UINT16 BottomLineWidth;
-
- CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));
-
- Status = EFI_SUCCESS;
- HelpString = NULL;
- HelpHeaderString = NULL;
- HelpBottomString = NULL;
- OptionString = NULL;
- ScreenOperation = UiNoOperation;
- NewLine = TRUE;
- MinRefreshInterval = 0;
- DefaultId = 0;
- HelpPageCount = 0;
- HelpLine = 0;
- RowCount = 0;
- HelpBottomLine = 0;
- HelpHeaderLine = 0;
- HelpPageIndex = 0;
- MultiHelpPage = FALSE;
- EachLineWidth = 0;
- HeaderLineWidth = 0;
- BottomLineWidth = 0;
- OutputString = NULL;
- UpArrow = FALSE;
- DownArrow = FALSE;
- SkipValue = 0;
- MenuRefreshEntry = gMenuRefreshHead;
-
- NextMenuOption = NULL;
- PreviousMenuOption = NULL;
- SavedMenuOption = NULL;
- HotKey = NULL;
- ModalSkipColumn = (LocalScreen.RightColumn - LocalScreen.LeftColumn) / 6;
-
- ZeroMem (&Key, sizeof (EFI_INPUT_KEY));
-
- if ((gClassOfVfr & FORMSET_CLASS_FRONT_PAGE) == FORMSET_CLASS_FRONT_PAGE){
- 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 (Selection->Form->ModalForm) {
- Col = LocalScreen.LeftColumn + LEFT_SKIPPED_COLUMNS + ModalSkipColumn;
- } else {
- Col = LocalScreen.LeftColumn + LEFT_SKIPPED_COLUMNS;
- }
-
- BottomRow = LocalScreen.BottomRow - STATUS_BAR_HEIGHT - gFooterHeight - SCROLL_ARROW_HEIGHT - 1;
-
- Selection->TopRow = TopRow;
- Selection->BottomRow = BottomRow;
- Selection->PromptCol = Col;
- Selection->OptionCol = gPromptBlockWidth + 1 + LocalScreen.LeftColumn;
- Selection->Statement = NULL;
-
- TopOfScreen = gMenuOption.ForwardLink;
- Repaint = TRUE;
- MenuOption = NULL;
-
- //
- // Find current Menu
- //
- CurrentMenu = UiFindMenuList (Selection->Handle, &Selection->FormSetGuid, Selection->FormId);
- if (CurrentMenu == NULL) {
- //
- // Current menu not found, add it to the menu tree
- //
- CurrentMenu = UiAddMenuList (Selection->CurrentMenu, Selection->Handle, &Selection->FormSetGuid, Selection->FormId);
- }
- ASSERT (CurrentMenu != NULL);
- Selection->CurrentMenu = CurrentMenu;
-
- if (Selection->QuestionId == 0) {
- //
- // Highlight not specified, fetch it from cached menu
- //
- Selection->QuestionId = CurrentMenu->QuestionId;
- Selection->Sequence = CurrentMenu->Sequence;
- }
-
- //
- // Init option as the current user's selection
- //
- InitializedFlag = TRUE;
- NewPos = gMenuOption.ForwardLink;
-
- gST->ConOut->EnableCursor (gST->ConOut, FALSE);
- UpdateStatusBar (Selection, REFRESH_STATUS_BAR, (UINT8) 0, TRUE);
-
- ControlFlag = CfInitialization;
- Selection->Action = UI_ACTION_NONE;
- while (TRUE) {
- switch (ControlFlag) {
- case CfInitialization:
- if (IsListEmpty (&gMenuOption)) {
- ControlFlag = CfReadKey;
- } else {
- ControlFlag = CfCheckSelection;
- }
- break;
-
- case CfCheckSelection:
- if (Selection->Action != UI_ACTION_NONE) {
- ControlFlag = CfExit;
- } else {
- ControlFlag = CfRepaint;
- }
- break;
-
- case CfRepaint:
- ControlFlag = CfRefreshHighLight;
-
- if (Repaint) {
- //
- // Display menu
- //
- DownArrow = FALSE;
- UpArrow = FALSE;
- Row = TopRow;
-
- Temp = (UINTN) SkipValue;
- Temp2 = (UINTN) SkipValue;
-
- //
- // 1. Clear the screen.
- //
- if (Selection->Form->ModalForm) {
- ClearLines (
- LocalScreen.LeftColumn + ModalSkipColumn,
- LocalScreen.LeftColumn + ModalSkipColumn + gPromptBlockWidth + gOptionBlockWidth,
- TopRow - SCROLL_ARROW_HEIGHT,
- BottomRow + SCROLL_ARROW_HEIGHT,
- PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND
- );
- } else {
- ClearLines (
- LocalScreen.LeftColumn,
- LocalScreen.RightColumn,
- TopRow - SCROLL_ARROW_HEIGHT,
- BottomRow + SCROLL_ARROW_HEIGHT,
- PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND
- );
- }
- UiFreeRefreshList ();
- MinRefreshInterval = 0;
-
- //
- // 2.Paint the menu.
- //
- for (Link = TopOfScreen; Link != &gMenuOption; Link = Link->ForwardLink) {
- MenuOption = MENU_OPTION_FROM_LINK (Link);
- MenuOption->Row = Row;
- MenuOption->Col = Col;
- if (Selection->Form->ModalForm) {
- MenuOption->OptCol = gPromptBlockWidth + 1 + LocalScreen.LeftColumn + ModalSkipColumn;
- } else {
- MenuOption->OptCol = gPromptBlockWidth + 1 + LocalScreen.LeftColumn;
- }
-
- Statement = MenuOption->ThisTag;
- if (Statement->InSubtitle) {
- MenuOption->Col += SUBTITLE_INDENT;
- }
-
- if (MenuOption->GrayOut) {
- gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT_GRAYED | FIELD_BACKGROUND);
- } else {
- if (Statement->Operand == EFI_IFR_SUBTITLE_OP) {
- gST->ConOut->SetAttribute (gST->ConOut, PcdGet8 (PcdBrowserSubtitleTextColor) | FIELD_BACKGROUND);
- }
- }
-
- Width = GetWidth (Statement, MenuOption->Handle);
- OriginalRow = Row;
- GlyphWidth = 1;
-
- if (Statement->Operand == EFI_IFR_REF_OP && MenuOption->Col >= 2) {
- //
- // Print Arrow for Goto button.
- //
- PrintAt (
- MenuOption->Col - 2,
- Row,
- L"%c",
- GEOMETRICSHAPE_RIGHT_TRIANGLE
- );
- }
-
- //
- // 2.1. Paint the description.
- //
- for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {
- //
- // Temp means need to skip how many lines from the start.
- //
- if ((Temp == 0) && (Row <= BottomRow)) {
- PrintStringAt (MenuOption->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]) != 0) {
- if (Temp == 0) {
- Row++;
- }
- }
-
- FreePool (OutputString);
- if (Temp != 0) {
- Temp--;
- }
- }
-
- Temp = 0;
- Row = OriginalRow;
-
- //
- // 2.2. Paint the option string.
- //
- Status = ProcessOptions (Selection, MenuOption, FALSE, &OptionString);
- if (EFI_ERROR (Status)) {
- //
- // Repaint to clear possible error prompt pop-up
- //
- Repaint = TRUE;
- NewLine = TRUE;
- ControlFlag = CfRepaint;
- break;
- }
-
- if (OptionString != NULL) {
- if (Statement->Operand == EFI_IFR_DATE_OP || Statement->Operand == EFI_IFR_TIME_OP) {
- ProcessStringForDateTime(MenuOption, OptionString, TRUE);
- }
-
- Width = (UINT16) gOptionBlockWidth;
- OriginalRow = Row;
- GlyphWidth = 1;
-
- for (Index = 0; GetLineByWidth (OptionString, Width, &GlyphWidth, &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]) != 0) {
- 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;
-
- FreePool (OptionString);
- }
-
- //
- // 2.4 Special process for Test opcode with test two.
- //
- if (!CompareGuid (&Statement->RefreshGuid, &gZeroGuid)) {
- if (gMenuEventGuidRefreshHead == NULL) {
- MenuUpdateEntry = AllocateZeroPool (sizeof (MENU_REFRESH_ENTRY));
- gMenuEventGuidRefreshHead = MenuUpdateEntry;
- } else {
- MenuUpdateEntry = gMenuEventGuidRefreshHead;
- while (MenuUpdateEntry->Next != NULL) {
- MenuUpdateEntry = MenuUpdateEntry->Next;
- }
- MenuUpdateEntry->Next = AllocateZeroPool (sizeof (MENU_REFRESH_ENTRY));
- MenuUpdateEntry = MenuUpdateEntry->Next;
- }
- ASSERT (MenuUpdateEntry != NULL);
- Status = gBS->CreateEventEx (EVT_NOTIFY_SIGNAL, TPL_NOTIFY, RefreshQuestionNotify, MenuUpdateEntry, &Statement->RefreshGuid, &MenuUpdateEntry->Event);
- ASSERT (!EFI_ERROR (Status));
- MenuUpdateEntry->MenuOption = MenuOption;
- MenuUpdateEntry->Selection = Selection;
- MenuUpdateEntry->CurrentColumn = MenuOption->OptCol;
- MenuUpdateEntry->CurrentRow = MenuOption->Row;
- if (MenuOption->GrayOut) {
- MenuUpdateEntry->CurrentAttribute = FIELD_TEXT_GRAYED | FIELD_BACKGROUND;
- } else {
- MenuUpdateEntry->CurrentAttribute = PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND;
- }
- }
-
- //
- // If Question request refresh, register the op-code
- //
- if (Statement->RefreshInterval != 0) {
- //
- // Menu will be refreshed at minimal interval of all Questions
- // which have refresh request
- //
- if (MinRefreshInterval == 0 || Statement->RefreshInterval < MinRefreshInterval) {
- MinRefreshInterval = Statement->RefreshInterval;
- }
-
- if (gMenuRefreshHead == NULL) {
- MenuRefreshEntry = AllocateZeroPool (sizeof (MENU_REFRESH_ENTRY));
- gMenuRefreshHead = MenuRefreshEntry;
- } else {
- MenuRefreshEntry = gMenuRefreshHead;
- while (MenuRefreshEntry->Next != NULL) {
- MenuRefreshEntry = MenuRefreshEntry->Next;
- }
- MenuRefreshEntry->Next = AllocateZeroPool (sizeof (MENU_REFRESH_ENTRY));
- MenuRefreshEntry = MenuRefreshEntry->Next;
- }
- ASSERT (MenuRefreshEntry != NULL);
- MenuRefreshEntry->MenuOption = MenuOption;
- MenuRefreshEntry->Selection = Selection;
- MenuRefreshEntry->CurrentColumn = MenuOption->OptCol;
- MenuRefreshEntry->CurrentRow = MenuOption->Row;
- if (MenuOption->GrayOut) {
- MenuRefreshEntry->CurrentAttribute = FIELD_TEXT_GRAYED | FIELD_BACKGROUND;
- } else {
- MenuRefreshEntry->CurrentAttribute = PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND;
- }
- }
-
- //
- // If this is a text op with secondary text information
- //
- if ((Statement->Operand == EFI_IFR_TEXT_OP) && (Statement->TextTwo != 0)) {
- StringPtr = GetToken (Statement->TextTwo, MenuOption->Handle);
-
- Width = (UINT16) gOptionBlockWidth;
- OriginalRow = Row;
- GlyphWidth = 1;
-
- for (Index = 0; GetLineByWidth (StringPtr, Width, &GlyphWidth, &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]) != 0) {
- 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);
- }
- gST->ConOut->SetAttribute (gST->ConOut, PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND);
-
- //
- // 3. Update the row info which will be used by next menu.
- //
- if (Link == TopOfScreen) {
- Row += MenuOption->Skip - SkipValue;
- } else {
- Row += MenuOption->Skip;
- }
-
- if (Row > BottomRow) {
- if (!ValueIsScroll (FALSE, Link)) {
- DownArrow = TRUE;
- }
-
- Row = BottomRow + 1;
- break;
- }
- }
-
- if (!ValueIsScroll (TRUE, TopOfScreen)) {
- UpArrow = TRUE;
- }
-
- if (UpArrow) {
- gST->ConOut->SetAttribute (gST->ConOut, ARROW_TEXT | ARROW_BACKGROUND);
- PrintAt (
- LocalScreen.LeftColumn + gPromptBlockWidth + gOptionBlockWidth + 1,
- TopRow - SCROLL_ARROW_HEIGHT,
- L"%c",
- ARROW_UP
- );
- gST->ConOut->SetAttribute (gST->ConOut, PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND);
- }
-
- if (DownArrow) {
- gST->ConOut->SetAttribute (gST->ConOut, ARROW_TEXT | ARROW_BACKGROUND);
- PrintAt (
- LocalScreen.LeftColumn + gPromptBlockWidth + gOptionBlockWidth + 1,
- BottomRow + SCROLL_ARROW_HEIGHT,
- L"%c",
- ARROW_DOWN
- );
- gST->ConOut->SetAttribute (gST->ConOut, PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND);
- }
-
- MenuOption = NULL;
- }
- break;
-
- case CfRefreshHighLight:
- //
- // MenuOption: Last menu option that need to remove hilight
- // MenuOption is set to NULL in Repaint
- // NewPos: Current menu option that need to hilight
- //
- ControlFlag = CfUpdateHelpString;
- if (TopOfScreen == &MenuOption->Link) {
- Temp = SkipValue;
- } else {
- Temp = 0;
- }
- if (NewPos == TopOfScreen) {
- Temp2 = SkipValue;
- } else {
- Temp2 = 0;
- }
- if (InitializedFlag) {
- InitializedFlag = FALSE;
- MoveToNextStatement (Selection, FALSE, &NewPos, BottomRow - TopRow);
- }
-
- //
- // 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 (Selection->QuestionId != 0) {
- NewPos = gMenuOption.ForwardLink;
- SavedMenuOption = MENU_OPTION_FROM_LINK (NewPos);
-
- while ((SavedMenuOption->ThisTag->QuestionId != Selection->QuestionId ||
- SavedMenuOption->Sequence != Selection->Sequence) &&
- NewPos->ForwardLink != &gMenuOption) {
- NewPos = NewPos->ForwardLink;
- SavedMenuOption = MENU_OPTION_FROM_LINK (NewPos);
- }
- if (SavedMenuOption->ThisTag->QuestionId == Selection->QuestionId) {
- //
- // Target Question found, find its MenuOption
- //
- Link = TopOfScreen;
-
- for (Index = TopRow; Index <= BottomRow && Link != NewPos;) {
- SavedMenuOption = MENU_OPTION_FROM_LINK (Link);
- Index += SavedMenuOption->Skip;
- if (Link == TopOfScreen) {
- Index -= SkipValue;
- }
- Link = Link->ForwardLink;
- }
- if (NewPos == Link) {
- SavedMenuOption = MENU_OPTION_FROM_LINK (Link);
- }
-
- //
- // Not find the selected menu in current show page.
- // Have two case to enter this if:
- // 1. Not find the menu at current page.
- // 2. Find the menu in current page, but the menu shows at the bottom and not all info shows.
- // For case 2, has an exception: The menu can show more than one pages and now only this menu shows.
- //
- // Base on the selected menu will show at the bottom of the page,
- // select the menu which will show at the top of the page.
- //
- if (Link != NewPos || Index > BottomRow ||
- (Link == NewPos && (SavedMenuOption->Row + SavedMenuOption->Skip - 1 > BottomRow) && (Link != TopOfScreen))) {
- //
- // Find the MenuOption which has the skip value for Date/Time opcode.
- //
- AdjustDateAndTimePosition(FALSE, &NewPos);
- //
- // NewPos is not in the current page, simply scroll page so that NewPos is in the end of the page
- //
- SavedMenuOption = MENU_OPTION_FROM_LINK (NewPos);
- //
- // SavedMenuOption->Row == 0 means the menu not show yet.
- //
- if (SavedMenuOption->Row == 0) {
- UpdateOptionSkipLines (Selection, SavedMenuOption);
- }
-
- //
- // Base on the selected menu will show at the bottome of next page,
- // select the menu show at the top of the next page.
- //
- Link = NewPos;
- for (Index = TopRow + SavedMenuOption->Skip; Index <= BottomRow + 1; ) {
- Link = Link->BackLink;
- SavedMenuOption = MENU_OPTION_FROM_LINK (Link);
- if (SavedMenuOption->Row == 0) {
- UpdateOptionSkipLines (Selection, SavedMenuOption);
- }
- Index += SavedMenuOption->Skip;
- }
-
- //
- // Found the menu which will show at the top of the page.
- //
- if (Link == NewPos) {
- //
- // The menu can show more than one pages, just show the menu at the top of the page.
- //
- SkipValue = 0;
- TopOfScreen = Link;
- } else {
- //
- // Check whether need to skip some line for menu shows at the top of the page.
- //
- SkipValue = Index - BottomRow - 1;
- if (SkipValue > 0 && SkipValue < (INTN) SavedMenuOption->Skip) {
- TopOfScreen = Link;
- } else {
- SkipValue = 0;
- TopOfScreen = Link->ForwardLink;
- }
- }
-
- Repaint = TRUE;
- NewLine = TRUE;
- ControlFlag = CfRepaint;
- break;
- }
- } else {
- //
- // Target Question not found, highlight the default menu option
- //
- NewPos = TopOfScreen;
- }
-
- Selection->QuestionId = 0;
- }
-
- if (NewPos != NULL && (MenuOption == NULL || NewPos != &MenuOption->Link)) {
- if (MenuOption != NULL) {
- //
- // Remove highlight on last Menu Option
- //
- gST->ConOut->SetCursorPosition (gST->ConOut, MenuOption->Col, MenuOption->Row);
- ProcessOptions (Selection, MenuOption, FALSE, &OptionString);
- gST->ConOut->SetAttribute (gST->ConOut, PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND);
- if (OptionString != NULL) {
- if ((MenuOption->ThisTag->Operand == EFI_IFR_DATE_OP) ||
- (MenuOption->ThisTag->Operand == EFI_IFR_TIME_OP)
- ) {
- ProcessStringForDateTime(MenuOption, OptionString, FALSE);
- }
-
- Width = (UINT16) gOptionBlockWidth;
- OriginalRow = MenuOption->Row;
- GlyphWidth = 1;
-
- for (Index = 0; GetLineByWidth (OptionString, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {
- if ((Temp == 0) && (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]) != 0) {
- if (Temp == 0) {
- MenuOption->Row++;
- }
- }
-
- FreePool (OutputString);
- if (Temp != 0) {
- Temp--;
- }
- }
-
- MenuOption->Row = OriginalRow;
-
- FreePool (OptionString);
- } else {
- if (NewLine) {
- if (MenuOption->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, PcdGet8 (PcdBrowserSubtitleTextColor) | FIELD_BACKGROUND);
- }
-
- OriginalRow = MenuOption->Row;
- Width = GetWidth (MenuOption->ThisTag, MenuOption->Handle);
- GlyphWidth = 1;
-
- for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {
- if ((Temp == 0) && (MenuOption->Row >= TopRow) && (MenuOption->Row <= BottomRow)) {
- PrintStringAt (MenuOption->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]) != 0) {
- if (Temp == 0) {
- MenuOption->Row++;
- }
- }
-
- FreePool (OutputString);
- if (Temp != 0) {
- Temp--;
- }
- }
-
- MenuOption->Row = OriginalRow;
- gST->ConOut->SetAttribute (gST->ConOut, PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND);
- }
- }
- }
-
- //
- // This is the current selected statement
- //
- MenuOption = MENU_OPTION_FROM_LINK (NewPos);
- Statement = MenuOption->ThisTag;
- Selection->Statement = Statement;
- if (!IsSelectable (MenuOption)) {
- Repaint = SavedValue;
- UpdateKeyHelp (Selection, MenuOption, FALSE);
- break;
- }
-
- //
- // Record highlight for current menu
- //
- CurrentMenu->QuestionId = Statement->QuestionId;
- CurrentMenu->Sequence = MenuOption->Sequence;
-
- //
- // Set reverse attribute
- //
- gST->ConOut->SetAttribute (gST->ConOut, PcdGet8 (PcdBrowserFieldTextHighlightColor) | PcdGet8 (PcdBrowserFieldBackgroundHighlightColor));
- 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) {
- if (MenuRefreshEntry->MenuOption->GrayOut) {
- MenuRefreshEntry->CurrentAttribute = FIELD_TEXT_GRAYED | FIELD_BACKGROUND;
- } else {
- MenuRefreshEntry->CurrentAttribute = PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND;
- }
- if (MenuRefreshEntry->MenuOption == MenuOption) {
- MenuRefreshEntry->CurrentAttribute = PcdGet8 (PcdBrowserFieldTextHighlightColor) | PcdGet8 (PcdBrowserFieldBackgroundHighlightColor);
- }
- }
- }
-
- ProcessOptions (Selection, MenuOption, FALSE, &OptionString);
- if (OptionString != NULL) {
- if (Statement->Operand == EFI_IFR_DATE_OP || Statement->Operand == EFI_IFR_TIME_OP) {
- ProcessStringForDateTime(MenuOption, OptionString, FALSE);
- }
- Width = (UINT16) gOptionBlockWidth;
-
- OriginalRow = MenuOption->Row;
- GlyphWidth = 1;
-
- for (Index = 0; GetLineByWidth (OptionString, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {
- if ((Temp2 == 0) && (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]) != 0) {
- if (Temp2 == 0) {
- MenuOption->Row++;
- }
- }
-
- FreePool (OutputString);
- if (Temp2 != 0) {
- Temp2--;
- }
- }
-
- MenuOption->Row = OriginalRow;
-
- FreePool (OptionString);
- } else {
- if (NewLine) {
- OriginalRow = MenuOption->Row;
-
- Width = GetWidth (Statement, MenuOption->Handle);
- GlyphWidth = 1;
-
- for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &GlyphWidth, &Index, &OutputString) != 0x0000;) {
- if ((Temp2 == 0) && (MenuOption->Row >= TopRow) && (MenuOption->Row <= BottomRow) ) {
- PrintStringAt (MenuOption->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]) != 0) {
- if (Temp2 == 0) {
- MenuOption->Row++;
- }
- }
-
- FreePool (OutputString);
- if (Temp2 != 0) {
- Temp2--;
- }
- }
-
- MenuOption->Row = OriginalRow;
-
- }
- }
-
- UpdateKeyHelp (Selection, MenuOption, FALSE);
-
- //
- // Clear reverse attribute
- //
- gST->ConOut->SetAttribute (gST->ConOut, PcdGet8 (PcdBrowserFieldTextColor) | 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 (Selection->Form->ModalForm) {
- break;
- }
-
- if (Repaint || NewLine) {
- //
- // Don't print anything if it is a NULL help token
- //
- ASSERT(MenuOption != NULL);
- if (MenuOption->ThisTag->Help == 0 || !IsSelectable (MenuOption)) {
- StringPtr = L"\0";
- } else {
- StringPtr = GetToken (MenuOption->ThisTag->Help, MenuOption->Handle);
- }
-
- RowCount = BottomRow - TopRow;
- HelpPageIndex = 0;
- //
- // 1.Calculate how many line the help string need to print.
- //
- if (HelpString != NULL) {
- FreePool (HelpString);
- }
- HelpLine = ProcessHelpString (StringPtr, &HelpString, &EachLineWidth, RowCount);
- if (HelpLine > RowCount) {
- MultiHelpPage = TRUE;
- StringPtr = GetToken (STRING_TOKEN(ADJUST_HELP_PAGE_UP), gHiiHandle);
- if (HelpHeaderString != NULL) {
- FreePool (HelpHeaderString);
- }
- HelpHeaderLine = ProcessHelpString (StringPtr, &HelpHeaderString, &HeaderLineWidth, RowCount);
- StringPtr = GetToken (STRING_TOKEN(ADJUST_HELP_PAGE_DOWN), gHiiHandle);
- if (HelpBottomString != NULL) {
- FreePool (HelpBottomString);
- }
- HelpBottomLine = ProcessHelpString (StringPtr, &HelpBottomString, &BottomLineWidth, RowCount);
- //
- // Calculate the help page count.
- //
- if (HelpLine > 2 * RowCount - 2) {
- HelpPageCount = (HelpLine - RowCount + 1) / (RowCount - 2) + 1;
- if ((HelpLine - RowCount + 1) % (RowCount - 2) > 1) {
- HelpPageCount += 1;
- }
- } else {
- HelpPageCount = 2;
- }
- } else {
- MultiHelpPage = FALSE;
- }
- }
-
- //
- // Clean the help field first.
- //
- ClearLines (
- LocalScreen.RightColumn - gHelpBlockWidth,
- LocalScreen.RightColumn,
- TopRow,
- BottomRow,
- PcdGet8 (PcdBrowserFieldTextColor) | FIELD_BACKGROUND
- );
-
- //
- // Check whether need to show the 'More(U/u)' at the begin.
- // Base on current direct info, here shows aligned to the right side of the column.
- // If the direction is multi line and aligned to right side may have problem, so
- // add ASSERT code here.
- //
- if (HelpPageIndex > 0) {
- gST->ConOut->SetAttribute (gST->ConOut, INFO_TEXT | FIELD_BACKGROUND);
- for (Index = 0; Index < HelpHeaderLine; Index++) {
- ASSERT (HelpHeaderLine == 1);
- ASSERT (GetStringWidth (HelpHeaderString) / 2 < (UINTN) (gHelpBlockWidth - 1));
- PrintStringAt (
- LocalScreen.RightColumn - GetStringWidth (HelpHeaderString) / 2 - 1,
- Index + TopRow,
- &HelpHeaderString[Index * HeaderLineWidth]
- );
- }
- }
-
- gST->ConOut->SetAttribute (gST->ConOut, HELP_TEXT | FIELD_BACKGROUND);
- //
- // Print the help string info.
- //
- if (!MultiHelpPage) {
- for (Index = 0; Index < HelpLine; Index++) {
- PrintStringAt (
- LocalScreen.RightColumn - gHelpBlockWidth,
- Index + TopRow,
- &HelpString[Index * EachLineWidth]
- );
- }
- gST->ConOut->SetCursorPosition(gST->ConOut, LocalScreen.RightColumn-1, BottomRow);
- } else {
- if (HelpPageIndex == 0) {
- for (Index = 0; Index < RowCount - HelpBottomLine; Index++) {
- PrintStringAt (
- LocalScreen.RightColumn - gHelpBlockWidth,
- Index + TopRow,
- &HelpString[Index * EachLineWidth]
- );
- }
- } else {
- for (Index = 0; (Index < RowCount - HelpBottomLine - HelpHeaderLine) &&
- (Index + HelpPageIndex * (RowCount - 2) + 1 < HelpLine); Index++) {
- PrintStringAt (
- LocalScreen.RightColumn - gHelpBlockWidth,
- Index + TopRow + HelpHeaderLine,
- &HelpString[(Index + HelpPageIndex * (RowCount - 2) + 1)* EachLineWidth]
- );
- }
- if (HelpPageIndex == HelpPageCount - 1) {
- gST->ConOut->SetCursorPosition(gST->ConOut, LocalScreen.RightColumn-1, BottomRow);
- }
- }
- }
-
- //
- // Check whether need to print the 'More(D/d)' at the bottom.
- // Base on current direct info, here shows aligned to the right side of the column.
- // If the direction is multi line and aligned to right side may have problem, so
- // add ASSERT code here.
- //
- if (HelpPageIndex < HelpPageCount - 1 && MultiHelpPage) {
- gST->ConOut->SetAttribute (gST->ConOut, INFO_TEXT | FIELD_BACKGROUND);
- for (Index = 0; Index < HelpBottomLine; Index++) {
- ASSERT (HelpBottomLine == 1);
- ASSERT (GetStringWidth (HelpBottomString) / 2 < (UINTN) (gHelpBlockWidth - 1));
- PrintStringAt (
- LocalScreen.RightColumn - GetStringWidth (HelpBottomString) / 2 - 1,
- Index + BottomRow - HelpBottomLine,
- &HelpBottomString[Index * BottomLineWidth]
- );
- }
- }
- //
- // Reset this flag every time we finish using it.
- //
- Repaint = FALSE;
- NewLine = FALSE;
- break;
-
- case CfPrepareToReadKey:
- ControlFlag = CfReadKey;
- ScreenOperation = UiNoOperation;
- break;
-
- case CfReadKey:
- ControlFlag = CfScreenOperation;
-
- //
- // Wait for user's selection
- //
- while (TRUE) {
- Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
- if (!EFI_ERROR (Status)) {
- break;
- }
-
- //
- // If we encounter error, continue to read another key in.
- //
- if (Status != EFI_NOT_READY) {
- continue;
- }
-
- Status = UiWaitForSingleEvent (gST->ConIn->WaitForKey, 0, MinRefreshInterval);
- ASSERT_EFI_ERROR (Status);
-
- if (Selection->Action == UI_ACTION_REFRESH_FORMSET) {
- //
- // IFR is updated in Callback of refresh opcode, re-parse it
- //
- ControlFlag = CfCheckSelection;
- Selection->Statement = NULL;
- break;
- }
- }
-
- if (ControlFlag == CfCheckSelection) {
- break;
- }
-
- switch (Key.UnicodeChar) {
- case CHAR_CARRIAGE_RETURN:
- if(MenuOption->GrayOut || MenuOption->ReadOnly) {
- ControlFlag = CfReadKey;
- break;
- }
-
- ScreenOperation = UiSelect;
- gDirection = 0;
- break;
-
- //
- // We will push the adjustment of these numeric values directly to the input handler
- // NOTE: we won't handle manual input numeric
- //
- case '+':
- case '-':
- //
- // If the screen has no menu items, and the user didn't select UiReset
- // ignore the selection and go back to reading keys.
- //
- if(IsListEmpty (&gMenuOption) || MenuOption->GrayOut || MenuOption->ReadOnly) {
- ControlFlag = CfReadKey;
- break;
- }
-
- ASSERT(MenuOption != NULL);
- Statement = MenuOption->ThisTag;
- if ((Statement->Operand == EFI_IFR_DATE_OP)
- || (Statement->Operand == EFI_IFR_TIME_OP)
- || ((Statement->Operand == EFI_IFR_NUMERIC_OP) && (Statement->Step != 0))
- ){
- if (Key.UnicodeChar == '+') {
- gDirection = SCAN_RIGHT;
- } else {
- gDirection = SCAN_LEFT;
- }
- Status = ProcessOptions (Selection, MenuOption, TRUE, &OptionString);
- if (EFI_ERROR (Status)) {
- //
- // Repaint to clear possible error prompt pop-up
- //
- Repaint = TRUE;
- NewLine = TRUE;
- } else {
- Selection->Action = UI_ACTION_REFRESH_FORM;
- }
- if (OptionString != NULL) {
- FreePool (OptionString);
- }
- }
- break;
-
- case '^':
- ScreenOperation = UiUp;
- break;
-
- case 'V':
- case 'v':
- ScreenOperation = UiDown;
- break;
-
- case ' ':
- if ((gClassOfVfr & FORMSET_CLASS_FRONT_PAGE) != FORMSET_CLASS_FRONT_PAGE) {
- //
- // If the screen has no menu items, and the user didn't select UiReset
- // ignore the selection and go back to reading keys.
- //
- if(IsListEmpty (&gMenuOption)) {
- ControlFlag = CfReadKey;
- break;
- }
-
- ASSERT(MenuOption != NULL);
- if (MenuOption->ThisTag->Operand == EFI_IFR_CHECKBOX_OP && !MenuOption->GrayOut && !MenuOption->ReadOnly) {
- ScreenOperation = UiSelect;
- }
- }
- break;
-
- case 'D':
- case 'd':
- if (!MultiHelpPage) {
- ControlFlag = CfReadKey;
- break;
- }
- ControlFlag = CfUpdateHelpString;
- HelpPageIndex = HelpPageIndex < HelpPageCount - 1 ? HelpPageIndex + 1 : HelpPageCount - 1;
- break;
-
- case 'U':
- case 'u':
- if (!MultiHelpPage) {
- ControlFlag = CfReadKey;
- break;
- }
- ControlFlag = CfUpdateHelpString;
- HelpPageIndex = HelpPageIndex > 0 ? HelpPageIndex - 1 : 0;
- break;
-
- case CHAR_NULL:
- for (Index = 0; Index < mScanCodeNumber; Index++) {
- if (Key.ScanCode == gScanCodeToOperation[Index].ScanCode) {
- ScreenOperation = gScanCodeToOperation[Index].ScreenOperation;
- break;
- }
- }
-
- if (Selection->Form->ModalForm && (Key.ScanCode == SCAN_ESC || Index == mScanCodeNumber)) {
- //
- // ModalForm has no ESC key and Hot Key.
- //
- ControlFlag = CfReadKey;
- } else if (Index == mScanCodeNumber) {
- //
- // Check whether Key matches the registered hot key.
- //
- HotKey = NULL;
- if ((gBrowserSettingScope == SystemLevel) ||
- (Selection->FormEditable && gFunctionKeySetting != NONE_FUNCTION_KEY_SETTING)) {
- HotKey = GetHotKeyFromRegisterList (&Key);
- }
- if (HotKey != NULL) {
- ScreenOperation = UiHotKey;
- }
- }
- break;
- }
- break;
-
- case CfScreenOperation:
- if (ScreenOperation != UiReset) {
- //
- // If the screen has no menu items, and the user didn't select UiReset
- // ignore the selection and go back to reading keys.
- //
- if (IsListEmpty (&gMenuOption)) {
- ControlFlag = CfReadKey;
- break;
- }
- }
-
- for (Index = 0;
- Index < sizeof (gScreenOperationToControlFlag) / sizeof (gScreenOperationToControlFlag[0]);
- Index++
- ) {
- if (ScreenOperation == gScreenOperationToControlFlag[Index].ScreenOperation) {
- ControlFlag = gScreenOperationToControlFlag[Index].ControlFlag;
- break;
- }
- }
- break;
-
- case CfUiSelect:
- ControlFlag = CfCheckSelection;
-
- ASSERT(MenuOption != NULL);
- Statement = MenuOption->ThisTag;
- if (Statement->Operand == EFI_IFR_TEXT_OP) {
- break;
- }
-
- //
- // Keep highlight on current MenuOption
- //
- Selection->QuestionId = Statement->QuestionId;
-
- switch (Statement->Operand) {
- case EFI_IFR_REF_OP:
- ProcessGotoOpCode(Statement, Selection, &Repaint, &NewLine);
- break;
-
- case EFI_IFR_ACTION_OP:
- //
- // Process the Config string <ConfigResp>
- //
- Status = ProcessQuestionConfig (Selection, Statement);
-
- if (EFI_ERROR (Status)) {
- break;
- }
-
- //
- // The action button may change some Question value, so refresh the form
- //
- Selection->Action = UI_ACTION_REFRESH_FORM;
- break;
-
- case EFI_IFR_RESET_BUTTON_OP:
- //
- // Reset Question to default value specified by DefaultId
- //
- ControlFlag = CfUiDefault;
- DefaultId = Statement->DefaultId;
- break;
-
- default:
- //
- // Editable Questions: oneof, ordered list, checkbox, numeric, string, password
- //
- UpdateKeyHelp (Selection, MenuOption, TRUE);
- Status = ProcessOptions (Selection, MenuOption, TRUE, &OptionString);
-
- if (EFI_ERROR (Status)) {
- Repaint = TRUE;
- NewLine = TRUE;
- UpdateKeyHelp (Selection, MenuOption, FALSE);
- } else {
- Selection->Action = UI_ACTION_REFRESH_FORM;
- }
-
- if (OptionString != NULL) {
- FreePool (OptionString);
- }
- break;
- }
- break;
-
- case CfUiReset:
- //
- // We come here when someone press ESC
- //
- ControlFlag = CfCheckSelection;
- FindNextMenu (Selection, &Repaint, &NewLine);
- break;
-
- case CfUiLeft:
- ControlFlag = CfCheckSelection;
- ASSERT(MenuOption != NULL);
- if ((MenuOption->ThisTag->Operand == EFI_IFR_DATE_OP) || (MenuOption->ThisTag->Operand == EFI_IFR_TIME_OP)) {
- if (MenuOption->Sequence != 0) {
- //
- // In the middle or tail of the Date/Time op-code set, go left.
- //
- ASSERT(NewPos != NULL);
- NewPos = NewPos->BackLink;
- }
- }
- break;
-
- case CfUiRight:
- ControlFlag = CfCheckSelection;
- ASSERT(MenuOption != NULL);
- if ((MenuOption->ThisTag->Operand == EFI_IFR_DATE_OP) || (MenuOption->ThisTag->Operand == EFI_IFR_TIME_OP)) {
- if (MenuOption->Sequence != 2) {
- //
- // In the middle or tail of the Date/Time op-code set, go left.
- //
- ASSERT(NewPos != NULL);
- NewPos = NewPos->ForwardLink;
- }
- }
- break;
-
- case CfUiUp:
- ControlFlag = CfCheckSelection;
-
- SavedListEntry = NewPos;
-
- ASSERT(NewPos != NULL);
- //
- // Adjust Date/Time position before we advance forward.
- //
- AdjustDateAndTimePosition (TRUE, &NewPos);
- if (NewPos->BackLink != &gMenuOption) {
- MenuOption = MENU_OPTION_FROM_LINK (NewPos);
- ASSERT (MenuOption != NULL);
- NewLine = TRUE;
- NewPos = NewPos->BackLink;
-
- PreviousMenuOption = MENU_OPTION_FROM_LINK (NewPos);
- if (PreviousMenuOption->Row == 0) {
- UpdateOptionSkipLines (Selection, PreviousMenuOption);
- }
- DistanceValue = PreviousMenuOption->Skip;
- Difference = 0;
- if (MenuOption->Row >= DistanceValue + TopRow) {
- Difference = MoveToNextStatement (Selection, TRUE, &NewPos, MenuOption->Row - TopRow - DistanceValue);
- }
- NextMenuOption = MENU_OPTION_FROM_LINK (NewPos);
-
- if (Difference < 0) {
- //
- // We hit the begining MenuOption that can be focused
- // so we simply scroll to the top.
- //
- if (TopOfScreen != gMenuOption.ForwardLink) {
- TopOfScreen = gMenuOption.ForwardLink;
- Repaint = TRUE;
- } else {
- //
- // Scroll up to the last page when we have arrived at top page.
- //
- NewPos = &gMenuOption;
- TopOfScreen = &gMenuOption;
- MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry);
- ScreenOperation = UiPageUp;
- ControlFlag = CfScreenOperation;
- break;
- }
- } else if (MenuOption->Row < TopRow + DistanceValue + Difference) {
- //
- // Previous focus MenuOption is above the TopOfScreen, so we need to scroll
- //
- TopOfScreen = NewPos;
- Repaint = TRUE;
- SkipValue = 0;
- } else if (!IsSelectable (NextMenuOption)) {
- //
- // Continue to go up until scroll to next page or the selectable option is found.
- //
- ScreenOperation = UiUp;
- ControlFlag = CfScreenOperation;
- }
-
- //
- // If we encounter a Date/Time op-code set, rewind to the first op-code of the set.
- //
- AdjustDateAndTimePosition (TRUE, &TopOfScreen);
- AdjustDateAndTimePosition (TRUE, &NewPos);
- MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry);
- UpdateStatusBar (Selection, INPUT_ERROR, MenuOption->ThisTag->QuestionFlags, FALSE);
- } else {
- //
- // Scroll up to the last page.
- //
- NewPos = &gMenuOption;
- TopOfScreen = &gMenuOption;
- MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry);
- ScreenOperation = UiPageUp;
- ControlFlag = CfScreenOperation;
- }
- break;
-
- case CfUiPageUp:
- //
- // SkipValue means lines is skipped when show the top menu option.
- //
- ControlFlag = CfCheckSelection;
-
- ASSERT(NewPos != NULL);
- //
- // Already at the first menu option, so do nothing.
- //
- if (NewPos->BackLink == &gMenuOption) {
- NewLine = FALSE;
- Repaint = FALSE;
- break;
- }
-
- NewLine = TRUE;
- Repaint = TRUE;
-
- //
- // SkipValue > (BottomRow - TopRow + 1) means current menu has more than one
- // form of options to be show, so just update the SkipValue to show the next
- // parts of options.
- //
- if (SkipValue > (INTN) (BottomRow - TopRow + 1)) {
- SkipValue -= BottomRow - TopRow + 1;
- break;
- }
-
- Link = TopOfScreen;
- //
- // First minus the menu of the top screen, it's value is SkipValue.
- //
- Index = (BottomRow + 1) - SkipValue;
- while ((Index >= TopRow) && (Link->BackLink != &gMenuOption)) {
- Link = Link->BackLink;
- PreviousMenuOption = MENU_OPTION_FROM_LINK (Link);
- if (PreviousMenuOption->Row == 0) {
- UpdateOptionSkipLines (Selection, PreviousMenuOption);
- }
- if (Index < PreviousMenuOption->Skip) {
- break;
- }
- Index = Index - PreviousMenuOption->Skip;
- }
-
- if ((Link->BackLink == &gMenuOption) && (Index >= TopRow)) {
- SkipValue = 0;
- if (TopOfScreen == &gMenuOption) {
- TopOfScreen = gMenuOption.ForwardLink;
- NewPos = gMenuOption.BackLink;
- MoveToNextStatement (Selection, TRUE, &NewPos, BottomRow - TopRow);
- Repaint = FALSE;
- } else if (TopOfScreen != Link) {
- TopOfScreen = Link;
- NewPos = Link;
- MoveToNextStatement (Selection, FALSE, &NewPos, BottomRow - TopRow);
- } else {
- //
- // Finally we know that NewPos is the last MenuOption can be focused.
- //
- Repaint = FALSE;
- NewPos = Link;
- MoveToNextStatement (Selection, FALSE, &NewPos, BottomRow - TopRow);
- }
- } else {
- if (Index >= TopRow) {
- //
- // At here, only case "Index < PreviousMenuOption->Skip" can reach here.
- //
- SkipValue = PreviousMenuOption->Skip - (Index - TopRow);
- } else {
- SkipValue = PreviousMenuOption->Skip - (TopRow - Index);
- Link = Link->ForwardLink;
- }
-
- //
- // Move to the option in Next page.
- //
- if (TopOfScreen == &gMenuOption) {
- NewPos = gMenuOption.BackLink;
- MoveToNextStatement (Selection, TRUE, &NewPos, BottomRow - TopRow);
- } else {
- NewPos = Link;
- MoveToNextStatement (Selection, FALSE, &NewPos, BottomRow - TopRow);
- }
-
- //
- // There are more MenuOption needing scrolling up.
- //
- TopOfScreen = Link;
- MenuOption = NULL;
- }
-
- //
- // 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.
- //
- AdjustDateAndTimePosition (TRUE, &TopOfScreen);
- AdjustDateAndTimePosition (TRUE, &NewPos);
- break;
-
- case CfUiPageDown:
- //
- // SkipValue means lines is skipped when show the top menu option.
- //
- ControlFlag = CfCheckSelection;
-
- ASSERT (NewPos != NULL);
- if (NewPos->ForwardLink == &gMenuOption) {
- NewLine = FALSE;
- Repaint = FALSE;
- break;
- }
-
- NewLine = TRUE;
- Repaint = TRUE;
- Link = TopOfScreen;
- NextMenuOption = MENU_OPTION_FROM_LINK (Link);
- Index = TopRow + NextMenuOption->Skip - SkipValue;
- //
- // Count to the menu option which will show at the top of the next form.
- //
- while ((Index <= BottomRow + 1) && (Link->ForwardLink != &gMenuOption)) {
- Link = Link->ForwardLink;
- NextMenuOption = MENU_OPTION_FROM_LINK (Link);
- Index = Index + NextMenuOption->Skip;
- }
-
- if ((Link->ForwardLink == &gMenuOption) && (Index <= BottomRow + 1)) {
- //
- // Finally we know that NewPos is the last MenuOption can be focused.
- //
- Repaint = FALSE;
- MoveToNextStatement (Selection, TRUE, &Link, Index - TopRow);
- SkipValue = 0;
- } else {
- //
- // Calculate the skip line for top of screen menu.
- //
- if (Link == TopOfScreen) {
- //
- // The top of screen menu option occupies the entire form.
- //
- SkipValue += BottomRow - TopRow + 1;
- } else {
- SkipValue = NextMenuOption->Skip - (Index - (BottomRow + 1));
- }
-
- TopOfScreen = Link;
- MenuOption = NULL;
- //
- // Move to the Next selectable menu.
- //
- MoveToNextStatement (Selection, FALSE, &Link, BottomRow - TopRow);
- }
-
- //
- // Save the menu as the next highlight menu.
- //
- 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 last page.
- //
- AdjustDateAndTimePosition (TRUE, &TopOfScreen);
- AdjustDateAndTimePosition (TRUE, &NewPos);
- break;
-
- case CfUiDown:
- //
- // SkipValue means lines is skipped when show the top menu option.
- // NewPos points to the menu which is highlighted now.
- //
- 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.
- //
- SavedListEntry = NewPos;
- AdjustDateAndTimePosition (FALSE, &NewPos);
-
- if (NewPos->ForwardLink != &gMenuOption) {
- MenuOption = MENU_OPTION_FROM_LINK (NewPos);
- NewLine = TRUE;
- NewPos = NewPos->ForwardLink;
-
- Difference = 0;
- //
- // Current menu not at the bottom of the form.
- //
- if (BottomRow >= MenuOption->Row + MenuOption->Skip) {
- //
- // Find the next selectable menu.
- //
- Difference = MoveToNextStatement (Selection, FALSE, &NewPos, BottomRow - MenuOption->Row - MenuOption->Skip);
- //
- // We hit the end of MenuOption that can be focused
- // so we simply scroll to the first page.
- //
- if (Difference < 0) {
- //
- // Scroll to the first page.
- //
- if (TopOfScreen != gMenuOption.ForwardLink) {
- TopOfScreen = gMenuOption.ForwardLink;
- Repaint = TRUE;
- MenuOption = NULL;
- } else {
- MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry);
- }
- NewPos = gMenuOption.ForwardLink;
- MoveToNextStatement (Selection, FALSE, &NewPos, BottomRow - TopRow);
-
- SkipValue = 0;
- //
- // If we are at the end of the list and sitting on a Date/Time op, rewind to the head.
- //
- AdjustDateAndTimePosition (TRUE, &TopOfScreen);
- AdjustDateAndTimePosition (TRUE, &NewPos);
- break;
- }
- }
- NextMenuOption = MENU_OPTION_FROM_LINK (NewPos);
- if (NextMenuOption->Row == 0) {
- UpdateOptionSkipLines (Selection, NextMenuOption);
- }
- DistanceValue = Difference + NextMenuOption->Skip;
-
- Temp = MenuOption->Row + MenuOption->Skip + DistanceValue - 1;
- if ((MenuOption->Row + MenuOption->Skip == BottomRow + 1) &&
- (NextMenuOption->ThisTag->Operand == EFI_IFR_DATE_OP ||
- NextMenuOption->ThisTag->Operand == EFI_IFR_TIME_OP)
- ) {
- Temp ++;
- }
-
- //
- // If we are going to scroll, update TopOfScreen
- //
- 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 = MENU_OPTION_FROM_LINK (TopOfScreen);
-
- //
- // If bottom op-code is more than one line or top op-code is more than one line
- //
- if ((DistanceValue > 1) || (SavedMenuOption->Skip > 1)) {
- //
- // Is the bottom op-code greater than or equal in size to the top op-code?
- //
- if ((Temp - BottomRow) >= (SavedMenuOption->Skip - SkipValue)) {
- //
- // Skip the top op-code
- //
- TopOfScreen = TopOfScreen->ForwardLink;
- Difference = (Temp - BottomRow) - (SavedMenuOption->Skip - SkipValue);
-
- SavedMenuOption = MENU_OPTION_FROM_LINK (TopOfScreen);
-
- //
- // If we have a remainder, skip that many more op-codes until we drain the remainder
- //
- while (Difference >= (INTN) SavedMenuOption->Skip) {
- //
- // Since the Difference is greater than or equal to this op-code's skip value, skip it
- //
- Difference = Difference - (INTN) SavedMenuOption->Skip;
- TopOfScreen = TopOfScreen->ForwardLink;
- SavedMenuOption = MENU_OPTION_FROM_LINK (TopOfScreen);
- }
- //
- // 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 += (Temp - BottomRow) - 1;
- }
- } else {
- if ((SkipValue + 1) == (INTN) SavedMenuOption->Skip) {
- TopOfScreen = TopOfScreen->ForwardLink;
- break;
- }
- }
- //
- // 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 if (SavedMenuOption->Skip == 1) {
- SkipValue = 0;
- } else {
- SkipValue = 0;
- TopOfScreen = TopOfScreen->ForwardLink;
- }
- } while (SavedMenuOption->Skip == 0);
-
- Repaint = TRUE;
- } else if (!IsSelectable (NextMenuOption)) {
- //
- // Continue to go down until scroll to next page or the selectable option is found.
- //
- ScreenOperation = UiDown;
- ControlFlag = CfScreenOperation;
- }
-
- MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry);
-
- UpdateStatusBar (Selection, INPUT_ERROR, MenuOption->ThisTag->QuestionFlags, FALSE);
-
- } else {
- //
- // Scroll to the first page.
- //
- if (TopOfScreen != gMenuOption.ForwardLink) {
- TopOfScreen = gMenuOption.ForwardLink;
- Repaint = TRUE;
- MenuOption = NULL;
- } else {
- //
- // Need to remove the current highlight menu.
- // MenuOption saved the last highlight menu info.
- //
- MenuOption = MENU_OPTION_FROM_LINK (SavedListEntry);
- }
-
- SkipValue = 0;
- NewLine = TRUE;
- //
- // Get the next highlight menu.
- //
- NewPos = gMenuOption.ForwardLink;
- MoveToNextStatement (Selection, FALSE, &NewPos, BottomRow - TopRow);
- }
-
- //
- // If we are at the end of the list and sitting on a Date/Time op, rewind to the head.
- //
- AdjustDateAndTimePosition (TRUE, &TopOfScreen);
- AdjustDateAndTimePosition (TRUE, &NewPos);
- break;
-
- case CfUiHotKey:
- ControlFlag = CfCheckSelection;
-
- Status = EFI_SUCCESS;
- //
- // Discard changes. After it, no NV flag is showed.
- //
- if ((HotKey->Action & BROWSER_ACTION_DISCARD) == BROWSER_ACTION_DISCARD) {
- Status = DiscardForm (Selection->FormSet, Selection->Form, gBrowserSettingScope);
- if (!EFI_ERROR (Status)) {
- Selection->Action = UI_ACTION_REFRESH_FORM;
- Selection->Statement = NULL;
- gResetRequired = FALSE;
- } else {
- do {
- CreateDialog (4, TRUE, 0, NULL, &Key, HotKey->HelpString, gDiscardFailed, gPressEnter, gEmptyString);
- } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
- //
- // Still show current page.
- //
- Selection->Action = UI_ACTION_NONE;
- Repaint = TRUE;
- NewLine = TRUE;
- break;
- }
- }
-
- //
- // Reterieve default setting. After it. NV flag will be showed.
- //
- if ((HotKey->Action & BROWSER_ACTION_DEFAULT) == BROWSER_ACTION_DEFAULT) {
- Status = ExtractDefault (Selection->FormSet, Selection->Form, HotKey->DefaultId, gBrowserSettingScope, GetDefaultForAll, NULL, FALSE);
- if (!EFI_ERROR (Status)) {
- Selection->Action = UI_ACTION_REFRESH_FORM;
- Selection->Statement = NULL;
- gResetRequired = TRUE;
- } else {
- do {
- CreateDialog (4, TRUE, 0, NULL, &Key, HotKey->HelpString, gDefaultFailed, gPressEnter, gEmptyString);
- } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
- //
- // Still show current page.
- //
- Selection->Action = UI_ACTION_NONE;
- Repaint = TRUE;
- NewLine = TRUE;
- break;
- }
- }
-
- //
- // Save changes. After it, no NV flag is showed.
- //
- if ((HotKey->Action & BROWSER_ACTION_SUBMIT) == BROWSER_ACTION_SUBMIT) {
- Status = SubmitForm (Selection->FormSet, Selection->Form, gBrowserSettingScope);
- if (!EFI_ERROR (Status)) {
- ASSERT(MenuOption != NULL);
- UpdateStatusBar (Selection, INPUT_ERROR, MenuOption->ThisTag->QuestionFlags, FALSE);
- UpdateStatusBar (Selection, NV_UPDATE_REQUIRED, MenuOption->ThisTag->QuestionFlags, FALSE);
- } else {
- do {
- CreateDialog (4, TRUE, 0, NULL, &Key, HotKey->HelpString, gSaveFailed, gPressEnter, gEmptyString);
- } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
- //
- // Still show current page.
- //
- Selection->Action = UI_ACTION_NONE;
- Repaint = TRUE;
- NewLine = TRUE;
- break;
- }
- }
-
- //
- // Set Reset required Flag
- //
- if ((HotKey->Action & BROWSER_ACTION_RESET) == BROWSER_ACTION_RESET) {
- gResetRequired = TRUE;
- }
-
- //
- // Exit Action
- //
- if ((HotKey->Action & BROWSER_ACTION_EXIT) == BROWSER_ACTION_EXIT) {
- //
- // Form Exit without saving, Similar to ESC Key.
- // FormSet Exit without saving, Exit SendForm.
- // System Exit without saving, CallExitHandler and Exit SendForm.
- //
- DiscardForm (Selection->FormSet, Selection->Form, gBrowserSettingScope);
- if (gBrowserSettingScope == FormLevel) {
- ControlFlag = CfUiReset;
- } else if (gBrowserSettingScope == FormSetLevel) {
- Selection->Action = UI_ACTION_EXIT;
- } else if (gBrowserSettingScope == SystemLevel) {
- if (ExitHandlerFunction != NULL) {
- ExitHandlerFunction ();
- }
- Selection->Action = UI_ACTION_EXIT;
- }
- Selection->Statement = NULL;
- }
- break;
-
- case CfUiDefault:
- ControlFlag = CfCheckSelection;
- //
- // Reset to default value for all forms in the whole system.
- //
- Status = ExtractDefault (Selection->FormSet, NULL, DefaultId, FormSetLevel, GetDefaultForAll, NULL, FALSE);
-
- if (!EFI_ERROR (Status)) {
- Selection->Action = UI_ACTION_REFRESH_FORM;
- Selection->Statement = NULL;
- gResetRequired = TRUE;
- }
- break;
-
- case CfUiNoOperation:
- ControlFlag = CfCheckSelection;
- break;
-
- case CfExit:
- UiFreeRefreshList ();
-
- gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));
- gST->ConOut->SetCursorPosition (gST->ConOut, 0, Row + 4);
- gST->ConOut->EnableCursor (gST->ConOut, TRUE);
- gST->ConOut->OutputString (gST->ConOut, L"\n");
- if (HelpString != NULL) {
- FreePool (HelpString);
- }
- if (HelpHeaderString != NULL) {
- FreePool (HelpHeaderString);
- }
- if (HelpBottomString != NULL) {
- FreePool (HelpBottomString);
- }
-
- return EFI_SUCCESS;
-
- default:
- break;
- }
- }
-}
diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/Ui.h b/MdeModulePkg/Universal/SetupBrowserDxe/Ui.h
deleted file mode 100644
index 03cb0cd75..000000000
--- a/MdeModulePkg/Universal/SetupBrowserDxe/Ui.h
+++ /dev/null
@@ -1,1067 +0,0 @@
-/** @file
-Private structure, MACRO and function definitions for User Interface related functionalities.
-
-Copyright (c) 2004 - 2013, Intel Corporation. All rights reserved.<BR>
-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 _UI_H_
-#define _UI_H_
-
-//
-// Globals
-//
-#define REGULAR_NUMERIC 0
-#define TIME_NUMERIC 1
-#define DATE_NUMERIC 2
-
-#define SUBTITLE_INDENT 2
-
-
-//
-// It take 23 characters including the NULL to print a 64 bits number with "[" and "]".
-// pow(2, 64) = [18446744073709551616]
-//
-#define MAX_NUMERIC_INPUT_WIDTH 23
-
-typedef enum {
- UiNoOperation,
- UiSelect,
- UiUp,
- UiDown,
- UiLeft,
- UiRight,
- UiReset,
- UiPrevious,
- UiPageUp,
- UiPageDown,
- UiHotKey,
- UiMaxOperation
-} UI_SCREEN_OPERATION;
-
-typedef enum {
- CfInitialization,
- CfCheckSelection,
- CfRepaint,
- CfRefreshHighLight,
- CfUpdateHelpString,
- CfPrepareToReadKey,
- CfReadKey,
- CfScreenOperation,
- CfUiSelect,
- CfUiReset,
- CfUiLeft,
- CfUiRight,
- CfUiUp,
- CfUiPageUp,
- CfUiPageDown,
- CfUiDown,
- CfUiDefault,
- CfUiNoOperation,
- CfExit,
- CfUiHotKey,
- CfMaxControlFlag
-} UI_CONTROL_FLAG;
-
-#define UI_ACTION_NONE 0
-#define UI_ACTION_REFRESH_FORM 1
-#define UI_ACTION_REFRESH_FORMSET 2
-#define UI_ACTION_EXIT 3
-
-typedef struct _UI_MENU_LIST UI_MENU_LIST;
-
-typedef struct {
- EFI_HII_HANDLE Handle;
-
- //
- // Target formset/form/Question information
- //
- EFI_GUID FormSetGuid;
- UINT16 FormId;
- UINT16 QuestionId;
- UINTN Sequence; // used for time/date only.
-
- UINTN TopRow;
- UINTN BottomRow;
- UINTN PromptCol;
- UINTN OptionCol;
- UINTN CurrentRow;
-
- //
- // Ation for Browser to taken:
- // UI_ACTION_NONE - navigation inside a form
- // UI_ACTION_REFRESH_FORM - re-evaluate expressions and repaint form
- // UI_ACTION_REFRESH_FORMSET - re-parse formset IFR binary
- //
- UINTN Action;
-
- //
- // Current selected fomset/form/Question
- //
- FORM_BROWSER_FORMSET *FormSet;
- FORM_BROWSER_FORM *Form;
- FORM_BROWSER_STATEMENT *Statement;
-
- //
- // Whether the Form is editable
- //
- BOOLEAN FormEditable;
-
- UI_MENU_LIST *CurrentMenu;
-} UI_MENU_SELECTION;
-
-#define UI_MENU_OPTION_SIGNATURE SIGNATURE_32 ('u', 'i', 'm', 'm')
-#define UI_MENU_LIST_SIGNATURE SIGNATURE_32 ('u', 'i', 'm', 'l')
-
-typedef struct {
- UINTN Signature;
- LIST_ENTRY Link;
-
- EFI_HII_HANDLE Handle;
- FORM_BROWSER_STATEMENT *ThisTag;
- UINT16 EntryNumber;
-
- UINTN Row;
- UINTN Col;
- UINTN OptCol;
- CHAR16 *Description;
- UINTN Skip; // Number of lines
-
- //
- // Display item sequence for date/time
- // Date: Month/Day/Year
- // Sequence: 0 1 2
- //
- // Time: Hour : Minute : Second
- // Sequence: 0 1 2
- //
- //
- UINTN Sequence;
-
- BOOLEAN GrayOut;
- BOOLEAN ReadOnly;
-
- //
- // Whether user could change value of this item
- //
- BOOLEAN IsQuestion;
-} UI_MENU_OPTION;
-
-#define MENU_OPTION_FROM_LINK(a) CR (a, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE)
-
-struct _UI_MENU_LIST {
- UINTN Signature;
- LIST_ENTRY Link;
-
- EFI_HII_HANDLE HiiHandle;
- EFI_GUID FormSetGuid;
- UINT16 FormId;
- UINT16 QuestionId;
- UINTN Sequence; // used for time/date only.
-
- UI_MENU_LIST *Parent;
- LIST_ENTRY ChildListHead;
-};
-
-#define UI_MENU_LIST_FROM_LINK(a) CR (a, UI_MENU_LIST, Link, UI_MENU_LIST_SIGNATURE)
-
-typedef struct _MENU_REFRESH_ENTRY MENU_REFRESH_ENTRY;
-struct _MENU_REFRESH_ENTRY {
- MENU_REFRESH_ENTRY *Next;
- UI_MENU_OPTION *MenuOption; // Describes the entry needing an update
- UI_MENU_SELECTION *Selection;
- UINTN CurrentColumn;
- UINTN CurrentRow;
- UINTN CurrentAttribute;
- EFI_EVENT Event;
-};
-
-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;
-
-
-extern LIST_ENTRY gMenuOption;
-extern LIST_ENTRY gMenuList;
-extern MENU_REFRESH_ENTRY *gMenuRefreshHead;
-extern UI_MENU_SELECTION *gCurrentSelection;
-extern BOOLEAN mHiiPackageListUpdated;
-
-//
-// Global Functions
-//
-/**
- Initialize Menu option list.
-
-**/
-VOID
-UiInitMenu (
- VOID
- );
-
-/**
- Initialize Menu option list.
-
-**/
-VOID
-UiInitMenuList (
- VOID
- );
-
-/**
- Free Menu option linked list.
-
-**/
-VOID
-UiFreeMenu (
- VOID
- );
-
-/**
- Create a menu with specified formset GUID and form ID, and add it as a child
- of the given parent menu.
-
- @param Parent The parent of menu to be added.
- @param HiiHandle Hii handle related to this formset.
- @param FormSetGuid The Formset Guid of menu to be added.
- @param FormId The Form ID of menu to be added.
-
- @return A pointer to the newly added menu or NULL if memory is insufficient.
-
-**/
-UI_MENU_LIST *
-UiAddMenuList (
- IN OUT UI_MENU_LIST *Parent,
- IN EFI_HII_HANDLE HiiHandle,
- IN EFI_GUID *FormSetGuid,
- IN UINT16 FormId
- );
-
-/**
- Search Menu with given FormId, FormSetGuid and Handle in all cached menu list.
-
- @param Parent The parent of menu to search.
- @param Handle Hii handle related to this formset.
- @param FormSetGuid The Formset GUID of the menu to search.
- @param FormId The Form ID of menu to search.
-
- @return A pointer to menu found or NULL if not found.
-
-**/
-UI_MENU_LIST *
-UiFindChildMenuList (
- IN UI_MENU_LIST *Parent,
- IN EFI_HII_HANDLE Handle,
- IN EFI_GUID *FormSetGuid,
- IN UINT16 FormId
- );
-
-/**
- Search Menu with given Handle, FormSetGuid and FormId in all cached menu list.
-
- @param Handle Hii handle related to this formset.
- @param FormSetGuid The Formset GUID of the menu to search.
- @param FormId The Form ID of menu to search.
-
- @return A pointer to menu found or NULL if not found.
-
-**/
-UI_MENU_LIST *
-UiFindMenuList (
- IN EFI_HII_HANDLE Handle,
- IN EFI_GUID *FormSetGuid,
- IN UINT16 FormId
- );
-
-/**
- Free Menu list linked list.
-
- @param MenuListHead One Menu list point in the menu list.
-
-**/
-VOID
-UiFreeMenuList (
- LIST_ENTRY *MenuListHead
- );
-
-/**
- Free Menu option linked list.
-
-**/
-VOID
-UiFreeRefreshList (
- VOID
- );
-
-/**
- Add one menu option by specified description and context.
-
- @param String String description for this option.
- @param Handle Hii handle for the package list.
- @param Form The form this statement belong to.
- @param Statement Statement of this Menu Option.
- @param NumberOfLines Display lines for this Menu Option.
- @param MenuItemCount The index for this Option in the Menu.
-
- @retval Pointer Pointer to the added Menu Option.
-
-**/
-UI_MENU_OPTION *
-UiAddMenuOption (
- IN CHAR16 *String,
- IN EFI_HII_HANDLE Handle,
- IN FORM_BROWSER_FORM *Form,
- IN FORM_BROWSER_STATEMENT *Statement,
- IN UINT16 NumberOfLines,
- IN UINT16 MenuItemCount
- );
-
-/**
- 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.
-
- @param Selection Menu selection.
-
- @return Return the pointer of the menu which selected,
- @return otherwise return NULL.
-
-**/
-EFI_STATUS
-UiDisplayMenu (
- IN OUT UI_MENU_SELECTION *Selection
- );
-
-/**
- Free up the resource allocated for all strings required
- by Setup Browser.
-
-**/
-VOID
-FreeBrowserStrings (
- VOID
- );
-
-/**
- Process the goto op code, update the info in the selection structure.
-
- @param Statement The statement belong to goto op code.
- @param Selection The selection info.
- @param Repaint Whether need to repaint the menu.
- @param NewLine Whether need to create new line.
-
- @retval EFI_SUCCESS The menu process successfully.
- @return Other value if the process failed.
-**/
-EFI_STATUS
-ProcessGotoOpCode (
- IN OUT FORM_BROWSER_STATEMENT *Statement,
- IN OUT UI_MENU_SELECTION *Selection,
- OUT BOOLEAN *Repaint,
- OUT BOOLEAN *NewLine
- );
-
-
-/**
- The worker function that send the displays to the screen. On output,
- the selection made by user is returned.
-
- @param Selection On input, Selection tell setup browser the information
- about the Selection, form and formset to be displayed.
- On output, Selection return the screen item that is selected
- by user.
-
- @retval EFI_SUCCESS The page is displayed successfully.
- @return Other value if the page failed to be diplayed.
-
-**/
-EFI_STATUS
-SetupBrowser (
- IN OUT UI_MENU_SELECTION *Selection
- );
-
-/**
- Set Buffer to Value for Size bytes.
-
- @param Buffer Memory to set.
- @param Size Number of bytes to set
- @param Value Value of the set operation.
-
-**/
-VOID
-SetUnicodeMem (
- IN VOID *Buffer,
- IN UINTN Size,
- IN CHAR16 Value
- );
-
-/**
- Wait for a given event to fire, or for an optional timeout to expire.
-
- @param Event The event to wait for
- @param Timeout An optional timeout value in 100 ns units.
- @param RefreshInterval Menu refresh interval (in seconds).
-
- @retval EFI_SUCCESS Event fired before Timeout expired.
- @retval EFI_TIME_OUT Timout expired before Event fired.
-
-**/
-EFI_STATUS
-UiWaitForSingleEvent (
- IN EFI_EVENT Event,
- IN UINT64 Timeout, OPTIONAL
- IN UINT8 RefreshInterval OPTIONAL
- );
-
-/**
- Draw a pop up windows based on the dimension, number of lines and
- strings specified.
-
- @param ScreenWidth The width of the pop-up.
- @param NumberOfLines The number of lines.
- @param ... A series of text strings that displayed in the pop-up.
-
-**/
-VOID
-EFIAPI
-CreateMultiStringPopUp (
- IN UINTN ScreenWidth,
- IN UINTN NumberOfLines,
- ...
- );
-
-/**
- Get string or password input from user.
-
- @param MenuOption Pointer to the current input menu.
- @param Prompt The prompt string shown on popup window.
- @param StringPtr Old user input and destination for use input string.
-
- @retval EFI_SUCCESS If string input is read successfully
- @retval EFI_DEVICE_ERROR If operation fails
-
-**/
-EFI_STATUS
-ReadString (
- IN UI_MENU_OPTION *MenuOption,
- IN CHAR16 *Prompt,
- IN OUT CHAR16 *StringPtr
- );
-
-/**
- Get selection for OneOf and OrderedList (Left/Right will be ignored).
-
- @param Selection Pointer to current selection.
- @param MenuOption Pointer to the current input menu.
-
- @retval EFI_SUCCESS If Option input is processed successfully
- @retval EFI_DEVICE_ERROR If operation fails
-
-**/
-EFI_STATUS
-GetSelectionInputPopUp (
- IN UI_MENU_SELECTION *Selection,
- IN UI_MENU_OPTION *MenuOption
- );
-
-/**
- This routine reads a numeric value from the user input.
-
- @param Selection Pointer to current selection.
- @param MenuOption Pointer to the current input menu.
-
- @retval EFI_SUCCESS If numerical input is read successfully
- @retval EFI_DEVICE_ERROR If operation fails
-
-**/
-EFI_STATUS
-GetNumericInput (
- IN UI_MENU_SELECTION *Selection,
- IN UI_MENU_OPTION *MenuOption
- );
-
-/**
- Update status bar on the bottom of menu.
-
- @param Selection Current selection info.
- @param MessageType The type of message to be shown.
- @param Flags The flags in Question header.
- @param State Set or clear.
-
-**/
-VOID
-UpdateStatusBar (
- IN UI_MENU_SELECTION *Selection,
- IN UINTN MessageType,
- IN UINT8 Flags,
- IN BOOLEAN State
- );
-
-/**
- Process Question Config.
-
- @param Selection The UI menu selection.
- @param Question The Question to be peocessed.
-
- @retval EFI_SUCCESS Question Config process success.
- @retval Other Question Config process fail.
-
-**/
-EFI_STATUS
-ProcessQuestionConfig (
- IN UI_MENU_SELECTION *Selection,
- IN FORM_BROWSER_STATEMENT *Question
- );
-
-/**
- Print Question Value according to it's storage width and display attributes.
-
- @param Question The Question to be printed.
- @param FormattedNumber Buffer for output string.
- @param BufferSize The FormattedNumber buffer size in bytes.
-
- @retval EFI_SUCCESS Print success.
- @retval EFI_BUFFER_TOO_SMALL Buffer size is not enough for formatted number.
-
-**/
-EFI_STATUS
-PrintFormattedNumber (
- IN FORM_BROWSER_STATEMENT *Question,
- IN OUT CHAR16 *FormattedNumber,
- IN UINTN BufferSize
- );
-
-/**
- Search an Option of a Question by its value.
-
- @param Question The Question
- @param OptionValue Value for Option to be searched.
-
- @retval Pointer Pointer to the found Option.
- @retval NULL Option not found.
-
-**/
-QUESTION_OPTION *
-ValueToOption (
- IN FORM_BROWSER_STATEMENT *Question,
- IN EFI_HII_VALUE *OptionValue
- );
-
-/**
- Return data element in an Array by its Index.
-
- @param Array The data array.
- @param Type Type of the data in this array.
- @param Index Zero based index for data in this array.
-
- @retval Value The data to be returned
-
-**/
-UINT64
-GetArrayData (
- IN VOID *Array,
- IN UINT8 Type,
- IN UINTN Index
- );
-
-/**
- Set value of a data element in an Array by its Index.
-
- @param Array The data array.
- @param Type Type of the data in this array.
- @param Index Zero based index for data in this array.
- @param Value The value to be set.
-
-**/
-VOID
-SetArrayData (
- IN VOID *Array,
- IN UINT8 Type,
- IN UINTN Index,
- IN UINT64 Value
- );
-
-/**
- Check whether this value already in the array, if yes, return the index.
-
- @param Array The data array.
- @param Type Type of the data in this array.
- @param Value The value to be find.
- @param Index The index in the array which has same value with Value.
-
- @retval TRUE Found the value in the array.
- @retval FALSE Not found the value.
-
-**/
-BOOLEAN
-FindArrayData (
- IN VOID *Array,
- IN UINT8 Type,
- IN UINT64 Value,
- OUT UINTN *Index OPTIONAL
- );
-
-/**
- Process a Question's Option (whether selected or un-selected).
-
- @param Selection Pointer to UI_MENU_SELECTION.
- @param MenuOption The MenuOption for this Question.
- @param Selected TRUE: if Question is selected.
- @param OptionString Pointer of the Option String to be displayed.
-
- @retval EFI_SUCCESS Question Option process success.
- @retval Other Question Option process fail.
-
-**/
-EFI_STATUS
-ProcessOptions (
- IN UI_MENU_SELECTION *Selection,
- IN UI_MENU_OPTION *MenuOption,
- IN BOOLEAN Selected,
- OUT CHAR16 **OptionString
- );
-
-/**
- Process the help string: Split StringPtr to several lines of strings stored in
- FormattedString and the glyph width of each line cannot exceed gHelpBlockWidth.
-
- @param StringPtr The entire help string.
- @param FormattedString The oupput formatted string.
- @param EachLineWidth The string length of each line in the formatted string.
- @param RowCount TRUE: if Question is selected.
-
-**/
-UINTN
-ProcessHelpString (
- IN CHAR16 *StringPtr,
- OUT CHAR16 **FormattedString,
- OUT UINT16 *EachLineWidth,
- IN UINTN RowCount
- );
-
-/**
- Update key's help imformation.
-
- @param Selection Tell setup browser the information about the Selection
- @param MenuOption The Menu option
- @param Selected Whether or not a tag be selected
-
-**/
-VOID
-UpdateKeyHelp (
- IN UI_MENU_SELECTION *Selection,
- IN UI_MENU_OPTION *MenuOption,
- IN BOOLEAN Selected
- );
-
-/**
- Clear retangle with specified text attribute.
-
- @param LeftColumn Left column of retangle.
- @param RightColumn Right column of retangle.
- @param TopRow Start row of retangle.
- @param BottomRow End row of retangle.
- @param TextAttribute The character foreground and background.
-
-**/
-VOID
-ClearLines (
- IN UINTN LeftColumn,
- IN UINTN RightColumn,
- IN UINTN TopRow,
- IN UINTN BottomRow,
- IN UINTN TextAttribute
- );
-
-/**
- Count the storage space of a Unicode string.
-
- This function handles the Unicode string with NARROW_CHAR
- and WIDE_CHAR control characters. NARROW_HCAR and WIDE_CHAR
- does not count in the resultant output. If a WIDE_CHAR is
- hit, then 2 Unicode character will consume an output storage
- space with size of CHAR16 till a NARROW_CHAR is hit.
-
- If String is NULL, then ASSERT ().
-
- @param String The input string to be counted.
-
- @return Storage space for the input string.
-
-**/
-UINTN
-GetStringWidth (
- IN CHAR16 *String
- );
-
-/**
- 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.
- In the code, it deals \r,\n,\r\n same as \n\r, also it not process the \r or \g.
-
- @param InputString String description for this option.
- @param LineWidth Width of the desired string to extract in CHAR16
- characters
- @param GlyphWidth The glyph width of the beging char in the string.
- @param Index Where in InputString to start the copy process
- @param OutputString Buffer to copy the string into
-
- @return Returns the number of CHAR16 characters that were copied into the OutputString buffer.
-
-**/
-UINT16
-GetLineByWidth (
- IN CHAR16 *InputString,
- IN UINT16 LineWidth,
- IN OUT UINT16 *GlyphWidth,
- IN OUT UINTN *Index,
- OUT CHAR16 **OutputString
- );
-
-/**
- Get the supported width for a particular op-code
-
- @param Statement The FORM_BROWSER_STATEMENT structure passed in.
- @param Handle The handle in the HII database being used
-
- @return Returns the number of CHAR16 characters that is support.
-
-**/
-UINT16
-GetWidth (
- IN FORM_BROWSER_STATEMENT *Statement,
- IN EFI_HII_HANDLE Handle
- );
-
-/**
- Concatenate a narrow string to another string.
-
- @param Destination The destination string.
- @param Source The source string. The string to be concatenated.
- to the end of Destination.
-
-**/
-VOID
-NewStrCat (
- IN OUT CHAR16 *Destination,
- IN CHAR16 *Source
- );
-
-/**
- Wait for a key to be pressed by user.
-
- @param Key The key which is pressed by user.
-
- @retval EFI_SUCCESS The function always completed successfully.
-
-**/
-EFI_STATUS
-WaitForKeyStroke (
- OUT EFI_INPUT_KEY *Key
- );
-
-/**
- Reset stack pointer to begin of the stack.
-
-**/
-VOID
-ResetScopeStack (
- VOID
- );
-
-/**
- Push the expression options onto the Stack.
-
- @param Pointer Pointer to the current expression.
- @param Level Which type this expression belong to. Form,
- statement or option?
-
- @retval EFI_SUCCESS The value was pushed onto the stack.
- @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.
-
-**/
-EFI_STATUS
-PushConditionalExpression (
- IN FORM_EXPRESSION *Pointer,
- IN EXPRESS_LEVEL Level
- );
-
-/**
- Pop the expression options from the Stack
-
- @param Level Which type this expression belong to. Form,
- statement or option?
-
- @retval EFI_SUCCESS The value was pushed onto the stack.
- @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.
-
-**/
-EFI_STATUS
-PopConditionalExpression (
- IN EXPRESS_LEVEL Level
- );
-
-/**
- Get the expression Buffer pointer.
-
- @param Level Which type this expression belong to. Form,
- statement or option?
-
- @retval The start pointer of the expression buffer or NULL.
-
-**/
-FORM_EXPRESSION **
-GetConditionalExpressionList (
- IN EXPRESS_LEVEL Level
- );
-
-/**
- Get the expression list count.
-
- @param Level Which type this expression belong to. Form,
- statement or option?
-
- @retval >=0 The expression count
- @retval -1 Input parameter error.
-
-**/
-INTN
-GetConditionalExpressionCount (
- IN EXPRESS_LEVEL Level
- );
-
-/**
- Push an Operand onto the Stack
-
- @param Operand Operand to push.
-
- @retval EFI_SUCCESS The value was pushed onto the stack.
- @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the
- stack.
-
-**/
-EFI_STATUS
-PushScope (
- IN UINT8 Operand
- );
-
-/**
- Pop an Operand from the Stack
-
- @param Operand Operand to pop.
-
- @retval EFI_SUCCESS The value was pushed onto the stack.
- @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the
- stack.
-
-**/
-EFI_STATUS
-PopScope (
- OUT UINT8 *Operand
- );
-
-/**
- Reset stack pointer to begin of the stack.
-
-**/
-VOID
-ResetCurrentExpressionStack (
- VOID
- );
-
-/**
- Push current expression onto the Stack
-
- @param Pointer Pointer to current expression.
-
- @retval EFI_SUCCESS The value was pushed onto the stack.
- @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.
-
-**/
-EFI_STATUS
-PushCurrentExpression (
- IN VOID *Pointer
- );
-
-/**
- Pop current expression from the Stack
-
- @param Pointer Pointer to current expression to be pop.
-
- @retval EFI_SUCCESS The value was pushed onto the stack.
- @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.
-
-**/
-EFI_STATUS
-PopCurrentExpression (
- OUT VOID **Pointer
- );
-
-/**
- Reset stack pointer to begin of the stack.
-
-**/
-VOID
-ResetMapExpressionListStack (
- VOID
- );
-
-/**
- Push the list of map expression onto the Stack
-
- @param Pointer Pointer to the list of map expression to be pushed.
-
- @retval EFI_SUCCESS The value was pushed onto the stack.
- @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.
-
-**/
-EFI_STATUS
-PushMapExpressionList (
- IN VOID *Pointer
- );
-
-/**
- Pop the list of map expression from the Stack
-
- @param Pointer Pointer to the list of map expression to be pop.
-
- @retval EFI_SUCCESS The value was pushed onto the stack.
- @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.
-
-**/
-EFI_STATUS
-PopMapExpressionList (
- OUT VOID **Pointer
- );
-
-/**
- Get Form given its FormId.
-
- @param FormSet The formset which contains this form.
- @param FormId Id of this form.
-
- @retval Pointer The form.
- @retval NULL Specified Form is not found in the formset.
-
-**/
-FORM_BROWSER_FORM *
-IdToForm (
- IN FORM_BROWSER_FORMSET *FormSet,
- IN UINT16 FormId
- );
-
-/**
- Search a Question in Formset scope using its QuestionId.
-
- @param FormSet The formset which contains this form.
- @param Form The form which contains this Question.
- @param QuestionId Id of this Question.
-
- @retval Pointer The Question.
- @retval NULL Specified Question not found in the form.
-
-**/
-FORM_BROWSER_STATEMENT *
-IdToQuestion (
- IN FORM_BROWSER_FORMSET *FormSet,
- IN FORM_BROWSER_FORM *Form,
- IN UINT16 QuestionId
- );
-
-/**
- Zero extend integer/boolean/date/time to UINT64 for comparing.
-
- @param Value HII Value to be converted.
-
-**/
-VOID
-ExtendValueToU64 (
- IN EFI_HII_VALUE *Value
- );
-
-/**
- Compare two Hii value.
-
- @param Value1 Expression value to compare on left-hand.
- @param Value2 Expression value to compare on right-hand.
- @param Result Return value after compare.
- retval 0 Two operators equal.
- return Positive value if Value1 is greater than Value2.
- retval Negative value if Value1 is less than Value2.
- @param HiiHandle Only required for string compare.
-
- @retval other Could not perform compare on two values.
- @retval EFI_SUCCESS Compare the value success.
-
-**/
-EFI_STATUS
-CompareHiiValue (
- IN EFI_HII_VALUE *Value1,
- IN EFI_HII_VALUE *Value2,
- OUT INTN *Result,
- IN EFI_HII_HANDLE HiiHandle OPTIONAL
- );
-
-/**
- Evaluate the result of a HII expression
-
- If Expression is NULL, then ASSERT.
-
- @param FormSet FormSet associated with this expression.
- @param Form Form associated with this expression.
- @param Expression Expression to be evaluated.
-
- @retval EFI_SUCCESS The expression evaluated successfuly
- @retval EFI_NOT_FOUND The Question which referenced by a QuestionId
- could not be found.
- @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the
- stack.
- @retval EFI_ACCESS_DENIED The pop operation underflowed the stack
- @retval EFI_INVALID_PARAMETER Syntax error with the Expression
-
-**/
-EFI_STATUS
-EvaluateExpression (
- IN FORM_BROWSER_FORMSET *FormSet,
- IN FORM_BROWSER_FORM *Form,
- IN OUT FORM_EXPRESSION *Expression
- );
-
-/**
- Return the result of the expression list. Check the expression list and
- return the highest priority express result.
- Priority: DisableIf > SuppressIf > GrayOutIf > FALSE
-
- @param ExpList The input expression list.
- @param Evaluate Whether need to evaluate the expression first.
- @param FormSet FormSet associated with this expression. Only
- needed when Evaluate is TRUE
- @param Form Form associated with this expression. Only
- needed when Evaluate is TRUE
-
- @retval EXPRESS_RESULT Return the higher priority express result.
- DisableIf > SuppressIf > GrayOutIf > FALSE
-
-**/
-EXPRESS_RESULT
-EvaluateExpressionList (
- IN FORM_EXPRESSION_LIST *ExpList,
- IN BOOLEAN Evaluate,
- IN FORM_BROWSER_FORMSET *FormSet, OPTIONAL
- IN FORM_BROWSER_FORM *Form OPTIONAL
- );
-
-#endif // _UI_H
diff --git a/MdeModulePkg/Universal/Variable/Pei/Variable.c b/MdeModulePkg/Universal/Variable/Pei/Variable.c
index 10ad3f51d..df0304748 100644
--- a/MdeModulePkg/Universal/Variable/Pei/Variable.c
+++ b/MdeModulePkg/Universal/Variable/Pei/Variable.c
@@ -11,7 +11,6 @@ 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:
**/
@@ -174,7 +173,6 @@ GetVariableNamePtr (
IN VARIABLE_HEADER *Variable
)
{
-
return (CHAR16 *) (Variable + 1);
}
@@ -182,14 +180,16 @@ GetVariableNamePtr (
/**
This code gets the pointer to the variable data.
- @param Variable Pointer to the Variable Header.
+ @param Variable Pointer to the Variable Header.
+ @param VariableHeader Pointer to the Variable Header that has consecutive content.
@return A UINT8* pointer to Variable Data.
**/
UINT8 *
GetVariableDataPtr (
- IN VARIABLE_HEADER *Variable
+ IN VARIABLE_HEADER *Variable,
+ IN VARIABLE_HEADER *VariableHeader
)
{
UINTN Value;
@@ -198,8 +198,8 @@ GetVariableDataPtr (
// Be careful about pad size for alignment
//
Value = (UINTN) GetVariableNamePtr (Variable);
- Value += NameSizeOfVariable (Variable);
- Value += GET_PAD_SIZE (NameSizeOfVariable (Variable));
+ Value += NameSizeOfVariable (VariableHeader);
+ Value += GET_PAD_SIZE (NameSizeOfVariable (VariableHeader));
return (UINT8 *) Value;
}
@@ -208,34 +208,48 @@ GetVariableDataPtr (
/**
This code gets the pointer to the next variable header.
- @param Variable Pointer to the Variable Header.
+ @param StoreInfo Pointer to variable store info structure.
+ @param Variable Pointer to the Variable Header.
+ @param VariableHeader Pointer to the Variable Header that has consecutive content.
@return A VARIABLE_HEADER* pointer to next variable header.
**/
VARIABLE_HEADER *
GetNextVariablePtr (
- IN VARIABLE_HEADER *Variable
+ IN VARIABLE_STORE_INFO *StoreInfo,
+ IN VARIABLE_HEADER *Variable,
+ IN VARIABLE_HEADER *VariableHeader
)
{
- UINTN Value;
-
- if (!IsValidVariableHeader (Variable)) {
- return NULL;
- }
-
- Value = (UINTN) GetVariableDataPtr (Variable);
- Value += DataSizeOfVariable (Variable);
- Value += GET_PAD_SIZE (DataSizeOfVariable (Variable));
+ EFI_PHYSICAL_ADDRESS TargetAddress;
+ EFI_PHYSICAL_ADDRESS SpareAddress;
+ UINTN Value;
+ Value = (UINTN) GetVariableDataPtr (Variable, VariableHeader);
+ Value += DataSizeOfVariable (VariableHeader);
+ Value += GET_PAD_SIZE (DataSizeOfVariable (VariableHeader));
//
// Be careful about pad size for alignment
//
- return (VARIABLE_HEADER *) HEADER_ALIGN (Value);
+ Value = HEADER_ALIGN (Value);
+
+ if (StoreInfo->FtwLastWriteData != NULL) {
+ TargetAddress = StoreInfo->FtwLastWriteData->TargetAddress;
+ SpareAddress = StoreInfo->FtwLastWriteData->SpareAddress;
+ if (((UINTN) Variable < (UINTN) TargetAddress) && (Value >= (UINTN) TargetAddress)) {
+ //
+ // Next variable is in spare block.
+ //
+ Value = (UINTN) SpareAddress + (Value - (UINTN) TargetAddress);
+ }
+ }
+
+ return (VARIABLE_HEADER *) Value;
}
/**
- This code gets the pointer to the variable name.
+ Get variable store status.
@param VarStoreHeader Pointer to the Variable Store Header.
@@ -249,7 +263,6 @@ GetVariableStoreStatus (
IN VARIABLE_STORE_HEADER *VarStoreHeader
)
{
-
if (CompareGuid (&VarStoreHeader->Signature, &gEfiVariableGuid) &&
VarStoreHeader->Format == VARIABLE_STORE_FORMATTED &&
VarStoreHeader->State == VARIABLE_STORE_HEALTHY
@@ -273,11 +286,85 @@ GetVariableStoreStatus (
}
}
+/**
+ Compare two variable names, one of them may be inconsecutive.
+
+ @param StoreInfo Pointer to variable store info structure.
+ @param Name1 Pointer to one variable name.
+ @param Name2 Pointer to another variable name.
+ @param NameSize Variable name size.
+
+ @retval TRUE Name1 and Name2 are identical.
+ @retval FALSE Name1 and Name2 are not identical.
+
+**/
+BOOLEAN
+CompareVariableName (
+ IN VARIABLE_STORE_INFO *StoreInfo,
+ IN CONST CHAR16 *Name1,
+ IN CONST CHAR16 *Name2,
+ IN UINTN NameSize
+ )
+{
+ EFI_PHYSICAL_ADDRESS TargetAddress;
+ EFI_PHYSICAL_ADDRESS SpareAddress;
+ UINTN PartialNameSize;
+
+ if (StoreInfo->FtwLastWriteData != NULL) {
+ TargetAddress = StoreInfo->FtwLastWriteData->TargetAddress;
+ SpareAddress = StoreInfo->FtwLastWriteData->SpareAddress;
+ if (((UINTN) Name1 < (UINTN) TargetAddress) && (((UINTN) Name1 + NameSize) > (UINTN) TargetAddress)) {
+ //
+ // Name1 is inconsecutive.
+ //
+ PartialNameSize = (UINTN) TargetAddress - (UINTN) Name1;
+ //
+ // Partial content is in NV storage.
+ //
+ if (CompareMem ((UINT8 *) Name1, (UINT8 *) Name2, PartialNameSize) == 0) {
+ //
+ // Another partial content is in spare block.
+ //
+ if (CompareMem ((UINT8 *) (UINTN) SpareAddress, (UINT8 *) Name2 + PartialNameSize, NameSize - PartialNameSize) == 0) {
+ return TRUE;
+ }
+ }
+ return FALSE;
+ } else if (((UINTN) Name2 < (UINTN) TargetAddress) && (((UINTN) Name2 + NameSize) > (UINTN) TargetAddress)) {
+ //
+ // Name2 is inconsecutive.
+ //
+ PartialNameSize = (UINTN) TargetAddress - (UINTN) Name2;
+ //
+ // Partial content is in NV storage.
+ //
+ if (CompareMem ((UINT8 *) Name2, (UINT8 *) Name1, PartialNameSize) == 0) {
+ //
+ // Another partial content is in spare block.
+ //
+ if (CompareMem ((UINT8 *) (UINTN) SpareAddress, (UINT8 *) Name1 + PartialNameSize, NameSize - PartialNameSize) == 0) {
+ return TRUE;
+ }
+ }
+ return FALSE;
+ }
+ }
+
+ //
+ // Both Name1 and Name2 are consecutive.
+ //
+ if (CompareMem ((UINT8 *) Name1, (UINT8 *) Name2, NameSize) == 0) {
+ return TRUE;
+ }
+ return FALSE;
+}
/**
This function compares a variable with variable entries in database.
+ @param StoreInfo Pointer to variable store info structure.
@param Variable Pointer to the variable in our database
+ @param VariableHeader Pointer to the Variable Header that has consecutive content.
@param VariableName Name of the variable to compare to 'Variable'
@param VendorGuid GUID of the variable to compare to 'Variable'
@param PtrTrack Variable Track Pointer structure that contains Variable Information.
@@ -288,7 +375,9 @@ GetVariableStoreStatus (
**/
EFI_STATUS
CompareWithValidVariable (
+ IN VARIABLE_STORE_INFO *StoreInfo,
IN VARIABLE_HEADER *Variable,
+ IN VARIABLE_HEADER *VariableHeader,
IN CONST CHAR16 *VariableName,
IN CONST EFI_GUID *VendorGuid,
OUT VARIABLE_POINTER_TRACK *PtrTrack
@@ -305,14 +394,14 @@ CompareWithValidVariable (
// Instead we compare the GUID a UINT32 at a time and branch
// on the first failed comparison.
//
- if ((((INT32 *) VendorGuid)[0] == ((INT32 *) &Variable->VendorGuid)[0]) &&
- (((INT32 *) VendorGuid)[1] == ((INT32 *) &Variable->VendorGuid)[1]) &&
- (((INT32 *) VendorGuid)[2] == ((INT32 *) &Variable->VendorGuid)[2]) &&
- (((INT32 *) VendorGuid)[3] == ((INT32 *) &Variable->VendorGuid)[3])
+ if ((((INT32 *) VendorGuid)[0] == ((INT32 *) &VariableHeader->VendorGuid)[0]) &&
+ (((INT32 *) VendorGuid)[1] == ((INT32 *) &VariableHeader->VendorGuid)[1]) &&
+ (((INT32 *) VendorGuid)[2] == ((INT32 *) &VariableHeader->VendorGuid)[2]) &&
+ (((INT32 *) VendorGuid)[3] == ((INT32 *) &VariableHeader->VendorGuid)[3])
) {
- ASSERT (NameSizeOfVariable (Variable) != 0);
+ ASSERT (NameSizeOfVariable (VariableHeader) != 0);
Point = (VOID *) GetVariableNamePtr (Variable);
- if (CompareMem (VariableName, Point, NameSizeOfVariable (Variable)) == 0) {
+ if (CompareVariableName (StoreInfo, VariableName, Point, NameSizeOfVariable (VariableHeader))) {
PtrTrack->CurrPtr = Variable;
return EFI_SUCCESS;
}
@@ -323,26 +412,29 @@ CompareWithValidVariable (
}
/**
- Return the variable store header and the index table based on the Index.
+ Return the variable store header and the store info based on the Index.
@param Type The type of the variable store.
- @param IndexTable Return the index table.
+ @param StoreInfo Return the store info.
@return Pointer to the variable store header.
**/
VARIABLE_STORE_HEADER *
GetVariableStore (
IN VARIABLE_STORE_TYPE Type,
- OUT VARIABLE_INDEX_TABLE **IndexTable OPTIONAL
+ OUT VARIABLE_STORE_INFO *StoreInfo
)
{
- EFI_HOB_GUID_TYPE *GuidHob;
- EFI_FIRMWARE_VOLUME_HEADER *FvHeader;
- VARIABLE_STORE_HEADER *VariableStoreHeader;
-
- if (IndexTable != NULL) {
- *IndexTable = NULL;
- }
+ EFI_HOB_GUID_TYPE *GuidHob;
+ EFI_FIRMWARE_VOLUME_HEADER *FvHeader;
+ VARIABLE_STORE_HEADER *VariableStoreHeader;
+ EFI_PHYSICAL_ADDRESS NvStorageBase;
+ UINT32 NvStorageSize;
+ FAULT_TOLERANT_WRITE_LAST_WRITE_DATA *FtwLastWriteData;
+ UINT32 BackUpOffset;
+
+ StoreInfo->IndexTable = NULL;
+ StoreInfo->FtwLastWriteData = NULL;
VariableStoreHeader = NULL;
switch (Type) {
case VariableStoreTypeHob:
@@ -357,10 +449,42 @@ GetVariableStore (
//
// The content of NV storage for variable is not reliable in recovery boot mode.
//
- FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) (PcdGet64 (PcdFlashNvStorageVariableBase64) != 0 ?
- PcdGet64 (PcdFlashNvStorageVariableBase64) :
- PcdGet32 (PcdFlashNvStorageVariableBase)
- );
+
+ NvStorageSize = PcdGet32 (PcdFlashNvStorageVariableSize);
+ NvStorageBase = (EFI_PHYSICAL_ADDRESS) (PcdGet64 (PcdFlashNvStorageVariableBase64) != 0 ?
+ PcdGet64 (PcdFlashNvStorageVariableBase64) :
+ PcdGet32 (PcdFlashNvStorageVariableBase)
+ );
+ //
+ // First let FvHeader point to NV storage base.
+ //
+ FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) NvStorageBase;
+
+ //
+ // Check the FTW last write data hob.
+ //
+ BackUpOffset = 0;
+ GuidHob = GetFirstGuidHob (&gEdkiiFaultTolerantWriteGuid);
+ if (GuidHob != NULL) {
+ FtwLastWriteData = (FAULT_TOLERANT_WRITE_LAST_WRITE_DATA *) GET_GUID_HOB_DATA (GuidHob);
+ if (FtwLastWriteData->TargetAddress == NvStorageBase) {
+ //
+ // Let FvHeader point to spare block.
+ //
+ FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) FtwLastWriteData->SpareAddress;
+ DEBUG ((EFI_D_INFO, "PeiVariable: NV storage is backed up in spare block: 0x%x\n", (UINTN) FtwLastWriteData->SpareAddress));
+ } else if ((FtwLastWriteData->TargetAddress > NvStorageBase) && (FtwLastWriteData->TargetAddress < (NvStorageBase + NvStorageSize))) {
+ StoreInfo->FtwLastWriteData = FtwLastWriteData;
+ //
+ // Flash NV storage from the offset is backed up in spare block.
+ //
+ BackUpOffset = (UINT32) (FtwLastWriteData->TargetAddress - NvStorageBase);
+ DEBUG ((EFI_D_INFO, "PeiVariable: High partial NV storage from offset: %x is backed up in spare block: 0x%x\n", BackUpOffset, (UINTN) FtwLastWriteData->SpareAddress));
+ //
+ // At least one block data in flash NV storage is still valid, so still leave FvHeader point to NV storage base.
+ //
+ }
+ }
//
// Check if the Firmware Volume is not corrupted
@@ -372,23 +496,21 @@ GetVariableStore (
VariableStoreHeader = (VARIABLE_STORE_HEADER *) ((UINT8 *) FvHeader + FvHeader->HeaderLength);
- if (IndexTable != NULL) {
- GuidHob = GetFirstGuidHob (&gEfiVariableIndexTableGuid);
- if (GuidHob != NULL) {
- *IndexTable = GET_GUID_HOB_DATA (GuidHob);
- } else {
- //
- // If it's the first time to access variable region in flash, create a guid hob to record
- // VAR_ADDED type variable info.
- // Note that as the resource of PEI phase is limited, only store the limited number of
- // VAR_ADDED type variables to reduce access time.
- //
- *IndexTable = BuildGuidHob (&gEfiVariableIndexTableGuid, sizeof (VARIABLE_INDEX_TABLE));
- (*IndexTable)->Length = 0;
- (*IndexTable)->StartPtr = GetStartPointer (VariableStoreHeader);
- (*IndexTable)->EndPtr = GetEndPointer (VariableStoreHeader);
- (*IndexTable)->GoneThrough = 0;
- }
+ GuidHob = GetFirstGuidHob (&gEfiVariableIndexTableGuid);
+ if (GuidHob != NULL) {
+ StoreInfo->IndexTable = GET_GUID_HOB_DATA (GuidHob);
+ } else {
+ //
+ // If it's the first time to access variable region in flash, create a guid hob to record
+ // VAR_ADDED type variable info.
+ // Note that as the resource of PEI phase is limited, only store the limited number of
+ // VAR_ADDED type variables to reduce access time.
+ //
+ StoreInfo->IndexTable = (VARIABLE_INDEX_TABLE *) BuildGuidHob (&gEfiVariableIndexTableGuid, sizeof (VARIABLE_INDEX_TABLE));
+ StoreInfo->IndexTable->Length = 0;
+ StoreInfo->IndexTable->StartPtr = GetStartPointer (VariableStoreHeader);
+ StoreInfo->IndexTable->EndPtr = GetEndPointer (VariableStoreHeader);
+ StoreInfo->IndexTable->GoneThrough = 0;
}
}
break;
@@ -398,14 +520,118 @@ GetVariableStore (
break;
}
+ StoreInfo->VariableStoreHeader = VariableStoreHeader;
return VariableStoreHeader;
}
/**
+ Get variable header that has consecutive content.
+
+ @param StoreInfo Pointer to variable store info structure.
+ @param Variable Pointer to the Variable Header.
+ @param VariableHeader Pointer to Pointer to the Variable Header that has consecutive content.
+
+ @retval TRUE Variable header is valid.
+ @retval FALSE Variable header is not valid.
+
+**/
+BOOLEAN
+GetVariableHeader (
+ IN VARIABLE_STORE_INFO *StoreInfo,
+ IN VARIABLE_HEADER *Variable,
+ OUT VARIABLE_HEADER **VariableHeader
+ )
+{
+ EFI_PHYSICAL_ADDRESS TargetAddress;
+ EFI_PHYSICAL_ADDRESS SpareAddress;
+ EFI_HOB_GUID_TYPE *GuidHob;
+ UINTN PartialHeaderSize;
+
+ //
+ // First assume variable header pointed by Variable is consecutive.
+ //
+ *VariableHeader = Variable;
+
+ if ((Variable != NULL) && (StoreInfo->FtwLastWriteData != NULL)) {
+ TargetAddress = StoreInfo->FtwLastWriteData->TargetAddress;
+ SpareAddress = StoreInfo->FtwLastWriteData->SpareAddress;
+ if (((UINTN) Variable < (UINTN) TargetAddress) && (((UINTN) Variable + sizeof (VARIABLE_HEADER)) > (UINTN) TargetAddress)) {
+ //
+ // Variable header pointed by Variable is inconsecutive,
+ // create a guid hob to combine the two partial variable header content together.
+ //
+ GuidHob = GetFirstGuidHob (&gEfiCallerIdGuid);
+ if (GuidHob != NULL) {
+ *VariableHeader = (VARIABLE_HEADER *) GET_GUID_HOB_DATA (GuidHob);
+ } else {
+ *VariableHeader = (VARIABLE_HEADER *) BuildGuidHob (&gEfiCallerIdGuid, sizeof (VARIABLE_HEADER));
+ PartialHeaderSize = (UINTN) TargetAddress - (UINTN) Variable;
+ //
+ // Partial content is in NV storage.
+ //
+ CopyMem ((UINT8 *) *VariableHeader, (UINT8 *) Variable, PartialHeaderSize);
+ //
+ // Another partial content is in spare block.
+ //
+ CopyMem ((UINT8 *) *VariableHeader + PartialHeaderSize, (UINT8 *) (UINTN) SpareAddress, sizeof (VARIABLE_HEADER) - PartialHeaderSize);
+ }
+ }
+ }
+
+ return IsValidVariableHeader (*VariableHeader);
+}
+
+/**
+ Get variable name or data to output buffer.
+
+ @param StoreInfo Pointer to variable store info structure.
+ @param NameOrData Pointer to the variable name/data that may be inconsecutive.
+ @param Size Variable name/data size.
+ @param Buffer Pointer to output buffer to hold the variable name/data.
+
+**/
+VOID
+GetVariableNameOrData (
+ IN VARIABLE_STORE_INFO *StoreInfo,
+ IN UINT8 *NameOrData,
+ IN UINTN Size,
+ OUT UINT8 *Buffer
+ )
+{
+ EFI_PHYSICAL_ADDRESS TargetAddress;
+ EFI_PHYSICAL_ADDRESS SpareAddress;
+ UINTN PartialSize;
+
+ if (StoreInfo->FtwLastWriteData != NULL) {
+ TargetAddress = StoreInfo->FtwLastWriteData->TargetAddress;
+ SpareAddress = StoreInfo->FtwLastWriteData->SpareAddress;
+ if (((UINTN) NameOrData < (UINTN) TargetAddress) && (((UINTN) NameOrData + Size) > (UINTN) TargetAddress)) {
+ //
+ // Variable name/data is inconsecutive.
+ //
+ PartialSize = (UINTN) TargetAddress - (UINTN) NameOrData;
+ //
+ // Partial content is in NV storage.
+ //
+ CopyMem (Buffer, NameOrData, PartialSize);
+ //
+ // Another partial content is in spare block.
+ //
+ CopyMem (Buffer + PartialSize, (UINT8 *) (UINTN) SpareAddress, Size - PartialSize);
+ return;
+ }
+ }
+
+ //
+ // Variable name/data is consecutive.
+ //
+ CopyMem (Buffer, NameOrData, Size);
+}
+
+/**
Find the variable in the specified variable store.
- @param VariableStoreHeader Pointer to the variable store header.
- @param IndexTable Pointer to the index table.
+ @param StoreInfo Pointer to the store info structure.
@param VariableName Name of the variable to be found
@param VendorGuid Vendor GUID to be found.
@param PtrTrack Variable Track Pointer structure that contains Variable Information.
@@ -417,8 +643,7 @@ GetVariableStore (
**/
EFI_STATUS
FindVariableEx (
- IN VARIABLE_STORE_HEADER *VariableStoreHeader,
- IN VARIABLE_INDEX_TABLE *IndexTable,
+ IN VARIABLE_STORE_INFO *StoreInfo,
IN CONST CHAR16 *VariableName,
IN CONST EFI_GUID *VendorGuid,
OUT VARIABLE_POINTER_TRACK *PtrTrack
@@ -431,6 +656,11 @@ FindVariableEx (
UINTN Offset;
BOOLEAN StopRecord;
VARIABLE_HEADER *InDeletedVariable;
+ VARIABLE_STORE_HEADER *VariableStoreHeader;
+ VARIABLE_INDEX_TABLE *IndexTable;
+ VARIABLE_HEADER *VariableHeader;
+
+ VariableStoreHeader = StoreInfo->VariableStoreHeader;
if (VariableStoreHeader == NULL) {
return EFI_INVALID_PARAMETER;
@@ -444,6 +674,7 @@ FindVariableEx (
return EFI_NOT_FOUND;
}
+ IndexTable = StoreInfo->IndexTable;
PtrTrack->StartPtr = GetStartPointer (VariableStoreHeader);
PtrTrack->EndPtr = GetEndPointer (VariableStoreHeader);
@@ -453,6 +684,7 @@ FindVariableEx (
// No Variable Address equals zero, so 0 as initial value is safe.
//
MaxIndex = NULL;
+ VariableHeader = NULL;
if (IndexTable != NULL) {
//
@@ -463,8 +695,9 @@ FindVariableEx (
ASSERT (Index < sizeof (IndexTable->Index) / sizeof (IndexTable->Index[0]));
Offset += IndexTable->Index[Index];
MaxIndex = (VARIABLE_HEADER *) ((UINT8 *) IndexTable->StartPtr + Offset);
- if (CompareWithValidVariable (MaxIndex, VariableName, VendorGuid, PtrTrack) == EFI_SUCCESS) {
- if (PtrTrack->CurrPtr->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {
+ GetVariableHeader (StoreInfo, MaxIndex, &VariableHeader);
+ if (CompareWithValidVariable (StoreInfo, MaxIndex, VariableHeader, VariableName, VendorGuid, PtrTrack) == EFI_SUCCESS) {
+ if (VariableHeader->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {
InDeletedVariable = PtrTrack->CurrPtr;
} else {
return EFI_SUCCESS;
@@ -486,7 +719,7 @@ FindVariableEx (
// HOB exists but the variable cannot be found in HOB
// If not found in HOB, then let's start from the MaxIndex we've found.
//
- Variable = GetNextVariablePtr (MaxIndex);
+ Variable = GetNextVariablePtr (StoreInfo, MaxIndex, VariableHeader);
LastVariable = MaxIndex;
} else {
//
@@ -501,8 +734,8 @@ FindVariableEx (
// Find the variable by walk through variable store
//
StopRecord = FALSE;
- while ((Variable < PtrTrack->EndPtr) && IsValidVariableHeader (Variable)) {
- if (Variable->State == VAR_ADDED || Variable->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {
+ while (GetVariableHeader (StoreInfo, Variable, &VariableHeader)) {
+ if (VariableHeader->State == VAR_ADDED || VariableHeader->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {
//
// Record Variable in VariableIndex HOB
//
@@ -520,8 +753,8 @@ FindVariableEx (
}
}
- if (CompareWithValidVariable (Variable, VariableName, VendorGuid, PtrTrack) == EFI_SUCCESS) {
- if (PtrTrack->CurrPtr->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {
+ if (CompareWithValidVariable (StoreInfo, Variable, VariableHeader, VariableName, VendorGuid, PtrTrack) == EFI_SUCCESS) {
+ if (VariableHeader->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {
InDeletedVariable = PtrTrack->CurrPtr;
} else {
return EFI_SUCCESS;
@@ -529,7 +762,7 @@ FindVariableEx (
}
}
- Variable = GetNextVariablePtr (Variable);
+ Variable = GetNextVariablePtr (StoreInfo, Variable, VariableHeader);
}
//
// If gone through the VariableStore, that means we never find in Firmware any more.
@@ -549,6 +782,7 @@ FindVariableEx (
@param VariableName Name of the variable to be found
@param VendorGuid Vendor GUID to be found.
@param PtrTrack Variable Track Pointer structure that contains Variable Information.
+ @param StoreInfo Return the store info.
@retval EFI_SUCCESS Variable found successfully
@retval EFI_NOT_FOUND Variable not found
@@ -558,12 +792,11 @@ EFI_STATUS
FindVariable (
IN CONST CHAR16 *VariableName,
IN CONST EFI_GUID *VendorGuid,
- OUT VARIABLE_POINTER_TRACK *PtrTrack
+ OUT VARIABLE_POINTER_TRACK *PtrTrack,
+ OUT VARIABLE_STORE_INFO *StoreInfo
)
{
EFI_STATUS Status;
- VARIABLE_STORE_HEADER *VariableStoreHeader;
- VARIABLE_INDEX_TABLE *IndexTable;
VARIABLE_STORE_TYPE Type;
if (VariableName[0] != 0 && VendorGuid == NULL) {
@@ -571,10 +804,9 @@ FindVariable (
}
for (Type = (VARIABLE_STORE_TYPE) 0; Type < VariableStoreTypeMax; Type++) {
- VariableStoreHeader = GetVariableStore (Type, &IndexTable);
+ GetVariableStore (Type, StoreInfo);
Status = FindVariableEx (
- VariableStoreHeader,
- IndexTable,
+ StoreInfo,
VariableName,
VendorGuid,
PtrTrack
@@ -627,6 +859,8 @@ PeiGetVariable (
VARIABLE_POINTER_TRACK Variable;
UINTN VarDataSize;
EFI_STATUS Status;
+ VARIABLE_STORE_INFO StoreInfo;
+ VARIABLE_HEADER *VariableHeader;
if (VariableName == NULL || VariableGuid == NULL || DataSize == NULL) {
return EFI_INVALID_PARAMETER;
@@ -635,23 +869,25 @@ PeiGetVariable (
//
// Find existing variable
//
- Status = FindVariable (VariableName, VariableGuid, &Variable);
+ Status = FindVariable (VariableName, VariableGuid, &Variable, &StoreInfo);
if (EFI_ERROR (Status)) {
return Status;
}
+ GetVariableHeader (&StoreInfo, Variable.CurrPtr, &VariableHeader);
+
//
// Get data size
//
- VarDataSize = DataSizeOfVariable (Variable.CurrPtr);
+ VarDataSize = DataSizeOfVariable (VariableHeader);
if (*DataSize >= VarDataSize) {
if (Data == NULL) {
return EFI_INVALID_PARAMETER;
}
- CopyMem (Data, GetVariableDataPtr (Variable.CurrPtr), VarDataSize);
+ GetVariableNameOrData (&StoreInfo, GetVariableDataPtr (Variable.CurrPtr, VariableHeader), VarDataSize, Data);
if (Attributes != NULL) {
- *Attributes = Variable.CurrPtr->Attributes;
+ *Attributes = VariableHeader->Attributes;
}
*DataSize = VarDataSize;
@@ -704,16 +940,19 @@ PeiGetNextVariableName (
VARIABLE_POINTER_TRACK Variable;
VARIABLE_POINTER_TRACK VariableInHob;
VARIABLE_POINTER_TRACK VariablePtrTrack;
- VARIABLE_INDEX_TABLE *IndexTable;
UINTN VarNameSize;
EFI_STATUS Status;
VARIABLE_STORE_HEADER *VariableStoreHeader[VariableStoreTypeMax];
+ VARIABLE_HEADER *VariableHeader;
+ VARIABLE_STORE_INFO StoreInfo;
+ VARIABLE_STORE_INFO StoreInfoForNv;
+ VARIABLE_STORE_INFO StoreInfoForHob;
if (VariableName == NULL || VariableGuid == NULL || VariableNameSize == NULL) {
return EFI_INVALID_PARAMETER;
}
- Status = FindVariable (VariableName, VariableGuid, &Variable);
+ Status = FindVariable (VariableName, VariableGuid, &Variable, &StoreInfo);
if (Variable.CurrPtr == NULL || Status != EFI_SUCCESS) {
return Status;
}
@@ -722,20 +961,18 @@ PeiGetNextVariableName (
//
// If variable name is not NULL, get next variable
//
- Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr);
+ GetVariableHeader (&StoreInfo, Variable.CurrPtr, &VariableHeader);
+ Variable.CurrPtr = GetNextVariablePtr (&StoreInfo, Variable.CurrPtr, VariableHeader);
}
- VariableStoreHeader[VariableStoreTypeHob] = GetVariableStore (VariableStoreTypeHob, NULL);
- VariableStoreHeader[VariableStoreTypeNv] = GetVariableStore (VariableStoreTypeNv, NULL);
+ VariableStoreHeader[VariableStoreTypeHob] = GetVariableStore (VariableStoreTypeHob, &StoreInfoForHob);
+ VariableStoreHeader[VariableStoreTypeNv] = GetVariableStore (VariableStoreTypeNv, &StoreInfoForNv);
while (TRUE) {
//
// Switch from HOB to Non-Volatile.
//
- while ((Variable.CurrPtr >= Variable.EndPtr) ||
- (Variable.CurrPtr == NULL) ||
- !IsValidVariableHeader (Variable.CurrPtr)
- ) {
+ while (!GetVariableHeader (&StoreInfo, Variable.CurrPtr, &VariableHeader)) {
//
// Find current storage index
//
@@ -764,31 +1001,24 @@ PeiGetNextVariableName (
Variable.StartPtr = GetStartPointer (VariableStoreHeader[Type]);
Variable.EndPtr = GetEndPointer (VariableStoreHeader[Type]);
Variable.CurrPtr = Variable.StartPtr;
+ GetVariableStore (Type, &StoreInfo);
}
- if (Variable.CurrPtr->State == VAR_ADDED || Variable.CurrPtr->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {
- if (Variable.CurrPtr->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {
+ if (VariableHeader->State == VAR_ADDED || VariableHeader->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {
+ if (VariableHeader->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {
//
// If it is a IN_DELETED_TRANSITION variable,
// and there is also a same ADDED one at the same time,
// don't return it.
//
- for (Type = (VARIABLE_STORE_TYPE) 0; Type < VariableStoreTypeMax; Type++) {
- if ((VariableStoreHeader[Type] != NULL) && (Variable.StartPtr == GetStartPointer (VariableStoreHeader[Type]))) {
- break;
- }
- }
- ASSERT (Type < VariableStoreTypeMax);
- GetVariableStore (Type, &IndexTable);
Status = FindVariableEx (
- VariableStoreHeader[Type],
- IndexTable,
+ &StoreInfo,
GetVariableNamePtr (Variable.CurrPtr),
- &Variable.CurrPtr->VendorGuid,
+ &VariableHeader->VendorGuid,
&VariablePtrTrack
);
- if (!EFI_ERROR (Status) && VariablePtrTrack.CurrPtr->State == VAR_ADDED) {
- Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr);
+ if (!EFI_ERROR (Status) && VariablePtrTrack.CurrPtr != Variable.CurrPtr) {
+ Variable.CurrPtr = GetNextVariablePtr (&StoreInfo, Variable.CurrPtr, VariableHeader);
continue;
}
}
@@ -800,25 +1030,24 @@ PeiGetNextVariableName (
(Variable.StartPtr == GetStartPointer (VariableStoreHeader[VariableStoreTypeNv]))
) {
Status = FindVariableEx (
- VariableStoreHeader[VariableStoreTypeHob],
- NULL,
+ &StoreInfoForHob,
GetVariableNamePtr (Variable.CurrPtr),
- &Variable.CurrPtr->VendorGuid,
+ &VariableHeader->VendorGuid,
&VariableInHob
);
if (!EFI_ERROR (Status)) {
- Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr);
+ Variable.CurrPtr = GetNextVariablePtr (&StoreInfo, Variable.CurrPtr, VariableHeader);
continue;
}
}
- VarNameSize = NameSizeOfVariable (Variable.CurrPtr);
+ VarNameSize = NameSizeOfVariable (VariableHeader);
ASSERT (VarNameSize != 0);
if (VarNameSize <= *VariableNameSize) {
- CopyMem (VariableName, GetVariableNamePtr (Variable.CurrPtr), VarNameSize);
+ GetVariableNameOrData (&StoreInfo, (UINT8 *) GetVariableNamePtr (Variable.CurrPtr), VarNameSize, (UINT8 *) VariableName);
- CopyMem (VariableGuid, &Variable.CurrPtr->VendorGuid, sizeof (EFI_GUID));
+ CopyMem (VariableGuid, &VariableHeader->VendorGuid, sizeof (EFI_GUID));
Status = EFI_SUCCESS;
} else {
@@ -831,7 +1060,7 @@ PeiGetNextVariableName (
//
return Status;
} else {
- Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr);
+ Variable.CurrPtr = GetNextVariablePtr (&StoreInfo, Variable.CurrPtr, VariableHeader);
}
}
}
diff --git a/MdeModulePkg/Universal/Variable/Pei/Variable.h b/MdeModulePkg/Universal/Variable/Pei/Variable.h
index e0d8679d6..55277b04f 100644
--- a/MdeModulePkg/Universal/Variable/Pei/Variable.h
+++ b/MdeModulePkg/Universal/Variable/Pei/Variable.h
@@ -3,7 +3,7 @@
The internal header file includes the common header files, defines
internal structure and functions used by PeiVariable module.
-Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
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
@@ -31,6 +31,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include <Guid/VariableFormat.h>
#include <Guid/VariableIndexTable.h>
#include <Guid/SystemNvDataGuid.h>
+#include <Guid/FaultTolerantWrite.h>
typedef enum {
VariableStoreTypeHob,
@@ -38,6 +39,17 @@ typedef enum {
VariableStoreTypeMax
} VARIABLE_STORE_TYPE;
+typedef struct {
+ VARIABLE_STORE_HEADER *VariableStoreHeader;
+ VARIABLE_INDEX_TABLE *IndexTable;
+ //
+ // If it is not NULL, it means there may be an inconsecutive variable whose
+ // partial content is still in NV storage, but another partial content is backed up
+ // in spare block.
+ //
+ FAULT_TOLERANT_WRITE_LAST_WRITE_DATA *FtwLastWriteData;
+} VARIABLE_STORE_INFO;
+
//
// Functions
//
diff --git a/MdeModulePkg/Universal/Variable/Pei/VariablePei.inf b/MdeModulePkg/Universal/Variable/Pei/VariablePei.inf
index da07cf7b7..8bae162a3 100644
--- a/MdeModulePkg/Universal/Variable/Pei/VariablePei.inf
+++ b/MdeModulePkg/Universal/Variable/Pei/VariablePei.inf
@@ -3,7 +3,7 @@
# Implement ReadOnly Variable Services required by PEIM and install
# PEI ReadOnly Varaiable2 PPI. These services operates the non-volatile storage space.
#
-# Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
# 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
@@ -49,16 +49,18 @@
gEfiVariableGuid
gEfiVariableIndexTableGuid
gEfiSystemNvDataFvGuid
+ gEdkiiFaultTolerantWriteGuid
[Ppis]
- gEfiPeiReadOnlyVariable2PpiGuid ## SOMETIMES_PRODUCES (Not for boot mode RECOVERY)
+ gEfiPeiReadOnlyVariable2PpiGuid ## PRODUCES
[Pcd]
- gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase ## CONSUMES
- gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64 ## CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase ## CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64 ## CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize ## CONSUMES
[Depex]
- TRUE
+ gEdkiiFaultTolerantWriteGuid
#
# [BootMode]
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c b/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c
index 9f983ffc9..51dd0fd6f 100644
--- a/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c
+++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c
@@ -44,6 +44,51 @@ BOOLEAN mEndOfDxe = FALSE;
///
BOOLEAN mEnableLocking = TRUE;
+//
+// To prevent name collisions with possible future globally defined variables,
+// other internal firmware data variables that are not defined here must be
+// saved with a unique VendorGuid other than EFI_GLOBAL_VARIABLE or
+// any other GUID defined by the UEFI Specification. Implementations must
+// only permit the creation of variables with a UEFI Specification-defined
+// VendorGuid when these variables are documented in the UEFI Specification.
+//
+GLOBAL_VARIABLE_ENTRY mGlobalVariableList[] = {
+ {EFI_LANG_CODES_VARIABLE_NAME, VARIABLE_ATTRIBUTE_BS_RT},
+ {EFI_LANG_VARIABLE_NAME, VARIABLE_ATTRIBUTE_NV_BS_RT},
+ {EFI_TIME_OUT_VARIABLE_NAME, VARIABLE_ATTRIBUTE_NV_BS_RT},
+ {EFI_PLATFORM_LANG_CODES_VARIABLE_NAME, VARIABLE_ATTRIBUTE_BS_RT},
+ {EFI_PLATFORM_LANG_VARIABLE_NAME, VARIABLE_ATTRIBUTE_NV_BS_RT},
+ {EFI_CON_IN_VARIABLE_NAME, VARIABLE_ATTRIBUTE_NV_BS_RT},
+ {EFI_CON_OUT_VARIABLE_NAME, VARIABLE_ATTRIBUTE_NV_BS_RT},
+ {EFI_ERR_OUT_VARIABLE_NAME, VARIABLE_ATTRIBUTE_NV_BS_RT},
+ {EFI_CON_IN_DEV_VARIABLE_NAME, VARIABLE_ATTRIBUTE_BS_RT},
+ {EFI_CON_OUT_DEV_VARIABLE_NAME, VARIABLE_ATTRIBUTE_BS_RT},
+ {EFI_ERR_OUT_DEV_VARIABLE_NAME, VARIABLE_ATTRIBUTE_BS_RT},
+ {EFI_BOOT_ORDER_VARIABLE_NAME, VARIABLE_ATTRIBUTE_NV_BS_RT},
+ {EFI_BOOT_NEXT_VARIABLE_NAME, VARIABLE_ATTRIBUTE_NV_BS_RT},
+ {EFI_BOOT_CURRENT_VARIABLE_NAME, VARIABLE_ATTRIBUTE_BS_RT},
+ {EFI_BOOT_OPTION_SUPPORT_VARIABLE_NAME, VARIABLE_ATTRIBUTE_BS_RT},
+ {EFI_DRIVER_ORDER_VARIABLE_NAME, VARIABLE_ATTRIBUTE_NV_BS_RT},
+ {EFI_HW_ERR_REC_SUPPORT_VARIABLE_NAME, VARIABLE_ATTRIBUTE_NV_BS_RT},
+ {EFI_SETUP_MODE_NAME, VARIABLE_ATTRIBUTE_BS_RT},
+ {EFI_KEY_EXCHANGE_KEY_NAME, VARIABLE_ATTRIBUTE_NV_BS_RT_AT},
+ {EFI_PLATFORM_KEY_NAME, VARIABLE_ATTRIBUTE_NV_BS_RT_AT},
+ {EFI_SIGNATURE_SUPPORT_NAME, VARIABLE_ATTRIBUTE_BS_RT},
+ {EFI_SECURE_BOOT_MODE_NAME, VARIABLE_ATTRIBUTE_BS_RT},
+ {EFI_KEK_DEFAULT_VARIABLE_NAME, VARIABLE_ATTRIBUTE_BS_RT},
+ {EFI_PK_DEFAULT_VARIABLE_NAME, VARIABLE_ATTRIBUTE_BS_RT},
+ {EFI_DB_DEFAULT_VARIABLE_NAME, VARIABLE_ATTRIBUTE_BS_RT},
+ {EFI_DBX_DEFAULT_VARIABLE_NAME, VARIABLE_ATTRIBUTE_BS_RT},
+ {EFI_DBT_DEFAULT_VARIABLE_NAME, VARIABLE_ATTRIBUTE_BS_RT},
+ {EFI_OS_INDICATIONS_SUPPORT_VARIABLE_NAME, VARIABLE_ATTRIBUTE_BS_RT},
+ {EFI_OS_INDICATIONS_VARIABLE_NAME, VARIABLE_ATTRIBUTE_NV_BS_RT},
+ {EFI_VENDOR_KEYS_VARIABLE_NAME, VARIABLE_ATTRIBUTE_BS_RT},
+};
+GLOBAL_VARIABLE_ENTRY mGlobalVariableList2[] = {
+ {L"Boot####", VARIABLE_ATTRIBUTE_NV_BS_RT},
+ {L"Driver####", VARIABLE_ATTRIBUTE_NV_BS_RT},
+ {L"Key####", VARIABLE_ATTRIBUTE_NV_BS_RT},
+};
/**
Routine used to track statistical information about variable usage.
@@ -1236,7 +1281,7 @@ AutoUpdateLangVariable (
SetLanguageCodes = FALSE;
- if (StrCmp (VariableName, L"PlatformLangCodes") == 0) {
+ if (StrCmp (VariableName, EFI_PLATFORM_LANG_CODES_VARIABLE_NAME) == 0) {
//
// PlatformLangCodes is a volatile variable, so it can not be updated at runtime.
//
@@ -1266,7 +1311,7 @@ AutoUpdateLangVariable (
mVariableModuleGlobal->PlatformLang = AllocateRuntimePool (DataSize);
ASSERT (mVariableModuleGlobal->PlatformLang != NULL);
- } else if (StrCmp (VariableName, L"LangCodes") == 0) {
+ } else if (StrCmp (VariableName, EFI_LANG_CODES_VARIABLE_NAME) == 0) {
//
// LangCodes is a volatile variable, so it can not be updated at runtime.
//
@@ -1294,21 +1339,21 @@ AutoUpdateLangVariable (
// Update Lang if PlatformLang is already set
// Update PlatformLang if Lang is already set
//
- Status = FindVariable (L"PlatformLang", &gEfiGlobalVariableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE);
+ Status = FindVariable (EFI_PLATFORM_LANG_VARIABLE_NAME, &gEfiGlobalVariableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE);
if (!EFI_ERROR (Status)) {
//
// Update Lang
//
- VariableName = L"PlatformLang";
+ VariableName = EFI_PLATFORM_LANG_VARIABLE_NAME;
Data = GetVariableDataPtr (Variable.CurrPtr);
DataSize = Variable.CurrPtr->DataSize;
} else {
- Status = FindVariable (L"Lang", &gEfiGlobalVariableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE);
+ Status = FindVariable (EFI_LANG_VARIABLE_NAME, &gEfiGlobalVariableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE);
if (!EFI_ERROR (Status)) {
//
// Update PlatformLang
//
- VariableName = L"Lang";
+ VariableName = EFI_LANG_VARIABLE_NAME;
Data = GetVariableDataPtr (Variable.CurrPtr);
DataSize = Variable.CurrPtr->DataSize;
} else {
@@ -1325,7 +1370,7 @@ AutoUpdateLangVariable (
//
Attributes = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS;
- if (StrCmp (VariableName, L"PlatformLang") == 0) {
+ if (StrCmp (VariableName, EFI_PLATFORM_LANG_VARIABLE_NAME) == 0) {
//
// Update Lang when PlatformLangCodes/LangCodes were set.
//
@@ -1348,9 +1393,9 @@ AutoUpdateLangVariable (
//
// Successfully convert PlatformLang to Lang, and set the BestLang value into Lang variable simultaneously.
//
- FindVariable (L"Lang", &gEfiGlobalVariableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE);
+ FindVariable (EFI_LANG_VARIABLE_NAME, &gEfiGlobalVariableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE);
- Status = UpdateVariable (L"Lang", &gEfiGlobalVariableGuid, BestLang,
+ Status = UpdateVariable (EFI_LANG_VARIABLE_NAME, &gEfiGlobalVariableGuid, BestLang,
ISO_639_2_ENTRY_SIZE + 1, Attributes, &Variable);
DEBUG ((EFI_D_INFO, "Variable Driver Auto Update PlatformLang, PlatformLang:%a, Lang:%a\n", BestPlatformLang, BestLang));
@@ -1359,7 +1404,7 @@ AutoUpdateLangVariable (
}
}
- } else if (StrCmp (VariableName, L"Lang") == 0) {
+ } else if (StrCmp (VariableName, EFI_LANG_VARIABLE_NAME) == 0) {
//
// Update PlatformLang when PlatformLangCodes/LangCodes were set.
//
@@ -1382,9 +1427,9 @@ AutoUpdateLangVariable (
//
// Successfully convert Lang to PlatformLang, and set the BestPlatformLang value into PlatformLang variable simultaneously.
//
- FindVariable (L"PlatformLang", &gEfiGlobalVariableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE);
+ FindVariable (EFI_PLATFORM_LANG_VARIABLE_NAME, &gEfiGlobalVariableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE);
- Status = UpdateVariable (L"PlatformLang", &gEfiGlobalVariableGuid, BestPlatformLang,
+ Status = UpdateVariable (EFI_PLATFORM_LANG_VARIABLE_NAME, &gEfiGlobalVariableGuid, BestPlatformLang,
AsciiStrSize (BestPlatformLang), Attributes, &Variable);
DEBUG ((EFI_D_INFO, "Variable Driver Auto Update Lang, Lang:%a, PlatformLang:%a\n", BestLang, BestPlatformLang));
@@ -1935,6 +1980,63 @@ IsHwErrRecVariable (
}
/**
+ This code checks if variable guid is global variable guid first.
+ If yes, further check if variable name is in mGlobalVariableList or mGlobalVariableList2 and attributes matched.
+
+ @param[in] VariableName Pointer to variable name.
+ @param[in] VendorGuid Variable Vendor Guid.
+ @param[in] Attributes Attributes of the variable.
+
+ @retval EFI_SUCCESS Variable is not global variable, or Variable is global variable, variable name is in the lists and attributes matched.
+ @retval EFI_INVALID_PARAMETER Variable is global variable, but variable name is not in the lists or attributes unmatched.
+
+**/
+EFI_STATUS
+EFIAPI
+CheckEfiGlobalVariable (
+ IN CHAR16 *VariableName,
+ IN EFI_GUID *VendorGuid,
+ IN UINT32 Attributes
+ )
+{
+ UINTN Index;
+ UINTN NameLength;
+
+ if (CompareGuid (VendorGuid, &gEfiGlobalVariableGuid)){
+ //
+ // Try list 1, exactly match.
+ //
+ for (Index = 0; Index < sizeof (mGlobalVariableList)/sizeof (mGlobalVariableList[0]); Index++) {
+ if ((StrCmp (mGlobalVariableList[Index].Name, VariableName) == 0) &&
+ (Attributes == 0 || Attributes == mGlobalVariableList[Index].Attributes)) {
+ return EFI_SUCCESS;
+ }
+ }
+
+ //
+ // Try list 2.
+ //
+ NameLength = StrLen (VariableName) - 4;
+ for (Index = 0; Index < sizeof (mGlobalVariableList2)/sizeof (mGlobalVariableList2[0]); Index++) {
+ if ((StrLen (VariableName) == StrLen (mGlobalVariableList2[Index].Name)) &&
+ (StrnCmp (mGlobalVariableList2[Index].Name, VariableName, NameLength) == 0) &&
+ IsHexaDecimalDigitCharacter (VariableName[NameLength]) &&
+ IsHexaDecimalDigitCharacter (VariableName[NameLength + 1]) &&
+ IsHexaDecimalDigitCharacter (VariableName[NameLength + 2]) &&
+ IsHexaDecimalDigitCharacter (VariableName[NameLength + 3]) &&
+ (Attributes == 0 || Attributes == mGlobalVariableList2[Index].Attributes)) {
+ return EFI_SUCCESS;
+ }
+ }
+
+ DEBUG ((EFI_D_INFO, "[Variable]: set global variable with invalid variable name or attributes - %g:%s:%x\n", VendorGuid, VariableName, Attributes));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
Mark a variable that will become read-only after leaving the DXE phase of execution.
@param[in] This The VARIABLE_LOCK_PROTOCOL instance.
@@ -2275,9 +2377,9 @@ VariableServiceSetVariable (
}
//
- // Not support authenticated variable write yet.
+ // Not support authenticated or append variable write yet.
//
- if ((Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) != 0) {
+ if ((Attributes & (EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS | EFI_VARIABLE_APPEND_WRITE)) != 0) {
return EFI_INVALID_PARAMETER;
}
@@ -2317,6 +2419,11 @@ VariableServiceSetVariable (
}
}
+ Status = CheckEfiGlobalVariable (VariableName, VendorGuid, Attributes);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
AcquireLockOnlyAtBootTime(&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);
//
@@ -2361,6 +2468,16 @@ VariableServiceSetVariable (
Status = EFI_WRITE_PROTECTED;
goto Done;
}
+ if (Attributes != 0 && Attributes != Variable.CurrPtr->Attributes) {
+ //
+ // If a preexisting variable is rewritten with different attributes, SetVariable() shall not
+ // modify the variable and shall return EFI_INVALID_PARAMETER. Two exceptions to this rule:
+ // 1. No access attributes specified
+ // 2. The only attribute differing is EFI_VARIABLE_APPEND_WRITE
+ //
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
}
//
@@ -2583,6 +2700,135 @@ ReclaimForOS(
}
/**
+ Init non-volatile variable store.
+
+ @retval EFI_SUCCESS Function successfully executed.
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate enough memory resource.
+ @retval EFI_VOLUME_CORRUPTED Variable Store or Firmware Volume for Variable Store is corrupted.
+
+**/
+EFI_STATUS
+InitNonVolatileVariableStore (
+ VOID
+ )
+{
+ EFI_FIRMWARE_VOLUME_HEADER *FvHeader;
+ VARIABLE_HEADER *NextVariable;
+ EFI_PHYSICAL_ADDRESS VariableStoreBase;
+ UINT64 VariableStoreLength;
+ UINTN VariableSize;
+ EFI_HOB_GUID_TYPE *GuidHob;
+ EFI_PHYSICAL_ADDRESS NvStorageBase;
+ UINT8 *NvStorageData;
+ UINT32 NvStorageSize;
+ FAULT_TOLERANT_WRITE_LAST_WRITE_DATA *FtwLastWriteData;
+ UINT32 BackUpOffset;
+ UINT32 BackUpSize;
+
+ mVariableModuleGlobal->FvbInstance = NULL;
+
+ //
+ // Note that in EdkII variable driver implementation, Hardware Error Record type variable
+ // is stored with common variable in the same NV region. So the platform integrator should
+ // ensure that the value of PcdHwErrStorageSize is less than or equal to the value of
+ // PcdFlashNvStorageVariableSize.
+ //
+ ASSERT (PcdGet32 (PcdHwErrStorageSize) <= PcdGet32 (PcdFlashNvStorageVariableSize));
+
+ //
+ // Allocate runtime memory used for a memory copy of the FLASH region.
+ // Keep the memory and the FLASH in sync as updates occur.
+ //
+ NvStorageSize = PcdGet32 (PcdFlashNvStorageVariableSize);
+ NvStorageData = AllocateRuntimeZeroPool (NvStorageSize);
+ if (NvStorageData == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ NvStorageBase = (EFI_PHYSICAL_ADDRESS) PcdGet64 (PcdFlashNvStorageVariableBase64);
+ if (NvStorageBase == 0) {
+ NvStorageBase = (EFI_PHYSICAL_ADDRESS) PcdGet32 (PcdFlashNvStorageVariableBase);
+ }
+ //
+ // Copy NV storage data to the memory buffer.
+ //
+ CopyMem (NvStorageData, (UINT8 *) (UINTN) NvStorageBase, NvStorageSize);
+
+ //
+ // Check the FTW last write data hob.
+ //
+ GuidHob = GetFirstGuidHob (&gEdkiiFaultTolerantWriteGuid);
+ if (GuidHob != NULL) {
+ FtwLastWriteData = (FAULT_TOLERANT_WRITE_LAST_WRITE_DATA *) GET_GUID_HOB_DATA (GuidHob);
+ if (FtwLastWriteData->TargetAddress == NvStorageBase) {
+ DEBUG ((EFI_D_INFO, "Variable: NV storage is backed up in spare block: 0x%x\n", (UINTN) FtwLastWriteData->SpareAddress));
+ //
+ // Copy the backed up NV storage data to the memory buffer from spare block.
+ //
+ CopyMem (NvStorageData, (UINT8 *) (UINTN) (FtwLastWriteData->SpareAddress), NvStorageSize);
+ } else if ((FtwLastWriteData->TargetAddress > NvStorageBase) &&
+ (FtwLastWriteData->TargetAddress < (NvStorageBase + NvStorageSize))) {
+ //
+ // Flash NV storage from the offset is backed up in spare block.
+ //
+ BackUpOffset = (UINT32) (FtwLastWriteData->TargetAddress - NvStorageBase);
+ BackUpSize = NvStorageSize - BackUpOffset;
+ DEBUG ((EFI_D_INFO, "Variable: High partial NV storage from offset: %x is backed up in spare block: 0x%x\n", BackUpOffset, (UINTN) FtwLastWriteData->SpareAddress));
+ //
+ // Copy the partial backed up NV storage data to the memory buffer from spare block.
+ //
+ CopyMem (NvStorageData + BackUpOffset, (UINT8 *) (UINTN) FtwLastWriteData->SpareAddress, BackUpSize);
+ }
+ }
+
+ FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) NvStorageData;
+
+ //
+ // Check if the Firmware Volume is not corrupted
+ //
+ if ((FvHeader->Signature != EFI_FVH_SIGNATURE) || (!CompareGuid (&gEfiSystemNvDataFvGuid, &FvHeader->FileSystemGuid))) {
+ FreePool (NvStorageData);
+ DEBUG ((EFI_D_ERROR, "Firmware Volume for Variable Store is corrupted\n"));
+ return EFI_VOLUME_CORRUPTED;
+ }
+
+ VariableStoreBase = (EFI_PHYSICAL_ADDRESS) ((UINTN) FvHeader + FvHeader->HeaderLength);
+ VariableStoreLength = (UINT64) (NvStorageSize - FvHeader->HeaderLength);
+
+ mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase = VariableStoreBase;
+ mNvVariableCache = (VARIABLE_STORE_HEADER *) (UINTN) VariableStoreBase;
+ if (GetVariableStoreStatus (mNvVariableCache) != EfiValid) {
+ FreePool (NvStorageData);
+ DEBUG((EFI_D_ERROR, "Variable Store header is corrupted\n"));
+ return EFI_VOLUME_CORRUPTED;
+ }
+ ASSERT(mNvVariableCache->Size == VariableStoreLength);
+
+ //
+ // The max variable or hardware error variable size should be < variable store size.
+ //
+ ASSERT(MAX (PcdGet32 (PcdMaxVariableSize), PcdGet32 (PcdMaxHardwareErrorVariableSize)) < VariableStoreLength);
+
+ //
+ // Parse non-volatile variable data and get last variable offset.
+ //
+ NextVariable = GetStartPointer ((VARIABLE_STORE_HEADER *)(UINTN)VariableStoreBase);
+ while (IsValidVariableHeader (NextVariable)) {
+ VariableSize = NextVariable->NameSize + NextVariable->DataSize + sizeof (VARIABLE_HEADER);
+ if ((NextVariable->Attributes & (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_HARDWARE_ERROR_RECORD)) == (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {
+ mVariableModuleGlobal->HwErrVariableTotalSize += HEADER_ALIGN (VariableSize);
+ } else {
+ mVariableModuleGlobal->CommonVariableTotalSize += HEADER_ALIGN (VariableSize);
+ }
+
+ NextVariable = GetNextVariablePtr (NextVariable);
+ }
+ mVariableModuleGlobal->NonVolatileLastVariableOffset = (UINTN) NextVariable - (UINTN) VariableStoreBase;
+
+ return EFI_SUCCESS;
+}
+
+/**
Flush the HOB variable to flash.
@param[in] VariableName Name of variable has been updated or deleted.
@@ -2673,7 +2919,7 @@ FlushHobVariableToFlash (
}
/**
- Initializes variable write service after FVB was ready.
+ Initializes variable write service after FTW was ready.
@retval EFI_SUCCESS Function successfully executed.
@retval Others Fail to initialize the variable service.
@@ -2689,8 +2935,18 @@ VariableWriteServiceInitialize (
UINTN Index;
UINT8 Data;
EFI_PHYSICAL_ADDRESS VariableStoreBase;
+ EFI_PHYSICAL_ADDRESS NvStorageBase;
+
+ NvStorageBase = (EFI_PHYSICAL_ADDRESS) PcdGet64 (PcdFlashNvStorageVariableBase64);
+ if (NvStorageBase == 0) {
+ NvStorageBase = (EFI_PHYSICAL_ADDRESS) PcdGet32 (PcdFlashNvStorageVariableBase);
+ }
+ VariableStoreBase = NvStorageBase + (((EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)(NvStorageBase))->HeaderLength);
- VariableStoreBase = mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase;
+ //
+ // Let NonVolatileVariableBase point to flash variable store base directly after FTW ready.
+ //
+ mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase = VariableStoreBase;
VariableStoreHeader = (VARIABLE_STORE_HEADER *)(UINTN)VariableStoreBase;
//
@@ -2737,12 +2993,8 @@ VariableCommonInitialize (
EFI_STATUS Status;
VARIABLE_STORE_HEADER *VolatileVariableStore;
VARIABLE_STORE_HEADER *VariableStoreHeader;
- VARIABLE_HEADER *NextVariable;
- EFI_PHYSICAL_ADDRESS TempVariableStoreHeader;
- EFI_PHYSICAL_ADDRESS VariableStoreBase;
UINT64 VariableStoreLength;
UINTN ScratchSize;
- UINTN VariableSize;
EFI_HOB_GUID_TYPE *GuidHob;
//
@@ -2756,14 +3008,6 @@ VariableCommonInitialize (
InitializeLock (&mVariableModuleGlobal->VariableGlobal.VariableServicesLock, TPL_NOTIFY);
//
- // Note that in EdkII variable driver implementation, Hardware Error Record type variable
- // is stored with common variable in the same NV region. So the platform integrator should
- // ensure that the value of PcdHwErrStorageSize is less than or equal to the value of
- // PcdFlashNvStorageVariableSize.
- //
- ASSERT (PcdGet32 (PcdHwErrStorageSize) <= PcdGet32 (PcdFlashNvStorageVariableSize));
-
- //
// Get HOB variable store.
//
GuidHob = GetFirstGuidHob (&gEfiVariableGuid);
@@ -2773,6 +3017,7 @@ VariableCommonInitialize (
if (GetVariableStoreStatus (VariableStoreHeader) == EfiValid) {
mVariableModuleGlobal->VariableGlobal.HobVariableBase = (EFI_PHYSICAL_ADDRESS) (UINTN) AllocateRuntimeCopyPool ((UINTN) VariableStoreLength, (VOID *) VariableStoreHeader);
if (mVariableModuleGlobal->VariableGlobal.HobVariableBase == 0) {
+ FreePool (mVariableModuleGlobal);
return EFI_OUT_OF_RESOURCES;
}
} else {
@@ -2786,6 +3031,9 @@ VariableCommonInitialize (
ScratchSize = MAX (PcdGet32 (PcdMaxVariableSize), PcdGet32 (PcdMaxHardwareErrorVariableSize));
VolatileVariableStore = AllocateRuntimePool (PcdGet32 (PcdVariableStoreSize) + ScratchSize);
if (VolatileVariableStore == NULL) {
+ if (mVariableModuleGlobal->VariableGlobal.HobVariableBase != 0) {
+ FreePool ((VOID *) (UINTN) mVariableModuleGlobal->VariableGlobal.HobVariableBase);
+ }
FreePool (mVariableModuleGlobal);
return EFI_OUT_OF_RESOURCES;
}
@@ -2797,7 +3045,6 @@ VariableCommonInitialize (
//
mVariableModuleGlobal->VariableGlobal.VolatileVariableBase = (EFI_PHYSICAL_ADDRESS) (UINTN) VolatileVariableStore;
mVariableModuleGlobal->VolatileLastVariableOffset = (UINTN) GetStartPointer (VolatileVariableStore) - (UINTN) VolatileVariableStore;
- mVariableModuleGlobal->FvbInstance = NULL;
CopyGuid (&VolatileVariableStore->Signature, &gEfiVariableGuid);
VolatileVariableStore->Size = PcdGet32 (PcdVariableStoreSize);
@@ -2807,74 +3054,13 @@ VariableCommonInitialize (
VolatileVariableStore->Reserved1 = 0;
//
- // Get non-volatile variable store.
- //
-
- TempVariableStoreHeader = (EFI_PHYSICAL_ADDRESS) PcdGet64 (PcdFlashNvStorageVariableBase64);
- if (TempVariableStoreHeader == 0) {
- TempVariableStoreHeader = (EFI_PHYSICAL_ADDRESS) PcdGet32 (PcdFlashNvStorageVariableBase);
- }
-
- //
- // Check if the Firmware Volume is not corrupted
- //
- if ((((EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)(TempVariableStoreHeader))->Signature != EFI_FVH_SIGNATURE) ||
- (!CompareGuid (&gEfiSystemNvDataFvGuid, &((EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)(TempVariableStoreHeader))->FileSystemGuid))) {
- Status = EFI_VOLUME_CORRUPTED;
- DEBUG ((EFI_D_ERROR, "Firmware Volume for Variable Store is corrupted\n"));
- goto Done;
- }
-
- VariableStoreBase = TempVariableStoreHeader + \
- (((EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)(TempVariableStoreHeader)) -> HeaderLength);
- VariableStoreLength = (UINT64) PcdGet32 (PcdFlashNvStorageVariableSize) - \
- (((EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)(TempVariableStoreHeader)) -> HeaderLength);
-
- mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase = VariableStoreBase;
- VariableStoreHeader = (VARIABLE_STORE_HEADER *)(UINTN)VariableStoreBase;
- if (GetVariableStoreStatus (VariableStoreHeader) != EfiValid) {
- Status = EFI_VOLUME_CORRUPTED;
- DEBUG((EFI_D_INFO, "Variable Store header is corrupted\n"));
- goto Done;
- }
- ASSERT(VariableStoreHeader->Size == VariableStoreLength);
-
- //
- // The max variable or hardware error variable size should be < variable store size.
+ // Init non-volatile variable store.
//
- ASSERT(MAX (PcdGet32 (PcdMaxVariableSize), PcdGet32 (PcdMaxHardwareErrorVariableSize)) < VariableStoreLength);
-
- //
- // Parse non-volatile variable data and get last variable offset.
- //
- NextVariable = GetStartPointer ((VARIABLE_STORE_HEADER *)(UINTN)VariableStoreBase);
- while (IsValidVariableHeader (NextVariable)) {
- VariableSize = NextVariable->NameSize + NextVariable->DataSize + sizeof (VARIABLE_HEADER);
- if ((NextVariable->Attributes & (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_HARDWARE_ERROR_RECORD)) == (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {
- mVariableModuleGlobal->HwErrVariableTotalSize += HEADER_ALIGN (VariableSize);
- } else {
- mVariableModuleGlobal->CommonVariableTotalSize += HEADER_ALIGN (VariableSize);
- }
-
- NextVariable = GetNextVariablePtr (NextVariable);
- }
-
- mVariableModuleGlobal->NonVolatileLastVariableOffset = (UINTN) NextVariable - (UINTN) VariableStoreBase;
-
- //
- // Allocate runtime memory used for a memory copy of the FLASH region.
- // Keep the memory and the FLASH in sync as updates occur
- //
- mNvVariableCache = AllocateRuntimeZeroPool ((UINTN)VariableStoreLength);
- if (mNvVariableCache == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto Done;
- }
- CopyMem (mNvVariableCache, (CHAR8 *)(UINTN)VariableStoreBase, (UINTN)VariableStoreLength);
- Status = EFI_SUCCESS;
-
-Done:
+ Status = InitNonVolatileVariableStore ();
if (EFI_ERROR (Status)) {
+ if (mVariableModuleGlobal->VariableGlobal.HobVariableBase != 0) {
+ FreePool ((VOID *) (UINTN) mVariableModuleGlobal->VariableGlobal.HobVariableBase);
+ }
FreePool (mVariableModuleGlobal);
FreePool (VolatileVariableStore);
}
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.h b/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.h
index b5e6edec9..a10ad8755 100644
--- a/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.h
+++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.h
@@ -39,9 +39,17 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include <Guid/EventGroup.h>
#include <Guid/VariableFormat.h>
#include <Guid/SystemNvDataGuid.h>
+#include <Guid/FaultTolerantWrite.h>
#include <Guid/HardwareErrorVariable.h>
-#define VARIABLE_RECLAIM_THRESHOLD (1024)
+#define VARIABLE_ATTRIBUTE_BS_RT (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS)
+#define VARIABLE_ATTRIBUTE_NV_BS_RT (VARIABLE_ATTRIBUTE_BS_RT | EFI_VARIABLE_NON_VOLATILE)
+#define VARIABLE_ATTRIBUTE_NV_BS_RT_AT (VARIABLE_ATTRIBUTE_NV_BS_RT | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS)
+
+typedef struct {
+ CHAR16 *Name;
+ UINT32 Attributes;
+} GLOBAL_VARIABLE_ENTRY;
///
/// The size of a 3 character ISO639 language code.
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableDxe.c b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableDxe.c
index 3cb2c6bcf..c02d63769 100644
--- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableDxe.c
+++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableDxe.c
@@ -3,6 +3,7 @@
Implement all four UEFI Runtime Variable services for the nonvolatile
and volatile storage space and install variable architecture protocol.
+Copyright (C) 2013, Red Hat, Inc.
Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
@@ -21,6 +22,7 @@ extern VARIABLE_INFO_ENTRY *gVariableInfo;
EFI_HANDLE mHandle = NULL;
EFI_EVENT mVirtualAddressChangeEvent = NULL;
EFI_EVENT mFtwRegistration = NULL;
+extern LIST_ENTRY mLockedVariableList;
extern BOOLEAN mEndOfDxe;
EDKII_VARIABLE_LOCK_PROTOCOL mVariableLock = { VariableLockRequestToLock };
@@ -220,6 +222,10 @@ VariableClassAddressChangeEvent (
IN VOID *Context
)
{
+ LIST_ENTRY *Link;
+ VARIABLE_ENTRY *Entry;
+ EFI_STATUS Status;
+
EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->FvbInstance->GetBlockSize);
EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->FvbInstance->GetPhysicalAddress);
EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->FvbInstance->GetAttributes);
@@ -236,6 +242,23 @@ VariableClassAddressChangeEvent (
EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->VariableGlobal.HobVariableBase);
EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal);
EfiConvertPointer (0x0, (VOID **) &mNvVariableCache);
+
+ //
+ // in the list of locked variables, convert the name pointers first
+ //
+ for ( Link = GetFirstNode (&mLockedVariableList)
+ ; !IsNull (&mLockedVariableList, Link)
+ ; Link = GetNextNode (&mLockedVariableList, Link)
+ ) {
+ Entry = BASE_CR (Link, VARIABLE_ENTRY, Link);
+ Status = EfiConvertPointer (0x0, (VOID **) &Entry->Name);
+ ASSERT_EFI_ERROR (Status);
+ }
+ //
+ // second, convert the list itself using UefiRuntimeLib
+ //
+ Status = EfiConvertList (0x0, &mLockedVariableList);
+ ASSERT_EFI_ERROR (Status);
}
@@ -312,6 +335,7 @@ FtwNotificationEvent (
UINT64 Length;
EFI_PHYSICAL_ADDRESS VariableStoreBase;
UINT64 VariableStoreLength;
+ UINTN FtwMaxBlockSize;
//
// Ensure FTW protocol is installed.
@@ -320,7 +344,12 @@ FtwNotificationEvent (
if (EFI_ERROR (Status)) {
return ;
}
-
+
+ Status = FtwProtocol->GetMaxBlockSize (FtwProtocol, &FtwMaxBlockSize);
+ if (!EFI_ERROR (Status)) {
+ ASSERT (PcdGet32 (PcdFlashNvStorageVariableSize) <= FtwMaxBlockSize);
+ }
+
//
// Find the proper FVB protocol for variable.
//
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf
index 8cbefefa1..c712ba020 100644
--- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf
+++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf
@@ -68,6 +68,7 @@
gEfiSystemNvDataFvGuid ## CONSUMES
gEfiHardwareErrorVariableGuid ## SOMETIMES_CONSUMES
gEfiEndOfDxeEventGroupGuid ## CONSUMES ## Event
+ gEdkiiFaultTolerantWriteGuid ## CONSUMES
[Pcd]
gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.c b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.c
index 1ffa74e6c..a80948bce 100644
--- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.c
+++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.c
@@ -792,6 +792,7 @@ SmmFtwNotificationEvent (
EFI_SMM_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvbProtocol;
EFI_SMM_FAULT_TOLERANT_WRITE_PROTOCOL *FtwProtocol;
EFI_PHYSICAL_ADDRESS NvStorageVariableBase;
+ UINTN FtwMaxBlockSize;
if (mVariableModuleGlobal->FvbInstance != NULL) {
return EFI_SUCCESS;
@@ -805,6 +806,11 @@ SmmFtwNotificationEvent (
return Status;
}
+ Status = FtwProtocol->GetMaxBlockSize (FtwProtocol, &FtwMaxBlockSize);
+ if (!EFI_ERROR (Status)) {
+ ASSERT (PcdGet32 (PcdFlashNvStorageVariableSize) <= FtwMaxBlockSize);
+ }
+
//
// Find the proper FVB protocol for variable.
//
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf
index c229805bc..89ec686ca 100644
--- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf
+++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf
@@ -77,6 +77,7 @@
gSmmVariableWriteGuid ## PRODUCES ## SMM Variable Write Guid
gEfiSystemNvDataFvGuid ## CONSUMES
gEfiHardwareErrorVariableGuid ## SOMETIMES_CONSUMES
+ gEdkiiFaultTolerantWriteGuid ## CONSUMES
[Pcd]
gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize