1 /** @file
2   A helper driver to save information to SMRAM after SMRR is enabled.
3 
4   This driver is for ECP platforms.
5 
6   Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved.<BR>
7 
8 
9   This program and the accompanying materials are licensed and made available under
10 
11   the terms and conditions of the BSD License that accompanies this distribution.
12 
13   The full text of the license may be found at
14 
15   http://opensource.org/licenses/bsd-license.php.
16 
17 
18 
19   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
20 
21   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
22 
23 
24 
25 
26 **/
27 
28 #include <PiSmm.h>
29 #include <Library/DebugLib.h>
30 #include <Library/UefiDriverEntryPoint.h>
31 #include <Library/UefiRuntimeServicesTableLib.h>
32 #include <Library/SmmServicesTableLib.h>
33 #include <Library/BaseLib.h>
34 #include <Library/BaseMemoryLib.h>
35 #include <Library/IoLib.h>
36 #include <Protocol/SmmSwDispatch.h>
37 #include <Protocol/SmmReadyToLock.h>
38 #include <Protocol/SmmControl.h>
39 #include <Guid/Vlv2DeviceRefCodePkgTokenSpace.h>
40 
41 #define SMM_FROM_SMBASE_DRIVER        0x55
42 #define SMM_FROM_CPU_DRIVER_SAVE_INFO 0x81
43 
44 #define EFI_SMRAM_CPU_NVS_HEADER_GUID \
45   { \
46     0x429501d9, 0xe447, 0x40f4, 0x86, 0x7b, 0x75, 0xc9, 0x3a, 0x1d, 0xb5, 0x4e \
47   }
48 
49 UINT8    mSmiDataRegister;
50 BOOLEAN  mLocked = FALSE;
51 EFI_GUID mSmramCpuNvsHeaderGuid = EFI_SMRAM_CPU_NVS_HEADER_GUID;
52 
53 /**
54   Dispatch function for a Software SMI handler.
55 
56   @param  DispatchHandle        The handle of this dispatch function.
57   @param  DispatchContext       The pointer to the dispatch function's context.
58                                 The SwSmiInputValue field is filled in
59                                 by the software dispatch driver prior to
SmramSaveInfoHandler(IN EFI_HANDLE DispatchHandle,IN EFI_SMM_SW_DISPATCH_CONTEXT * DispatchContext)60                                 invoking this dispatch function.
61                                 The dispatch function will only be called
62                                 for input values for which it is registered.
63 
64   @return None
65 
66 **/
67 VOID
68 EFIAPI
69 SmramSaveInfoHandler (
70   IN  EFI_HANDLE                    DispatchHandle,
71   IN  EFI_SMM_SW_DISPATCH_CONTEXT   *DispatchContext
72   )
73 {
74   ASSERT (DispatchContext != NULL);
75   ASSERT (DispatchContext->SwSmiInputValue == SMM_FROM_SMBASE_DRIVER);
76 
77   if (!mLocked && IoRead8 (mSmiDataRegister) == SMM_FROM_CPU_DRIVER_SAVE_INFO) {
78       CopyMem (
79         (VOID *)(UINTN)(PcdGetEx64 (&gEfiVLVTokenSpaceGuid, PcdCpuLockBoxDataAddress)),
80         (VOID *)(UINTN)(PcdGetEx64 (&gEfiVLVTokenSpaceGuid, PcdCpuSmramCpuDataAddress)),
81         (UINTN)(PcdGetEx64 (&gEfiVLVTokenSpaceGuid, PcdCpuLockBoxSize))
82         );
83   }
84 }
85 
86 /**
87   Smm Ready To Lock event notification handler.
88 
89   It sets a flag indicating that SMRAM has been locked.
SmmReadyToLockEventNotify(IN CONST EFI_GUID * Protocol,IN VOID * Interface,IN EFI_HANDLE Handle)90 
91   @param[in] Protocol   Points to the protocol's unique identifier.
92   @param[in] Interface  Points to the interface instance.
93   @param[in] Handle     The handle on which the interface was installed.
94 
95   @retval EFI_SUCCESS   Notification handler runs successfully.
96  **/
97 EFI_STATUS
98 EFIAPI
99 SmmReadyToLockEventNotify (
100   IN CONST EFI_GUID  *Protocol,
101   IN VOID            *Interface,
102   IN EFI_HANDLE      Handle
103   )
104 {
105   mLocked = TRUE;
106   return EFI_SUCCESS;
107 }
108 
109 /**
110   Entry point function of this driver.
SmramSaveInfoHandlerSmmMain(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)111 
112   @param[in] ImageHandle  The firmware allocated handle for the EFI image.
113   @param[in] SystemTable  A pointer to the EFI System Table.
114 
115   @retval EFI_SUCCESS     The entry point is executed successfully.
116   @retval other           Some error occurs when executing this entry point.
117 **/
118 EFI_STATUS
119 EFIAPI
120 SmramSaveInfoHandlerSmmMain (
121   IN EFI_HANDLE        ImageHandle,
122   IN EFI_SYSTEM_TABLE  *SystemTable
123   )
124 {
125   EFI_STATUS                    Status;
126   EFI_SMM_SW_DISPATCH_PROTOCOL  *SmmSwDispatch;
127   EFI_SMM_SW_DISPATCH_CONTEXT   SmmSwDispatchContext;
128   EFI_HANDLE                    DispatchHandle;
129   EFI_SMM_CONTROL_PROTOCOL      *SmmControl;
130   EFI_SMM_CONTROL_REGISTER      SmmControlRegister;
131   VOID                          *Registration;
132 
133   //
134   // Get SMI data register
135   //
136   Status = SystemTable->BootServices->LocateProtocol (
137                                         &gEfiSmmControlProtocolGuid,
138                                         NULL,
139                                         (VOID **)&SmmControl
140                                         );
141   ASSERT_EFI_ERROR (Status);
142   Status = SmmControl->GetRegisterInfo (SmmControl, &SmmControlRegister);
143   ASSERT_EFI_ERROR (Status);
144   mSmiDataRegister = SmmControlRegister.SmiDataRegister;
145 
146   //
147   // Register software SMI handler
148   //
149 
150   Status = SystemTable->BootServices->LocateProtocol (
151                                         &gEfiSmmSwDispatchProtocolGuid,
152                                         NULL,
153                                         (VOID **)&SmmSwDispatch
154                                         );
155   ASSERT_EFI_ERROR (Status);
156 
157   SmmSwDispatchContext.SwSmiInputValue = SMM_FROM_SMBASE_DRIVER;
158   Status = SmmSwDispatch->Register (
159                             SmmSwDispatch,
160                             &SmramSaveInfoHandler,
161                             &SmmSwDispatchContext,
162                             &DispatchHandle
163                             );
164   ASSERT_EFI_ERROR (Status);
165 
166   //
167   // Register SMM Ready To Lock Protocol notification
168   //
169   Status = gSmst->SmmRegisterProtocolNotify (
170                     &gEfiSmmReadyToLockProtocolGuid,
171                     SmmReadyToLockEventNotify,
172                     &Registration
173                     );
174   ASSERT_EFI_ERROR (Status);
175 
176   return Status;
177 }
178 
179