summaryrefslogtreecommitdiff
path: root/MdeModulePkg
diff options
context:
space:
mode:
Diffstat (limited to 'MdeModulePkg')
-rw-r--r--MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBus.c27
-rw-r--r--MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c46
-rw-r--r--MdeModulePkg/Bus/Pci/XhciDxe/Xhci.c8
-rw-r--r--MdeModulePkg/Bus/Usb/UsbBusDxe/UsbDesc.c9
-rw-r--r--MdeModulePkg/Include/Guid/FirmwarePerformance.h14
-rw-r--r--MdeModulePkg/Include/Guid/Performance.h3
-rw-r--r--MdeModulePkg/Include/Guid/SmmVariableCommon.h10
-rw-r--r--MdeModulePkg/Include/Protocol/VariableLock.h63
-rw-r--r--MdeModulePkg/Library/DxeNetLib/DxeNetLib.c43
-rw-r--r--MdeModulePkg/Library/SmmCorePerformanceLib/SmmCorePerformanceLib.c89
-rw-r--r--MdeModulePkg/MdeModulePkg.dec5
-rw-r--r--MdeModulePkg/MdeModulePkg.dsc8
-rw-r--r--MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/X64/S3Asm.S8
-rw-r--r--MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTableDxe/FirmwarePerformanceDxe.c240
-rw-r--r--MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTableDxe/FirmwarePerformanceDxe.inf7
-rw-r--r--MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTablePei/FirmwarePerformancePei.c37
-rw-r--r--MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTablePei/FirmwarePerformancePei.inf4
-rw-r--r--MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTableSmm/FirmwarePerformanceSmm.c50
-rw-r--r--MdeModulePkg/Universal/DevicePathDxe/DevicePathFromText.c100
-rw-r--r--MdeModulePkg/Universal/DevicePathDxe/DevicePathToText.c36
-rw-r--r--MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmm.c184
-rw-r--r--MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmm.inf3
-rw-r--r--MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmmDxe.c10
-rw-r--r--MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmmDxe.inf7
-rw-r--r--MdeModulePkg/Universal/LockBox/SmmLockBox/SmmLockBox.c80
-rw-r--r--MdeModulePkg/Universal/Network/IScsiDxe/IScsiProto.c4
-rw-r--r--MdeModulePkg/Universal/Network/Ip4ConfigDxe/Ip4ConfigDriver.c6
-rw-r--r--MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Driver.c33
-rw-r--r--MdeModulePkg/Universal/Network/Ip4Dxe/Ip4If.c36
-rw-r--r--MdeModulePkg/Universal/Network/Tcp4Dxe/Tcp4Driver.c14
-rw-r--r--MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcDhcp.c14
-rw-r--r--MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcDhcp.h3
-rw-r--r--MdeModulePkg/Universal/Network/UefiPxeBcDxe/UefiPxeBcDxe.inf5
-rw-r--r--MdeModulePkg/Universal/SetupBrowserDxe/IfrParse.c398
-rw-r--r--MdeModulePkg/Universal/SetupBrowserDxe/InputHandler.c30
-rw-r--r--MdeModulePkg/Universal/SetupBrowserDxe/Setup.c557
-rw-r--r--MdeModulePkg/Universal/SetupBrowserDxe/Setup.h54
-rw-r--r--MdeModulePkg/Universal/Variable/EmuRuntimeDxe/EmuVariable.c17
-rw-r--r--MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c118
-rw-r--r--MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.h32
-rw-r--r--MdeModulePkg/Universal/Variable/RuntimeDxe/VariableDxe.c51
-rw-r--r--MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf6
-rw-r--r--MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.c288
-rw-r--r--MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf3
-rw-r--r--MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.c194
-rw-r--r--MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.inf3
46 files changed, 2206 insertions, 751 deletions
diff --git a/MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBus.c b/MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBus.c
index 11e90f97a9..6732fd5e0d 100644
--- a/MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBus.c
+++ b/MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBus.c
@@ -4,7 +4,7 @@
This file implements protocol interfaces: Driver Binding protocol,
Block IO protocol and DiskInfo protocol.
- 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
@@ -630,11 +630,36 @@ AtaBusDriverBindingSupported (
}
//
+ // Test to see if this ATA Pass Thru Protocol is for a LOGICAL channel
+ //
+ if ((AtaPassThru->Mode->Attributes & EFI_ATA_PASS_THRU_ATTRIBUTES_LOGICAL) == 0) {
+ //
+ // Close the I/O Abstraction(s) used to perform the supported test
+ //
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiAtaPassThruProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ return EFI_UNSUPPORTED;
+ }
+
+ //
// Test RemainingDevicePath is valid or not.
//
if ((RemainingDevicePath != NULL) && !IsDevicePathEnd (RemainingDevicePath)) {
Status = AtaPassThru->GetDevice (AtaPassThru, RemainingDevicePath, &Port, &PortMultiplierPort);
if (EFI_ERROR (Status)) {
+ //
+ // Close the I/O Abstraction(s) used to perform the supported test
+ //
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiAtaPassThruProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
return Status;
}
}
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c
index e17f4bae44..d8d988cbfc 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c
@@ -1,7 +1,7 @@
/** @file
PCI resouces support functions implemntation for PCI Bus 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
@@ -1472,7 +1472,14 @@ ProgramPpbApperture (
case PPB_BAR_0:
case PPB_BAR_1:
- PciIo->Pci.Write (
+ switch ((Node->PciDev->PciBar[Node->Bar]).BarType) {
+
+ case PciBarTypeIo16:
+ case PciBarTypeIo32:
+ case PciBarTypeMem32:
+ case PciBarTypePMem32:
+
+ PciIo->Pci.Write (
PciIo,
EfiPciIoWidthUint32,
(Node->PciDev->PciBar[Node->Bar]).Offset,
@@ -1480,9 +1487,40 @@ ProgramPpbApperture (
&Address
);
- Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
- Node->PciDev->PciBar[Node->Bar].Length = Node->Length;
+ Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
+ Node->PciDev->PciBar[Node->Bar].Length = Node->Length;
+ break;
+
+ case PciBarTypeMem64:
+ case PciBarTypePMem64:
+ Address32 = (UINT32) (Address & 0x00000000FFFFFFFF);
+
+ PciIo->Pci.Write (
+ PciIo,
+ EfiPciIoWidthUint32,
+ (Node->PciDev->PciBar[Node->Bar]).Offset,
+ 1,
+ &Address32
+ );
+
+ Address32 = (UINT32) RShiftU64 (Address, 32);
+
+ PciIo->Pci.Write (
+ PciIo,
+ EfiPciIoWidthUint32,
+ (UINT8) ((Node->PciDev->PciBar[Node->Bar]).Offset + 4),
+ 1,
+ &Address32
+ );
+
+ Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
+ Node->PciDev->PciBar[Node->Bar].Length = Node->Length;
+ break;
+
+ default:
+ break;
+ }
break;
case PPB_IO_RANGE:
diff --git a/MdeModulePkg/Bus/Pci/XhciDxe/Xhci.c b/MdeModulePkg/Bus/Pci/XhciDxe/Xhci.c
index 5809a0f914..8e6bc6ff64 100644
--- a/MdeModulePkg/Bus/Pci/XhciDxe/Xhci.c
+++ b/MdeModulePkg/Bus/Pci/XhciDxe/Xhci.c
@@ -932,9 +932,9 @@ XhcControlTransfer (
}
Xhc->UsbDevContext[SlotId].ConfDesc = AllocateZeroPool (Xhc->UsbDevContext[SlotId].DevDesc.NumConfigurations * sizeof (EFI_USB_CONFIG_DESCRIPTOR *));
if (Xhc->HcCParams.Data.Csz == 0) {
- Status = XhcEvaluateContext (Xhc, SlotId, MaxPacket0);
+ Status = XhcEvaluateContext (Xhc, SlotId, MaxPacket0);
} else {
- Status = XhcEvaluateContext64 (Xhc, SlotId, MaxPacket0);
+ Status = XhcEvaluateContext64 (Xhc, SlotId, MaxPacket0);
}
ASSERT_EFI_ERROR (Status);
} else if (DescriptorType == USB_DESC_TYPE_CONFIG) {
@@ -1802,6 +1802,8 @@ XhcExitBootService (
gBS->CloseEvent (Xhc->PollTimer);
}
+ XhcClearBiosOwnership (Xhc);
+
//
// Restore original PCI attributes
//
@@ -1811,8 +1813,6 @@ XhcExitBootService (
Xhc->OriginalPciAttributes,
NULL
);
-
- XhcClearBiosOwnership (Xhc);
}
/**
diff --git a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbDesc.c b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbDesc.c
index 35cdaf5527..1713e3c421 100644
--- a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbDesc.c
+++ b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbDesc.c
@@ -786,10 +786,13 @@ UsbBuildDescTable (
return Status;
}
- DevDesc = UsbDev->DevDesc;
- NumConfig = DevDesc->Desc.NumConfigurations;
- DevDesc->Configs = AllocateZeroPool (NumConfig * sizeof (USB_CONFIG_DESC *));
+ DevDesc = UsbDev->DevDesc;
+ NumConfig = DevDesc->Desc.NumConfigurations;
+ if (NumConfig == 0) {
+ return EFI_DEVICE_ERROR;
+ }
+ DevDesc->Configs = AllocateZeroPool (NumConfig * sizeof (USB_CONFIG_DESC *));
if (DevDesc->Configs == NULL) {
return EFI_OUT_OF_RESOURCES;
}
diff --git a/MdeModulePkg/Include/Guid/FirmwarePerformance.h b/MdeModulePkg/Include/Guid/FirmwarePerformance.h
index 7da07f9ea7..a4aeda2759 100644
--- a/MdeModulePkg/Include/Guid/FirmwarePerformance.h
+++ b/MdeModulePkg/Include/Guid/FirmwarePerformance.h
@@ -1,7 +1,7 @@
/** @file
ACPI Firmware Performance Data Table (FPDT) implementation specific definitions.
- 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
@@ -50,6 +50,15 @@
#define EFI_FIRMWARE_PERFORMANCE_VARIABLE_NAME L"FirmwarePerformance"
+/// LockBox:
+/// GUID - gFirmwarePerformanceS3PointerGuid
+/// Data - S3 performance table pointer
+///
+#define FIRMWARE_PERFORMANCE_S3_POINTER_GUID \
+ { \
+ 0xdc65adc, 0xa973, 0x4130, { 0x8d, 0xf0, 0x2a, 0xdb, 0xeb, 0x9e, 0x4a, 0x31 } \
+ }
+
#pragma pack(1)
///
@@ -95,7 +104,7 @@ typedef struct {
///
/// Variable defined for FPDT implementation.
-/// This Variable is produced by FPDT DXE module and consumed by FPDT PEIM.
+/// This Variable is produced by FPDT DXE module.
///
typedef struct {
EFI_PHYSICAL_ADDRESS BootPerformanceTablePointer; ///< Pointer to Boot Performance Table.
@@ -118,5 +127,6 @@ typedef struct {
} SMM_BOOT_RECORD_COMMUNICATE;
extern EFI_GUID gEfiFirmwarePerformanceGuid;
+extern EFI_GUID gFirmwarePerformanceS3PointerGuid;
#endif
diff --git a/MdeModulePkg/Include/Guid/Performance.h b/MdeModulePkg/Include/Guid/Performance.h
index d7768e1fc1..c40046c878 100644
--- a/MdeModulePkg/Include/Guid/Performance.h
+++ b/MdeModulePkg/Include/Guid/Performance.h
@@ -4,7 +4,7 @@
* performance protocol interfaces.
* performance variables.
-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 that accompanies this distribution.
The full text of the license may be found at
@@ -48,6 +48,7 @@ typedef struct {
#define PERF_TOKEN_SIZE 28
#define PERF_TOKEN_LENGTH (PERF_TOKEN_SIZE - 1)
#define PERF_PEI_ENTRY_MAX_NUM 50
+#define PERF_DATA_MAX_LENGTH 0x4000
typedef struct {
CHAR8 Token[PERF_TOKEN_SIZE];
diff --git a/MdeModulePkg/Include/Guid/SmmVariableCommon.h b/MdeModulePkg/Include/Guid/SmmVariableCommon.h
index c7fde00ca2..a2daae8fe3 100644
--- a/MdeModulePkg/Include/Guid/SmmVariableCommon.h
+++ b/MdeModulePkg/Include/Guid/SmmVariableCommon.h
@@ -1,7 +1,7 @@
/** @file
The file defined some common structures used for communicating between SMM variable module and SMM variable wrapper module.
-Copyright (c) 2011, 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 that accompanies this distribution.
The full text of the license may be found at
@@ -60,6 +60,10 @@ typedef struct {
// is gEfiSmmVariableProtocolGuid.
//
#define SMM_VARIABLE_FUNCTION_GET_STATISTICS 7
+//
+// The payload for this function is SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE
+//
+#define SMM_VARIABLE_FUNCTION_LOCK_VARIABLE 8
///
/// Size of SMM communicate header, without including the payload.
@@ -87,7 +91,7 @@ typedef struct {
///
typedef struct {
EFI_GUID Guid;
- UINTN NameSize;
+ UINTN NameSize; // Return name buffer size
CHAR16 Name[1];
} SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME;
@@ -101,4 +105,6 @@ typedef struct {
UINT32 Attributes;
} SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO;
+typedef SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE;
+
#endif // _SMM_VARIABLE_COMMON_H_ \ No newline at end of file
diff --git a/MdeModulePkg/Include/Protocol/VariableLock.h b/MdeModulePkg/Include/Protocol/VariableLock.h
new file mode 100644
index 0000000000..a2a73bc161
--- /dev/null
+++ b/MdeModulePkg/Include/Protocol/VariableLock.h
@@ -0,0 +1,63 @@
+/** @file
+ Variable Lock Protocol is related to EDK II-specific implementation of variables
+ and intended for use as a means to mark a variable read-only after the event
+ EFI_END_OF_DXE_EVENT_GUID is signaled.
+
+ 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 __VARIABLE_LOCK_H__
+#define __VARIABLE_LOCK_H__
+
+#define EDKII_VARIABLE_LOCK_PROTOCOL_GUID \
+ { \
+ 0xcd3d0a05, 0x9e24, 0x437c, { 0xa8, 0x91, 0x1e, 0xe0, 0x53, 0xdb, 0x76, 0x38 } \
+ }
+
+typedef struct _EDKII_VARIABLE_LOCK_PROTOCOL EDKII_VARIABLE_LOCK_PROTOCOL;
+
+/**
+ Mark a variable that will become read-only after leaving the DXE phase of execution.
+ Write request coming from SMM environment through EFI_SMM_VARIABLE_PROTOCOL is allowed.
+
+ @param[in] This The EDKII_VARIABLE_LOCK_PROTOCOL instance.
+ @param[in] VariableName A pointer to the variable name that will be made read-only subsequently.
+ @param[in] VendorGuid A pointer to the vendor GUID that will be made read-only subsequently.
+
+ @retval EFI_SUCCESS The variable specified by the VariableName and the VendorGuid was marked
+ as pending to be read-only.
+ @retval EFI_INVALID_PARAMETER VariableName or VendorGuid is NULL.
+ Or VariableName is an empty string.
+ @retval EFI_ACCESS_DENIED EFI_END_OF_DXE_EVENT_GROUP_GUID or EFI_EVENT_GROUP_READY_TO_BOOT has
+ already been signaled.
+ @retval EFI_OUT_OF_RESOURCES There is not enough resource to hold the lock request.
+**/
+typedef
+EFI_STATUS
+(EFIAPI * EDKII_VARIABLE_LOCK_PROTOCOL_REQUEST_TO_LOCK) (
+ IN CONST EDKII_VARIABLE_LOCK_PROTOCOL *This,
+ IN CHAR16 *VariableName,
+ IN EFI_GUID *VendorGuid
+ );
+
+///
+/// Variable Lock Protocol is related to EDK II-specific implementation of variables
+/// and intended for use as a means to mark a variable read-only after the event
+/// EFI_END_OF_DXE_EVENT_GUID is signaled.
+///
+struct _EDKII_VARIABLE_LOCK_PROTOCOL {
+ EDKII_VARIABLE_LOCK_PROTOCOL_REQUEST_TO_LOCK RequestToLock;
+};
+
+extern EFI_GUID gEdkiiVariableLockProtocolGuid;
+
+#endif
+
diff --git a/MdeModulePkg/Library/DxeNetLib/DxeNetLib.c b/MdeModulePkg/Library/DxeNetLib/DxeNetLib.c
index 61e4c8c9d1..cfda3962bb 100644
--- a/MdeModulePkg/Library/DxeNetLib/DxeNetLib.c
+++ b/MdeModulePkg/Library/DxeNetLib/DxeNetLib.c
@@ -1,7 +1,7 @@
/** @file
Network library.
-Copyright (c) 2005 - 2012, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2005 - 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
@@ -1788,6 +1788,7 @@ NetLibDefaultUnload (
EFI_HANDLE *DeviceHandleBuffer;
UINTN DeviceHandleCount;
UINTN Index;
+ UINTN Index2;
EFI_DRIVER_BINDING_PROTOCOL *DriverBinding;
EFI_COMPONENT_NAME_PROTOCOL *ComponentName;
EFI_COMPONENT_NAME2_PROTOCOL *ComponentName2;
@@ -1809,28 +1810,12 @@ NetLibDefaultUnload (
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;
}
@@ -1838,12 +1823,28 @@ NetLibDefaultUnload (
if (DriverBinding->ImageHandle != ImageHandle) {
continue;
}
-
+
+ //
+ // Disconnect the driver specified by ImageHandle from all
+ // the devices in the handle database.
+ //
+ for (Index2 = 0; Index2 < DeviceHandleCount; Index2++) {
+ Status = gBS->DisconnectController (
+ DeviceHandleBuffer[Index2],
+ DriverBinding->DriverBindingHandle,
+ NULL
+ );
+ }
+
+ //
+ // Uninstall all the protocols installed in the driver entry point
+ //
gBS->UninstallProtocolInterface (
- ImageHandle,
+ DriverBinding->DriverBindingHandle,
&gEfiDriverBindingProtocolGuid,
DriverBinding
);
+
Status = gBS->HandleProtocol (
DeviceHandleBuffer[Index],
&gEfiComponentNameProtocolGuid,
@@ -1851,7 +1852,7 @@ NetLibDefaultUnload (
);
if (!EFI_ERROR (Status)) {
gBS->UninstallProtocolInterface (
- ImageHandle,
+ DriverBinding->DriverBindingHandle,
&gEfiComponentNameProtocolGuid,
ComponentName
);
@@ -1864,7 +1865,7 @@ NetLibDefaultUnload (
);
if (!EFI_ERROR (Status)) {
gBS->UninstallProtocolInterface (
- ImageHandle,
+ DriverBinding->DriverBindingHandle,
&gEfiComponentName2ProtocolGuid,
ComponentName2
);
diff --git a/MdeModulePkg/Library/SmmCorePerformanceLib/SmmCorePerformanceLib.c b/MdeModulePkg/Library/SmmCorePerformanceLib/SmmCorePerformanceLib.c
index 314d46d03a..f95079bd27 100644
--- a/MdeModulePkg/Library/SmmCorePerformanceLib/SmmCorePerformanceLib.c
+++ b/MdeModulePkg/Library/SmmCorePerformanceLib/SmmCorePerformanceLib.c
@@ -16,7 +16,7 @@
SmmPerformanceHandlerEx(), SmmPerformanceHandler() will receive untrusted input and do basic validation.
-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
@@ -478,6 +478,33 @@ IsAddressInSmram (
}
/**
+ This function check if the address refered by Buffer and Length is valid.
+
+ @param Buffer the buffer address to be checked.
+ @param Length the buffer length to be checked.
+
+ @retval TRUE this address is valid.
+ @retval FALSE this address is NOT valid.
+**/
+BOOLEAN
+IsAddressValid (
+ IN UINTN Buffer,
+ IN UINTN Length
+ )
+{
+ if (Buffer > (MAX_ADDRESS - Length)) {
+ //
+ // Overflow happen
+ //
+ return FALSE;
+ }
+ if (IsAddressInSmram ((EFI_PHYSICAL_ADDRESS)Buffer, (UINT64)Length)) {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/**
Communication service SMI Handler entry.
This SMI handler provides services for the performance wrapper driver.
@@ -513,6 +540,10 @@ SmmPerformanceHandlerEx (
SMM_PERF_COMMUNICATE_EX *SmmPerfCommData;
GAUGE_DATA_ENTRY_EX *GaugeEntryExArray;
UINTN DataSize;
+ GAUGE_DATA_ENTRY_EX *GaugeDataEx;
+ UINTN NumberOfEntries;
+ UINTN LogEntryKey;
+ UINTN TempCommBufferSize;
GaugeEntryExArray = NULL;
@@ -523,12 +554,14 @@ SmmPerformanceHandlerEx (
return EFI_SUCCESS;
}
- if(*CommBufferSize < sizeof (SMM_PERF_COMMUNICATE_EX)) {
+ TempCommBufferSize = *CommBufferSize;
+
+ if(TempCommBufferSize < sizeof (SMM_PERF_COMMUNICATE_EX)) {
return EFI_SUCCESS;
}
- if (IsAddressInSmram ((EFI_PHYSICAL_ADDRESS)(UINTN)CommBuffer, *CommBufferSize)) {
- DEBUG ((EFI_D_ERROR, "SMM communcation data buffer is in SMRAM!\n"));
+ if (!IsAddressValid ((UINTN)CommBuffer, TempCommBufferSize)) {
+ DEBUG ((EFI_D_ERROR, "SmmPerformanceHandlerEx: SMM communcation data buffer in SMRAM or overflow!\n"));
return EFI_SUCCESS;
}
@@ -541,8 +574,11 @@ SmmPerformanceHandlerEx (
break;
case SMM_PERF_FUNCTION_GET_GAUGE_DATA :
- if ( SmmPerfCommData->GaugeDataEx == NULL || SmmPerfCommData->NumberOfEntries == 0 ||
- (SmmPerfCommData->LogEntryKey + SmmPerfCommData->NumberOfEntries) > mGaugeData->NumberOfEntries) {
+ GaugeDataEx = SmmPerfCommData->GaugeDataEx;
+ NumberOfEntries = SmmPerfCommData->NumberOfEntries;
+ LogEntryKey = SmmPerfCommData->LogEntryKey;
+ if (GaugeDataEx == NULL || NumberOfEntries == 0 || LogEntryKey > mGaugeData->NumberOfEntries ||
+ NumberOfEntries > mGaugeData->NumberOfEntries || (LogEntryKey + NumberOfEntries) > mGaugeData->NumberOfEntries) {
Status = EFI_INVALID_PARAMETER;
break;
}
@@ -550,17 +586,17 @@ SmmPerformanceHandlerEx (
//
// Sanity check
//
- DataSize = SmmPerfCommData->NumberOfEntries * sizeof(GAUGE_DATA_ENTRY_EX);
- if (IsAddressInSmram ((EFI_PHYSICAL_ADDRESS)(UINTN)SmmPerfCommData->GaugeDataEx, DataSize)) {
- DEBUG ((EFI_D_ERROR, "SMM Performance Data buffer is in SMRAM!\n"));
+ DataSize = NumberOfEntries * sizeof(GAUGE_DATA_ENTRY_EX);
+ if (!IsAddressValid ((UINTN)GaugeDataEx, DataSize)) {
+ DEBUG ((EFI_D_ERROR, "SmmPerformanceHandlerEx: SMM Performance Data buffer in SMRAM or overflow!\n"));
Status = EFI_ACCESS_DENIED;
break;
}
GaugeEntryExArray = (GAUGE_DATA_ENTRY_EX *) (mGaugeData + 1);
CopyMem(
- (UINT8 *) (SmmPerfCommData->GaugeDataEx),
- (UINT8 *) &GaugeEntryExArray[SmmPerfCommData->LogEntryKey],
+ (UINT8 *) GaugeDataEx,
+ (UINT8 *) &GaugeEntryExArray[LogEntryKey],
DataSize
);
Status = EFI_SUCCESS;
@@ -613,8 +649,11 @@ SmmPerformanceHandler (
GAUGE_DATA_ENTRY_EX *GaugeEntryExArray;
UINTN DataSize;
UINTN Index;
+ GAUGE_DATA_ENTRY *GaugeData;
+ UINTN NumberOfEntries;
UINTN LogEntryKey;
-
+ UINTN TempCommBufferSize;
+
GaugeEntryExArray = NULL;
//
@@ -624,12 +663,14 @@ SmmPerformanceHandler (
return EFI_SUCCESS;
}
- if(*CommBufferSize < sizeof (SMM_PERF_COMMUNICATE)) {
+ TempCommBufferSize = *CommBufferSize;
+
+ if(TempCommBufferSize < sizeof (SMM_PERF_COMMUNICATE)) {
return EFI_SUCCESS;
}
- if (IsAddressInSmram ((EFI_PHYSICAL_ADDRESS)(UINTN)CommBuffer, *CommBufferSize)) {
- DEBUG ((EFI_D_ERROR, "SMM communcation data buffer is in SMRAM!\n"));
+ if (!IsAddressValid ((UINTN)CommBuffer, TempCommBufferSize)) {
+ DEBUG ((EFI_D_ERROR, "SmmPerformanceHandler: SMM communcation data buffer in SMRAM or overflow!\n"));
return EFI_SUCCESS;
}
@@ -642,8 +683,11 @@ SmmPerformanceHandler (
break;
case SMM_PERF_FUNCTION_GET_GAUGE_DATA :
- if ( SmmPerfCommData->GaugeData == NULL || SmmPerfCommData->NumberOfEntries == 0 ||
- (SmmPerfCommData->LogEntryKey + SmmPerfCommData->NumberOfEntries) > mGaugeData->NumberOfEntries) {
+ GaugeData = SmmPerfCommData->GaugeData;
+ NumberOfEntries = SmmPerfCommData->NumberOfEntries;
+ LogEntryKey = SmmPerfCommData->LogEntryKey;
+ if (GaugeData == NULL || NumberOfEntries == 0 || LogEntryKey > mGaugeData->NumberOfEntries ||
+ NumberOfEntries > mGaugeData->NumberOfEntries || (LogEntryKey + NumberOfEntries) > mGaugeData->NumberOfEntries) {
Status = EFI_INVALID_PARAMETER;
break;
}
@@ -651,19 +695,18 @@ SmmPerformanceHandler (
//
// Sanity check
//
- DataSize = SmmPerfCommData->NumberOfEntries * sizeof(GAUGE_DATA_ENTRY);
- if (IsAddressInSmram ((EFI_PHYSICAL_ADDRESS)(UINTN)SmmPerfCommData->GaugeData, DataSize)) {
- DEBUG ((EFI_D_ERROR, "SMM Performance Data buffer is in SMRAM!\n"));
+ DataSize = NumberOfEntries * sizeof(GAUGE_DATA_ENTRY);
+ if (!IsAddressValid ((UINTN)GaugeData, DataSize)) {
+ DEBUG ((EFI_D_ERROR, "SmmPerformanceHandler: SMM Performance Data buffer in SMRAM or overflow!\n"));
Status = EFI_ACCESS_DENIED;
break;
}
GaugeEntryExArray = (GAUGE_DATA_ENTRY_EX *) (mGaugeData + 1);
- LogEntryKey = SmmPerfCommData->LogEntryKey;
- for (Index = 0; Index < SmmPerfCommData->NumberOfEntries; Index++) {
+ for (Index = 0; Index < NumberOfEntries; Index++) {
CopyMem(
- (UINT8 *) &(SmmPerfCommData->GaugeData[Index]),
+ (UINT8 *) &GaugeData[Index],
(UINT8 *) &GaugeEntryExArray[LogEntryKey++],
sizeof (GAUGE_DATA_ENTRY)
);
diff --git a/MdeModulePkg/MdeModulePkg.dec b/MdeModulePkg/MdeModulePkg.dec
index ba80b809dc..3c07c69a97 100644
--- a/MdeModulePkg/MdeModulePkg.dec
+++ b/MdeModulePkg/MdeModulePkg.dec
@@ -246,6 +246,7 @@
## Guid for Firmware Performance Data Table (FPDT) implementation.
# Include/Guid/FirmwarePerformance.h
gEfiFirmwarePerformanceGuid = { 0xc095791a, 0x3001, 0x47b2, { 0x80, 0xc9, 0xea, 0xc7, 0x31, 0x9f, 0x2f, 0xa4 }}
+ gFirmwarePerformanceS3PointerGuid = { 0xdc65adc, 0xa973, 0x4130, { 0x8d, 0xf0, 0x2a, 0xdb, 0xeb, 0x9e, 0x4a, 0x31 }}
## Include/Guid/ExitBootServiceFailed.h
gEventExitBootServicesFailedGuid = { 0x4f6c5507, 0x232f, 0x4787, { 0xb9, 0x5e, 0x72, 0xf8, 0x62, 0x49, 0xc, 0xb1 } }
@@ -325,6 +326,10 @@
# Include/Protocol/SmmVariableProtocol.h
gEfiSmmVariableProtocolGuid = { 0xed32d533, 0x99e6, 0x4209, { 0x9c, 0xc0, 0x2d, 0x72, 0xcd, 0xd9, 0x98, 0xa7 }}
+ ## This protocol is intended for use as a means to mark a variable read-only after the event EFI_END_OF_DXE_EVENT_GUID is signaled.
+ # Include/Protocol/VariableLock.h
+ gEdkiiVariableLockProtocolGuid = { 0xcd3d0a05, 0x9e24, 0x437c, { 0xa8, 0x91, 0x1e, 0xe0, 0x53, 0xdb, 0x76, 0x38 }}
+
## This protocol is similar with DXE FVB protocol and used in the UEFI SMM evvironment.
# Include/Protocol/SmmFirmwareVolumeBlock.h
gEfiSmmFirmwareVolumeBlockProtocolGuid = { 0xd326d041, 0xbd31, 0x4c01, { 0xb5, 0xa8, 0x62, 0x8b, 0xe8, 0x7f, 0x6, 0x53 }}
diff --git a/MdeModulePkg/MdeModulePkg.dsc b/MdeModulePkg/MdeModulePkg.dsc
index 835f621b69..444cd8358c 100644
--- a/MdeModulePkg/MdeModulePkg.dsc
+++ b/MdeModulePkg/MdeModulePkg.dsc
@@ -1,7 +1,7 @@
## @file
# EFI/PI Reference Module Package for All Architectures
#
-# 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
@@ -151,6 +151,8 @@
#
NULL|ArmPkg/Library/CompilerIntrinsicsLib/CompilerIntrinsicsLib.inf
+[LibraryClasses.EBC]
+ LockBoxLib|MdeModulePkg/Library/LockBoxNullLib/LockBoxNullLib.inf
[PcdsFeatureFlag]
gEfiMdePkgTokenSpaceGuid.PcdDriverDiagnostics2Disable|TRUE
@@ -242,8 +244,6 @@
MdeModulePkg/Library/BaseSerialPortLib16550/BaseSerialPortLib16550.inf
MdeModulePkg/Library/BasePlatformHookLibNull/BasePlatformHookLibNull.inf
MdeModulePkg/Library/DxeDebugPrintErrorLevelLib/DxeDebugPrintErrorLevelLib.inf
- MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxDxeLib.inf
- MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxSmmLib.inf
MdeModulePkg/Library/PiDxeS3BootScriptLib/DxeS3BootScriptLib.inf
MdeModulePkg/Library/PeiDebugPrintHobLib/PeiDebugPrintHobLib.inf
MdeModulePkg/Library/CpuExceptionHandlerLibNull/CpuExceptionHandlerLibNull.inf
@@ -336,6 +336,8 @@
MdeModulePkg/Library/SmmPerformanceLib/SmmPerformanceLib.inf
MdeModulePkg/Library/DxeSmmPerformanceLib/DxeSmmPerformanceLib.inf
MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxPeiLib.inf
+ MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxDxeLib.inf
+ MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxSmmLib.inf
MdeModulePkg/Library/SmmCorePlatformHookLibNull/SmmCorePlatformHookLibNull.inf
MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/BootScriptExecutorDxe.inf
MdeModulePkg/Universal/Acpi/S3SaveStateDxe/S3SaveStateDxe.inf
diff --git a/MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/X64/S3Asm.S b/MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/X64/S3Asm.S
index dcce6fb6ae..e59fd048b0 100644
--- a/MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/X64/S3Asm.S
+++ b/MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/X64/S3Asm.S
@@ -2,7 +2,7 @@
# This is the assembly code for transferring to control to OS S3 waking vector
# for X64 platform
#
-# 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
@@ -18,14 +18,14 @@ ASM_GLOBAL ASM_PFX(AsmTransferControl)
ASM_PFX(AsmTransferControl):
# rcx S3WakingVector :DWORD
# rdx AcpiLowMemoryBase :DWORD
- lea _AsmTransferControl_al_0000, %eax
+ lea _AsmTransferControl_al_0000(%rip), %eax
movq $0x2800000000, %r8
orq %r8, %rax
pushq %rax
shrd $20, %ecx, %ebx
andl $0x0f, %ecx
movw %cx, %bx
- movl %ebx, jmp_addr
+ movl %ebx, jmp_addr(%rip)
lret
_AsmTransferControl_al_0000:
.byte 0x0b8, 0x30, 0 # mov ax, 30h as selector
@@ -124,7 +124,7 @@ ASM_PFX(PageFaultHandlerHook):
popq %rcx
popq %rax # restore all volatile registers
jnz L1
- jmpq *ASM_PFX(mOriginalHandler)
+ jmpq *ASM_PFX(mOriginalHandler)(%rip)
L1:
addq $0x08, %rsp # skip error code for PF
iretq
diff --git a/MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTableDxe/FirmwarePerformanceDxe.c b/MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTableDxe/FirmwarePerformanceDxe.c
index ce17e4f928..f834778acd 100644
--- a/MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTableDxe/FirmwarePerformanceDxe.c
+++ b/MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTableDxe/FirmwarePerformanceDxe.c
@@ -5,7 +5,7 @@
for Firmware Basic Boot Performance Record and other boot performance records,
and install FPDT to ACPI table.
- 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
@@ -21,6 +21,8 @@
#include <Protocol/ReportStatusCodeHandler.h>
#include <Protocol/AcpiTable.h>
#include <Protocol/SmmCommunication.h>
+#include <Protocol/LockBox.h>
+#include <Protocol/Variable.h>
#include <Guid/Acpi.h>
#include <Guid/FirmwarePerformance.h>
@@ -36,7 +38,8 @@
#include <Library/MemoryAllocationLib.h>
#include <Library/PcdLib.h>
#include <Library/HobLib.h>
-#include <Library/PcdLib.h>
+#include <Library/LockBoxLib.h>
+#include <Library/UefiLib.h>
//
// ACPI table information used to initialize tables.
@@ -51,6 +54,7 @@
EFI_RSC_HANDLER_PROTOCOL *mRscHandlerProtocol = NULL;
+BOOLEAN mLockBoxReady = FALSE;
EFI_EVENT mReadyToBootEvent;
EFI_EVENT mLegacyBootEvent;
EFI_EVENT mExitBootServicesEvent;
@@ -206,6 +210,7 @@ FpdtAllocateReservedMemoryBelow4G (
EFI_STATUS Status;
VOID *Buffer;
+ Buffer = NULL;
Pages = EFI_SIZE_TO_PAGES (Size);
Address = 0xffffffff;
@@ -217,13 +222,107 @@ FpdtAllocateReservedMemoryBelow4G (
);
ASSERT_EFI_ERROR (Status);
- Buffer = (VOID *) (UINTN) Address;
- ZeroMem (Buffer, Size);
+ if (!EFI_ERROR (Status)) {
+ Buffer = (VOID *) (UINTN) Address;
+ ZeroMem (Buffer, Size);
+ }
return Buffer;
}
/**
+ Callback function upon VariableArchProtocol and LockBoxProtocol
+ to allocate S3 performance table memory and save the pointer to LockBox.
+
+ @param[in] Event Event whose notification function is being invoked.
+ @param[in] Context Pointer to the notification function's context.
+**/
+VOID
+EFIAPI
+FpdtAllocateS3PerformanceTableMemory (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+ VOID *Interface;
+ FIRMWARE_PERFORMANCE_VARIABLE PerformanceVariable;
+ UINTN Size;
+ EFI_PHYSICAL_ADDRESS S3PerformanceTablePointer;
+
+ if (mLockBoxReady && (mAcpiS3PerformanceTable != NULL)) {
+ //
+ // The memory for S3 performance table should have been ready,
+ // and the pointer should have been saved to LockBox, just return.
+ //
+ return;
+ }
+
+ if (!mLockBoxReady) {
+ Status = gBS->LocateProtocol (&gEfiLockBoxProtocolGuid, NULL, &Interface);
+ if (!EFI_ERROR (Status)) {
+ //
+ // LockBox services has been ready.
+ //
+ mLockBoxReady = TRUE;
+ }
+ }
+
+ if (mAcpiS3PerformanceTable == NULL) {
+ Status = gBS->LocateProtocol (&gEfiVariableArchProtocolGuid, NULL, &Interface);
+ if (!EFI_ERROR (Status)) {
+ //
+ // Try to allocate the same runtime buffer as last time boot.
+ //
+ ZeroMem (&PerformanceVariable, sizeof (PerformanceVariable));
+ Size = sizeof (PerformanceVariable);
+ Status = gRT->GetVariable (
+ EFI_FIRMWARE_PERFORMANCE_VARIABLE_NAME,
+ &gEfiFirmwarePerformanceGuid,
+ NULL,
+ &Size,
+ &PerformanceVariable
+ );
+ if (!EFI_ERROR (Status)) {
+ Status = gBS->AllocatePages (
+ AllocateAddress,
+ EfiReservedMemoryType,
+ EFI_SIZE_TO_PAGES (sizeof (S3_PERFORMANCE_TABLE)),
+ &PerformanceVariable.S3PerformanceTablePointer
+ );
+ if (!EFI_ERROR (Status)) {
+ mAcpiS3PerformanceTable = (S3_PERFORMANCE_TABLE *) (UINTN) PerformanceVariable.S3PerformanceTablePointer;
+ }
+ }
+ if (mAcpiS3PerformanceTable == NULL) {
+ //
+ // Fail to allocate at specified address, continue to allocate at any address.
+ //
+ mAcpiS3PerformanceTable = (S3_PERFORMANCE_TABLE *) FpdtAllocateReservedMemoryBelow4G (sizeof (S3_PERFORMANCE_TABLE));
+ }
+ DEBUG ((EFI_D_INFO, "FPDT: ACPI S3 Performance Table address = 0x%x\n", mAcpiS3PerformanceTable));
+ if (mAcpiS3PerformanceTable != NULL) {
+ CopyMem (mAcpiS3PerformanceTable, &mS3PerformanceTableTemplate, sizeof (mS3PerformanceTableTemplate));
+ }
+ }
+ }
+
+ if (mLockBoxReady && (mAcpiS3PerformanceTable != NULL)) {
+ //
+ // If LockBox services has been ready and memory for FPDT S3 performance table has been allocated,
+ // save the pointer to LockBox for use in S3 resume.
+ //
+ S3PerformanceTablePointer = (EFI_PHYSICAL_ADDRESS) (UINTN) mAcpiS3PerformanceTable;
+ Status = SaveLockBox (
+ &gFirmwarePerformanceS3PointerGuid,
+ &S3PerformanceTablePointer,
+ sizeof (EFI_PHYSICAL_ADDRESS)
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+}
+
+/**
Install ACPI Firmware Performance Data Table (FPDT).
@return Status code.
@@ -236,15 +335,13 @@ InstallFirmwarePerformanceDataTable (
{
EFI_STATUS Status;
EFI_ACPI_TABLE_PROTOCOL *AcpiTableProtocol;
- EFI_PHYSICAL_ADDRESS Address;
UINTN Size;
- UINT8 SmmBootRecordCommBuffer[SMM_BOOT_RECORD_COMM_SIZE];
+ UINT8 *SmmBootRecordCommBuffer;
EFI_SMM_COMMUNICATE_HEADER *SmmCommBufferHeader;
SMM_BOOT_RECORD_COMMUNICATE *SmmCommData;
UINTN CommSize;
- UINTN PerformanceRuntimeDataSize;
- UINT8 *PerformanceRuntimeData;
- UINT8 *PerformanceRuntimeDataHead;
+ UINTN BootPerformanceDataSize;
+ UINT8 *BootPerformanceData;
EFI_SMM_COMMUNICATION_PROTOCOL *Communication;
FIRMWARE_PERFORMANCE_VARIABLE PerformanceVariable;
@@ -259,12 +356,15 @@ InstallFirmwarePerformanceDataTable (
//
// Collect boot records from SMM drivers.
//
- SmmCommData = NULL;
+ SmmBootRecordCommBuffer = NULL;
+ SmmCommData = NULL;
Status = gBS->LocateProtocol (&gEfiSmmCommunicationProtocolGuid, NULL, (VOID **) &Communication);
if (!EFI_ERROR (Status)) {
//
// Initialize communicate buffer
//
+ SmmBootRecordCommBuffer = AllocateZeroPool (SMM_BOOT_RECORD_COMM_SIZE);
+ ASSERT (SmmBootRecordCommBuffer != NULL);
SmmCommBufferHeader = (EFI_SMM_COMMUNICATE_HEADER*)SmmBootRecordCommBuffer;
SmmCommData = (SMM_BOOT_RECORD_COMMUNICATE*)SmmCommBufferHeader->Data;
ZeroMem((UINT8*)SmmCommData, sizeof(SMM_BOOT_RECORD_COMMUNICATE));
@@ -296,15 +396,12 @@ InstallFirmwarePerformanceDataTable (
}
//
- // Prepare memory for runtime Performance Record.
- // Runtime performance records includes two tables S3 performance table and Boot performance table.
- // S3 Performance table includes S3Resume and S3Suspend records.
+ // Prepare memory for Boot Performance table.
// Boot Performance table includes BasicBoot record, and one or more appended Boot Records.
//
- PerformanceRuntimeData = NULL;
- PerformanceRuntimeDataSize = sizeof (S3_PERFORMANCE_TABLE) + sizeof (BOOT_PERFORMANCE_TABLE) + mBootRecordSize + PcdGet32 (PcdExtFpdtBootRecordPadSize);
+ BootPerformanceDataSize = sizeof (BOOT_PERFORMANCE_TABLE) + mBootRecordSize + PcdGet32 (PcdExtFpdtBootRecordPadSize);
if (SmmCommData != NULL) {
- PerformanceRuntimeDataSize += SmmCommData->BootRecordSize;
+ BootPerformanceDataSize += SmmCommData->BootRecordSize;
}
//
@@ -320,87 +417,66 @@ InstallFirmwarePerformanceDataTable (
&PerformanceVariable
);
if (!EFI_ERROR (Status)) {
- Address = PerformanceVariable.S3PerformanceTablePointer;
Status = gBS->AllocatePages (
AllocateAddress,
EfiReservedMemoryType,
- EFI_SIZE_TO_PAGES (PerformanceRuntimeDataSize),
- &Address
+ EFI_SIZE_TO_PAGES (BootPerformanceDataSize),
+ &PerformanceVariable.BootPerformanceTablePointer
);
if (!EFI_ERROR (Status)) {
- PerformanceRuntimeData = (UINT8 *) (UINTN) Address;
+ mAcpiBootPerformanceTable = (BOOT_PERFORMANCE_TABLE *) (UINTN) PerformanceVariable.BootPerformanceTablePointer;
}
}
- if (PerformanceRuntimeData == NULL) {
+ if (mAcpiBootPerformanceTable == NULL) {
//
// Fail to allocate at specified address, continue to allocate at any address.
//
- PerformanceRuntimeData = FpdtAllocateReservedMemoryBelow4G (PerformanceRuntimeDataSize);
+ mAcpiBootPerformanceTable = (BOOT_PERFORMANCE_TABLE *) FpdtAllocateReservedMemoryBelow4G (BootPerformanceDataSize);
}
- DEBUG ((EFI_D_INFO, "FPDT: Performance Runtime Data address = 0x%x\n", PerformanceRuntimeData));
+ DEBUG ((EFI_D_INFO, "FPDT: ACPI Boot Performance Table address = 0x%x\n", mAcpiBootPerformanceTable));
- if (PerformanceRuntimeData == NULL) {
+ if (mAcpiBootPerformanceTable == NULL) {
if (SmmCommData != NULL && SmmCommData->BootRecordData != NULL) {
FreePool (SmmCommData->BootRecordData);
}
+ if (SmmBootRecordCommBuffer != NULL) {
+ FreePool (SmmBootRecordCommBuffer);
+ }
+ if (mAcpiS3PerformanceTable != NULL) {
+ FreePages (mAcpiS3PerformanceTable, EFI_SIZE_TO_PAGES (sizeof (S3_PERFORMANCE_TABLE)));
+ }
return EFI_OUT_OF_RESOURCES;
}
-
- PerformanceRuntimeDataHead = PerformanceRuntimeData;
-
- if (FeaturePcdGet (PcdFirmwarePerformanceDataTableS3Support)) {
- //
- // Prepare S3 Performance Table.
- //
- mAcpiS3PerformanceTable = (S3_PERFORMANCE_TABLE *) PerformanceRuntimeData;
- CopyMem (mAcpiS3PerformanceTable, &mS3PerformanceTableTemplate, sizeof (mS3PerformanceTableTemplate));
- PerformanceRuntimeData = PerformanceRuntimeData + mAcpiS3PerformanceTable->Header.Length;
- DEBUG ((EFI_D_INFO, "FPDT: ACPI S3 Performance Table address = 0x%x\n", mAcpiS3PerformanceTable));
- //
- // Save S3 Performance Table address to Variable for use in Firmware Performance PEIM.
- //
- PerformanceVariable.S3PerformanceTablePointer = (EFI_PHYSICAL_ADDRESS) (UINTN) mAcpiS3PerformanceTable;
- //
- // Update S3 Performance Table Pointer in template.
- //
- mFirmwarePerformanceTableTemplate.S3PointerRecord.S3PerformanceTablePointer = (UINT64) PerformanceVariable.S3PerformanceTablePointer;
- } else {
- //
- // Exclude S3 Performance Table Pointer from FPDT table template.
- //
- mFirmwarePerformanceTableTemplate.Header.Length -= sizeof (EFI_ACPI_5_0_FPDT_S3_PERFORMANCE_TABLE_POINTER_RECORD);
- }
//
// Prepare Boot Performance Table.
//
- mAcpiBootPerformanceTable = (BOOT_PERFORMANCE_TABLE *) PerformanceRuntimeData;
+ BootPerformanceData = (UINT8 *) mAcpiBootPerformanceTable;
//
// Fill Basic Boot record to Boot Performance Table.
//
- CopyMem (PerformanceRuntimeData, &mBootPerformanceTableTemplate, sizeof (mBootPerformanceTableTemplate));
- PerformanceRuntimeData = PerformanceRuntimeData + mAcpiBootPerformanceTable->Header.Length;
+ CopyMem (mAcpiBootPerformanceTable, &mBootPerformanceTableTemplate, sizeof (mBootPerformanceTableTemplate));
+ BootPerformanceData = BootPerformanceData + mAcpiBootPerformanceTable->Header.Length;
//
// Fill Boot records from boot drivers.
//
- CopyMem (PerformanceRuntimeData, mBootRecordBuffer, mBootRecordSize);
+ CopyMem (BootPerformanceData, mBootRecordBuffer, mBootRecordSize);
mAcpiBootPerformanceTable->Header.Length += mBootRecordSize;
- PerformanceRuntimeData = PerformanceRuntimeData + mBootRecordSize;
+ BootPerformanceData = BootPerformanceData + mBootRecordSize;
if (SmmCommData != NULL && SmmCommData->BootRecordData != NULL) {
//
// Fill Boot records from SMM drivers.
//
- CopyMem (PerformanceRuntimeData, SmmCommData->BootRecordData, SmmCommData->BootRecordSize);
+ CopyMem (BootPerformanceData, SmmCommData->BootRecordData, SmmCommData->BootRecordSize);
FreePool (SmmCommData->BootRecordData);
mAcpiBootPerformanceTable->Header.Length = (UINT32) (mAcpiBootPerformanceTable->Header.Length + SmmCommData->BootRecordSize);
- PerformanceRuntimeData = PerformanceRuntimeData + SmmCommData->BootRecordSize;
+ BootPerformanceData = BootPerformanceData + SmmCommData->BootRecordSize;
}
- //
- // Reserve space for boot records after ReadyToBoot.
- //
- PerformanceRuntimeData = PerformanceRuntimeData + PcdGet32 (PcdExtFpdtBootRecordPadSize);
- DEBUG ((EFI_D_INFO, "FPDT: ACPI Boot Performance Table address = 0x%x\n", mAcpiBootPerformanceTable));
+ if (SmmBootRecordCommBuffer != NULL) {
+ FreePool (SmmBootRecordCommBuffer);
+ }
+
//
// Save Boot Performance Table address to Variable for use in S4 resume.
//
@@ -411,12 +487,20 @@ InstallFirmwarePerformanceDataTable (
mFirmwarePerformanceTableTemplate.BootPointerRecord.BootPerformanceTablePointer = (UINT64) (UINTN) mAcpiBootPerformanceTable;
//
+ // Save S3 Performance Table address to Variable for use in S4 resume.
+ //
+ PerformanceVariable.S3PerformanceTablePointer = (EFI_PHYSICAL_ADDRESS) (UINTN) mAcpiS3PerformanceTable;
+ //
+ // Update S3 Performance Table Pointer in template.
+ //
+ mFirmwarePerformanceTableTemplate.S3PointerRecord.S3PerformanceTablePointer = (UINT64) (UINTN) mAcpiS3PerformanceTable;
+ //
// Save Runtime Performance Table pointers to Variable.
//
Status = gRT->SetVariable (
EFI_FIRMWARE_PERFORMANCE_VARIABLE_NAME,
&gEfiFirmwarePerformanceGuid,
- EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
sizeof (PerformanceVariable),
&PerformanceVariable
);
@@ -433,7 +517,10 @@ InstallFirmwarePerformanceDataTable (
&mFirmwarePerformanceTableTemplateKey
);
if (EFI_ERROR (Status)) {
- FreePool (PerformanceRuntimeDataHead);
+ FreePages (mAcpiBootPerformanceTable, EFI_SIZE_TO_PAGES (BootPerformanceDataSize));
+ if (mAcpiS3PerformanceTable != NULL) {
+ FreePages (mAcpiS3PerformanceTable, EFI_SIZE_TO_PAGES (sizeof (S3_PERFORMANCE_TABLE)));
+ }
mAcpiBootPerformanceTable = NULL;
mAcpiS3PerformanceTable = NULL;
return Status;
@@ -700,6 +787,7 @@ FirmwarePerformanceDxeEntryPoint (
EFI_STATUS Status;
EFI_HOB_GUID_TYPE *GuidHob;
FIRMWARE_SEC_PERFORMANCE *Performance;
+ VOID *Registration;
//
// Get Report Status Code Handler Protocol.
@@ -766,5 +854,31 @@ FirmwarePerformanceDxeEntryPoint (
DEBUG ((EFI_D_ERROR, "FPDT: WARNING: SEC Performance Data Hob not found, ResetEnd will be set to 0!\n"));
}
+ if (FeaturePcdGet (PcdFirmwarePerformanceDataTableS3Support)) {
+ //
+ // Register callback function upon VariableArchProtocol and LockBoxProtocol
+ // to allocate S3 performance table memory and save the pointer to LockBox.
+ //
+ EfiCreateProtocolNotifyEvent (
+ &gEfiVariableArchProtocolGuid,
+ TPL_CALLBACK,
+ FpdtAllocateS3PerformanceTableMemory,
+ NULL,
+ &Registration
+ );
+ EfiCreateProtocolNotifyEvent (
+ &gEfiLockBoxProtocolGuid,
+ TPL_CALLBACK,
+ FpdtAllocateS3PerformanceTableMemory,
+ NULL,
+ &Registration
+ );
+ } else {
+ //
+ // Exclude S3 Performance Table Pointer from FPDT table template.
+ //
+ mFirmwarePerformanceTableTemplate.Header.Length -= sizeof (EFI_ACPI_5_0_FPDT_S3_PERFORMANCE_TABLE_POINTER_RECORD);
+ }
+
return EFI_SUCCESS;
}
diff --git a/MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTableDxe/FirmwarePerformanceDxe.inf b/MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTableDxe/FirmwarePerformanceDxe.inf
index 89424acaae..5a9628f924 100644
--- a/MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTableDxe/FirmwarePerformanceDxe.inf
+++ b/MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTableDxe/FirmwarePerformanceDxe.inf
@@ -5,7 +5,7 @@
# for Firmware Basic Boot Performance Record and other boot performance records,
# and install FPDT to ACPI table.
#
-# 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
@@ -48,11 +48,15 @@
MemoryAllocationLib
PcdLib
HobLib
+ LockBoxLib
+ UefiLib
[Protocols]
gEfiAcpiTableProtocolGuid ## SOMETIMES_CONSUMES
gEfiRscHandlerProtocolGuid ## CONSUMES
gEfiSmmCommunicationProtocolGuid ## SOMETIMES_CONSUMES
+ gEfiVariableArchProtocolGuid ## SOMETIMES_CONSUMES
+ gEfiLockBoxProtocolGuid ## SOMETIMES_CONSUMES
[Guids]
gEfiEventExitBootServicesGuid ## CONSUMES
@@ -65,6 +69,7 @@
gEfiFirmwarePerformanceGuid ## SOMETIMES_CONSUMES ## Hob
gEfiFirmwarePerformanceGuid ## SOMETIMES_CONSUMES ## SmiHandler
gEfiFirmwarePerformanceGuid ## SOMETIMES_CONSUMES ## StatusCode Data
+ gFirmwarePerformanceS3PointerGuid ## SOMETIMES_PRODUCES # SaveLockBox
[Pcd]
gEfiMdeModulePkgTokenSpaceGuid.PcdProgressCodeOsLoaderLoad
diff --git a/MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTablePei/FirmwarePerformancePei.c b/MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTablePei/FirmwarePerformancePei.c
index af9b4e3c65..70592cbc3c 100644
--- a/MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTablePei/FirmwarePerformancePei.c
+++ b/MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTablePei/FirmwarePerformancePei.c
@@ -7,7 +7,7 @@
This module register report status code listener to collect performance data
for S3 Resume Performance Record on S3 resume boot path.
- 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
@@ -20,7 +20,6 @@
#include <PiPei.h>
-#include <Ppi/ReadOnlyVariable2.h>
#include <Ppi/ReportStatusCodeHandler.h>
#include <Ppi/SecPerformance.h>
@@ -68,9 +67,8 @@ FpdtStatusCodeListenerPei (
{
EFI_STATUS Status;
UINT64 CurrentTime;
- EFI_PEI_READ_ONLY_VARIABLE2_PPI *VariableServices;
UINTN VarSize;
- FIRMWARE_PERFORMANCE_VARIABLE PerformanceVariable;
+ EFI_PHYSICAL_ADDRESS S3PerformanceTablePointer;
S3_PERFORMANCE_TABLE *AcpiS3PerformanceTable;
EFI_ACPI_5_0_FPDT_S3_RESUME_RECORD *AcpiS3ResumeRecord;
UINT64 S3ResumeTotal;
@@ -90,33 +88,20 @@ FpdtStatusCodeListenerPei (
//
CurrentTime = GetTimeInNanoSecond (GetPerformanceCounter ());
- Status = PeiServicesLocatePpi (
- &gEfiPeiReadOnlyVariable2PpiGuid,
- 0,
- NULL,
- (VOID **) &VariableServices
- );
- ASSERT_EFI_ERROR (Status);
-
//
// Update S3 Resume Performance Record.
//
- VarSize = sizeof (FIRMWARE_PERFORMANCE_VARIABLE);
- Status = VariableServices->GetVariable (
- VariableServices,
- EFI_FIRMWARE_PERFORMANCE_VARIABLE_NAME,
- &gEfiFirmwarePerformanceGuid,
- NULL,
- &VarSize,
- &PerformanceVariable
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
+ S3PerformanceTablePointer = 0;
+ VarSize = sizeof (EFI_PHYSICAL_ADDRESS);
+ Status = RestoreLockBox (&gFirmwarePerformanceS3PointerGuid, &S3PerformanceTablePointer, &VarSize);
+ ASSERT_EFI_ERROR (Status);
- AcpiS3PerformanceTable = (S3_PERFORMANCE_TABLE *) (UINTN) PerformanceVariable.S3PerformanceTablePointer;
+ AcpiS3PerformanceTable = (S3_PERFORMANCE_TABLE *) (UINTN) S3PerformanceTablePointer;
ASSERT (AcpiS3PerformanceTable != NULL);
- ASSERT (AcpiS3PerformanceTable->Header.Signature == EFI_ACPI_5_0_FPDT_S3_PERFORMANCE_TABLE_SIGNATURE);
+ if (AcpiS3PerformanceTable->Header.Signature != EFI_ACPI_5_0_FPDT_S3_PERFORMANCE_TABLE_SIGNATURE) {
+ DEBUG ((EFI_D_ERROR, "FPDT S3 performance data in ACPI memory get corrupted\n"));
+ return EFI_ABORTED;
+ }
AcpiS3ResumeRecord = &AcpiS3PerformanceTable->S3Resume;
AcpiS3ResumeRecord->FullResume = CurrentTime;
//
diff --git a/MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTablePei/FirmwarePerformancePei.inf b/MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTablePei/FirmwarePerformancePei.inf
index 0694899bcb..aced5c521e 100644
--- a/MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTablePei/FirmwarePerformancePei.inf
+++ b/MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTablePei/FirmwarePerformancePei.inf
@@ -7,7 +7,7 @@
# This module register report status code listener to collect performance data
# for S3 Resume Performance Record on S3 resume boot path.
#
-# Copyright (c) 2011, 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
@@ -52,11 +52,11 @@
[Ppis]
gEfiPeiRscHandlerPpiGuid ## CONSUMES
- gEfiPeiReadOnlyVariable2PpiGuid ## SOMETIMES_CONSUMES
gPeiSecPerformancePpiGuid ## CONSUMES
[Guids]
gEfiFirmwarePerformanceGuid ## CONSUMES
+ gFirmwarePerformanceS3PointerGuid ## CONSUMES
[FeaturePcd]
gEfiMdeModulePkgTokenSpaceGuid.PcdFirmwarePerformanceDataTableS3Support
diff --git a/MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTableSmm/FirmwarePerformanceSmm.c b/MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTableSmm/FirmwarePerformanceSmm.c
index 54a2275d4e..9c5fd4db85 100644
--- a/MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTableSmm/FirmwarePerformanceSmm.c
+++ b/MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTableSmm/FirmwarePerformanceSmm.c
@@ -11,7 +11,7 @@
FpdtSmiHandler() will receive untrusted input and do basic validation.
- 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
@@ -205,6 +205,33 @@ InternalIsAddressInSmram (
}
/**
+ This function check if the address refered by Buffer and Length is valid.
+
+ @param Buffer the buffer address to be checked.
+ @param Length the buffer length to be checked.
+
+ @retval TRUE this address is valid.
+ @retval FALSE this address is NOT valid.
+**/
+BOOLEAN
+InternalIsAddressValid (
+ IN UINTN Buffer,
+ IN UINTN Length
+ )
+{
+ if (Buffer > (MAX_ADDRESS - Length)) {
+ //
+ // Overflow happen
+ //
+ return FALSE;
+ }
+ if (InternalIsAddressInSmram ((EFI_PHYSICAL_ADDRESS)Buffer, (UINT64)Length)) {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/**
Communication service SMI Handler entry.
This SMI handler provides services for report SMM boot records.
@@ -239,6 +266,9 @@ FpdtSmiHandler (
{
EFI_STATUS Status;
SMM_BOOT_RECORD_COMMUNICATE *SmmCommData;
+ UINTN BootRecordSize;
+ VOID *BootRecordData;
+ UINTN TempCommBufferSize;
//
// If input is invalid, stop processing this SMI
@@ -247,12 +277,14 @@ FpdtSmiHandler (
return EFI_SUCCESS;
}
- if(*CommBufferSize < sizeof (SMM_BOOT_RECORD_COMMUNICATE)) {
+ TempCommBufferSize = *CommBufferSize;
+
+ if(TempCommBufferSize < sizeof (SMM_BOOT_RECORD_COMMUNICATE)) {
return EFI_SUCCESS;
}
- if (InternalIsAddressInSmram ((EFI_PHYSICAL_ADDRESS)(UINTN)CommBuffer, *CommBufferSize)) {
- DEBUG ((EFI_D_ERROR, "SMM communication data buffer is in SMRAM!\n"));
+ if (!InternalIsAddressValid ((UINTN)CommBuffer, TempCommBufferSize)) {
+ DEBUG ((EFI_D_ERROR, "FpdtSmiHandler: SMM communication data buffer in SMRAM or overflow!\n"));
return EFI_SUCCESS;
}
@@ -266,7 +298,9 @@ FpdtSmiHandler (
break;
case SMM_FPDT_FUNCTION_GET_BOOT_RECORD_DATA :
- if (SmmCommData->BootRecordData == NULL || SmmCommData->BootRecordSize < mBootRecordSize) {
+ BootRecordData = SmmCommData->BootRecordData;
+ BootRecordSize = SmmCommData->BootRecordSize;
+ if (BootRecordData == NULL || BootRecordSize < mBootRecordSize) {
Status = EFI_INVALID_PARAMETER;
break;
}
@@ -275,14 +309,14 @@ FpdtSmiHandler (
// Sanity check
//
SmmCommData->BootRecordSize = mBootRecordSize;
- if (InternalIsAddressInSmram ((EFI_PHYSICAL_ADDRESS)(UINTN)SmmCommData->BootRecordData, mBootRecordSize)) {
- DEBUG ((EFI_D_ERROR, "SMM Data buffer is in SMRAM!\n"));
+ if (!InternalIsAddressValid ((UINTN)BootRecordData, mBootRecordSize)) {
+ DEBUG ((EFI_D_ERROR, "FpdtSmiHandler: SMM Data buffer in SMRAM or overflow!\n"));
Status = EFI_ACCESS_DENIED;
break;
}
CopyMem (
- (UINT8*)SmmCommData->BootRecordData,
+ (UINT8*)BootRecordData,
mBootRecordBuffer,
mBootRecordSize
);
diff --git a/MdeModulePkg/Universal/DevicePathDxe/DevicePathFromText.c b/MdeModulePkg/Universal/DevicePathDxe/DevicePathFromText.c
index d94e149e58..f96bea1477 100644
--- a/MdeModulePkg/Universal/DevicePathDxe/DevicePathFromText.c
+++ b/MdeModulePkg/Universal/DevicePathDxe/DevicePathFromText.c
@@ -1,7 +1,7 @@
/** @file
DevicePathFromText protocol as defined in the UEFI 2.0 specification.
-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
@@ -1636,6 +1636,7 @@ DevPathFromTextSAS (
CHAR16 *DriveBayStr;
CHAR16 *ReservedStr;
UINT16 Info;
+ UINT16 Uint16;
SAS_DEVICE_PATH *Sas;
AddressStr = GetNextParamStr (&TextDeviceNode);
@@ -1646,7 +1647,6 @@ DevPathFromTextSAS (
ConnectStr = GetNextParamStr (&TextDeviceNode);
DriveBayStr = GetNextParamStr (&TextDeviceNode);
ReservedStr = GetNextParamStr (&TextDeviceNode);
- Info = 0x0000;
Sas = (SAS_DEVICE_PATH *) CreateDeviceNode (
MESSAGING_DEVICE_PATH,
MSG_VENDOR_DP,
@@ -1657,25 +1657,51 @@ DevPathFromTextSAS (
Strtoi64 (AddressStr, &Sas->SasAddress);
Strtoi64 (LunStr, &Sas->Lun);
Sas->RelativeTargetPort = (UINT16) Strtoi (RTPStr);
- if (StrCmp (SASSATAStr, L"NoTopology") != 0) {
- if (StrCmp (DriveBayStr, L"0") == 0) {
- Info |= 0x0001;
+
+ 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 |= 0x0002;
- Info = (UINT16) (Info | (Strtoi (DriveBayStr) << 8));
+ Info = (UINT16) (0x2 | ((Uint16 - 1) << 8));
}
if (StrCmp (SASSATAStr, L"SATA") == 0) {
- Info |= 0x0010;
+ 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) {
- Info |= 0x0020;
+ 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) {
- Info |= 0x0040;
+ 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;
@@ -1705,6 +1731,9 @@ DevPathFromTextSasEx (
CHAR16 *ConnectStr;
CHAR16 *DriveBayStr;
UINT16 Info;
+ UINT16 Uint16;
+ UINT64 SasAddress;
+ UINT64 Lun;
SASEX_DEVICE_PATH *SasEx;
AddressStr = GetNextParamStr (&TextDeviceNode);
@@ -1714,37 +1743,62 @@ DevPathFromTextSasEx (
LocationStr = GetNextParamStr (&TextDeviceNode);
ConnectStr = GetNextParamStr (&TextDeviceNode);
DriveBayStr = GetNextParamStr (&TextDeviceNode);
- Info = 0x0000;
SasEx = (SASEX_DEVICE_PATH *) CreateDeviceNode (
MESSAGING_DEVICE_PATH,
MSG_SASEX_DP,
(UINT16) sizeof (SASEX_DEVICE_PATH)
);
- Strtoi64 (AddressStr, (UINT64 *) &SasEx->SasAddress);
- Strtoi64 (LunStr, (UINT64 *) &SasEx->Lun);
- *(UINT64 *) &SasEx->SasAddress = SwapBytes64 (*(UINT64 *) &SasEx->SasAddress);
- *(UINT64 *) &SasEx->Lun = SwapBytes64 (*(UINT64 *) &SasEx->Lun);
+ 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) {
- if (StrCmp (DriveBayStr, L"0") == 0) {
- Info |= 0x0001;
+
+ 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 |= 0x0002;
- Info = (UINT16) (Info | (Strtoi (DriveBayStr) << 8));
+ Info = (UINT16) (0x2 | ((Uint16 - 1) << 8));
}
if (StrCmp (SASSATAStr, L"SATA") == 0) {
- Info |= 0x0010;
+ 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) {
- Info |= 0x0020;
+ 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) {
- Info |= 0x0040;
+ 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;
diff --git a/MdeModulePkg/Universal/DevicePathDxe/DevicePathToText.c b/MdeModulePkg/Universal/DevicePathDxe/DevicePathToText.c
index 1f90f64204..3d9d7c7a7e 100644
--- a/MdeModulePkg/Universal/DevicePathDxe/DevicePathToText.c
+++ b/MdeModulePkg/Universal/DevicePathDxe/DevicePathToText.c
@@ -1,7 +1,7 @@
/** @file
DevicePathToText protocol as defined in the UEFI 2.0 specification.
-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
@@ -234,23 +234,26 @@ DevPathToTextVendor (
((SAS_DEVICE_PATH *) Vendor)->RelativeTargetPort
);
Info = (((SAS_DEVICE_PATH *) Vendor)->DeviceTopology);
- if ((Info & 0x0f) == 0) {
+ if (((Info & 0x0f) == 0) && ((Info & BIT7) == 0)) {
CatPrint (Str, L"NoTopology,0,0,0,");
- } else if (((Info & 0x0f) == 1) || ((Info & 0x0f) == 2)) {
+ } else if (((Info & 0x0f) <= 2) && ((Info & BIT7) == 0)) {
CatPrint (
Str,
L"%s,%s,%s,",
- ((Info & (0x1 << 4)) != 0) ? L"SATA" : L"SAS",
- ((Info & (0x1 << 5)) != 0) ? L"External" : L"Internal",
- ((Info & (0x1 << 6)) != 0) ? L"Expanded" : L"Direct"
+ ((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 {
- CatPrint (Str, L"0x%x,", (Info >> 8) & 0xff);
+ //
+ // Value 0x0 thru 0xFF -> Drive 1 thru Drive 256
+ //
+ CatPrint (Str, L"0x%x,", ((Info >> 8) & 0xff) + 1);
}
} else {
- CatPrint (Str, L"0,0,0,0,");
+ CatPrint (Str, L"0x%x,0,0,0,", Info);
}
CatPrint (Str, L"0x%x)", ((SAS_DEVICE_PATH *) Vendor)->Reserved);
@@ -689,23 +692,26 @@ DevPathToTextSasEx (
}
CatPrint (Str, L",0x%x,", SasEx->RelativeTargetPort);
- if ((SasEx->DeviceTopology & 0x0f) == 0) {
+ if (((SasEx->DeviceTopology & 0x0f) == 0) && ((SasEx->DeviceTopology & BIT7) == 0)) {
CatPrint (Str, L"NoTopology,0,0,0");
- } else if (((SasEx->DeviceTopology & 0x0f) == 1) || ((SasEx->DeviceTopology & 0x0f) == 2)) {
+ } else if (((SasEx->DeviceTopology & 0x0f) <= 2) && ((SasEx->DeviceTopology & BIT7) == 0)) {
CatPrint (
Str,
L"%s,%s,%s,",
- ((SasEx->DeviceTopology & (0x1 << 4)) != 0) ? L"SATA" : L"SAS",
- ((SasEx->DeviceTopology & (0x1 << 5)) != 0) ? L"External" : L"Internal",
- ((SasEx->DeviceTopology & (0x1 << 6)) != 0) ? L"Expanded" : L"Direct"
+ ((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 {
- CatPrint (Str, L"0x%x", (SasEx->DeviceTopology >> 8) & 0xff);
+ //
+ // Value 0x0 thru 0xFF -> Drive 1 thru Drive 256
+ //
+ CatPrint (Str, L"0x%x", ((SasEx->DeviceTopology >> 8) & 0xff) + 1);
}
} else {
- CatPrint (Str, L"0,0,0,0");
+ CatPrint (Str, L"0x%x,0,0,0", SasEx->DeviceTopology);
}
CatPrint (Str, L")");
diff --git a/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmm.c b/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmm.c
index e7d79c1aa5..2b3a63081d 100644
--- a/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmm.c
+++ b/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmm.c
@@ -43,7 +43,7 @@
Caution: This module requires additional review when modified.
This driver need to make sure the CommBuffer is not in the SMRAM range.
-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
@@ -60,12 +60,17 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include "FaultTolerantWrite.h"
#include "FaultTolerantWriteSmmCommon.h"
#include <Protocol/SmmAccess2.h>
+#include <Protocol/SmmEndOfDxe.h>
EFI_EVENT mFvbRegistration = NULL;
EFI_FTW_DEVICE *mFtwDevice = NULL;
EFI_SMRAM_DESCRIPTOR *mSmramRanges;
UINTN mSmramRangeCount;
+///
+/// The flag to indicate whether the platform has left the DXE phase of execution.
+///
+BOOLEAN mEndOfDxe = FALSE;
/**
This function check if the address is in SMRAM.
@@ -94,6 +99,32 @@ InternalIsAddressInSmram (
return FALSE;
}
+/**
+ This function check if the address refered by Buffer and Length is valid.
+
+ @param Buffer the buffer address to be checked.
+ @param Length the buffer length to be checked.
+
+ @retval TRUE this address is valid.
+ @retval FALSE this address is NOT valid.
+**/
+BOOLEAN
+InternalIsAddressValid (
+ IN UINTN Buffer,
+ IN UINTN Length
+ )
+{
+ if (Buffer > (MAX_ADDRESS - Length)) {
+ //
+ // Overflow happen
+ //
+ return FALSE;
+ }
+ if (InternalIsAddressInSmram ((EFI_PHYSICAL_ADDRESS)Buffer, (UINT64)Length)) {
+ return FALSE;
+ }
+ return TRUE;
+}
/**
Retrive the SMM FVB protocol interface by HANDLE.
@@ -338,7 +369,10 @@ SmmFaultTolerantWriteHandler (
VOID *PrivateData;
EFI_HANDLE SmmFvbHandle;
UINTN InfoSize;
-
+ UINTN CommBufferPayloadSize;
+ UINTN PrivateDataSize;
+ UINTN Length;
+ UINTN TempCommBufferSize;
//
// If input is invalid, stop processing this SMI
@@ -347,29 +381,37 @@ SmmFaultTolerantWriteHandler (
return EFI_SUCCESS;
}
- if (*CommBufferSize < SMM_FTW_COMMUNICATE_HEADER_SIZE) {
+ TempCommBufferSize = *CommBufferSize;
+
+ if (TempCommBufferSize < SMM_FTW_COMMUNICATE_HEADER_SIZE) {
+ DEBUG ((EFI_D_ERROR, "SmmFtwHandler: SMM communication buffer size invalid!\n"));
return EFI_SUCCESS;
}
+ CommBufferPayloadSize = TempCommBufferSize - SMM_FTW_COMMUNICATE_HEADER_SIZE;
- if (InternalIsAddressInSmram ((EFI_PHYSICAL_ADDRESS)(UINTN)CommBuffer, *CommBufferSize)) {
- DEBUG ((EFI_D_ERROR, "SMM communication buffer size is in SMRAM!\n"));
+ if (!InternalIsAddressValid ((UINTN)CommBuffer, TempCommBufferSize)) {
+ DEBUG ((EFI_D_ERROR, "SmmFtwHandler: SMM communication buffer in SMRAM or overflow!\n"));
return EFI_SUCCESS;
}
SmmFtwFunctionHeader = (SMM_FTW_COMMUNICATE_FUNCTION_HEADER *)CommBuffer;
+
+ if (mEndOfDxe) {
+ //
+ // It will be not safe to expose the operations after End Of Dxe.
+ //
+ DEBUG ((EFI_D_ERROR, "SmmFtwHandler: Not safe to do the operation: %x after End Of Dxe, so access denied!\n", SmmFtwFunctionHeader->Function));
+ SmmFtwFunctionHeader->ReturnStatus = EFI_ACCESS_DENIED;
+ return EFI_SUCCESS;
+ }
+
switch (SmmFtwFunctionHeader->Function) {
case FTW_FUNCTION_GET_MAX_BLOCK_SIZE:
- SmmGetMaxBlockSizeHeader = (SMM_FTW_GET_MAX_BLOCK_SIZE_HEADER *) SmmFtwFunctionHeader->Data;
- InfoSize = sizeof (SMM_FTW_GET_MAX_BLOCK_SIZE_HEADER);
-
- //
- // SMRAM range check already covered before
- //
- if (InfoSize > *CommBufferSize - SMM_FTW_COMMUNICATE_HEADER_SIZE) {
- DEBUG ((EFI_D_ERROR, "Data size exceed communication buffer size limit!\n"));
- Status = EFI_ACCESS_DENIED;
- break;
+ if (CommBufferPayloadSize < sizeof (SMM_FTW_GET_MAX_BLOCK_SIZE_HEADER)) {
+ DEBUG ((EFI_D_ERROR, "GetMaxBlockSize: SMM communication buffer size invalid!\n"));
+ return EFI_SUCCESS;
}
+ SmmGetMaxBlockSizeHeader = (SMM_FTW_GET_MAX_BLOCK_SIZE_HEADER *) SmmFtwFunctionHeader->Data;
Status = FtwGetMaxBlockSize (
&mFtwDevice->FtwInstance,
@@ -378,6 +420,10 @@ SmmFaultTolerantWriteHandler (
break;
case FTW_FUNCTION_ALLOCATE:
+ if (CommBufferPayloadSize < sizeof (SMM_FTW_ALLOCATE_HEADER)) {
+ DEBUG ((EFI_D_ERROR, "Allocate: SMM communication buffer size invalid!\n"));
+ return EFI_SUCCESS;
+ }
SmmFtwAllocateHeader = (SMM_FTW_ALLOCATE_HEADER *) SmmFtwFunctionHeader->Data;
Status = FtwAllocate (
&mFtwDevice->FtwInstance,
@@ -388,11 +434,36 @@ SmmFaultTolerantWriteHandler (
break;
case FTW_FUNCTION_WRITE:
+ if (CommBufferPayloadSize < OFFSET_OF (SMM_FTW_WRITE_HEADER, Data)) {
+ DEBUG ((EFI_D_ERROR, "Write: SMM communication buffer size invalid!\n"));
+ return EFI_SUCCESS;
+ }
SmmFtwWriteHeader = (SMM_FTW_WRITE_HEADER *) SmmFtwFunctionHeader->Data;
- if (SmmFtwWriteHeader->PrivateDataSize == 0) {
+ Length = SmmFtwWriteHeader->Length;
+ PrivateDataSize = SmmFtwWriteHeader->PrivateDataSize;
+ if (((UINTN)(~0) - Length < OFFSET_OF (SMM_FTW_WRITE_HEADER, Data)) ||
+ ((UINTN)(~0) - PrivateDataSize < OFFSET_OF (SMM_FTW_WRITE_HEADER, Data) + Length)) {
+ //
+ // Prevent InfoSize overflow
+ //
+ Status = EFI_ACCESS_DENIED;
+ break;
+ }
+ InfoSize = OFFSET_OF (SMM_FTW_WRITE_HEADER, Data) + Length + PrivateDataSize;
+
+ //
+ // SMRAM range check already covered before
+ //
+ if (InfoSize > CommBufferPayloadSize) {
+ DEBUG ((EFI_D_ERROR, "Write: Data size exceed communication buffer size limit!\n"));
+ Status = EFI_ACCESS_DENIED;
+ break;
+ }
+
+ if (PrivateDataSize == 0) {
PrivateData = NULL;
} else {
- PrivateData = (VOID *)&SmmFtwWriteHeader->Data[SmmFtwWriteHeader->Length];
+ PrivateData = (VOID *)&SmmFtwWriteHeader->Data[Length];
}
Status = GetFvbByAddressAndAttribute (
SmmFtwWriteHeader->FvbBaseAddress,
@@ -404,7 +475,7 @@ SmmFaultTolerantWriteHandler (
&mFtwDevice->FtwInstance,
SmmFtwWriteHeader->Lba,
SmmFtwWriteHeader->Offset,
- SmmFtwWriteHeader->Length,
+ Length,
PrivateData,
SmmFvbHandle,
SmmFtwWriteHeader->Data
@@ -413,6 +484,10 @@ SmmFaultTolerantWriteHandler (
break;
case FTW_FUNCTION_RESTART:
+ if (CommBufferPayloadSize < sizeof (SMM_FTW_RESTART_HEADER)) {
+ DEBUG ((EFI_D_ERROR, "Restart: SMM communication buffer size invalid!\n"));
+ return EFI_SUCCESS;
+ }
SmmFtwRestartHeader = (SMM_FTW_RESTART_HEADER *) SmmFtwFunctionHeader->Data;
Status = GetFvbByAddressAndAttribute (
SmmFtwRestartHeader->FvbBaseAddress,
@@ -429,13 +504,25 @@ SmmFaultTolerantWriteHandler (
break;
case FTW_FUNCTION_GET_LAST_WRITE:
+ if (CommBufferPayloadSize < OFFSET_OF (SMM_FTW_GET_LAST_WRITE_HEADER, Data)) {
+ DEBUG ((EFI_D_ERROR, "GetLastWrite: SMM communication buffer size invalid!\n"));
+ return EFI_SUCCESS;
+ }
SmmFtwGetLastWriteHeader = (SMM_FTW_GET_LAST_WRITE_HEADER *) SmmFtwFunctionHeader->Data;
- InfoSize = OFFSET_OF (SMM_FTW_GET_LAST_WRITE_HEADER, Data) + SmmFtwGetLastWriteHeader->PrivateDataSize;
+ PrivateDataSize = SmmFtwGetLastWriteHeader->PrivateDataSize;
+ if ((UINTN)(~0) - PrivateDataSize < OFFSET_OF (SMM_FTW_GET_LAST_WRITE_HEADER, Data)){
+ //
+ // Prevent InfoSize overflow
+ //
+ Status = EFI_ACCESS_DENIED;
+ break;
+ }
+ InfoSize = OFFSET_OF (SMM_FTW_GET_LAST_WRITE_HEADER, Data) + PrivateDataSize;
//
// SMRAM range check already covered before
//
- if (InfoSize > *CommBufferSize - SMM_FTW_COMMUNICATE_HEADER_SIZE) {
+ if (InfoSize > CommBufferPayloadSize) {
DEBUG ((EFI_D_ERROR, "Data size exceed communication buffer size limit!\n"));
Status = EFI_ACCESS_DENIED;
break;
@@ -447,10 +534,11 @@ SmmFaultTolerantWriteHandler (
&SmmFtwGetLastWriteHeader->Lba,
&SmmFtwGetLastWriteHeader->Offset,
&SmmFtwGetLastWriteHeader->Length,
- &SmmFtwGetLastWriteHeader->PrivateDataSize,
+ &PrivateDataSize,
(VOID *)SmmFtwGetLastWriteHeader->Data,
&SmmFtwGetLastWriteHeader->Complete
);
+ SmmFtwGetLastWriteHeader->PrivateDataSize = PrivateDataSize;
break;
default:
@@ -484,6 +572,7 @@ FvbNotificationEvent (
EFI_STATUS Status;
EFI_SMM_FAULT_TOLERANT_WRITE_PROTOCOL *FtwProtocol;
EFI_HANDLE SmmFtwHandle;
+ EFI_HANDLE FtwHandle;
//
// Just return to avoid install SMM FaultTolerantWriteProtocol again
@@ -505,7 +594,7 @@ FvbNotificationEvent (
if (EFI_ERROR(Status)) {
return Status;
}
-
+
//
// Install protocol interface
//
@@ -517,12 +606,18 @@ FvbNotificationEvent (
);
ASSERT_EFI_ERROR (Status);
+ ///
+ /// Register SMM FTW SMI handler
+ ///
+ Status = gSmst->SmiHandlerRegister (SmmFaultTolerantWriteHandler, &gEfiSmmFaultTolerantWriteProtocolGuid, &SmmFtwHandle);
+ ASSERT_EFI_ERROR (Status);
+
//
// Notify the Ftw wrapper driver SMM Ftw is ready
//
- SmmFtwHandle = NULL;
+ FtwHandle = NULL;
Status = gBS->InstallProtocolInterface (
- &SmmFtwHandle,
+ &FtwHandle,
&gEfiSmmFaultTolerantWriteProtocolGuid,
EFI_NATIVE_INTERFACE,
NULL
@@ -532,6 +627,27 @@ FvbNotificationEvent (
return EFI_SUCCESS;
}
+/**
+ SMM END_OF_DXE protocol notification event handler.
+
+ @param Protocol Points to the protocol's unique identifier
+ @param Interface Points to the interface instance
+ @param Handle The handle on which the interface was installed
+
+ @retval EFI_SUCCESS SmmEndOfDxeCallback runs successfully
+
+**/
+EFI_STATUS
+EFIAPI
+SmmEndOfDxeCallback (
+ IN CONST EFI_GUID *Protocol,
+ IN VOID *Interface,
+ IN EFI_HANDLE Handle
+ )
+{
+ mEndOfDxe = TRUE;
+ return EFI_SUCCESS;
+}
/**
This function is the entry point of the Fault Tolerant Write driver.
@@ -552,10 +668,10 @@ SmmFaultTolerantWriteInitialize (
)
{
EFI_STATUS Status;
- EFI_HANDLE FtwHandle;
EFI_SMM_ACCESS2_PROTOCOL *SmmAccess;
UINTN Size;
-
+ VOID *SmmEndOfDxeRegistration;
+
//
// Allocate private data structure for SMM FTW protocol and do some initialization
//
@@ -587,6 +703,16 @@ SmmFaultTolerantWriteInitialize (
mSmramRangeCount = Size / sizeof (EFI_SMRAM_DESCRIPTOR);
//
+ // Register EFI_SMM_END_OF_DXE_PROTOCOL_GUID notify function.
+ //
+ Status = gSmst->SmmRegisterProtocolNotify (
+ &gEfiSmmEndOfDxeProtocolGuid,
+ SmmEndOfDxeCallback,
+ &SmmEndOfDxeRegistration
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
// Register FvbNotificationEvent () notify function.
//
Status = gSmst->SmmRegisterProtocolNotify (
@@ -597,12 +723,6 @@ SmmFaultTolerantWriteInitialize (
ASSERT_EFI_ERROR (Status);
FvbNotificationEvent (NULL, NULL, NULL);
-
- ///
- /// Register SMM FTW SMI handler
- ///
- Status = gSmst->SmiHandlerRegister (SmmFaultTolerantWriteHandler, &gEfiSmmFaultTolerantWriteProtocolGuid, &FtwHandle);
- ASSERT_EFI_ERROR (Status);
return EFI_SUCCESS;
}
diff --git a/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmm.inf b/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmm.inf
index 7e07dc850d..c39f84ca3c 100644
--- a/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmm.inf
+++ b/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmm.inf
@@ -4,7 +4,7 @@
# depends on the full functionality SMM FVB protocol that support read, write/erase
# flash access.
#
-# 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
@@ -59,6 +59,7 @@
gEfiSmmFirmwareVolumeBlockProtocolGuid ## CONSUMES
gEfiSmmFaultTolerantWriteProtocolGuid ## PRODUCES
gEfiSmmAccess2ProtocolGuid ## CONSUMES
+ gEfiSmmEndOfDxeProtocolGuid ## CONSUMES
[FeaturePcd]
gEfiMdeModulePkgTokenSpaceGuid.PcdFullFtwServiceEnable
diff --git a/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmmDxe.c b/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmmDxe.c
index 24b157df08..772d10dcd4 100644
--- a/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmmDxe.c
+++ b/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmmDxe.c
@@ -3,7 +3,7 @@
Implement the Fault Tolerant Write (FTW) protocol based on SMM FTW
module.
-Copyright (c) 2011, 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
@@ -463,13 +463,17 @@ FtwGetLastWrite (
// Get data from SMM
//
*PrivateDataSize = SmmFtwGetLastWriteHeader->PrivateDataSize;
- if (!EFI_ERROR (Status)) {
+ if (Status == EFI_SUCCESS || Status == EFI_BUFFER_TOO_SMALL) {
*Lba = SmmFtwGetLastWriteHeader->Lba;
*Offset = SmmFtwGetLastWriteHeader->Offset;
*Length = SmmFtwGetLastWriteHeader->Length;
*Complete = SmmFtwGetLastWriteHeader->Complete;
CopyGuid (CallerId, &SmmFtwGetLastWriteHeader->CallerId);
- CopyMem (PrivateData, SmmFtwGetLastWriteHeader->Data, *PrivateDataSize);
+ if (Status == EFI_SUCCESS) {
+ CopyMem (PrivateData, SmmFtwGetLastWriteHeader->Data, *PrivateDataSize);
+ }
+ } else if (Status == EFI_NOT_FOUND) {
+ *Complete = SmmFtwGetLastWriteHeader->Complete;
}
FreePool (SmmCommunicateHeader);
diff --git a/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmmDxe.inf b/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmmDxe.inf
index 3ed0393229..a0dda0588b 100644
--- a/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmmDxe.inf
+++ b/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmmDxe.inf
@@ -1,8 +1,11 @@
## @file
-# This module is the Runtime DXE part corresponding to SMM Fault Tolerant Write (FTW) module.
+# This module is the DXE part corresponding to SMM Fault Tolerant Write (FTW) module.
# It installs FTW protocol and works with SMM FTW module together.
+# The FTW protocol will not work after End Of Dxe because it will be not safe to expose
+# the related operations in SMM handler in SMM FTW module. You can use the FTW protocol
+# before End Of Dxe or use FaultTolerantWriteDxe module instead if you really want to.
#
-# 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
diff --git a/MdeModulePkg/Universal/LockBox/SmmLockBox/SmmLockBox.c b/MdeModulePkg/Universal/LockBox/SmmLockBox/SmmLockBox.c
index e8b831e1fb..ad4b2645cb 100644
--- a/MdeModulePkg/Universal/LockBox/SmmLockBox/SmmLockBox.c
+++ b/MdeModulePkg/Universal/LockBox/SmmLockBox/SmmLockBox.c
@@ -9,7 +9,7 @@
SmmLockBoxHandler(), SmmLockBoxRestore(), SmmLockBoxUpdate(), SmmLockBoxSave()
will receive untrusted input and do basic validation.
-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
@@ -111,6 +111,7 @@ SmmLockBoxSave (
)
{
EFI_STATUS Status;
+ EFI_SMM_LOCK_BOX_PARAMETER_SAVE TempLockBoxParameterSave;
//
// Sanity check
@@ -121,11 +122,13 @@ SmmLockBoxSave (
return ;
}
+ CopyMem (&TempLockBoxParameterSave, LockBoxParameterSave, sizeof (EFI_SMM_LOCK_BOX_PARAMETER_SAVE));
+
//
// Sanity check
//
- if (!IsAddressValid ((UINTN)LockBoxParameterSave->Buffer, (UINTN)LockBoxParameterSave->Length)) {
- DEBUG ((EFI_D_ERROR, "SmmLockBox Save address in SMRAM!\n"));
+ if (!IsAddressValid ((UINTN)TempLockBoxParameterSave.Buffer, (UINTN)TempLockBoxParameterSave.Length)) {
+ DEBUG ((EFI_D_ERROR, "SmmLockBox Save address in SMRAM or buffer overflow!\n"));
LockBoxParameterSave->Header.ReturnStatus = (UINT64)EFI_ACCESS_DENIED;
return ;
}
@@ -134,9 +137,9 @@ SmmLockBoxSave (
// Save data
//
Status = SaveLockBox (
- &LockBoxParameterSave->Guid,
- (VOID *)(UINTN)LockBoxParameterSave->Buffer,
- (UINTN)LockBoxParameterSave->Length
+ &TempLockBoxParameterSave.Guid,
+ (VOID *)(UINTN)TempLockBoxParameterSave.Buffer,
+ (UINTN)TempLockBoxParameterSave.Length
);
LockBoxParameterSave->Header.ReturnStatus = (UINT64)Status;
return ;
@@ -153,6 +156,7 @@ SmmLockBoxSetAttributes (
)
{
EFI_STATUS Status;
+ EFI_SMM_LOCK_BOX_PARAMETER_SET_ATTRIBUTES TempLockBoxParameterSetAttributes;
//
// Sanity check
@@ -163,12 +167,14 @@ SmmLockBoxSetAttributes (
return ;
}
+ CopyMem (&TempLockBoxParameterSetAttributes, LockBoxParameterSetAttributes, sizeof (EFI_SMM_LOCK_BOX_PARAMETER_SET_ATTRIBUTES));
+
//
// Update data
//
Status = SetLockBoxAttributes (
- &LockBoxParameterSetAttributes->Guid,
- LockBoxParameterSetAttributes->Attributes
+ &TempLockBoxParameterSetAttributes.Guid,
+ TempLockBoxParameterSetAttributes.Attributes
);
LockBoxParameterSetAttributes->Header.ReturnStatus = (UINT64)Status;
return ;
@@ -189,6 +195,7 @@ SmmLockBoxUpdate (
)
{
EFI_STATUS Status;
+ EFI_SMM_LOCK_BOX_PARAMETER_UPDATE TempLockBoxParameterUpdate;
//
// Sanity check
@@ -199,11 +206,13 @@ SmmLockBoxUpdate (
return ;
}
+ CopyMem (&TempLockBoxParameterUpdate, LockBoxParameterUpdate, sizeof (EFI_SMM_LOCK_BOX_PARAMETER_UPDATE));
+
//
// Sanity check
//
- if (!IsAddressValid ((UINTN)LockBoxParameterUpdate->Buffer, (UINTN)LockBoxParameterUpdate->Length)) {
- DEBUG ((EFI_D_ERROR, "SmmLockBox Update address in SMRAM!\n"));
+ if (!IsAddressValid ((UINTN)TempLockBoxParameterUpdate.Buffer, (UINTN)TempLockBoxParameterUpdate.Length)) {
+ DEBUG ((EFI_D_ERROR, "SmmLockBox Update address in SMRAM or buffer overflow!\n"));
LockBoxParameterUpdate->Header.ReturnStatus = (UINT64)EFI_ACCESS_DENIED;
return ;
}
@@ -212,10 +221,10 @@ SmmLockBoxUpdate (
// Update data
//
Status = UpdateLockBox (
- &LockBoxParameterUpdate->Guid,
- (UINTN)LockBoxParameterUpdate->Offset,
- (VOID *)(UINTN)LockBoxParameterUpdate->Buffer,
- (UINTN)LockBoxParameterUpdate->Length
+ &TempLockBoxParameterUpdate.Guid,
+ (UINTN)TempLockBoxParameterUpdate.Offset,
+ (VOID *)(UINTN)TempLockBoxParameterUpdate.Buffer,
+ (UINTN)TempLockBoxParameterUpdate.Length
);
LockBoxParameterUpdate->Header.ReturnStatus = (UINT64)Status;
return ;
@@ -236,12 +245,15 @@ SmmLockBoxRestore (
)
{
EFI_STATUS Status;
+ EFI_SMM_LOCK_BOX_PARAMETER_RESTORE TempLockBoxParameterRestore;
+
+ CopyMem (&TempLockBoxParameterRestore, LockBoxParameterRestore, sizeof (EFI_SMM_LOCK_BOX_PARAMETER_RESTORE));
//
// Sanity check
//
- if (!IsAddressValid ((UINTN)LockBoxParameterRestore->Buffer, (UINTN)LockBoxParameterRestore->Length)) {
- DEBUG ((EFI_D_ERROR, "SmmLockBox Restore address in SMRAM!\n"));
+ if (!IsAddressValid ((UINTN)TempLockBoxParameterRestore.Buffer, (UINTN)TempLockBoxParameterRestore.Length)) {
+ DEBUG ((EFI_D_ERROR, "SmmLockBox Restore address in SMRAM or buffer overflow!\n"));
LockBoxParameterRestore->Header.ReturnStatus = (UINT64)EFI_ACCESS_DENIED;
return ;
}
@@ -249,17 +261,17 @@ SmmLockBoxRestore (
//
// Restore data
//
- if ((LockBoxParameterRestore->Length == 0) && (LockBoxParameterRestore->Buffer == 0)) {
+ if ((TempLockBoxParameterRestore.Length == 0) && (TempLockBoxParameterRestore.Buffer == 0)) {
Status = RestoreLockBox (
- &LockBoxParameterRestore->Guid,
+ &TempLockBoxParameterRestore.Guid,
NULL,
NULL
);
} else {
Status = RestoreLockBox (
- &LockBoxParameterRestore->Guid,
- (VOID *)(UINTN)LockBoxParameterRestore->Buffer,
- (UINTN *)&LockBoxParameterRestore->Length
+ &TempLockBoxParameterRestore.Guid,
+ (VOID *)(UINTN)TempLockBoxParameterRestore.Buffer,
+ (UINTN *)&TempLockBoxParameterRestore.Length
);
}
LockBoxParameterRestore->Header.ReturnStatus = (UINT64)Status;
@@ -309,18 +321,28 @@ SmmLockBoxHandler (
)
{
EFI_SMM_LOCK_BOX_PARAMETER_HEADER *LockBoxParameterHeader;
+ UINTN TempCommBufferSize;
DEBUG ((EFI_D_ERROR, "SmmLockBox SmmLockBoxHandler Enter\n"));
//
+ // If input is invalid, stop processing this SMI
+ //
+ if (CommBuffer == NULL || CommBufferSize == NULL) {
+ return EFI_SUCCESS;
+ }
+
+ TempCommBufferSize = *CommBufferSize;
+
+ //
// Sanity check
//
- if (*CommBufferSize < sizeof(EFI_SMM_LOCK_BOX_PARAMETER_HEADER)) {
+ if (TempCommBufferSize < sizeof(EFI_SMM_LOCK_BOX_PARAMETER_HEADER)) {
DEBUG ((EFI_D_ERROR, "SmmLockBox Command Buffer Size invalid!\n"));
return EFI_SUCCESS;
}
- if (!IsAddressValid ((UINTN)CommBuffer, *CommBufferSize)) {
- DEBUG ((EFI_D_ERROR, "SmmLockBox Command Buffer in SMRAM!\n"));
+ if (!IsAddressValid ((UINTN)CommBuffer, TempCommBufferSize)) {
+ DEBUG ((EFI_D_ERROR, "SmmLockBox Command Buffer in SMRAM or overflow!\n"));
return EFI_SUCCESS;
}
@@ -334,35 +356,35 @@ SmmLockBoxHandler (
switch (LockBoxParameterHeader->Command) {
case EFI_SMM_LOCK_BOX_COMMAND_SAVE:
- if (*CommBufferSize < sizeof(EFI_SMM_LOCK_BOX_PARAMETER_SAVE)) {
+ if (TempCommBufferSize < sizeof(EFI_SMM_LOCK_BOX_PARAMETER_SAVE)) {
DEBUG ((EFI_D_ERROR, "SmmLockBox Command Buffer Size for SAVE invalid!\n"));
break;
}
SmmLockBoxSave ((EFI_SMM_LOCK_BOX_PARAMETER_SAVE *)(UINTN)LockBoxParameterHeader);
break;
case EFI_SMM_LOCK_BOX_COMMAND_UPDATE:
- if (*CommBufferSize < sizeof(EFI_SMM_LOCK_BOX_PARAMETER_UPDATE)) {
+ if (TempCommBufferSize < sizeof(EFI_SMM_LOCK_BOX_PARAMETER_UPDATE)) {
DEBUG ((EFI_D_ERROR, "SmmLockBox Command Buffer Size for UPDATE invalid!\n"));
break;
}
SmmLockBoxUpdate ((EFI_SMM_LOCK_BOX_PARAMETER_UPDATE *)(UINTN)LockBoxParameterHeader);
break;
case EFI_SMM_LOCK_BOX_COMMAND_RESTORE:
- if (*CommBufferSize < sizeof(EFI_SMM_LOCK_BOX_PARAMETER_RESTORE)) {
+ if (TempCommBufferSize < sizeof(EFI_SMM_LOCK_BOX_PARAMETER_RESTORE)) {
DEBUG ((EFI_D_ERROR, "SmmLockBox Command Buffer Size for RESTORE invalid!\n"));
break;
}
SmmLockBoxRestore ((EFI_SMM_LOCK_BOX_PARAMETER_RESTORE *)(UINTN)LockBoxParameterHeader);
break;
case EFI_SMM_LOCK_BOX_COMMAND_SET_ATTRIBUTES:
- if (*CommBufferSize < sizeof(EFI_SMM_LOCK_BOX_PARAMETER_SET_ATTRIBUTES)) {
+ if (TempCommBufferSize < sizeof(EFI_SMM_LOCK_BOX_PARAMETER_SET_ATTRIBUTES)) {
DEBUG ((EFI_D_ERROR, "SmmLockBox Command Buffer Size for SET_ATTRIBUTES invalid!\n"));
break;
}
SmmLockBoxSetAttributes ((EFI_SMM_LOCK_BOX_PARAMETER_SET_ATTRIBUTES *)(UINTN)LockBoxParameterHeader);
break;
case EFI_SMM_LOCK_BOX_COMMAND_RESTORE_ALL_IN_PLACE:
- if (*CommBufferSize < sizeof(EFI_SMM_LOCK_BOX_PARAMETER_RESTORE_ALL_IN_PLACE)) {
+ if (TempCommBufferSize < sizeof(EFI_SMM_LOCK_BOX_PARAMETER_RESTORE_ALL_IN_PLACE)) {
DEBUG ((EFI_D_ERROR, "SmmLockBox Command Buffer Size for RESTORE_ALL_IN_PLACE invalid!\n"));
break;
}
diff --git a/MdeModulePkg/Universal/Network/IScsiDxe/IScsiProto.c b/MdeModulePkg/Universal/Network/IScsiDxe/IScsiProto.c
index b1f250b55e..aff036bb7a 100644
--- a/MdeModulePkg/Universal/Network/IScsiDxe/IScsiProto.c
+++ b/MdeModulePkg/Universal/Network/IScsiDxe/IScsiProto.c
@@ -1,7 +1,7 @@
/** @file
The implementation of iSCSI protocol based on RFC3720.
-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
@@ -742,7 +742,7 @@ IScsiProcessLoginRsp (
NetbufQueAppend (&Conn->RspQue, Pdu);
Conn->PartialRspRcvd = Continue;
- if (Continue) {
+ if ((!Transit) || 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/Ip4ConfigDxe/Ip4ConfigDriver.c b/MdeModulePkg/Universal/Network/Ip4ConfigDxe/Ip4ConfigDriver.c
index 2a9fcb94e5..790e44be4c 100644
--- a/MdeModulePkg/Universal/Network/Ip4ConfigDxe/Ip4ConfigDriver.c
+++ b/MdeModulePkg/Universal/Network/Ip4ConfigDxe/Ip4ConfigDriver.c
@@ -1,7 +1,7 @@
/** @file
The driver binding for IP4 CONFIG 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<BR>
@@ -71,7 +71,7 @@ IP4_CONFIG_INSTANCE mIp4ConfigTemplate = {
NULL,
NULL,
NULL,
- EFI_NOT_READY,
+ 0,
{
0,
0,
@@ -109,6 +109,8 @@ Ip4ConfigDriverEntryPoint (
IN EFI_SYSTEM_TABLE *SystemTable
)
{
+ mIp4ConfigTemplate.Result = EFI_NOT_READY;
+
return EfiLibInstallDriverBindingComponentName2 (
ImageHandle,
SystemTable,
diff --git a/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Driver.c b/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Driver.c
index 4a3d342711..73b4e246e0 100644
--- a/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Driver.c
+++ b/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Driver.c
@@ -1,7 +1,7 @@
/** @file
The driver binding and service binding protocol for IP4 driver.
-Copyright (c) 2005 - 2012, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2005 - 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
@@ -572,6 +572,8 @@ Ip4DriverBindingStop (
INTN State;
LIST_ENTRY *List;
IP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT Context;
+ IP4_INTERFACE *IpIf;
+ IP4_ROUTE_TABLE *RouteTable;
//
// IP4 driver opens the MNP child, ARP children or the IP4_CONFIG protocol
@@ -681,6 +683,35 @@ Ip4DriverBindingStop (
&Context,
NULL
);
+ } else if (IpSb->DefaultInterface->ArpHandle == ControllerHandle) {
+ //
+ // The ARP protocol for the default interface is being uninstalled and all
+ // its IP child handles should have been destroyed before. So, release the
+ // default interface and route table, create a new one and mark it as not started.
+ //
+ Ip4CancelReceive (IpSb->DefaultInterface);
+ Ip4FreeInterface (IpSb->DefaultInterface, NULL);
+ Ip4FreeRouteTable (IpSb->DefaultRouteTable);
+
+ IpIf = Ip4CreateInterface (IpSb->Mnp, IpSb->Controller, IpSb->Image);
+ if (IpIf == NULL) {
+ goto ON_ERROR;
+ }
+ RouteTable = Ip4CreateRouteTable ();
+ if (RouteTable == NULL) {
+ Ip4FreeInterface (IpIf, NULL);
+ goto ON_ERROR;;
+ }
+
+ IpSb->DefaultInterface = IpIf;
+ InsertHeadList (&IpSb->Interfaces, &IpIf->Link);
+ IpSb->DefaultRouteTable = RouteTable;
+ Ip4ReceiveFrame (IpIf, NULL, Ip4AccpetFrame, IpSb);
+
+ if (IpSb->Ip4Config != NULL && IpSb->State != IP4_SERVICE_DESTROY) {
+ IpSb->Ip4Config->Stop (IpSb->Ip4Config);
+ }
+ IpSb->State = IP4_SERVICE_UNSTARTED;
} else if (IsListEmpty (&IpSb->Children)) {
State = IpSb->State;
IpSb->State = IP4_SERVICE_DESTROY;
diff --git a/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4If.c b/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4If.c
index 6711636333..e4ab17a37e 100644
--- a/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4If.c
+++ b/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4If.c
@@ -740,11 +740,24 @@ Ip4FreeInterface (
//
Ip4CancelFrames (Interface, EFI_ABORTED, Ip4CancelInstanceFrame, IpInstance);
+ if (--Interface->RefCnt > 0) {
+ return EFI_SUCCESS;
+ }
+
//
- // Destroy the ARP instance if this is the last IP instance that
- // has the address.
+ // Destroy the interface if this is the last IP instance that
+ // has the address. Remove all the system transmitted packets
+ // from this interface, cancel the receive request if there is
+ // one, and destroy the ARP requests.
//
- if (Interface->Arp != NULL && IsListEmpty (&Interface->IpInstances)) {
+ Ip4CancelFrames (Interface, EFI_ABORTED, Ip4CancelInstanceFrame, NULL);
+ Ip4CancelReceive (Interface);
+
+ ASSERT (IsListEmpty (&Interface->IpInstances));
+ ASSERT (IsListEmpty (&Interface->ArpQues));
+ ASSERT (IsListEmpty (&Interface->SentFrames));
+
+ if (Interface->Arp != NULL) {
gBS->CloseProtocol (
Interface->ArpHandle,
&gEfiArpProtocolGuid,
@@ -758,25 +771,8 @@ Ip4FreeInterface (
&gEfiArpServiceBindingProtocolGuid,
Interface->ArpHandle
);
- Interface->Arp = NULL;
- }
-
- if (--Interface->RefCnt > 0) {
- return EFI_SUCCESS;
}
- //
- // Destroy the interface if it is not referenced by any IP instance (for common Interface)
- // or the IP service (for the DefaultInterface). Remove all the system transmitted packets
- // from this interface, cancel the receive request if there is one.
- //
- Ip4CancelFrames (Interface, EFI_ABORTED, Ip4CancelInstanceFrame, NULL);
- Ip4CancelReceive (Interface);
-
- ASSERT (IsListEmpty (&Interface->IpInstances));
- ASSERT (IsListEmpty (&Interface->ArpQues));
- ASSERT (IsListEmpty (&Interface->SentFrames));
-
RemoveEntryList (&Interface->Link);
FreePool (Interface);
diff --git a/MdeModulePkg/Universal/Network/Tcp4Dxe/Tcp4Driver.c b/MdeModulePkg/Universal/Network/Tcp4Dxe/Tcp4Driver.c
index 76eac722cb..29a0cf76c2 100644
--- a/MdeModulePkg/Universal/Network/Tcp4Dxe/Tcp4Driver.c
+++ b/MdeModulePkg/Universal/Network/Tcp4Dxe/Tcp4Driver.c
@@ -1,7 +1,7 @@
/** @file
Tcp driver function.
-Copyright (c) 2005 - 2012, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2005 - 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
@@ -607,7 +607,7 @@ Tcp4CreateSocketCallback (
(VOID **) &This->ParentDevicePath,
TcpServiceData->DriverBindingHandle,
This->SockHandle,
- EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
if (EFI_ERROR (Status)) {
gBS->CloseProtocol (
@@ -649,16 +649,6 @@ Tcp4DestroySocketCallback (
RemoveEntryList (&This->Link);
//
- // Close the device path protocol
- //
- gBS->CloseProtocol (
- TcpServiceData->ControllerHandle,
- &gEfiDevicePathProtocolGuid,
- TcpServiceData->DriverBindingHandle,
- This->SockHandle
- );
-
- //
// Close the Ip4 protocol.
//
gBS->CloseProtocol (
diff --git a/MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcDhcp.c b/MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcDhcp.c
index fa3594d36b..8be753151c 100644
--- a/MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcDhcp.c
+++ b/MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcDhcp.c
@@ -1,6 +1,7 @@
/** @file
Support for PxeBc dhcp functions.
+Copyright (c) 2013, Red Hat, Inc.
Copyright (c) 2007 - 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
@@ -1536,6 +1537,19 @@ PxeBcSelectBootPrompt (
}
VendorOpt = &Packet->PxeVendorOption;
+ //
+ // According to the PXE specification 2.1, Table 2-1 PXE DHCP Options (Full
+ // List), we must not consider a boot prompt or boot menu if all of the
+ // following hold:
+ // - the PXE_DISCOVERY_CONTROL PXE tag is present inside the Vendor Options
+ // (=43) DHCP tag, and
+ // - the PXE_DISCOVERY_CONTROL PXE tag has bit 3 set, and
+ // - a boot file name has been presented with DHCP option 67.
+ //
+ if (IS_DISABLE_PROMPT_MENU (VendorOpt->DiscoverCtrl) &&
+ Packet->Dhcp4Option[PXEBC_DHCP4_TAG_INDEX_BOOTFILE] != NULL) {
+ return EFI_ABORTED;
+ }
if (!IS_VALID_BOOT_PROMPT (VendorOpt->BitMap)) {
return EFI_SUCCESS;
diff --git a/MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcDhcp.h b/MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcDhcp.h
index 5e37228efa..b56d10d82a 100644
--- a/MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcDhcp.h
+++ b/MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcDhcp.h
@@ -1,6 +1,7 @@
/** @file
Dhcp and Discover routines for PxeBc.
+Copyright (c) 2013, Red Hat, Inc.
Copyright (c) 2007 - 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
@@ -160,7 +161,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#define IS_DISABLE_BCAST_DISCOVER(x) (((x) & BIT (0)) == BIT (0))
#define IS_DISABLE_MCAST_DISCOVER(x) (((x) & BIT (1)) == BIT (1))
#define IS_ENABLE_USE_SERVER_LIST(x) (((x) & BIT (2)) == BIT (2))
-#define IS_ENABLE_BOOT_FILE_NAME(x) (((x) & BIT (3)) == BIT (3))
+#define IS_DISABLE_PROMPT_MENU(x) (((x) & BIT (3)) == BIT (3))
#define SET_VENDOR_OPTION_BIT_MAP(x, y) (((x)[(y) / 32]) = (UINT32) ((x)[(y) / 32]) | BIT ((y) % 32))
diff --git a/MdeModulePkg/Universal/Network/UefiPxeBcDxe/UefiPxeBcDxe.inf b/MdeModulePkg/Universal/Network/UefiPxeBcDxe/UefiPxeBcDxe.inf
index 3ac4fb041f..423555aecc 100644
--- a/MdeModulePkg/Universal/Network/UefiPxeBcDxe/UefiPxeBcDxe.inf
+++ b/MdeModulePkg/Universal/Network/UefiPxeBcDxe/UefiPxeBcDxe.inf
@@ -1,7 +1,7 @@
## @file
# Component name for module UefiPxeBc
#
-# 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
@@ -66,9 +66,6 @@
DpcLib
PcdLib
-[Guids]
- gEfiSmbiosTableGuid # ALWAYS_CONSUMED
-
[Protocols]
gEfiArpServiceBindingProtocolGuid # PROTOCOL ALWAYS_CONSUMED
gEfiArpProtocolGuid # PROTOCOL ALWAYS_CONSUMED
diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/IfrParse.c b/MdeModulePkg/Universal/SetupBrowserDxe/IfrParse.c
index cc3823f0ef..2464aebd09 100644
--- a/MdeModulePkg/Universal/SetupBrowserDxe/IfrParse.c
+++ b/MdeModulePkg/Universal/SetupBrowserDxe/IfrParse.c
@@ -18,6 +18,7 @@ UINT16 mStatementIndex;
UINT16 mExpressionOpCodeIndex;
BOOLEAN mInScopeSubtitle;
+extern LIST_ENTRY gBrowserStorageList;
/**
Initialize Statement header members.
@@ -179,6 +180,7 @@ CreateQuestion (
FORMSET_STORAGE *Storage;
NAME_VALUE_NODE *NameValueNode;
EFI_STATUS Status;
+ BOOLEAN Find;
Statement = CreateStatement (OpCodeData, FormSet, Form);
if (Statement == NULL) {
@@ -220,7 +222,7 @@ CreateQuestion (
Storage = FORMSET_STORAGE_FROM_LINK (Link);
if (Storage->VarStoreId == Statement->VarStoreId) {
- Statement->Storage = Storage;
+ Statement->Storage = Storage->BrowserStorage;
break;
}
@@ -238,19 +240,39 @@ CreateQuestion (
if (Statement->Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {
//
- // Insert to Name/Value varstore list
+ // Check whether old string node already exist.
//
- NameValueNode = AllocateZeroPool (sizeof (NAME_VALUE_NODE));
- ASSERT (NameValueNode != NULL);
- NameValueNode->Signature = NAME_VALUE_NODE_SIGNATURE;
- NameValueNode->Name = AllocateCopyPool (StrSize (Statement->VariableName), Statement->VariableName);
- ASSERT (NameValueNode->Name != NULL);
- NameValueNode->Value = AllocateZeroPool (0x10);
- ASSERT (NameValueNode->Value != NULL);
- NameValueNode->EditValue = AllocateZeroPool (0x10);
- ASSERT (NameValueNode->EditValue != NULL);
+ Find = FALSE;
+ if (!IsListEmpty(&Statement->Storage->NameValueListHead)) {
+ Link = GetFirstNode (&Statement->Storage->NameValueListHead);
+ while (!IsNull (&Statement->Storage->NameValueListHead, Link)) {
+ NameValueNode = NAME_VALUE_NODE_FROM_LINK (Link);
- InsertTailList (&Statement->Storage->NameValueListHead, &NameValueNode->Link);
+ if (StrCmp (Statement->VariableName, NameValueNode->Name) == 0) {
+ Find = TRUE;
+ break;
+ }
+
+ Link = GetNextNode (&Statement->Storage->NameValueListHead, Link);
+ }
+ }
+
+ if (!Find) {
+ //
+ // Insert to Name/Value varstore list
+ //
+ NameValueNode = AllocateZeroPool (sizeof (NAME_VALUE_NODE));
+ ASSERT (NameValueNode != NULL);
+ NameValueNode->Signature = NAME_VALUE_NODE_SIGNATURE;
+ NameValueNode->Name = AllocateCopyPool (StrSize (Statement->VariableName), Statement->VariableName);
+ ASSERT (NameValueNode->Name != NULL);
+ NameValueNode->Value = AllocateZeroPool (0x10);
+ ASSERT (NameValueNode->Value != NULL);
+ NameValueNode->EditValue = AllocateZeroPool (0x10);
+ ASSERT (NameValueNode->EditValue != NULL);
+
+ InsertTailList (&Statement->Storage->NameValueListHead, &NameValueNode->Link);
+ }
}
}
@@ -281,32 +303,6 @@ CreateExpression (
return Expression;
}
-
-/**
- Allocate a FORMSET_STORAGE data structure and insert to FormSet Storage List.
-
- @param FormSet Pointer of the current FormSet
-
- @return Pointer to a FORMSET_STORAGE data structure.
-
-**/
-FORMSET_STORAGE *
-CreateStorage (
- IN FORM_BROWSER_FORMSET *FormSet
- )
-{
- FORMSET_STORAGE *Storage;
-
- Storage = AllocateZeroPool (sizeof (FORMSET_STORAGE));
- ASSERT (Storage != NULL);
- Storage->Signature = FORMSET_STORAGE_SIGNATURE;
- InitializeListHead (&Storage->NameValueListHead);
- InsertTailList (&FormSet->StorageListHead, &Storage->Link);
-
- return Storage;
-}
-
-
/**
Create ConfigHdr string for a storage.
@@ -319,7 +315,7 @@ CreateStorage (
EFI_STATUS
InitializeConfigHdr (
IN FORM_BROWSER_FORMSET *FormSet,
- IN OUT FORMSET_STORAGE *Storage
+ IN OUT BROWSER_STORAGE *Storage
)
{
CHAR16 *Name;
@@ -341,12 +337,185 @@ InitializeConfigHdr (
return EFI_NOT_FOUND;
}
- Storage->ConfigRequest = AllocateCopyPool (StrSize (Storage->ConfigHdr), Storage->ConfigHdr);
- Storage->SpareStrLen = 0;
-
return EFI_SUCCESS;
}
+/**
+ Find the global storage link base on the input storate type, name and guid.
+
+ @param StorageType Storage type.
+ @param StorageGuid Storage guid.
+ @param StorageName Storage Name.
+
+ @return Pointer to a GLOBAL_STORAGE data structure.
+
+**/
+BROWSER_STORAGE *
+FindStorageInList (
+ IN UINT8 StorageType,
+ IN EFI_GUID *StorageGuid,
+ IN CHAR16 *StorageName
+ )
+{
+ LIST_ENTRY *Link;
+ BROWSER_STORAGE *BrowserStorage;
+
+ Link = GetFirstNode (&gBrowserStorageList);
+ while (!IsNull (&gBrowserStorageList, Link)) {
+ BrowserStorage = BROWSER_STORAGE_FROM_LINK (Link);
+
+ if ((BrowserStorage->Type == StorageType) && CompareGuid (&BrowserStorage->Guid, StorageGuid)) {
+ if (StorageType == EFI_HII_VARSTORE_NAME_VALUE) {
+ return BrowserStorage;
+ }
+
+ if (StrCmp (BrowserStorage->Name, StorageName) == 0) {
+ return BrowserStorage;
+ }
+ }
+
+ //
+ // Get Next Storage.
+ //
+ Link = GetNextNode (&gBrowserStorageList, Link);
+ }
+
+ return NULL;
+}
+
+/**
+ Intialize the Global Storage.
+
+ @param BrowserStorage Pointer to the global storage.
+ @param StorageType Storage type.
+ @param OpCodeData Binary data for this opcode.
+
+**/
+VOID
+IntializeBrowserStorage (
+ IN BROWSER_STORAGE *BrowserStorage,
+ IN UINT8 StorageType,
+ IN UINT8 *OpCodeData
+ )
+{
+ switch (StorageType) {
+ case EFI_HII_VARSTORE_BUFFER:
+ CopyMem (&BrowserStorage->Guid, &((EFI_IFR_VARSTORE *) OpCodeData)->Guid, sizeof (EFI_GUID));
+ CopyMem (&BrowserStorage->Size, &((EFI_IFR_VARSTORE *) OpCodeData)->Size, sizeof (UINT16));
+
+ BrowserStorage->Buffer = AllocateZeroPool (BrowserStorage->Size);
+ BrowserStorage->EditBuffer = AllocateZeroPool (BrowserStorage->Size);
+ break;
+
+ case EFI_HII_VARSTORE_EFI_VARIABLE:
+ case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:
+ CopyMem (&BrowserStorage->Guid, &((EFI_IFR_VARSTORE_EFI *) OpCodeData)->Guid, sizeof (EFI_GUID));
+ CopyMem (&BrowserStorage->Attributes, &((EFI_IFR_VARSTORE_EFI *) OpCodeData)->Attributes, sizeof (UINT32));
+ CopyMem (&BrowserStorage->Size, &((EFI_IFR_VARSTORE_EFI *) OpCodeData)->Size, sizeof (UINT16));
+
+ if (StorageType == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) {
+ BrowserStorage->Buffer = AllocateZeroPool (BrowserStorage->Size);
+ BrowserStorage->EditBuffer = AllocateZeroPool (BrowserStorage->Size);
+ }
+ break;
+
+ case EFI_HII_VARSTORE_NAME_VALUE:
+ CopyMem (&BrowserStorage->Guid, &((EFI_IFR_VARSTORE_NAME_VALUE *) OpCodeData)->Guid, sizeof (EFI_GUID));
+
+ InitializeListHead (&BrowserStorage->NameValueListHead);
+ break;
+
+ default:
+ break;
+ }
+}
+
+/**
+ Allocate a FORMSET_STORAGE data structure and insert to FormSet Storage List.
+
+ @param FormSet Pointer of the current FormSet
+ @param StorageType Storage type.
+ @param OpCodeData Binary data for this opcode.
+
+ @return Pointer to a FORMSET_STORAGE data structure.
+
+**/
+FORMSET_STORAGE *
+CreateStorage (
+ IN FORM_BROWSER_FORMSET *FormSet,
+ IN UINT8 StorageType,
+ IN UINT8 *OpCodeData
+ )
+{
+ FORMSET_STORAGE *Storage;
+ CHAR16 *UnicodeString;
+ UINT16 Index;
+ BROWSER_STORAGE *BrowserStorage;
+ EFI_GUID *StorageGuid;
+ CHAR8 *StorageName;
+
+ UnicodeString = NULL;
+ StorageName = NULL;
+ switch (StorageType) {
+ case EFI_HII_VARSTORE_BUFFER:
+ StorageGuid = (EFI_GUID *) (CHAR8*) &((EFI_IFR_VARSTORE *) OpCodeData)->Guid;
+ StorageName = (CHAR8 *) ((EFI_IFR_VARSTORE *) OpCodeData)->Name;
+ break;
+
+ case EFI_HII_VARSTORE_EFI_VARIABLE:
+ case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:
+ StorageGuid = (EFI_GUID *) (CHAR8*) &((EFI_IFR_VARSTORE_EFI *) OpCodeData)->Guid;
+ StorageName = (CHAR8 *) ((EFI_IFR_VARSTORE_EFI *) OpCodeData)->Name;
+ break;
+
+ default:
+ ASSERT (StorageType == EFI_HII_VARSTORE_NAME_VALUE);
+ StorageGuid = &((EFI_IFR_VARSTORE_NAME_VALUE *) OpCodeData)->Guid;
+ break;
+ }
+
+ if (StorageType != EFI_HII_VARSTORE_NAME_VALUE) {
+ ASSERT (StorageName != NULL);
+
+ UnicodeString = AllocateZeroPool (AsciiStrSize (StorageName) * 2);
+ ASSERT (UnicodeString != NULL);
+ for (Index = 0; StorageName[Index] != 0; Index++) {
+ UnicodeString[Index] = (CHAR16) StorageName[Index];
+ }
+ }
+
+ Storage = AllocateZeroPool (sizeof (FORMSET_STORAGE));
+ ASSERT (Storage != NULL);
+ Storage->Signature = FORMSET_STORAGE_SIGNATURE;
+ InsertTailList (&FormSet->StorageListHead, &Storage->Link);
+
+ BrowserStorage = FindStorageInList(StorageType, StorageGuid, UnicodeString);
+ if (BrowserStorage == NULL) {
+ BrowserStorage = AllocateZeroPool (sizeof (BROWSER_STORAGE));
+ ASSERT (BrowserStorage != NULL);
+
+ BrowserStorage->Signature = BROWSER_STORAGE_SIGNATURE;
+ InsertTailList (&gBrowserStorageList, &BrowserStorage->Link);
+
+ IntializeBrowserStorage (BrowserStorage, StorageType, OpCodeData);
+ BrowserStorage->Type = StorageType;
+ if (StorageType != EFI_HII_VARSTORE_NAME_VALUE) {
+ BrowserStorage->Name = UnicodeString;
+ }
+
+ InitializeConfigHdr (FormSet, BrowserStorage);
+ }
+ //
+ // Add count because one formset storage use this global storage.
+ //
+ BrowserStorage->ReferenceCount++;
+
+ Storage->BrowserStorage = BrowserStorage;
+ Storage->ConfigRequest = AllocateCopyPool (StrSize (BrowserStorage->ConfigHdr), BrowserStorage->ConfigHdr);
+ Storage->SpareStrLen = 0;
+
+ return Storage;
+}
/**
Initialize Request Element of a Question. <RequestElement> ::= '&'<BlockName> | '&'<Label>
@@ -366,7 +535,8 @@ InitializeRequestElement (
IN OUT FORM_BROWSER_FORM *Form
)
{
- FORMSET_STORAGE *Storage;
+ BROWSER_STORAGE *Storage;
+ FORMSET_STORAGE *FormsetStorage;
UINTN StrLen;
UINTN StringSize;
CHAR16 *NewStr;
@@ -414,26 +584,42 @@ InitializeRequestElement (
}
//
+ // Find Formset Storage for this Question
+ //
+ FormsetStorage = NULL;
+ Link = GetFirstNode (&FormSet->StorageListHead);
+ while (!IsNull (&FormSet->StorageListHead, Link)) {
+ FormsetStorage = FORMSET_STORAGE_FROM_LINK (Link);
+
+ if (FormsetStorage->VarStoreId == Question->VarStoreId) {
+ break;
+ }
+
+ Link = GetNextNode (&FormSet->StorageListHead, Link);
+ }
+ ASSERT (FormsetStorage != NULL);
+
+ //
// Append <RequestElement> to <ConfigRequest>
//
- if (StrLen > Storage->SpareStrLen) {
+ if (StrLen > FormsetStorage->SpareStrLen) {
//
// Old String buffer is not sufficient for RequestElement, allocate a new one
//
- StringSize = (Storage->ConfigRequest != NULL) ? StrSize (Storage->ConfigRequest) : sizeof (CHAR16);
+ StringSize = (FormsetStorage->ConfigRequest != NULL) ? StrSize (FormsetStorage->ConfigRequest) : sizeof (CHAR16);
NewStr = AllocateZeroPool (StringSize + CONFIG_REQUEST_STRING_INCREMENTAL * sizeof (CHAR16));
ASSERT (NewStr != NULL);
- if (Storage->ConfigRequest != NULL) {
- CopyMem (NewStr, Storage->ConfigRequest, StringSize);
- FreePool (Storage->ConfigRequest);
+ if (FormsetStorage->ConfigRequest != NULL) {
+ CopyMem (NewStr, FormsetStorage->ConfigRequest, StringSize);
+ FreePool (FormsetStorage->ConfigRequest);
}
- Storage->ConfigRequest = NewStr;
- Storage->SpareStrLen = CONFIG_REQUEST_STRING_INCREMENTAL;
+ FormsetStorage->ConfigRequest = NewStr;
+ FormsetStorage->SpareStrLen = CONFIG_REQUEST_STRING_INCREMENTAL;
}
- StrCat (Storage->ConfigRequest, RequestElement);
- Storage->ElementCount++;
- Storage->SpareStrLen -= StrLen;
+ StrCat (FormsetStorage->ConfigRequest, RequestElement);
+ FormsetStorage->ElementCount++;
+ FormsetStorage->SpareStrLen -= StrLen;
//
// Update the Config Request info saved in the form.
@@ -444,7 +630,7 @@ InitializeRequestElement (
while (!IsNull (&Form->ConfigRequestHead, Link)) {
ConfigInfo = FORM_BROWSER_CONFIG_REQUEST_FROM_LINK (Link);
- if (ConfigInfo != NULL && ConfigInfo->Storage->VarStoreId == Storage->VarStoreId) {
+ if (ConfigInfo != NULL && ConfigInfo->Storage == Storage) {
Find = TRUE;
break;
}
@@ -532,7 +718,6 @@ DestroyExpression (
FreePool (Expression);
}
-
/**
Free resources of a storage.
@@ -544,47 +729,20 @@ DestroyStorage (
IN FORMSET_STORAGE *Storage
)
{
- LIST_ENTRY *Link;
- NAME_VALUE_NODE *NameValueNode;
-
if (Storage == NULL) {
return;
}
- if (Storage->Name != NULL) {
- FreePool (Storage->Name);
- }
- if (Storage->Buffer != NULL) {
- FreePool (Storage->Buffer);
- }
- if (Storage->EditBuffer != NULL) {
- FreePool (Storage->EditBuffer);
- }
-
- while (!IsListEmpty (&Storage->NameValueListHead)) {
- Link = GetFirstNode (&Storage->NameValueListHead);
- NameValueNode = NAME_VALUE_NODE_FROM_LINK (Link);
- RemoveEntryList (&NameValueNode->Link);
-
- if (NameValueNode->Name != NULL) {
- FreePool (NameValueNode->Name);
- }
- if (NameValueNode->Value != NULL) {
- FreePool (NameValueNode->Value);
- }
- if (NameValueNode->EditValue != NULL) {
- FreePool (NameValueNode->EditValue);
- }
- FreePool (NameValueNode);
- }
-
- if (Storage->ConfigHdr != NULL) {
- FreePool (Storage->ConfigHdr);
- }
if (Storage->ConfigRequest != NULL) {
FreePool (Storage->ConfigRequest);
}
+ //
+ // Minus the reference to the global storage.
+ //
+ ASSERT (Storage->BrowserStorage->ReferenceCount > 0);
+ Storage->BrowserStorage->ReferenceCount--;
+
FreePool (Storage);
}
@@ -915,7 +1073,6 @@ ParseOpCodes (
)
{
EFI_STATUS Status;
- UINT16 Index;
FORM_BROWSER_FORM *CurrentForm;
FORM_BROWSER_STATEMENT *CurrentStatement;
EXPRESSION_OPCODE *ExpressionOpCode;
@@ -931,7 +1088,6 @@ ParseOpCodes (
QUESTION_DEFAULT *CurrentDefault;
QUESTION_OPTION *CurrentOption;
UINT8 Width;
- CHAR8 *AsciiString;
UINT16 NumberOfStatement;
UINT16 NumberOfExpression;
EFI_IMAGE_ID *ImageId;
@@ -1104,7 +1260,7 @@ ParseOpCodes (
while (!IsNull (&FormSet->StorageListHead, Link)) {
VarStorage = FORMSET_STORAGE_FROM_LINK (Link);
if (VarStorage->VarStoreId == ((EFI_IFR_GET *) OpCodeData)->VarStoreId) {
- ExpressionOpCode->VarStorage = VarStorage;
+ ExpressionOpCode->VarStorage = VarStorage->BrowserStorage;
break;
}
Link = GetNextNode (&FormSet->StorageListHead, Link);
@@ -1448,76 +1604,28 @@ ParseOpCodes (
//
// Create a buffer Storage for this FormSet
//
- Storage = CreateStorage (FormSet);
- Storage->Type = EFI_HII_VARSTORE_BUFFER;
-
+ Storage = CreateStorage (FormSet, EFI_HII_VARSTORE_BUFFER, OpCodeData);
CopyMem (&Storage->VarStoreId, &((EFI_IFR_VARSTORE *) OpCodeData)->VarStoreId, sizeof (EFI_VARSTORE_ID));
- CopyMem (&Storage->Guid, &((EFI_IFR_VARSTORE *) OpCodeData)->Guid, sizeof (EFI_GUID));
- CopyMem (&Storage->Size, &((EFI_IFR_VARSTORE *) OpCodeData)->Size, sizeof (UINT16));
-
- Storage->Buffer = AllocateZeroPool (Storage->Size);
- Storage->EditBuffer = AllocateZeroPool (Storage->Size);
-
- AsciiString = (CHAR8 *) ((EFI_IFR_VARSTORE *) OpCodeData)->Name;
- Storage->Name = AllocateZeroPool (AsciiStrSize (AsciiString) * 2);
- ASSERT (Storage->Name != NULL);
- for (Index = 0; AsciiString[Index] != 0; Index++) {
- Storage->Name[Index] = (CHAR16) AsciiString[Index];
- }
-
- //
- // Initialize <ConfigHdr>
- //
- InitializeConfigHdr (FormSet, Storage);
break;
case EFI_IFR_VARSTORE_NAME_VALUE_OP:
//
// Create a name/value Storage for this FormSet
//
- Storage = CreateStorage (FormSet);
- Storage->Type = EFI_HII_VARSTORE_NAME_VALUE;
-
+ Storage = CreateStorage (FormSet, EFI_HII_VARSTORE_NAME_VALUE, OpCodeData);
CopyMem (&Storage->VarStoreId, &((EFI_IFR_VARSTORE_NAME_VALUE *) OpCodeData)->VarStoreId, sizeof (EFI_VARSTORE_ID));
- CopyMem (&Storage->Guid, &((EFI_IFR_VARSTORE_NAME_VALUE *) OpCodeData)->Guid, sizeof (EFI_GUID));
-
- //
- // Initialize <ConfigHdr>
- //
- InitializeConfigHdr (FormSet, Storage);
break;
case EFI_IFR_VARSTORE_EFI_OP:
//
// Create a EFI variable Storage for this FormSet
//
- Storage = CreateStorage (FormSet);
-
- CopyMem (&Storage->VarStoreId, &((EFI_IFR_VARSTORE_EFI *) OpCodeData)->VarStoreId, sizeof (EFI_VARSTORE_ID));
- CopyMem (&Storage->Guid, &((EFI_IFR_VARSTORE_EFI *) OpCodeData)->Guid, sizeof (EFI_GUID));
- CopyMem (&Storage->Attributes, &((EFI_IFR_VARSTORE_EFI *) OpCodeData)->Attributes, sizeof (UINT32));
- CopyMem (&Storage->Size, &((EFI_IFR_VARSTORE_EFI *) OpCodeData)->Size, sizeof (UINT16));
-
if (OpCodeLength < sizeof (EFI_IFR_VARSTORE_EFI)) {
- Storage->Type = EFI_HII_VARSTORE_EFI_VARIABLE;
- break;
- }
-
- Storage->Type = EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER;
- Storage->Buffer = AllocateZeroPool (Storage->Size);
- Storage->EditBuffer = AllocateZeroPool (Storage->Size);
-
- AsciiString = (CHAR8 *) ((EFI_IFR_VARSTORE_EFI *) OpCodeData)->Name;
- Storage->Name = AllocateZeroPool (AsciiStrSize (AsciiString) * 2);
- ASSERT (Storage->Name != NULL);
- for (Index = 0; AsciiString[Index] != 0; Index++) {
- Storage->Name[Index] = (CHAR16) AsciiString[Index];
+ Storage = CreateStorage (FormSet, EFI_HII_VARSTORE_EFI_VARIABLE, OpCodeData);
+ } else {
+ Storage = CreateStorage (FormSet, EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER, OpCodeData);
}
-
- //
- // Initialize <ConfigHdr>
- //
- InitializeConfigHdr (FormSet, Storage);
+ CopyMem (&Storage->VarStoreId, &((EFI_IFR_VARSTORE_EFI *) OpCodeData)->VarStoreId, sizeof (EFI_VARSTORE_ID));
break;
//
diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/InputHandler.c b/MdeModulePkg/Universal/SetupBrowserDxe/InputHandler.c
index ae783b4ae3..844590770a 100644
--- a/MdeModulePkg/Universal/SetupBrowserDxe/InputHandler.c
+++ b/MdeModulePkg/Universal/SetupBrowserDxe/InputHandler.c
@@ -1023,10 +1023,10 @@ GetSelectionInputPopUp (
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) {
- RemoveEntryList (&OneOfOption->Link);
- InsertHeadList (&Question->OptionListHead, &OneOfOption->Link);
+ if ((OneOfOption->SuppressExpression != NULL) &&
+ EvaluateExpressionList(OneOfOption->SuppressExpression, FALSE, NULL, NULL) > ExpressFalse) {
+ continue;
+ } else {
PopUpMenuLines++;
}
}
@@ -1040,6 +1040,13 @@ GetSelectionInputPopUp (
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;
+ }
StringPtr = GetToken (OneOfOption->Text, MenuOption->Handle);
if (StrLen (StringPtr) > PopUpWidth) {
@@ -1053,8 +1060,6 @@ GetSelectionInputPopUp (
//
HighlightOptionIndex = Index;
}
-
- Link = GetNextNode (&Question->OptionListHead, Link);
}
//
@@ -1123,6 +1128,13 @@ 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;
+ }
}
//
@@ -1133,6 +1145,12 @@ GetSelectionInputPopUp (
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;
+ }
+
StringPtr = GetToken (OneOfOption->Text, MenuOption->Handle);
ASSERT (StringPtr != NULL);
//
diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/Setup.c b/MdeModulePkg/Universal/SetupBrowserDxe/Setup.c
index 6c019f0454..ed904161b6 100644
--- a/MdeModulePkg/Universal/SetupBrowserDxe/Setup.c
+++ b/MdeModulePkg/Universal/SetupBrowserDxe/Setup.c
@@ -38,6 +38,7 @@ 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);
BANNER_DATA *gBannerData;
EFI_HII_HANDLE gFrontPageHandle;
@@ -366,6 +367,7 @@ SendForm (
// 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);
}
@@ -475,9 +477,9 @@ BrowserCallback (
Storage = FORMSET_STORAGE_FROM_LINK (Link);
Link = GetNextNode (&FormSet->StorageListHead, Link);
- if (CompareGuid (&Storage->Guid, (EFI_GUID *) VariableGuid)) {
- if (Storage->Type == EFI_HII_VARSTORE_BUFFER ||
- Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) {
+ 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
//
@@ -485,7 +487,7 @@ BrowserCallback (
return EFI_NOT_FOUND;
}
- if (StrCmp (Storage->Name, (CHAR16 *) VariableName) != 0) {
+ if (StrCmp (Storage->BrowserStorage->Name, (CHAR16 *) VariableName) != 0) {
continue;
}
}
@@ -515,7 +517,7 @@ BrowserCallback (
//
// Generate <ConfigResp>
//
- Status = StorageToConfigResp (Storage, &ConfigResp, FALSE);
+ Status = StorageToConfigResp (Storage->BrowserStorage, &ConfigResp, Storage->ConfigRequest);
if (EFI_ERROR (Status)) {
return Status;
}
@@ -523,7 +525,7 @@ BrowserCallback (
//
// Skip <ConfigHdr> and '&' to point to <ConfigBody>
//
- StrPtr = ConfigResp + StrLen (Storage->ConfigHdr) + 1;
+ StrPtr = ConfigResp + StrLen (Storage->BrowserStorage->ConfigHdr) + 1;
BufferSize = StrSize (StrPtr);
if (*ResultsDataSize < BufferSize) {
@@ -542,18 +544,18 @@ BrowserCallback (
// Prepare <ConfigResp>
//
TmpSize = StrLen (ResultsData);
- BufferSize = (TmpSize + StrLen (Storage->ConfigHdr) + 2) * sizeof (CHAR16);
+ BufferSize = (TmpSize + StrLen (Storage->BrowserStorage->ConfigHdr) + 2) * sizeof (CHAR16);
ConfigResp = AllocateZeroPool (BufferSize);
ASSERT (ConfigResp != NULL);
- StrCpy (ConfigResp, Storage->ConfigHdr);
+ StrCpy (ConfigResp, Storage->BrowserStorage->ConfigHdr);
StrCat (ConfigResp, L"&");
StrCat (ConfigResp, ResultsData);
//
// Update Browser uncommited data
//
- Status = ConfigRespToStorage (Storage, ConfigResp);
+ Status = ConfigRespToStorage (Storage->BrowserStorage, ConfigResp);
if (EFI_ERROR (Status)) {
return Status;
}
@@ -826,7 +828,7 @@ NewStringCat (
**/
VOID
SynchronizeStorage (
- IN FORMSET_STORAGE *Storage,
+ IN BROWSER_STORAGE *Storage,
IN BOOLEAN SyncOrRestore
)
{
@@ -879,7 +881,7 @@ SynchronizeStorage (
**/
EFI_STATUS
GetValueByName (
- IN FORMSET_STORAGE *Storage,
+ IN BROWSER_STORAGE *Storage,
IN CHAR16 *Name,
IN OUT CHAR16 **Value,
IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
@@ -928,7 +930,7 @@ GetValueByName (
**/
EFI_STATUS
SetValueByName (
- IN FORMSET_STORAGE *Storage,
+ IN BROWSER_STORAGE *Storage,
IN CHAR16 *Name,
IN CHAR16 *Value,
IN GET_SET_QUESTION_VALUE_WITH SetValueTo
@@ -975,9 +977,9 @@ SetValueByName (
/**
Convert setting of Buffer Storage or NameValue Storage to <ConfigResp>.
- @param Buffer The Storage to be conveted.
+ @param Storage The Storage to be conveted.
@param ConfigResp The returned <ConfigResp>.
- @param SingleForm Whether update data for single form or formset level.
+ @param ConfigRequest The ConfigRequest string.
@retval EFI_SUCCESS Convert success.
@retval EFI_INVALID_PARAMETER Incorrect storage type.
@@ -985,28 +987,17 @@ SetValueByName (
**/
EFI_STATUS
StorageToConfigResp (
- IN VOID *Buffer,
+ IN BROWSER_STORAGE *Storage,
IN CHAR16 **ConfigResp,
- IN BOOLEAN SingleForm
+ IN CHAR16 *ConfigRequest
)
{
- EFI_STATUS Status;
- EFI_STRING Progress;
+ EFI_STATUS Status;
+ EFI_STRING Progress;
LIST_ENTRY *Link;
NAME_VALUE_NODE *Node;
- CHAR16 *ConfigRequest;
- FORMSET_STORAGE *Storage;
- FORM_BROWSER_CONFIG_REQUEST *ConfigInfo;
Status = EFI_SUCCESS;
- if (SingleForm) {
- ConfigInfo = (FORM_BROWSER_CONFIG_REQUEST *) Buffer;
- Storage = ConfigInfo->Storage;
- ConfigRequest = ConfigInfo->ConfigRequest;
- } else {
- Storage = (FORMSET_STORAGE *) Buffer;
- ConfigRequest = Storage->ConfigRequest;
- }
switch (Storage->Type) {
case EFI_HII_VARSTORE_BUFFER:
@@ -1061,7 +1052,7 @@ StorageToConfigResp (
**/
EFI_STATUS
ConfigRespToStorage (
- IN FORMSET_STORAGE *Storage,
+ IN BROWSER_STORAGE *Storage,
IN CHAR16 *ConfigResp
)
{
@@ -1153,7 +1144,7 @@ GetQuestionValue (
UINT8 *Dst;
UINTN StorageWidth;
EFI_TIME EfiTime;
- FORMSET_STORAGE *Storage;
+ BROWSER_STORAGE *Storage;
EFI_IFR_TYPE_VALUE *QuestionValue;
CHAR16 *ConfigRequest;
CHAR16 *Progress;
@@ -1578,7 +1569,7 @@ SetQuestionValue (
EFI_TIME EfiTime;
UINTN BufferLen;
UINTN StorageWidth;
- FORMSET_STORAGE *Storage;
+ BROWSER_STORAGE *Storage;
EFI_IFR_TYPE_VALUE *QuestionValue;
CHAR16 *ConfigResp;
CHAR16 *Progress;
@@ -2225,6 +2216,7 @@ ValidateFormSet (
}
if (!Find) {
+ CleanBrowserStorage(FormSet);
RemoveEntryList (&FormSet->Link);
DestroyFormSet (FormSet);
}
@@ -2304,7 +2296,7 @@ DiscardForm (
Storage = FORMSET_STORAGE_FROM_LINK (Link);
Link = GetNextNode (&FormSet->StorageListHead, Link);
- if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {
+ if (Storage->BrowserStorage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {
continue;
}
@@ -2315,7 +2307,7 @@ DiscardForm (
continue;
}
- SynchronizeStorage(Storage, FALSE);
+ SynchronizeStorage(Storage->BrowserStorage, FALSE);
}
Link = GetFirstNode (&FormSet->FormListHead);
@@ -2350,6 +2342,7 @@ DiscardForm (
//
// Remove maintain backup list after discard except for the current using FormSet.
//
+ CleanBrowserStorage(LocalFormSet);
RemoveEntryList (&LocalFormSet->Link);
DestroyFormSet (LocalFormSet);
}
@@ -2381,7 +2374,8 @@ SubmitForm (
LIST_ENTRY *Link;
EFI_STRING ConfigResp;
EFI_STRING Progress;
- FORMSET_STORAGE *Storage;
+ BROWSER_STORAGE *Storage;
+ FORMSET_STORAGE *FormSetStorage;
UINTN BufferSize;
UINT8 *TmpBuf;
FORM_BROWSER_FORMSET *LocalFormSet;
@@ -2429,7 +2423,7 @@ SubmitForm (
//
// 1. Prepare <ConfigResp>
//
- Status = StorageToConfigResp (ConfigInfo, &ConfigResp, TRUE);
+ Status = StorageToConfigResp (ConfigInfo->Storage, &ConfigResp, ConfigInfo->ConfigRequest);
if (EFI_ERROR (Status)) {
return Status;
}
@@ -2518,7 +2512,8 @@ SubmitForm (
//
Link = GetFirstNode (&FormSet->StorageListHead);
while (!IsNull (&FormSet->StorageListHead, Link)) {
- Storage = FORMSET_STORAGE_FROM_LINK (Link);
+ FormSetStorage = (FORMSET_STORAGE_FROM_LINK (Link));
+ Storage = FormSetStorage->BrowserStorage;
Link = GetNextNode (&FormSet->StorageListHead, Link);
if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {
@@ -2528,14 +2523,14 @@ SubmitForm (
//
// Skip if there is no RequestElement
//
- if (Storage->ElementCount == 0) {
+ if (FormSetStorage->ElementCount == 0) {
continue;
}
//
// 1. Prepare <ConfigResp>
//
- Status = StorageToConfigResp (Storage, &ConfigResp, FALSE);
+ Status = StorageToConfigResp (Storage, &ConfigResp, FormSetStorage->ConfigRequest);
if (EFI_ERROR (Status)) {
return Status;
}
@@ -2634,6 +2629,7 @@ SubmitForm (
//
// Remove maintain backup list after save except for the current using FormSet.
//
+ CleanBrowserStorage(LocalFormSet);
RemoveEntryList (&LocalFormSet->Link);
DestroyFormSet (LocalFormSet);
}
@@ -2663,7 +2659,7 @@ GetDefaultValueFromAltCfg (
BOOLEAN IsBufferStorage;
BOOLEAN IsString;
UINTN Length;
- FORMSET_STORAGE *Storage;
+ BROWSER_STORAGE *Storage;
CHAR16 *ConfigRequest;
CHAR16 *Progress;
CHAR16 *Result;
@@ -3151,7 +3147,7 @@ ExtractDefault (
IN UINT16 DefaultId,
IN BROWSER_SETTING_SCOPE SettingScope,
IN BROWSER_GET_DEFAULT_VALUE GetDefaultValueScope,
- IN FORMSET_STORAGE *Storage OPTIONAL,
+ IN BROWSER_STORAGE *Storage OPTIONAL,
IN BOOLEAN RetrieveValueFirst
)
{
@@ -3445,200 +3441,405 @@ LoadFormSetConfig (
}
/**
- Fill storage's edit copy with settings requested from Configuration Driver.
+ Remove the Request element from the Config Request.
- @param FormSet FormSet data structure.
- @param Storage Buffer Storage.
-
- @retval EFI_SUCCESS The function completed successfully.
+ @param Storage Pointer to the browser storage.
+ @param RequestElement The pointer to the Request element.
**/
-EFI_STATUS
-LoadStorage (
- IN FORM_BROWSER_FORMSET *FormSet,
- IN FORMSET_STORAGE *Storage
+VOID
+RemoveElement (
+ IN OUT BROWSER_STORAGE *Storage,
+ IN CHAR16 *RequestElement
)
{
- EFI_STATUS Status;
- EFI_STRING Progress;
- EFI_STRING Result;
- CHAR16 *StrPtr;
+ CHAR16 *NewStr;
+ CHAR16 *DestStr;
- if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {
- return EFI_SUCCESS;
- }
+ ASSERT (Storage->ConfigRequest != NULL && RequestElement != NULL);
- if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER) {
- Status = gRT->GetVariable (
- Storage->Name,
- &Storage->Guid,
- NULL,
- (UINTN*)&Storage->Size,
- Storage->EditBuffer
- );
- return Status;
- }
+ NewStr = StrStr (Storage->ConfigRequest, RequestElement);
- if (FormSet->ConfigAccess == NULL) {
- return EFI_NOT_FOUND;
+ if (NewStr == NULL) {
+ return;
}
- if (Storage->ElementCount == 0) {
+ //
+ // Remove this element from this ConfigRequest.
+ //
+ DestStr = NewStr;
+ NewStr += StrLen (RequestElement);
+ CopyMem (DestStr, NewStr, StrSize (NewStr));
+
+ Storage->SpareStrLen += StrLen (RequestElement);
+}
+
+/**
+ Adjust config request in storage, remove the request elements existed in the input ConfigRequest.
+
+ @param Storage Pointer to the browser storage.
+ @param ConfigRequest The pointer to the Request element.
+
+**/
+VOID
+RemoveConfigRequest (
+ BROWSER_STORAGE *Storage,
+ CHAR16 *ConfigRequest
+ )
+{
+ CHAR16 *RequestElement;
+ CHAR16 *NextRequestElement;
+ CHAR16 *SearchKey;
+
+ if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {
//
- // Skip if there is no RequestElement
+ // "&Name1&Name2" section for EFI_HII_VARSTORE_NAME_VALUE storage
//
- return EFI_SUCCESS;
+ SearchKey = L"&";
+ } else {
+ //
+ // "&OFFSET=####&WIDTH=####" section for EFI_HII_VARSTORE_BUFFER storage
+ //
+ SearchKey = L"&OFFSET";
}
//
- // Request current settings from Configuration Driver
+ // Find SearchKey storage
//
- Status = FormSet->ConfigAccess->ExtractConfig (
- FormSet->ConfigAccess,
- Storage->ConfigRequest,
- &Progress,
- &Result
- );
- if (EFI_ERROR (Status)) {
- return Status;
+ if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {
+ RequestElement = StrStr (ConfigRequest, L"PATH");
+ ASSERT (RequestElement != NULL);
+ RequestElement = StrStr (RequestElement, SearchKey);
+ } else {
+ RequestElement = StrStr (ConfigRequest, SearchKey);
+ }
+
+ while (RequestElement != NULL) {
+ //
+ // +1 to avoid find header itself.
+ //
+ NextRequestElement = StrStr (RequestElement + 1, SearchKey);
+
+ //
+ // The last Request element in configRequest string.
+ //
+ if (NextRequestElement != NULL) {
+ //
+ // Replace "&" with '\0'.
+ //
+ *NextRequestElement = L'\0';
+ }
+
+ RemoveElement (Storage, RequestElement);
+
+ if (NextRequestElement != NULL) {
+ //
+ // Restore '&' with '\0' for later used.
+ //
+ *NextRequestElement = L'&';
+ }
+
+ RequestElement = NextRequestElement;
}
//
- // Convert Result from <ConfigAltResp> to <ConfigResp>
+ // If no request element remain, just remove the ConfigRequest string.
//
- StrPtr = StrStr (Result, L"&GUID=");
- if (StrPtr != NULL) {
- *StrPtr = L'\0';
+ if (StrCmp (Storage->ConfigRequest, Storage->ConfigHdr) == 0) {
+ FreePool (Storage->ConfigRequest);
+ Storage->ConfigRequest = NULL;
+ Storage->SpareStrLen = 0;
}
-
- Status = ConfigRespToStorage (Storage, Result);
- FreePool (Result);
- return Status;
}
+/**
+ Base on the current formset info, clean the ConfigRequest string in browser storage.
+
+ @param FormSet Pointer of the FormSet
+
+**/
+VOID
+CleanBrowserStorage (
+ IN OUT FORM_BROWSER_FORMSET *FormSet
+ )
+{
+ LIST_ENTRY *Link;
+ FORMSET_STORAGE *Storage;
+
+ Link = GetFirstNode (&FormSet->StorageListHead);
+ while (!IsNull (&FormSet->StorageListHead, Link)) {
+ Storage = FORMSET_STORAGE_FROM_LINK (Link);
+ Link = GetNextNode (&FormSet->StorageListHead, Link);
+
+ if ((Storage->BrowserStorage->Type != EFI_HII_VARSTORE_BUFFER) &&
+ (Storage->BrowserStorage->Type != EFI_HII_VARSTORE_NAME_VALUE)) {
+ continue;
+ }
+
+ if (Storage->ConfigRequest == NULL || Storage->BrowserStorage->ConfigRequest == NULL) {
+ continue;
+ }
+
+ RemoveConfigRequest (Storage->BrowserStorage, Storage->ConfigRequest);
+ }
+}
/**
- Copy uncommitted data from source Storage to destination Storage.
+ Check whether current element in the ConfigReqeust string.
- @param Dst Target Storage for uncommitted data.
- @param Src Source Storage for uncommitted data.
+ @param BrowserStorage Storage which includes ConfigReqeust.
+ @param RequestElement New element need to check.
- @retval EFI_SUCCESS The function completed successfully.
- @retval EFI_INVALID_PARAMETER Source and destination Storage is not the same type.
+ @retval TRUE The Element is in the ConfigReqeust string.
+ @retval FALSE The Element not in the configReqeust String.
**/
-EFI_STATUS
-CopyStorage (
- IN OUT FORMSET_STORAGE *Dst,
- IN FORMSET_STORAGE *Src
+BOOLEAN
+ElementValidation (
+ BROWSER_STORAGE *BrowserStorage,
+ CHAR16 *RequestElement
)
{
- LIST_ENTRY *Link;
- NAME_VALUE_NODE *Node;
+ return StrStr (BrowserStorage->ConfigRequest, RequestElement) != NULL ? TRUE : FALSE;
+}
- if ((Dst->Type != Src->Type) || (Dst->Size != Src->Size)) {
- return EFI_INVALID_PARAMETER;
- }
+/**
+ Append the Request element to the Config Request.
- switch (Src->Type) {
- case EFI_HII_VARSTORE_BUFFER:
- case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:
- CopyMem (Dst->EditBuffer, Src->EditBuffer, Src->Size);
- CopyMem (Dst->Buffer, Src->Buffer, Src->Size);
- break;
+ @param ConfigRequest Current ConfigRequest info.
+ @param SpareStrLen Current remain free buffer for config reqeust.
+ @param RequestElement New Request element.
- case EFI_HII_VARSTORE_NAME_VALUE:
- Link = GetFirstNode (&Src->NameValueListHead);
- while (!IsNull (&Src->NameValueListHead, Link)) {
- Node = NAME_VALUE_NODE_FROM_LINK (Link);
+**/
+VOID
+AppendConfigRequest (
+ IN OUT CHAR16 **ConfigRequest,
+ IN OUT UINTN *SpareStrLen,
+ IN CHAR16 *RequestElement
+ )
+{
+ CHAR16 *NewStr;
+ UINTN StringSize;
+ UINTN StrLength;
- SetValueByName (Dst, Node->Name, Node->EditValue, GetSetValueWithEditBuffer);
- SetValueByName (Dst, Node->Name, Node->Value, GetSetValueWithBuffer);
+ StrLength = StrLen (RequestElement);
- Link = GetNextNode (&Src->NameValueListHead, Link);
- }
- break;
+ //
+ // Append <RequestElement> to <ConfigRequest>
+ //
+ if (StrLength > *SpareStrLen) {
+ //
+ // Old String buffer is not sufficient for RequestElement, allocate a new one
+ //
+ StringSize = (*ConfigRequest != NULL) ? StrSize (*ConfigRequest) : sizeof (CHAR16);
+ NewStr = AllocateZeroPool (StringSize + CONFIG_REQUEST_STRING_INCREMENTAL * sizeof (CHAR16));
+ ASSERT (NewStr != NULL);
- case EFI_HII_VARSTORE_EFI_VARIABLE:
- default:
- break;
+ if (*ConfigRequest != NULL) {
+ CopyMem (NewStr, *ConfigRequest, StringSize);
+ FreePool (*ConfigRequest);
+ }
+ *ConfigRequest = NewStr;
+ *SpareStrLen = CONFIG_REQUEST_STRING_INCREMENTAL;
}
- return EFI_SUCCESS;
+ StrCat (*ConfigRequest, RequestElement);
+ *SpareStrLen -= StrLength;
}
/**
- Get old question value from the saved formset.
+ 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.
- @param Statement The question which need to get old question value.
- @param OldFormSet FormSet data structure saved in the list.
+ @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.
**/
-VOID
-GetOldQuestionValue (
- IN OUT FORM_BROWSER_STATEMENT *Statement,
- IN FORM_BROWSER_FORMSET *OldFormSet
+BOOLEAN
+ConfigRequestAdjust (
+ IN FORMSET_STORAGE *Storage,
+ OUT CHAR16 **ConfigRequest
)
{
- LIST_ENTRY *FormLink;
- LIST_ENTRY *Link;
- FORM_BROWSER_STATEMENT *Question;
- FORM_BROWSER_FORM *Form;
+ CHAR16 *RequestElement;
+ CHAR16 *NextRequestElement;
+ CHAR16 *RetBuf;
+ UINTN SpareBufLen;
+ CHAR16 *SearchKey;
+ BOOLEAN RetVal;
+
+ SpareBufLen = 0;
+ RetBuf = NULL;
+ RetVal = FALSE;
+
+ if (Storage->BrowserStorage->ConfigRequest == NULL) {
+ Storage->BrowserStorage->ConfigRequest = AllocateCopyPool (StrSize (Storage->ConfigRequest), Storage->ConfigRequest);
+ *ConfigRequest = AllocateCopyPool (StrSize (Storage->ConfigRequest), Storage->ConfigRequest);
+ return TRUE;
+ }
- FormLink = GetFirstNode (&OldFormSet->FormListHead);
- while (!IsNull (&OldFormSet->FormListHead, FormLink)) {
- Form = FORM_BROWSER_FORM_FROM_LINK (FormLink);
- FormLink = GetNextNode (&OldFormSet->FormListHead, FormLink);
+ if (Storage->BrowserStorage->Type == EFI_HII_VARSTORE_NAME_VALUE) {
+ //
+ // "&Name1&Name2" section for EFI_HII_VARSTORE_NAME_VALUE storage
+ //
+ SearchKey = L"&";
+ } else {
+ //
+ // "&OFFSET=####&WIDTH=####" section for EFI_HII_VARSTORE_BUFFER storage
+ //
+ SearchKey = L"&OFFSET";
+ }
- Link = GetFirstNode (&Form->StatementListHead);
- while (!IsNull (&Form->StatementListHead, Link)) {
- Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);
- Link = GetNextNode (&Form->StatementListHead, Link);
+ //
+ // Prepare the config header.
+ //
+ RetBuf = AllocateCopyPool(StrSize (Storage->BrowserStorage->ConfigHdr), Storage->BrowserStorage->ConfigHdr);
+ ASSERT (RetBuf != NULL);
- if (Question->QuestionId != Statement->QuestionId) {
- continue;
- }
+ //
+ // Find SearchKey storage
+ //
+ if (Storage->BrowserStorage->Type == EFI_HII_VARSTORE_NAME_VALUE) {
+ RequestElement = StrStr (Storage->ConfigRequest, L"PATH");
+ ASSERT (RequestElement != NULL);
+ RequestElement = StrStr (RequestElement, SearchKey);
+ } else {
+ RequestElement = StrStr (Storage->ConfigRequest, SearchKey);
+ }
+
+ while (RequestElement != NULL) {
+ //
+ // +1 to avoid find header itself.
+ //
+ NextRequestElement = StrStr (RequestElement + 1, SearchKey);
- CopyMem (&Statement->HiiValue, &Question->HiiValue, sizeof (EFI_HII_VALUE));
- return;
+ //
+ // The last Request element in configRequest string.
+ //
+ if (NextRequestElement != NULL) {
+ //
+ // Replace "&" with '\0'.
+ //
+ *NextRequestElement = L'\0';
}
+
+ if (!ElementValidation (Storage->BrowserStorage, RequestElement)) {
+ //
+ // Add this element to the Storage->BrowserStorage->AllRequestElement.
+ //
+ AppendConfigRequest(&Storage->BrowserStorage->ConfigRequest, &Storage->BrowserStorage->SpareStrLen, RequestElement);
+ AppendConfigRequest (&RetBuf, &SpareBufLen, RequestElement);
+ RetVal = TRUE;
+ }
+
+ if (NextRequestElement != NULL) {
+ //
+ // Restore '&' with '\0' for later used.
+ //
+ *NextRequestElement = L'&';
+ }
+
+ RequestElement = NextRequestElement;
}
+
+ if (RetVal) {
+ *ConfigRequest = RetBuf;
+ } else {
+ FreePool (RetBuf);
+ }
+
+ return RetVal;
}
/**
- Get old question value from the saved formset, all these questions not have
- storage.
+ Fill storage's edit copy with settings requested from Configuration Driver.
+
+ @param FormSet FormSet data structure.
+ @param Storage Buffer Storage.
- @param FormSet FormSet data structure which is used now.
- @param OldFormSet FormSet data structure saved in the list.
+ @retval EFI_SUCCESS The function completed successfully.
**/
-VOID
-CopyOldValueForNoStorageQst (
- IN OUT FORM_BROWSER_FORMSET *FormSet,
- IN FORM_BROWSER_FORMSET *OldFormSet
+EFI_STATUS
+LoadStorage (
+ IN FORM_BROWSER_FORMSET *FormSet,
+ IN FORMSET_STORAGE *Storage
)
{
- LIST_ENTRY *FormLink;
- LIST_ENTRY *Link;
- FORM_BROWSER_STATEMENT *Question;
- FORM_BROWSER_FORM *Form;
-
- FormLink = GetFirstNode (&FormSet->FormListHead);
- while (!IsNull (&FormSet->FormListHead, FormLink)) {
- Form = FORM_BROWSER_FORM_FROM_LINK (FormLink);
- FormLink = GetNextNode (&FormSet->FormListHead, FormLink);
+ EFI_STATUS Status;
+ EFI_STRING Progress;
+ EFI_STRING Result;
+ CHAR16 *StrPtr;
+ CHAR16 *ConfigRequest;
- Link = GetFirstNode (&Form->StatementListHead);
- while (!IsNull (&Form->StatementListHead, Link)) {
- Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);
- Link = GetNextNode (&Form->StatementListHead, Link);
+ if (Storage->BrowserStorage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {
+ return EFI_SUCCESS;
+ }
- if (Question->Storage == NULL) {
- GetOldQuestionValue (Question, OldFormSet);
- }
+ 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,
+ NULL,
+ (UINTN*)&Storage->BrowserStorage->Size,
+ Storage->BrowserStorage->EditBuffer
+ );
}
+ return Status;
}
+
+ if (FormSet->ConfigAccess == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ if (Storage->ElementCount == 0) {
+ //
+ // Skip if there is no RequestElement
+ //
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Adjust the ConfigRequest string, only the field not saved in BrowserStorage->AllConfig
+ // will used to call ExtractConfig.
+ //
+ if (!ConfigRequestAdjust(Storage, &ConfigRequest)) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Request current settings from Configuration Driver
+ //
+ Status = FormSet->ConfigAccess->ExtractConfig (
+ FormSet->ConfigAccess,
+ ConfigRequest,
+ &Progress,
+ &Result
+ );
+ FreePool (ConfigRequest);
+
+ if (EFI_ERROR (Status)) {
+ return 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);
+ return Status;
}
/**
@@ -3693,17 +3894,18 @@ InitializeCurrentSetting (
}
}
+ //
+ // Storage is not found in backup formset and current global storage not has other driver used,
+ // request it from ConfigDriver
+ //
if (OldStorage == NULL) {
- //
- // Storage is not found in backup formset, request it from ConfigDriver
- //
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, TRUE);
+ 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.
@@ -3715,12 +3917,7 @@ InitializeCurrentSetting (
// Now Edit Buffer is filled with default values(lower priority) or current
// settings(higher priority), sychronize it to shadow Buffer
//
- SynchronizeStorage (Storage, TRUE);
- } else {
- //
- // Storage found in backup formset, use it
- //
- Status = CopyStorage (Storage, OldStorage);
+ SynchronizeStorage (Storage->BrowserStorage, TRUE);
}
Link = GetNextNode (&FormSet->StorageListHead, Link);
diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/Setup.h b/MdeModulePkg/Universal/SetupBrowserDxe/Setup.h
index 8e32cb4e4a..9a0c739094 100644
--- a/MdeModulePkg/Universal/SetupBrowserDxe/Setup.h
+++ b/MdeModulePkg/Universal/SetupBrowserDxe/Setup.h
@@ -216,7 +216,7 @@ typedef struct {
#define NAME_VALUE_NODE_FROM_LINK(a) CR (a, NAME_VALUE_NODE, Link, NAME_VALUE_NODE_SIGNATURE)
-#define FORMSET_STORAGE_SIGNATURE SIGNATURE_32 ('F', 'S', 'T', 'G')
+#define BROWSER_STORAGE_SIGNATURE SIGNATURE_32 ('B', 'S', 'T', 'G')
typedef struct {
UINTN Signature;
@@ -224,7 +224,6 @@ typedef struct {
UINT8 Type; // Storage type
- UINT16 VarStoreId;
EFI_GUID Guid;
CHAR16 *Name; // For EFI_IFR_VARSTORE
@@ -238,6 +237,24 @@ typedef struct {
CHAR16 *ConfigHdr; // <ConfigHdr>
CHAR16 *ConfigRequest; // <ConfigRequest> = <ConfigHdr> + <RequestElement>
+ // <RequestElement> includes all fields which is used by current form sets.
+ UINTN SpareStrLen; // Spare length of ConfigRequest string buffer
+ UINT8 ReferenceCount; // How many form set storage refrence this storage.
+} BROWSER_STORAGE;
+
+#define BROWSER_STORAGE_FROM_LINK(a) CR (a, BROWSER_STORAGE, Link, BROWSER_STORAGE_SIGNATURE)
+
+#define FORMSET_STORAGE_SIGNATURE SIGNATURE_32 ('F', 'S', 'T', 'G')
+
+typedef struct {
+ UINTN Signature;
+ LIST_ENTRY Link;
+
+ UINT16 VarStoreId;
+
+ BROWSER_STORAGE *BrowserStorage;
+
+ CHAR16 *ConfigRequest; // <ConfigRequest> = <ConfigHdr> + <RequestElement>
UINTN ElementCount; // Number of <RequestElement> in the <ConfigRequest>
UINTN SpareStrLen; // Spare length of ConfigRequest string buffer
} FORMSET_STORAGE;
@@ -272,7 +289,7 @@ typedef struct {
EFI_STRING_ID DevicePath; // For EFI_IFR_QUESTION_REF3_2, EFI_IFR_QUESTION_REF3_3
EFI_GUID Guid;
- FORMSET_STORAGE *VarStorage; // For EFI_IFR_SET, EFI_IFR_GET
+ BROWSER_STORAGE *VarStorage; // For EFI_IFR_SET, EFI_IFR_GET
VAR_STORE_INFO VarStoreInfo;// For EFI_IFR_SET, EFI_IFR_GET
UINT8 ValueType; // For EFI_IFR_SET, EFI_IFR_GET
UINT8 ValueWidth; // For EFI_IFR_SET, EFI_IFR_GET
@@ -372,7 +389,7 @@ typedef struct {
//
EFI_QUESTION_ID QuestionId; // The value of zero is reserved
EFI_VARSTORE_ID VarStoreId; // A value of zero indicates no variable storage
- FORMSET_STORAGE *Storage;
+ BROWSER_STORAGE *Storage;
VAR_STORE_INFO VarStoreInfo;
UINT16 StorageWidth;
UINT8 QuestionFlags;
@@ -430,7 +447,7 @@ typedef struct {
UINTN ElementCount; // Number of <RequestElement> in the <ConfigRequest>
UINTN SpareStrLen;
- FORMSET_STORAGE *Storage;
+ BROWSER_STORAGE *Storage;
} FORM_BROWSER_CONFIG_REQUEST;
#define FORM_BROWSER_CONFIG_REQUEST_FROM_LINK(a) CR (a, FORM_BROWSER_CONFIG_REQUEST, Link, FORM_BROWSER_CONFIG_REQUEST_SIGNATURE)
@@ -909,7 +926,7 @@ CreateDialog (
**/
EFI_STATUS
GetValueByName (
- IN FORMSET_STORAGE *Storage,
+ IN BROWSER_STORAGE *Storage,
IN CHAR16 *Name,
IN OUT CHAR16 **Value,
IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
@@ -929,7 +946,7 @@ GetValueByName (
**/
EFI_STATUS
SetValueByName (
- IN FORMSET_STORAGE *Storage,
+ IN BROWSER_STORAGE *Storage,
IN CHAR16 *Name,
IN CHAR16 *Value,
IN GET_SET_QUESTION_VALUE_WITH SetValueTo
@@ -1111,7 +1128,7 @@ ExtractDefault (
IN UINT16 DefaultId,
IN BROWSER_SETTING_SCOPE SettingScope,
IN BROWSER_GET_DEFAULT_VALUE GetDefaultValueScope,
- IN FORMSET_STORAGE *Storage,
+ IN BROWSER_STORAGE *Storage,
IN BOOLEAN RetrieveValueFirst
);
@@ -1156,9 +1173,9 @@ LoadFormSetConfig (
/**
Convert setting of Buffer Storage or NameValue Storage to <ConfigResp>.
- @param Buffer The Storage to be conveted.
+ @param Storage The Storage to be conveted.
@param ConfigResp The returned <ConfigResp>.
- @param SingleForm Whether update data for single form or formset level.
+ @param ConfigRequest The ConfigRequest string.
@retval EFI_SUCCESS Convert success.
@retval EFI_INVALID_PARAMETER Incorrect storage type.
@@ -1166,9 +1183,9 @@ LoadFormSetConfig (
**/
EFI_STATUS
StorageToConfigResp (
- IN VOID *Buffer,
+ IN BROWSER_STORAGE *Storage,
IN CHAR16 **ConfigResp,
- IN BOOLEAN SingleForm
+ IN CHAR16 *ConfigRequest
);
/**
@@ -1183,7 +1200,7 @@ StorageToConfigResp (
**/
EFI_STATUS
ConfigRespToStorage (
- IN FORMSET_STORAGE *Storage,
+ IN BROWSER_STORAGE *Storage,
IN CHAR16 *ConfigResp
);
@@ -1527,4 +1544,15 @@ GetHotKeyFromRegisterList (
IN EFI_INPUT_KEY *KeyData
);
+/**
+ Base on the current formset info, clean the ConfigRequest string in browser storage.
+
+ @param FormSet Pointer of the FormSet
+
+**/
+VOID
+CleanBrowserStorage (
+ IN OUT FORM_BROWSER_FORMSET *FormSet
+ );
+
#endif
diff --git a/MdeModulePkg/Universal/Variable/EmuRuntimeDxe/EmuVariable.c b/MdeModulePkg/Universal/Variable/EmuRuntimeDxe/EmuVariable.c
index 84d22d8dcf..ae31e3ac59 100644
--- a/MdeModulePkg/Universal/Variable/EmuRuntimeDxe/EmuVariable.c
+++ b/MdeModulePkg/Universal/Variable/EmuRuntimeDxe/EmuVariable.c
@@ -3,7 +3,7 @@
Emulation Variable services operate on the runtime volatile memory.
The nonvolatile variable space doesn't exist.
-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
@@ -1397,14 +1397,22 @@ EmuSetVariable (
if ((Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == EFI_VARIABLE_RUNTIME_ACCESS) {
return EFI_INVALID_PARAMETER;
}
+
+
+ if ((UINTN)(~0) - DataSize < StrSize(VariableName)){
+ //
+ // Prevent whole variable size overflow
+ //
+ return EFI_INVALID_PARAMETER;
+ }
+
//
// The size of the VariableName, including the Unicode Null in bytes plus
// the DataSize is limited to maximum size of PcdGet32 (PcdMaxHardwareErrorVariableSize)
// bytes for HwErrRec, and PcdGet32 (PcdMaxVariableSize) bytes for the others.
//
if ((Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD) {
- if ((DataSize > PcdGet32 (PcdMaxHardwareErrorVariableSize)) ||
- (sizeof (VARIABLE_HEADER) + StrSize (VariableName) + DataSize > PcdGet32 (PcdMaxHardwareErrorVariableSize))) {
+ if (StrSize (VariableName) + DataSize > PcdGet32 (PcdMaxHardwareErrorVariableSize) - sizeof (VARIABLE_HEADER)) {
return EFI_INVALID_PARAMETER;
}
//
@@ -1418,8 +1426,7 @@ EmuSetVariable (
// The size of the VariableName, including the Unicode Null in bytes plus
// the DataSize is limited to maximum size of PcdGet32 (PcdMaxVariableSize) bytes.
//
- if ((DataSize > PcdGet32 (PcdMaxVariableSize)) ||
- (sizeof (VARIABLE_HEADER) + StrSize (VariableName) + DataSize > PcdGet32 (PcdMaxVariableSize))) {
+ if (StrSize (VariableName) + DataSize > PcdGet32 (PcdMaxVariableSize) - sizeof (VARIABLE_HEADER)) {
return EFI_INVALID_PARAMETER;
}
}
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c b/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c
index 956c1f2ae1..9f983ffc9f 100644
--- a/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c
+++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c
@@ -21,12 +21,28 @@ VARIABLE_MODULE_GLOBAL *mVariableModuleGlobal;
///
/// Define a memory cache that improves the search performance for a variable.
///
-VARIABLE_STORE_HEADER *mNvVariableCache = NULL;
+VARIABLE_STORE_HEADER *mNvVariableCache = NULL;
///
/// The memory entry used for variable statistics data.
///
-VARIABLE_INFO_ENTRY *gVariableInfo = NULL;
+VARIABLE_INFO_ENTRY *gVariableInfo = NULL;
+
+///
+/// The list to store the variables which cannot be set after the EFI_END_OF_DXE_EVENT_GROUP_GUID
+/// or EVT_GROUP_READY_TO_BOOT event.
+///
+LIST_ENTRY mLockedVariableList = INITIALIZE_LIST_HEAD_VARIABLE (mLockedVariableList);
+
+///
+/// The flag to indicate whether the platform has left the DXE phase of execution.
+///
+BOOLEAN mEndOfDxe = FALSE;
+
+///
+/// The flag to indicate whether the variable storage locking is enabled.
+///
+BOOLEAN mEnableLocking = TRUE;
/**
@@ -1919,6 +1935,58 @@ IsHwErrRecVariable (
}
/**
+ Mark a variable that will become read-only after leaving the DXE phase of execution.
+
+ @param[in] This The VARIABLE_LOCK_PROTOCOL instance.
+ @param[in] VariableName A pointer to the variable name that will be made read-only subsequently.
+ @param[in] VendorGuid A pointer to the vendor GUID that will be made read-only subsequently.
+
+ @retval EFI_SUCCESS The variable specified by the VariableName and the VendorGuid was marked
+ as pending to be read-only.
+ @retval EFI_INVALID_PARAMETER VariableName or VendorGuid is NULL.
+ Or VariableName is an empty string.
+ @retval EFI_ACCESS_DENIED EFI_END_OF_DXE_EVENT_GROUP_GUID or EFI_EVENT_GROUP_READY_TO_BOOT has
+ already been signaled.
+ @retval EFI_OUT_OF_RESOURCES There is not enough resource to hold the lock request.
+**/
+EFI_STATUS
+EFIAPI
+VariableLockRequestToLock (
+ IN CONST EDKII_VARIABLE_LOCK_PROTOCOL *This,
+ IN CHAR16 *VariableName,
+ IN EFI_GUID *VendorGuid
+ )
+{
+ VARIABLE_ENTRY *Entry;
+
+ if (VariableName == NULL || VariableName[0] == 0 || VendorGuid == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (mEndOfDxe) {
+ return EFI_ACCESS_DENIED;
+ }
+
+ Entry = AllocateRuntimePool (sizeof (*Entry) + StrSize (VariableName));
+ if (Entry == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ DEBUG ((EFI_D_INFO, "[Variable] Lock: %g:%s\n", VendorGuid, VariableName));
+
+ AcquireLockOnlyAtBootTime(&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);
+
+ Entry->Name = (CHAR16 *) (Entry + 1);
+ StrCpy (Entry->Name, VariableName);
+ CopyGuid (&Entry->Guid, VendorGuid);
+ InsertTailList (&mLockedVariableList, &Entry->Link);
+
+ ReleaseLockOnlyAtBootTime (&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);
+
+ return EFI_SUCCESS;
+}
+
+/**
This code finds variable in storage blocks (Volatile or Non-Volatile).
@@ -2192,6 +2260,8 @@ VariableServiceSetVariable (
EFI_STATUS Status;
VARIABLE_HEADER *NextVariable;
EFI_PHYSICAL_ADDRESS Point;
+ LIST_ENTRY *Link;
+ VARIABLE_ENTRY *Entry;
//
// Check input parameters.
@@ -2218,14 +2288,20 @@ VariableServiceSetVariable (
return EFI_INVALID_PARAMETER;
}
+ if ((UINTN)(~0) - DataSize < StrSize(VariableName)){
+ //
+ // Prevent whole variable size overflow
+ //
+ return EFI_INVALID_PARAMETER;
+ }
+
//
// The size of the VariableName, including the Unicode Null in bytes plus
// the DataSize is limited to maximum size of PcdGet32 (PcdMaxHardwareErrorVariableSize)
// bytes for HwErrRec, and PcdGet32 (PcdMaxVariableSize) bytes for the others.
//
if ((Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD) {
- if ((DataSize > PcdGet32 (PcdMaxHardwareErrorVariableSize)) ||
- (sizeof (VARIABLE_HEADER) + StrSize (VariableName) + DataSize > PcdGet32 (PcdMaxHardwareErrorVariableSize))) {
+ if ( StrSize (VariableName) + DataSize > PcdGet32 (PcdMaxHardwareErrorVariableSize) - sizeof (VARIABLE_HEADER)) {
return EFI_INVALID_PARAMETER;
}
if (!IsHwErrRecVariable(VariableName, VendorGuid)) {
@@ -2236,22 +2312,11 @@ VariableServiceSetVariable (
// The size of the VariableName, including the Unicode Null in bytes plus
// the DataSize is limited to maximum size of PcdGet32 (PcdMaxVariableSize) bytes.
//
- if ((DataSize > PcdGet32 (PcdMaxVariableSize)) ||
- (sizeof (VARIABLE_HEADER) + StrSize (VariableName) + DataSize > PcdGet32 (PcdMaxVariableSize))) {
+ if (StrSize (VariableName) + DataSize > PcdGet32 (PcdMaxVariableSize) - sizeof (VARIABLE_HEADER)) {
return EFI_INVALID_PARAMETER;
}
}
- if (AtRuntime ()) {
- //
- // HwErrRecSupport Global Variable identifies the level of hardware error record persistence
- // support implemented by the platform. This variable is only modified by firmware and is read-only to the OS.
- //
- if (CompareGuid (VendorGuid, &gEfiGlobalVariableGuid) && (StrCmp (VariableName, L"HwErrRecSupport") == 0)) {
- return EFI_WRITE_PROTECTED;
- }
- }
-
AcquireLockOnlyAtBootTime(&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);
//
@@ -2270,13 +2335,31 @@ VariableServiceSetVariable (
mVariableModuleGlobal->NonVolatileLastVariableOffset = (UINTN) NextVariable - (UINTN) Point;
}
+ if (mEndOfDxe && mEnableLocking) {
+ //
+ // Treat the variables listed in the forbidden variable list as read-only after leaving DXE phase.
+ //
+ for ( Link = GetFirstNode (&mLockedVariableList)
+ ; !IsNull (&mLockedVariableList, Link)
+ ; Link = GetNextNode (&mLockedVariableList, Link)
+ ) {
+ Entry = BASE_CR (Link, VARIABLE_ENTRY, Link);
+ if (CompareGuid (&Entry->Guid, VendorGuid) && (StrCmp (Entry->Name, VariableName) == 0)) {
+ Status = EFI_WRITE_PROTECTED;
+ DEBUG ((EFI_D_INFO, "[Variable]: Changing readonly variable after leaving DXE phase - %g:%s\n", VendorGuid, VariableName));
+ goto Done;
+ }
+ }
+ }
+
//
// Check whether the input variable is already existed.
//
Status = FindVariable (VariableName, VendorGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, TRUE);
if (!EFI_ERROR (Status)) {
if (((Variable.CurrPtr->Attributes & EFI_VARIABLE_RUNTIME_ACCESS) == 0) && AtRuntime ()) {
- return EFI_WRITE_PROTECTED;
+ Status = EFI_WRITE_PROTECTED;
+ goto Done;
}
}
@@ -2287,6 +2370,7 @@ VariableServiceSetVariable (
Status = UpdateVariable (VariableName, VendorGuid, Data, DataSize, Attributes, &Variable);
+Done:
InterlockedDecrement (&mVariableModuleGlobal->VariableGlobal.ReentrantState);
ReleaseLockOnlyAtBootTime (&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.h b/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.h
index 8504ce05f7..b5e6edec93 100644
--- a/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.h
+++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.h
@@ -22,6 +22,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include <Protocol/FaultTolerantWrite.h>
#include <Protocol/FirmwareVolumeBlock.h>
#include <Protocol/Variable.h>
+#include <Protocol/VariableLock.h>
#include <Library/PcdLib.h>
#include <Library/HobLib.h>
#include <Library/UefiDriverEntryPoint.h>
@@ -97,6 +98,12 @@ typedef struct {
VOID *Data;
} VARIABLE_CACHE_ENTRY;
+typedef struct {
+ EFI_GUID Guid;
+ CHAR16 *Name;
+ LIST_ENTRY Link;
+} VARIABLE_ENTRY;
+
/**
Flush the HOB variable to flash.
@@ -456,7 +463,30 @@ VariableServiceQueryVariableInfo (
OUT UINT64 *RemainingVariableStorageSize,
OUT UINT64 *MaximumVariableSize
);
-
+
+/**
+ Mark a variable that will become read-only after leaving the DXE phase of execution.
+
+ @param[in] This The VARIABLE_LOCK_PROTOCOL instance.
+ @param[in] VariableName A pointer to the variable name that will be made read-only subsequently.
+ @param[in] VendorGuid A pointer to the vendor GUID that will be made read-only subsequently.
+
+ @retval EFI_SUCCESS The variable specified by the VariableName and the VendorGuid was marked
+ as pending to be read-only.
+ @retval EFI_INVALID_PARAMETER VariableName or VendorGuid is NULL.
+ Or VariableName is an empty string.
+ @retval EFI_ACCESS_DENIED EFI_END_OF_DXE_EVENT_GROUP_GUID or EFI_EVENT_GROUP_READY_TO_BOOT has
+ already been signaled.
+ @retval EFI_OUT_OF_RESOURCES There is not enough resource to hold the lock request.
+**/
+EFI_STATUS
+EFIAPI
+VariableLockRequestToLock (
+ IN CONST EDKII_VARIABLE_LOCK_PROTOCOL *This,
+ IN CHAR16 *VariableName,
+ IN EFI_GUID *VendorGuid
+ );
+
extern VARIABLE_MODULE_GLOBAL *mVariableModuleGlobal;
#endif
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableDxe.c b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableDxe.c
index ba4d29ab30..3cb2c6bcf3 100644
--- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableDxe.c
+++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableDxe.c
@@ -3,7 +3,7 @@
Implement all four UEFI Runtime Variable services for the nonvolatile
and volatile storage space and install variable architecture 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
@@ -21,6 +21,8 @@ extern VARIABLE_INFO_ENTRY *gVariableInfo;
EFI_HANDLE mHandle = NULL;
EFI_EVENT mVirtualAddressChangeEvent = NULL;
EFI_EVENT mFtwRegistration = NULL;
+extern BOOLEAN mEndOfDxe;
+EDKII_VARIABLE_LOCK_PROTOCOL mVariableLock = { VariableLockRequestToLock };
/**
Return TRUE if ExitBootServices () has been called.
@@ -255,12 +257,34 @@ OnReadyToBoot (
VOID *Context
)
{
+ //
+ // Set the End Of DXE bit in case the EFI_END_OF_DXE_EVENT_GROUP_GUID event is not signaled.
+ //
+ mEndOfDxe = TRUE;
ReclaimForOS ();
if (FeaturePcdGet (PcdVariableCollectStatistics)) {
gBS->InstallConfigurationTable (&gEfiVariableGuid, gVariableInfo);
}
}
+/**
+ Notification function of EFI_END_OF_DXE_EVENT_GROUP_GUID event group.
+
+ This is a notification function registered on EFI_END_OF_DXE_EVENT_GROUP_GUID event group.
+
+ @param Event Event whose notification function is being invoked.
+ @param Context Pointer to the notification function's context.
+
+**/
+VOID
+EFIAPI
+OnEndOfDxe (
+ EFI_EVENT Event,
+ VOID *Context
+ )
+{
+ mEndOfDxe = TRUE;
+}
/**
Fault Tolerant Write protocol notification event handler.
@@ -375,11 +399,20 @@ VariableServiceInitialize (
)
{
EFI_STATUS Status;
- EFI_EVENT ReadyToBootEvent;
+ EFI_EVENT ReadyToBootEvent;
+ EFI_EVENT EndOfDxeEvent;
Status = VariableCommonInitialize ();
ASSERT_EFI_ERROR (Status);
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &mHandle,
+ &gEdkiiVariableLockProtocolGuid,
+ &mVariableLock,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
SystemTable->RuntimeServices->GetVariable = VariableServiceGetVariable;
SystemTable->RuntimeServices->GetNextVariableName = VariableServiceGetNextVariableName;
SystemTable->RuntimeServices->SetVariable = VariableServiceSetVariable;
@@ -426,6 +459,20 @@ VariableServiceInitialize (
NULL,
&ReadyToBootEvent
);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Register the event handling function to set the End Of DXE flag.
+ //
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ OnEndOfDxe,
+ NULL,
+ &gEfiEndOfDxeEventGroupGuid,
+ &EndOfDxeEvent
+ );
+ ASSERT_EFI_ERROR (Status);
return EFI_SUCCESS;
}
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf
index 28b69c34de..8cbefefa1b 100644
--- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf
+++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf
@@ -2,7 +2,7 @@
# Component description file for Variable module.
#
# This module installs three EFI_RUNTIME_SERVICES: SetVariable, GetVariable, GetNextVariableName.
-# 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
@@ -59,13 +59,15 @@
gEfiVariableWriteArchProtocolGuid ## ALWAYS_PRODUCES
gEfiVariableArchProtocolGuid ## ALWAYS_PRODUCES
gEfiFaultTolerantWriteProtocolGuid ## SOMETIMES_CONSUMES
+ gEdkiiVariableLockProtocolGuid ## ALWAYS_PRODUCES
[Guids]
gEfiVariableGuid ## PRODUCES ## Configuration Table Guid
gEfiGlobalVariableGuid ## PRODUCES ## Variable Guid
- gEfiEventVirtualAddressChangeGuid ## PRODUCES ## Event
+ gEfiEventVirtualAddressChangeGuid ## CONSUMES ## Event
gEfiSystemNvDataFvGuid ## CONSUMES
gEfiHardwareErrorVariableGuid ## SOMETIMES_CONSUMES
+ gEfiEndOfDxeEventGroupGuid ## CONSUMES ## Event
[Pcd]
gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.c b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.c
index 550f01a525..1ffa74e6cc 100644
--- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.c
+++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.c
@@ -15,7 +15,7 @@
VariableServiceSetVariable(), VariableServiceQueryVariableInfo(), ReclaimForOS(),
SmmVariableGetStatistics() should also do validation based on its own knowledge.
-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
@@ -29,6 +29,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include <Protocol/SmmFirmwareVolumeBlock.h>
#include <Protocol/SmmFaultTolerantWrite.h>
#include <Protocol/SmmAccess2.h>
+#include <Protocol/SmmEndOfDxe.h>
#include <Library/SmmServicesTableLib.h>
@@ -44,15 +45,63 @@ EFI_HANDLE mSmmVariableHandle = N
EFI_HANDLE mVariableHandle = NULL;
BOOLEAN mAtRuntime = FALSE;
EFI_GUID mZeroGuid = {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}};
-
+UINT8 *mVariableBufferPayload = NULL;
+UINTN mVariableBufferPayloadSize;
+extern BOOLEAN mEndOfDxe;
+extern BOOLEAN mEnableLocking;
+
+/**
+
+ This code sets variable in storage blocks (Volatile or Non-Volatile).
+
+ @param VariableName Name of Variable to be found.
+ @param VendorGuid Variable vendor GUID.
+ @param Attributes Attribute value of the variable found
+ @param DataSize Size of Data found. If size is less than the
+ data, this value contains the required size.
+ @param Data Data pointer.
+
+ @return EFI_INVALID_PARAMETER Invalid parameter.
+ @return EFI_SUCCESS Set successfully.
+ @return EFI_OUT_OF_RESOURCES Resource not enough to set variable.
+ @return EFI_NOT_FOUND Not found.
+ @return EFI_WRITE_PROTECTED Variable is read-only.
+
+**/
+EFI_STATUS
+EFIAPI
+SmmVariableSetVariable (
+ IN CHAR16 *VariableName,
+ IN EFI_GUID *VendorGuid,
+ IN UINT32 Attributes,
+ IN UINTN DataSize,
+ IN VOID *Data
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Disable write protection when the calling SetVariable() through EFI_SMM_VARIABLE_PROTOCOL.
+ //
+ mEnableLocking = FALSE;
+ Status = VariableServiceSetVariable (
+ VariableName,
+ VendorGuid,
+ Attributes,
+ DataSize,
+ Data
+ );
+ mEnableLocking = TRUE;
+ return Status;
+}
+
EFI_SMM_VARIABLE_PROTOCOL gSmmVariable = {
VariableServiceGetVariable,
VariableServiceGetNextVariableName,
- VariableServiceSetVariable,
+ SmmVariableSetVariable,
VariableServiceQueryVariableInfo
};
-
/**
Return TRUE if ExitBootServices () has been called.
@@ -93,6 +142,32 @@ InternalIsAddressInSmram (
return FALSE;
}
+/**
+ This function check if the address refered by Buffer and Length is valid.
+
+ @param Buffer the buffer address to be checked.
+ @param Length the buffer length to be checked.
+
+ @retval TRUE this address is valid.
+ @retval FALSE this address is NOT valid.
+**/
+BOOLEAN
+InternalIsAddressValid (
+ IN UINTN Buffer,
+ IN UINTN Length
+ )
+{
+ if (Buffer > (MAX_ADDRESS - Length)) {
+ //
+ // Overflow happen
+ //
+ return FALSE;
+ }
+ if (InternalIsAddressInSmram ((EFI_PHYSICAL_ADDRESS)Buffer, (UINT64)Length)) {
+ return FALSE;
+ }
+ return TRUE;
+}
/**
Initializes a basic mutual exclusion lock.
@@ -276,6 +351,8 @@ GetFvbCountAndBuffer (
*NumberHandles = BufferSize / sizeof(EFI_HANDLE);
if (EFI_ERROR(Status)) {
*NumberHandles = 0;
+ FreePool (*Buffer);
+ *Buffer = NULL;
}
return Status;
@@ -311,7 +388,8 @@ SmmVariableGetStatistics (
UINTN NameLength;
UINTN StatisticsInfoSize;
CHAR16 *InfoName;
-
+ EFI_GUID VendorGuid;
+
ASSERT (InfoEntry != NULL);
VariableInfo = gVariableInfo;
if (VariableInfo == NULL) {
@@ -325,7 +403,9 @@ SmmVariableGetStatistics (
}
InfoName = (CHAR16 *)(InfoEntry + 1);
- if (CompareGuid (&InfoEntry->VendorGuid, &mZeroGuid)) {
+ CopyGuid (&VendorGuid, &InfoEntry->VendorGuid);
+
+ if (CompareGuid (&VendorGuid, &mZeroGuid)) {
//
// Return the first variable info
//
@@ -339,7 +419,7 @@ SmmVariableGetStatistics (
// Get the next variable info
//
while (VariableInfo != NULL) {
- if (CompareGuid (&VariableInfo->VendorGuid, &InfoEntry->VendorGuid)) {
+ if (CompareGuid (&VariableInfo->VendorGuid, &VendorGuid)) {
NameLength = StrSize (VariableInfo->Name);
if (NameLength == StrSize (InfoName)) {
if (CompareMem (VariableInfo->Name, InfoName, NameLength) == 0) {
@@ -417,7 +497,11 @@ SmmVariableHandler (
SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME *GetNextVariableName;
SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO *QueryVariableInfo;
VARIABLE_INFO_ENTRY *VariableInfo;
+ SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE *VariableToLock;
UINTN InfoSize;
+ UINTN NameBufferSize;
+ UINTN CommBufferPayloadSize;
+ UINTN TempCommBufferSize;
//
// If input is invalid, stop processing this SMI
@@ -426,27 +510,59 @@ SmmVariableHandler (
return EFI_SUCCESS;
}
- if (*CommBufferSize < SMM_VARIABLE_COMMUNICATE_HEADER_SIZE) {
+ TempCommBufferSize = *CommBufferSize;
+
+ if (TempCommBufferSize < SMM_VARIABLE_COMMUNICATE_HEADER_SIZE) {
+ DEBUG ((EFI_D_ERROR, "SmmVariableHandler: SMM communication buffer size invalid!\n"));
+ return EFI_SUCCESS;
+ }
+ CommBufferPayloadSize = TempCommBufferSize - SMM_VARIABLE_COMMUNICATE_HEADER_SIZE;
+ if (CommBufferPayloadSize > mVariableBufferPayloadSize) {
+ DEBUG ((EFI_D_ERROR, "SmmVariableHandler: SMM communication buffer payload size invalid!\n"));
return EFI_SUCCESS;
}
- if (InternalIsAddressInSmram ((EFI_PHYSICAL_ADDRESS)(UINTN)CommBuffer, *CommBufferSize)) {
- DEBUG ((EFI_D_ERROR, "SMM communication buffer size is in SMRAM!\n"));
+ if (!InternalIsAddressValid ((UINTN)CommBuffer, TempCommBufferSize)) {
+ DEBUG ((EFI_D_ERROR, "SmmVariableHandler: SMM communication buffer in SMRAM or overflow!\n"));
return EFI_SUCCESS;
}
SmmVariableFunctionHeader = (SMM_VARIABLE_COMMUNICATE_HEADER *)CommBuffer;
switch (SmmVariableFunctionHeader->Function) {
case SMM_VARIABLE_FUNCTION_GET_VARIABLE:
- SmmVariableHeader = (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *) SmmVariableFunctionHeader->Data;
+ if (CommBufferPayloadSize < OFFSET_OF(SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name)) {
+ DEBUG ((EFI_D_ERROR, "GetVariable: SMM communication buffer size invalid!\n"));
+ return EFI_SUCCESS;
+ }
+ //
+ // Copy the input communicate buffer payload to pre-allocated SMM variable buffer payload.
+ //
+ CopyMem (mVariableBufferPayload, SmmVariableFunctionHeader->Data, CommBufferPayloadSize);
+ SmmVariableHeader = (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *) mVariableBufferPayload;
+ if (((UINTN)(~0) - SmmVariableHeader->DataSize < OFFSET_OF(SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name)) ||
+ ((UINTN)(~0) - SmmVariableHeader->NameSize < OFFSET_OF(SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) + SmmVariableHeader->DataSize)) {
+ //
+ // Prevent InfoSize overflow happen
+ //
+ Status = EFI_ACCESS_DENIED;
+ goto EXIT;
+ }
InfoSize = OFFSET_OF(SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name)
+ SmmVariableHeader->DataSize + SmmVariableHeader->NameSize;
//
// SMRAM range check already covered before
//
- if (InfoSize > *CommBufferSize - SMM_VARIABLE_COMMUNICATE_HEADER_SIZE) {
- DEBUG ((EFI_D_ERROR, "Data size exceed communication buffer size limit!\n"));
+ if (InfoSize > CommBufferPayloadSize) {
+ DEBUG ((EFI_D_ERROR, "GetVariable: Data size exceed communication buffer size limit!\n"));
+ Status = EFI_ACCESS_DENIED;
+ goto EXIT;
+ }
+
+ if (SmmVariableHeader->NameSize < sizeof (CHAR16) || SmmVariableHeader->Name[SmmVariableHeader->NameSize/sizeof (CHAR16) - 1] != L'\0') {
+ //
+ // Make sure VariableName is A Null-terminated string.
+ //
Status = EFI_ACCESS_DENIED;
goto EXIT;
}
@@ -458,17 +574,42 @@ SmmVariableHandler (
&SmmVariableHeader->DataSize,
(UINT8 *)SmmVariableHeader->Name + SmmVariableHeader->NameSize
);
+ CopyMem (SmmVariableFunctionHeader->Data, mVariableBufferPayload, CommBufferPayloadSize);
break;
case SMM_VARIABLE_FUNCTION_GET_NEXT_VARIABLE_NAME:
- GetNextVariableName = (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME *) SmmVariableFunctionHeader->Data;
+ if (CommBufferPayloadSize < OFFSET_OF(SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name)) {
+ DEBUG ((EFI_D_ERROR, "GetNextVariableName: SMM communication buffer size invalid!\n"));
+ return EFI_SUCCESS;
+ }
+ //
+ // Copy the input communicate buffer payload to pre-allocated SMM variable buffer payload.
+ //
+ CopyMem (mVariableBufferPayload, SmmVariableFunctionHeader->Data, CommBufferPayloadSize);
+ GetNextVariableName = (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME *) mVariableBufferPayload;
+ if ((UINTN)(~0) - GetNextVariableName->NameSize < OFFSET_OF(SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name)) {
+ //
+ // Prevent InfoSize overflow happen
+ //
+ Status = EFI_ACCESS_DENIED;
+ goto EXIT;
+ }
InfoSize = OFFSET_OF(SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name) + GetNextVariableName->NameSize;
//
// SMRAM range check already covered before
//
- if (InfoSize > *CommBufferSize - SMM_VARIABLE_COMMUNICATE_HEADER_SIZE) {
- DEBUG ((EFI_D_ERROR, "Data size exceed communication buffer size limit!\n"));
+ if (InfoSize > CommBufferPayloadSize) {
+ DEBUG ((EFI_D_ERROR, "GetNextVariableName: Data size exceed communication buffer size limit!\n"));
+ Status = EFI_ACCESS_DENIED;
+ goto EXIT;
+ }
+
+ NameBufferSize = CommBufferPayloadSize - OFFSET_OF(SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name);
+ if (NameBufferSize < sizeof (CHAR16) || GetNextVariableName->Name[NameBufferSize/sizeof (CHAR16) - 1] != L'\0') {
+ //
+ // Make sure input VariableName is A Null-terminated string.
+ //
Status = EFI_ACCESS_DENIED;
goto EXIT;
}
@@ -478,10 +619,48 @@ SmmVariableHandler (
GetNextVariableName->Name,
&GetNextVariableName->Guid
);
+ CopyMem (SmmVariableFunctionHeader->Data, mVariableBufferPayload, CommBufferPayloadSize);
break;
case SMM_VARIABLE_FUNCTION_SET_VARIABLE:
- SmmVariableHeader = (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *) SmmVariableFunctionHeader->Data;
+ if (CommBufferPayloadSize < OFFSET_OF(SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name)) {
+ DEBUG ((EFI_D_ERROR, "SetVariable: SMM communication buffer size invalid!\n"));
+ return EFI_SUCCESS;
+ }
+ //
+ // Copy the input communicate buffer payload to pre-allocated SMM variable buffer payload.
+ //
+ CopyMem (mVariableBufferPayload, SmmVariableFunctionHeader->Data, CommBufferPayloadSize);
+ SmmVariableHeader = (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *) mVariableBufferPayload;
+ if (((UINTN)(~0) - SmmVariableHeader->DataSize < OFFSET_OF(SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name)) ||
+ ((UINTN)(~0) - SmmVariableHeader->NameSize < OFFSET_OF(SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) + SmmVariableHeader->DataSize)) {
+ //
+ // Prevent InfoSize overflow happen
+ //
+ Status = EFI_ACCESS_DENIED;
+ goto EXIT;
+ }
+ InfoSize = OFFSET_OF(SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name)
+ + SmmVariableHeader->DataSize + SmmVariableHeader->NameSize;
+
+ //
+ // SMRAM range check already covered before
+ // Data buffer should not contain SMM range
+ //
+ if (InfoSize > CommBufferPayloadSize) {
+ DEBUG ((EFI_D_ERROR, "SetVariable: Data size exceed communication buffer size limit!\n"));
+ Status = EFI_ACCESS_DENIED;
+ goto EXIT;
+ }
+
+ if (SmmVariableHeader->NameSize < sizeof (CHAR16) || SmmVariableHeader->Name[SmmVariableHeader->NameSize/sizeof (CHAR16) - 1] != L'\0') {
+ //
+ // Make sure VariableName is A Null-terminated string.
+ //
+ Status = EFI_ACCESS_DENIED;
+ goto EXIT;
+ }
+
Status = VariableServiceSetVariable (
SmmVariableHeader->Name,
&SmmVariableHeader->Guid,
@@ -492,17 +671,11 @@ SmmVariableHandler (
break;
case SMM_VARIABLE_FUNCTION_QUERY_VARIABLE_INFO:
- QueryVariableInfo = (SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO *) SmmVariableFunctionHeader->Data;
- InfoSize = sizeof(SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO);
-
- //
- // SMRAM range check already covered before
- //
- if (InfoSize > *CommBufferSize - SMM_VARIABLE_COMMUNICATE_HEADER_SIZE) {
- DEBUG ((EFI_D_ERROR, "Data size exceed communication buffer size limit!\n"));
- Status = EFI_ACCESS_DENIED;
- goto EXIT;
+ if (CommBufferPayloadSize < sizeof (SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO)) {
+ DEBUG ((EFI_D_ERROR, "QueryVariableInfo: SMM communication buffer size invalid!\n"));
+ return EFI_SUCCESS;
}
+ QueryVariableInfo = (SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO *) SmmVariableFunctionHeader->Data;
Status = VariableServiceQueryVariableInfo (
QueryVariableInfo->Attributes,
@@ -513,6 +686,7 @@ SmmVariableHandler (
break;
case SMM_VARIABLE_FUNCTION_READY_TO_BOOT:
+ mEndOfDxe = TRUE;
if (AtRuntime()) {
Status = EFI_UNSUPPORTED;
break;
@@ -528,7 +702,7 @@ SmmVariableHandler (
case SMM_VARIABLE_FUNCTION_GET_STATISTICS:
VariableInfo = (VARIABLE_INFO_ENTRY *) SmmVariableFunctionHeader->Data;
- InfoSize = *CommBufferSize - SMM_VARIABLE_COMMUNICATE_HEADER_SIZE;
+ InfoSize = TempCommBufferSize - SMM_VARIABLE_COMMUNICATE_HEADER_SIZE;
//
// Do not need to check SmmVariableFunctionHeader->Data in SMRAM here.
@@ -536,7 +710,7 @@ SmmVariableHandler (
//
if (InternalIsAddressInSmram ((EFI_PHYSICAL_ADDRESS)(UINTN)CommBufferSize, sizeof(UINTN))) {
- DEBUG ((EFI_D_ERROR, "SMM communication buffer size is in SMRAM!\n"));
+ DEBUG ((EFI_D_ERROR, "GetStatistics: SMM communication buffer in SMRAM!\n"));
Status = EFI_ACCESS_DENIED;
goto EXIT;
}
@@ -545,6 +719,19 @@ SmmVariableHandler (
*CommBufferSize = InfoSize + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE;
break;
+ case SMM_VARIABLE_FUNCTION_LOCK_VARIABLE:
+ if (mEndOfDxe) {
+ Status = EFI_ACCESS_DENIED;
+ } else {
+ VariableToLock = (SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE *) SmmVariableFunctionHeader->Data;
+ Status = VariableLockRequestToLock (
+ NULL,
+ VariableToLock->Name,
+ &VariableToLock->Guid
+ );
+ }
+ break;
+
default:
Status = EFI_UNSUPPORTED;
}
@@ -556,6 +743,28 @@ EXIT:
return EFI_SUCCESS;
}
+/**
+ SMM END_OF_DXE protocol notification event handler.
+
+ @param Protocol Points to the protocol's unique identifier
+ @param Interface Points to the interface instance
+ @param Handle The handle on which the interface was installed
+
+ @retval EFI_SUCCESS SmmEndOfDxeCallback runs successfully
+
+**/
+EFI_STATUS
+EFIAPI
+SmmEndOfDxeCallback (
+ IN CONST EFI_GUID *Protocol,
+ IN VOID *Interface,
+ IN EFI_HANDLE Handle
+ )
+{
+ DEBUG ((EFI_D_INFO, "[Variable]END_OF_DXE is signaled\n"));
+ mEndOfDxe = TRUE;
+ return EFI_SUCCESS;
+}
/**
SMM Fault Tolerant Write protocol notification event handler.
@@ -652,6 +861,7 @@ VariableServiceInitialize (
VOID *SmmFtwRegistration;
EFI_SMM_ACCESS2_PROTOCOL *SmmAccess;
UINTN Size;
+ VOID *SmmEndOfDxeRegistration;
//
// Variable initialize.
@@ -693,6 +903,16 @@ VariableServiceInitialize (
mSmramRangeCount = Size / sizeof (EFI_SMRAM_DESCRIPTOR);
+ mVariableBufferPayloadSize = MAX (PcdGet32 (PcdMaxVariableSize), PcdGet32 (PcdMaxHardwareErrorVariableSize)) +
+ OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) - sizeof (VARIABLE_HEADER);
+
+ Status = gSmst->SmmAllocatePool (
+ EfiRuntimeServicesData,
+ mVariableBufferPayloadSize,
+ (VOID **)&mVariableBufferPayload
+ );
+ ASSERT_EFI_ERROR (Status);
+
///
/// Register SMM variable SMI handler
///
@@ -712,6 +932,16 @@ VariableServiceInitialize (
ASSERT_EFI_ERROR (Status);
//
+ // Register EFI_SMM_END_OF_DXE_PROTOCOL_GUID notify function.
+ //
+ Status = gSmst->SmmRegisterProtocolNotify (
+ &gEfiSmmEndOfDxeProtocolGuid,
+ SmmEndOfDxeCallback,
+ &SmmEndOfDxeRegistration
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
// Register FtwNotificationEvent () notify function.
//
Status = gSmst->SmmRegisterProtocolNotify (
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf
index e2c5d9c40d..c229805bc9 100644
--- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf
+++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf
@@ -14,7 +14,7 @@
# This external input must be validated carefully to avoid security issue like
# buffer overflow, integer overflow.
#
-# 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
@@ -69,6 +69,7 @@
gEfiSmmVariableProtocolGuid ## ALWAYS_PRODUCES
gEfiSmmFaultTolerantWriteProtocolGuid ## SOMETIMES_CONSUMES
gEfiSmmAccess2ProtocolGuid ## ALWAYS_CONSUMES
+ gEfiSmmEndOfDxeProtocolGuid ## ALWAYS_CONSUMES
[Guids]
gEfiVariableGuid ## PRODUCES ## Configuration Table Guid
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.c b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.c
index 2fca25981a..e7b10149fb 100644
--- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.c
+++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.c
@@ -19,6 +19,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include <Protocol/Variable.h>
#include <Protocol/SmmCommunication.h>
#include <Protocol/SmmVariable.h>
+#include <Protocol/VariableLock.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiRuntimeServicesTableLib.h>
@@ -42,7 +43,9 @@ EFI_SMM_COMMUNICATION_PROTOCOL *mSmmCommunication = NULL;
UINT8 *mVariableBuffer = NULL;
UINT8 *mVariableBufferPhysical = NULL;
UINTN mVariableBufferSize;
+UINTN mVariableBufferPayloadSize;
EFI_LOCK mVariableServicesLock;
+EDKII_VARIABLE_LOCK_PROTOCOL mVariableLock;
/**
Acquires lock only at boot time. Simply returns at runtime.
@@ -159,6 +162,73 @@ SendCommunicateBuffer (
return SmmVariableFunctionHeader->ReturnStatus;
}
+/**
+ Mark a variable that will become read-only after leaving the DXE phase of execution.
+
+ @param[in] This The VARIABLE_LOCK_PROTOCOL instance.
+ @param[in] VariableName A pointer to the variable name that will be made read-only subsequently.
+ @param[in] VendorGuid A pointer to the vendor GUID that will be made read-only subsequently.
+
+ @retval EFI_SUCCESS The variable specified by the VariableName and the VendorGuid was marked
+ as pending to be read-only.
+ @retval EFI_INVALID_PARAMETER VariableName or VendorGuid is NULL.
+ Or VariableName is an empty string.
+ @retval EFI_ACCESS_DENIED EFI_END_OF_DXE_EVENT_GROUP_GUID or EFI_EVENT_GROUP_READY_TO_BOOT has
+ already been signaled.
+ @retval EFI_OUT_OF_RESOURCES There is not enough resource to hold the lock request.
+**/
+EFI_STATUS
+EFIAPI
+VariableLockRequestToLock (
+ IN CONST EDKII_VARIABLE_LOCK_PROTOCOL *This,
+ IN CHAR16 *VariableName,
+ IN EFI_GUID *VendorGuid
+ )
+{
+ EFI_STATUS Status;
+ UINTN VariableNameSize;
+ UINTN PayloadSize;
+ SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE *VariableToLock;
+
+ if (VariableName == NULL || VariableName[0] == 0 || VendorGuid == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ VariableNameSize = StrSize (VariableName);
+
+ //
+ // If VariableName exceeds SMM payload limit. Return failure
+ //
+ if (VariableNameSize > mVariableBufferPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE, Name)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ AcquireLockOnlyAtBootTime(&mVariableServicesLock);
+
+ //
+ // Init the communicate buffer. The buffer data size is:
+ // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize.
+ //
+ PayloadSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE, Name) + VariableNameSize;
+ Status = InitCommunicateBuffer ((VOID **) &VariableToLock, PayloadSize, SMM_VARIABLE_FUNCTION_LOCK_VARIABLE);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+ ASSERT (VariableToLock != NULL);
+
+ CopyGuid (&VariableToLock->Guid, VendorGuid);
+ VariableToLock->NameSize = VariableNameSize;
+ CopyMem (VariableToLock->Name, VariableName, VariableToLock->NameSize);
+
+ //
+ // Send data to SMM.
+ //
+ Status = SendCommunicateBuffer (PayloadSize);
+
+Done:
+ ReleaseLockOnlyAtBootTime (&mVariableServicesLock);
+ return Status;
+}
/**
This code finds variable in storage blocks (Volatile or Non-Volatile).
@@ -189,6 +259,8 @@ RuntimeServiceGetVariable (
EFI_STATUS Status;
UINTN PayloadSize;
SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *SmmVariableHeader;
+ UINTN TempDataSize;
+ UINTN VariableNameSize;
if (VariableName == NULL || VendorGuid == NULL || DataSize == NULL) {
return EFI_INVALID_PARAMETER;
@@ -198,13 +270,13 @@ RuntimeServiceGetVariable (
return EFI_INVALID_PARAMETER;
}
- if (*DataSize >= mVariableBufferSize) {
- //
- // DataSize may be near MAX_ADDRESS incorrectly, this can cause the computed PayLoadSize to
- // overflow to a small value and pass the check in InitCommunicateBuffer().
- // To protect against this vulnerability, return EFI_INVALID_PARAMETER if DataSize is >= mVariableBufferSize.
- // And there will be further check to ensure the total size is also not > mVariableBufferSize.
- //
+ TempDataSize = *DataSize;
+ VariableNameSize = StrSize (VariableName);
+
+ //
+ // If VariableName exceeds SMM payload limit. Return failure
+ //
+ if (VariableNameSize > mVariableBufferPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name)) {
return EFI_INVALID_PARAMETER;
}
@@ -214,7 +286,14 @@ RuntimeServiceGetVariable (
// Init the communicate buffer. The buffer data size is:
// SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize.
//
- PayloadSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) + StrSize (VariableName) + *DataSize;
+ if (TempDataSize > mVariableBufferPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) - VariableNameSize) {
+ //
+ // If output data buffer exceed SMM payload limit. Trim output buffer to SMM payload size
+ //
+ TempDataSize = mVariableBufferPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) - VariableNameSize;
+ }
+ PayloadSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) + VariableNameSize + TempDataSize;
+
Status = InitCommunicateBuffer ((VOID **)&SmmVariableHeader, PayloadSize, SMM_VARIABLE_FUNCTION_GET_VARIABLE);
if (EFI_ERROR (Status)) {
goto Done;
@@ -222,8 +301,8 @@ RuntimeServiceGetVariable (
ASSERT (SmmVariableHeader != NULL);
CopyGuid (&SmmVariableHeader->Guid, VendorGuid);
- SmmVariableHeader->DataSize = *DataSize;
- SmmVariableHeader->NameSize = StrSize (VariableName);
+ SmmVariableHeader->DataSize = TempDataSize;
+ SmmVariableHeader->NameSize = VariableNameSize;
if (Attributes == NULL) {
SmmVariableHeader->Attributes = 0;
} else {
@@ -239,7 +318,13 @@ RuntimeServiceGetVariable (
//
// Get data from SMM.
//
- *DataSize = SmmVariableHeader->DataSize;
+ if (Status == EFI_SUCCESS || Status == EFI_BUFFER_TOO_SMALL) {
+ //
+ // SMM CommBuffer DataSize can be a trimed value
+ // Only update DataSize when needed
+ //
+ *DataSize = SmmVariableHeader->DataSize;
+ }
if (Attributes != NULL) {
*Attributes = SmmVariableHeader->Attributes;
}
@@ -280,18 +365,20 @@ RuntimeServiceGetNextVariableName (
EFI_STATUS Status;
UINTN PayloadSize;
SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME *SmmGetNextVariableName;
+ UINTN OutVariableNameSize;
+ UINTN InVariableNameSize;
if (VariableNameSize == NULL || VariableName == NULL || VendorGuid == NULL) {
return EFI_INVALID_PARAMETER;
}
- if (*VariableNameSize >= mVariableBufferSize) {
- //
- // VariableNameSize may be near MAX_ADDRESS incorrectly, this can cause the computed PayLoadSize to
- // overflow to a small value and pass the check in InitCommunicateBuffer().
- // To protect against this vulnerability, return EFI_INVALID_PARAMETER if VariableNameSize is >= mVariableBufferSize.
- // And there will be further check to ensure the total size is also not > mVariableBufferSize.
- //
+ OutVariableNameSize = *VariableNameSize;
+ InVariableNameSize = StrSize (VariableName);
+
+ //
+ // If input string exceeds SMM payload limit. Return failure
+ //
+ if (InVariableNameSize > mVariableBufferPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name)) {
return EFI_INVALID_PARAMETER;
}
@@ -301,16 +388,37 @@ RuntimeServiceGetNextVariableName (
// Init the communicate buffer. The buffer data size is:
// SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize.
//
- PayloadSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name) + *VariableNameSize;
+ if (OutVariableNameSize > mVariableBufferPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name)) {
+ //
+ // If output buffer exceed SMM payload limit. Trim output buffer to SMM payload size
+ //
+ OutVariableNameSize = mVariableBufferPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name);
+ }
+ //
+ // Payload should be Guid + NameSize + MAX of Input & Output buffer
+ //
+ PayloadSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name) + MAX (OutVariableNameSize, InVariableNameSize);
+
+
Status = InitCommunicateBuffer ((VOID **)&SmmGetNextVariableName, PayloadSize, SMM_VARIABLE_FUNCTION_GET_NEXT_VARIABLE_NAME);
if (EFI_ERROR (Status)) {
goto Done;
}
ASSERT (SmmGetNextVariableName != NULL);
- SmmGetNextVariableName->NameSize = *VariableNameSize;
+ //
+ // SMM comm buffer->NameSize is buffer size for return string
+ //
+ SmmGetNextVariableName->NameSize = OutVariableNameSize;
+
CopyGuid (&SmmGetNextVariableName->Guid, VendorGuid);
- CopyMem (SmmGetNextVariableName->Name, VariableName, *VariableNameSize);
+ //
+ // Copy whole string
+ //
+ CopyMem (SmmGetNextVariableName->Name, VariableName, InVariableNameSize);
+ if (OutVariableNameSize > InVariableNameSize) {
+ ZeroMem ((UINT8 *) SmmGetNextVariableName->Name + InVariableNameSize, OutVariableNameSize - InVariableNameSize);
+ }
//
// Send data to SMM
@@ -320,7 +428,13 @@ RuntimeServiceGetNextVariableName (
//
// Get data from SMM.
//
- *VariableNameSize = SmmGetNextVariableName->NameSize;
+ if (Status == EFI_SUCCESS || Status == EFI_BUFFER_TOO_SMALL) {
+ //
+ // SMM CommBuffer NameSize can be a trimed value
+ // Only update VariableNameSize when needed
+ //
+ *VariableNameSize = SmmGetNextVariableName->NameSize;
+ }
if (EFI_ERROR (Status)) {
goto Done;
}
@@ -363,6 +477,7 @@ RuntimeServiceSetVariable (
EFI_STATUS Status;
UINTN PayloadSize;
SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *SmmVariableHeader;
+ UINTN VariableNameSize;
//
// Check input parameters.
@@ -375,13 +490,13 @@ RuntimeServiceSetVariable (
return EFI_INVALID_PARAMETER;
}
- if (DataSize >= mVariableBufferSize) {
- //
- // DataSize may be near MAX_ADDRESS incorrectly, this can cause the computed PayLoadSize to
- // overflow to a small value and pass the check in InitCommunicateBuffer().
- // To protect against this vulnerability, return EFI_INVALID_PARAMETER if DataSize is >= mVariableBufferSize.
- // And there will be further check to ensure the total size is also not > mVariableBufferSize.
- //
+ VariableNameSize = StrSize (VariableName);
+
+ //
+ // If VariableName or DataSize exceeds SMM payload limit. Return failure
+ //
+ if ((VariableNameSize > mVariableBufferPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name)) ||
+ (DataSize > mVariableBufferPayloadSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) - VariableNameSize)){
return EFI_INVALID_PARAMETER;
}
@@ -391,7 +506,7 @@ RuntimeServiceSetVariable (
// Init the communicate buffer. The buffer data size is:
// SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize.
//
- PayloadSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) + StrSize (VariableName) + DataSize;
+ PayloadSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) + VariableNameSize + DataSize;
Status = InitCommunicateBuffer ((VOID **)&SmmVariableHeader, PayloadSize, SMM_VARIABLE_FUNCTION_SET_VARIABLE);
if (EFI_ERROR (Status)) {
goto Done;
@@ -400,7 +515,7 @@ RuntimeServiceSetVariable (
CopyGuid ((EFI_GUID *) &SmmVariableHeader->Guid, VendorGuid);
SmmVariableHeader->DataSize = DataSize;
- SmmVariableHeader->NameSize = StrSize (VariableName);
+ SmmVariableHeader->NameSize = VariableNameSize;
SmmVariableHeader->Attributes = Attributes;
CopyMem (SmmVariableHeader->Name, VariableName, SmmVariableHeader->NameSize);
CopyMem ((UINT8 *) SmmVariableHeader->Name + SmmVariableHeader->NameSize, Data, DataSize);
@@ -591,10 +706,11 @@ SmmVariableReady (
ASSERT_EFI_ERROR (Status);
//
- // Allocate memory for variable store.
+ // Allocate memory for variable communicate buffer.
//
- mVariableBufferSize = SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE;
- mVariableBufferSize += MAX (PcdGet32 (PcdMaxVariableSize), PcdGet32 (PcdMaxHardwareErrorVariableSize));
+ mVariableBufferPayloadSize = MAX (PcdGet32 (PcdMaxVariableSize), PcdGet32 (PcdMaxHardwareErrorVariableSize)) +
+ OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) - sizeof (VARIABLE_HEADER);
+ mVariableBufferSize = SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + mVariableBufferPayloadSize;
mVariableBuffer = AllocateRuntimePool (mVariableBufferSize);
ASSERT (mVariableBuffer != NULL);
@@ -675,6 +791,7 @@ VariableSmmRuntimeInitialize (
IN EFI_SYSTEM_TABLE *SystemTable
)
{
+ EFI_STATUS Status;
VOID *SmmVariableRegistration;
VOID *SmmVariableWriteRegistration;
EFI_EVENT OnReadyToBootEvent;
@@ -682,6 +799,15 @@ VariableSmmRuntimeInitialize (
EfiInitializeLock (&mVariableServicesLock, TPL_NOTIFY);
+ mVariableLock.RequestToLock = VariableLockRequestToLock;
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &mHandle,
+ &gEdkiiVariableLockProtocolGuid,
+ &mVariableLock,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
//
// Smm variable service is ready
//
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.inf b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.inf
index 05dd49d368..761ea66e6b 100644
--- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.inf
+++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.inf
@@ -4,7 +4,7 @@
# This module is the Runtime DXE part correspond to SMM variable module. It
# installs variable arch protocol and variable write arch protocol and works
# with SMM variable module together.
-# 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 of the BSD License
@@ -54,6 +54,7 @@
gEfiVariableArchProtocolGuid ## ALWAYS_PRODUCES
gEfiSmmCommunicationProtocolGuid
gEfiSmmVariableProtocolGuid
+ gEdkiiVariableLockProtocolGuid ## ALWAYS_PRODUCES
[Guids]
gEfiEventVirtualAddressChangeGuid ## PRODUCES ## Event