During normal boot, when EFI_DXE_SMM_READY_TO_LOCK_PROTOCOL is installed by platform BDS, the SMM IPL locks SMRAM (TSEG) through EFI_SMM_ACCESS2_PROTOCOL.Lock(). See SmmIplReadyToLockEventNotify() in "MdeModulePkg/Core/PiSmmCore/PiSmmIpl.c". During S3 resume, S3Resume2Pei locks SMRAM (TSEG) through PEI_SMM_ACCESS_PPI.Lock(), before executing the boot script. See S3ResumeExecuteBootScript() in "UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume.c". Those are precisely the places where the SMRAM at the default SMBASE should be locked too. Add such an action to SmramAccessLock(). Notes: - The SMRAM at the default SMBASE doesn't support the "closed and unlocked" state (and so it can't be closed without locking it, and it cannot be opened after closing it). - The SMRAM at the default SMBASE isn't (and shouldn't) be exposed with another EFI_SMRAM_DESCRIPTOR in the GetCapabilities() members of EFI_SMM_ACCESS2_PROTOCOL / PEI_SMM_ACCESS_PPI. That's because the SMRAM in question is not "general purpose"; it's only QEMU's solution to protect the initial SMI handler from the OS, when a VCPU is hot-plugged. Consequently, the state of the SMRAM at the default SMBASE is not reflected in the "OpenState" / "LockState" fields of the protocol and PPI. - An alternative to extending SmramAccessLock() would be to register an EFI_DXE_SMM_READY_TO_LOCK_PROTOCOL notify in SmmAccess2Dxe (for locking at normal boot), and an EDKII_S3_SMM_INIT_DONE_GUID PPI notify in SmmAccessPei (for locking at S3 resume). Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org> Cc: Jordan Justen <jordan.l.justen@intel.com> Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=1512 Signed-off-by: Laszlo Ersek <lersek@redhat.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com> Message-Id: <20200129214412.2361-10-lersek@redhat.com> Reviewed-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
		
			
				
	
	
		
			159 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			159 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
| 
 | |
|   A DXE_DRIVER providing SMRAM access by producing EFI_SMM_ACCESS2_PROTOCOL.
 | |
| 
 | |
|   Q35 TSEG is expected to have been verified and set up by the SmmAccessPei
 | |
|   driver.
 | |
| 
 | |
|   Copyright (C) 2013, 2015, Red Hat, Inc.<BR>
 | |
|   Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
 | |
| 
 | |
|   SPDX-License-Identifier: BSD-2-Clause-Patent
 | |
| 
 | |
| **/
 | |
| 
 | |
| #include <Library/DebugLib.h>
 | |
| #include <Library/PcdLib.h>
 | |
| #include <Library/UefiBootServicesTableLib.h>
 | |
| #include <Protocol/SmmAccess2.h>
 | |
| 
 | |
| #include "SmramInternal.h"
 | |
| 
 | |
| /**
 | |
|   Opens the SMRAM area to be accessible by a boot-service driver.
 | |
| 
 | |
|   This function "opens" SMRAM so that it is visible while not inside of SMM.
 | |
|   The function should return EFI_UNSUPPORTED if the hardware does not support
 | |
|   hiding of SMRAM. The function should return EFI_DEVICE_ERROR if the SMRAM
 | |
|   configuration is locked.
 | |
| 
 | |
|   @param[in] This           The EFI_SMM_ACCESS2_PROTOCOL instance.
 | |
| 
 | |
|   @retval EFI_SUCCESS       The operation was successful.
 | |
|   @retval EFI_UNSUPPORTED   The system does not support opening and closing of
 | |
|                             SMRAM.
 | |
|   @retval EFI_DEVICE_ERROR  SMRAM cannot be opened, perhaps because it is
 | |
|                             locked.
 | |
| **/
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| SmmAccess2DxeOpen (
 | |
|   IN EFI_SMM_ACCESS2_PROTOCOL  *This
 | |
|   )
 | |
| {
 | |
|   return SmramAccessOpen (&This->LockState, &This->OpenState);
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Inhibits access to the SMRAM.
 | |
| 
 | |
|   This function "closes" SMRAM so that it is not visible while outside of SMM.
 | |
|   The function should return EFI_UNSUPPORTED if the hardware does not support
 | |
|   hiding of SMRAM.
 | |
| 
 | |
|   @param[in] This           The EFI_SMM_ACCESS2_PROTOCOL instance.
 | |
| 
 | |
|   @retval EFI_SUCCESS       The operation was successful.
 | |
|   @retval EFI_UNSUPPORTED   The system does not support opening and closing of
 | |
|                             SMRAM.
 | |
|   @retval EFI_DEVICE_ERROR  SMRAM cannot be closed.
 | |
| **/
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| SmmAccess2DxeClose (
 | |
|   IN EFI_SMM_ACCESS2_PROTOCOL  *This
 | |
|   )
 | |
| {
 | |
|   return SmramAccessClose (&This->LockState, &This->OpenState);
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Inhibits access to the SMRAM.
 | |
| 
 | |
|   This function prohibits access to the SMRAM region.  This function is usually
 | |
|   implemented such that it is a write-once operation.
 | |
| 
 | |
|   @param[in] This          The EFI_SMM_ACCESS2_PROTOCOL instance.
 | |
| 
 | |
|   @retval EFI_SUCCESS      The device was successfully locked.
 | |
|   @retval EFI_UNSUPPORTED  The system does not support locking of SMRAM.
 | |
| **/
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| SmmAccess2DxeLock (
 | |
|   IN EFI_SMM_ACCESS2_PROTOCOL  *This
 | |
|   )
 | |
| {
 | |
|   return SmramAccessLock (&This->LockState, &This->OpenState);
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Queries the memory controller for the possible regions that will support
 | |
|   SMRAM.
 | |
| 
 | |
|   @param[in]     This           The EFI_SMM_ACCESS2_PROTOCOL instance.
 | |
|   @param[in,out] SmramMapSize   A pointer to the size, in bytes, of the
 | |
|                                 SmramMemoryMap buffer.
 | |
|   @param[in,out] SmramMap       A pointer to the buffer in which firmware
 | |
|                                 places the current memory map.
 | |
| 
 | |
|   @retval EFI_SUCCESS           The chipset supported the given resource.
 | |
|   @retval EFI_BUFFER_TOO_SMALL  The SmramMap parameter was too small.  The
 | |
|                                 current buffer size needed to hold the memory
 | |
|                                 map is returned in SmramMapSize.
 | |
| **/
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| SmmAccess2DxeGetCapabilities (
 | |
|   IN CONST EFI_SMM_ACCESS2_PROTOCOL  *This,
 | |
|   IN OUT UINTN                       *SmramMapSize,
 | |
|   IN OUT EFI_SMRAM_DESCRIPTOR        *SmramMap
 | |
|   )
 | |
| {
 | |
|   return SmramAccessGetCapabilities (This->LockState, This->OpenState,
 | |
|            SmramMapSize, SmramMap);
 | |
| }
 | |
| 
 | |
| //
 | |
| // LockState and OpenState will be filled in by the entry point.
 | |
| //
 | |
| STATIC EFI_SMM_ACCESS2_PROTOCOL mAccess2 = {
 | |
|   &SmmAccess2DxeOpen,
 | |
|   &SmmAccess2DxeClose,
 | |
|   &SmmAccess2DxeLock,
 | |
|   &SmmAccess2DxeGetCapabilities
 | |
| };
 | |
| 
 | |
| //
 | |
| // Entry point of this driver.
 | |
| //
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| SmmAccess2DxeEntryPoint (
 | |
|   IN EFI_HANDLE       ImageHandle,
 | |
|   IN EFI_SYSTEM_TABLE *SystemTable
 | |
|   )
 | |
| {
 | |
|   //
 | |
|   // This module should only be included if SMRAM support is required.
 | |
|   //
 | |
|   ASSERT (FeaturePcdGet (PcdSmmSmramRequire));
 | |
| 
 | |
|   InitQ35TsegMbytes ();
 | |
|   GetStates (&mAccess2.LockState, &mAccess2.OpenState);
 | |
| 
 | |
|   //
 | |
|   // SmramAccessLock() depends on "mQ35SmramAtDefaultSmbase"; init the latter
 | |
|   // just before exposing the former via EFI_SMM_ACCESS2_PROTOCOL.Lock().
 | |
|   //
 | |
|   InitQ35SmramAtDefaultSmbase ();
 | |
| 
 | |
|   return gBS->InstallMultipleProtocolInterfaces (&ImageHandle,
 | |
|                 &gEfiSmmAccess2ProtocolGuid, &mAccess2,
 | |
|                 NULL);
 | |
| }
 |