2 PiSmmCommunication PEI Driver.
4 Copyright (c) 2010 - 2021, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
12 #include <Library/PeiServicesTablePointerLib.h>
13 #include <Library/PeiServicesLib.h>
14 #include <Library/BaseLib.h>
15 #include <Library/BaseMemoryLib.h>
16 #include <Library/HobLib.h>
17 #include <Library/DebugLib.h>
18 #include <Protocol/SmmCommunication.h>
19 #include <Ppi/SmmCommunication.h>
20 #include <Ppi/SmmAccess.h>
21 #include <Ppi/SmmControl.h>
22 #include <Guid/AcpiS3Context.h>
24 #include "PiSmmCommunicationPrivate.h"
27 the whole picture is below:
29 +----------------------------------+
31 | SmramDescriptor | <- DRAM
33 +----------------------------------+ |
35 +----------------------------------+<--
36 | SMM_S3_RESUME_STATE |
37 | Signature | <- SMRAM
39 +----------------------------------+ |
41 +----------------------------------+<--
42 | EFI_SMM_SYSTEM_TABLE2 |
43 | NumberOfTableEntries | <- SMRAM
44 | SmmConfigurationTable |---
45 +----------------------------------+ |
47 +----------------------------------+<--
48 | EFI_SMM_COMMUNICATION_CONTEXT |
49 | SwSmiNumber | <- SMRAM
50 | BufferPtrAddress |---
51 +----------------------------------+ |
53 +----------------------------------+<--
54 | Communication Buffer Pointer | <- AcpiNvs
55 +----------------------------------+---
57 +----------------------------------+<--
58 | EFI_SMM_COMMUNICATE_HEADER |
59 | HeaderGuid | <- DRAM
61 +----------------------------------+
65 #if defined (MDE_CPU_IA32)
68 UINT64 SmmFirmwareVendor
;
69 UINT64 SmmFirmwareRevision
;
70 UINT64 SmmInstallConfigurationTable
;
75 UINT64 SmmAllocatePool
;
77 UINT64 SmmAllocatePages
;
79 UINT64 SmmStartupThisAp
;
80 UINT64 CurrentlyExecutingCpu
;
82 UINT64 CpuSaveStateSize
;
84 UINT64 NumberOfTableEntries
;
85 UINT64 SmmConfigurationTable
;
86 } EFI_SMM_SYSTEM_TABLE2_64
;
91 } EFI_CONFIGURATION_TABLE64
;
94 #if defined (MDE_CPU_X64)
95 typedef EFI_SMM_SYSTEM_TABLE2 EFI_SMM_SYSTEM_TABLE2_64
;
96 typedef EFI_CONFIGURATION_TABLE EFI_CONFIGURATION_TABLE64
;
100 Communicates with a registered handler.
102 This function provides a service to send and receive messages from a registered UEFI service.
104 @param[in] This The EFI_PEI_SMM_COMMUNICATION_PPI instance.
105 @param[in, out] CommBuffer A pointer to the buffer to convey into SMRAM.
106 @param[in, out] CommSize The size of the data buffer being passed in.On exit, the size of data
107 being returned. Zero if the handler does not wish to reply with any data.
109 @retval EFI_SUCCESS The message was successfully posted.
110 @retval EFI_INVALID_PARAMETER The CommBuffer was NULL.
111 @retval EFI_NOT_STARTED The service is NOT started.
116 IN CONST EFI_PEI_SMM_COMMUNICATION_PPI
*This
,
117 IN OUT VOID
*CommBuffer
,
118 IN OUT UINTN
*CommSize
121 EFI_PEI_SMM_COMMUNICATION_PPI mSmmCommunicationPpi
= { Communicate
};
123 EFI_PEI_PPI_DESCRIPTOR mPpiList
= {
124 (EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
125 &gEfiPeiSmmCommunicationPpiGuid
,
126 &mSmmCommunicationPpi
130 Get SMM communication context.
132 @return SMM communication context.
134 EFI_SMM_COMMUNICATION_CONTEXT
*
135 GetCommunicationContext (
139 EFI_HOB_GUID_TYPE
*GuidHob
;
140 EFI_SMM_COMMUNICATION_CONTEXT
*SmmCommunicationContext
;
142 GuidHob
= GetFirstGuidHob (&gEfiPeiSmmCommunicationPpiGuid
);
143 ASSERT (GuidHob
!= NULL
);
145 SmmCommunicationContext
= (EFI_SMM_COMMUNICATION_CONTEXT
*)GET_GUID_HOB_DATA (GuidHob
);
147 return SmmCommunicationContext
;
151 Set SMM communication context.
153 @param SmmCommunicationContext SMM communication context.
156 SetCommunicationContext (
157 IN EFI_SMM_COMMUNICATION_CONTEXT
*SmmCommunicationContext
160 EFI_PEI_HOB_POINTERS Hob
;
163 BufferSize
= sizeof (*SmmCommunicationContext
);
164 Hob
.Raw
= BuildGuidHob (
165 &gEfiPeiSmmCommunicationPpiGuid
,
170 CopyMem ((VOID
*)Hob
.Raw
, SmmCommunicationContext
, sizeof (*SmmCommunicationContext
));
174 Get VendorTable by VendorGuid in Smst.
176 @param Signature Signature of SMM_S3_RESUME_STATE
177 @param Smst SMM system table
178 @param VendorGuid vendor guid
180 @return vendor table.
183 InternalSmstGetVendorTableByGuid (
185 IN EFI_SMM_SYSTEM_TABLE2
*Smst
,
186 IN EFI_GUID
*VendorGuid
189 EFI_CONFIGURATION_TABLE
*SmmConfigurationTable
;
190 UINTN NumberOfTableEntries
;
192 EFI_SMM_SYSTEM_TABLE2_64
*Smst64
;
193 EFI_CONFIGURATION_TABLE64
*SmmConfigurationTable64
;
195 if ((sizeof (UINTN
) == sizeof (UINT32
)) && (Signature
== SMM_S3_RESUME_SMM_64
)) {
199 Smst64
= (EFI_SMM_SYSTEM_TABLE2_64
*)Smst
;
200 DEBUG ((DEBUG_INFO
, "InitCommunicationContext - SmmConfigurationTable: %x\n", Smst64
->SmmConfigurationTable
));
201 DEBUG ((DEBUG_INFO
, "InitCommunicationContext - NumberOfTableEntries: %x\n", Smst64
->NumberOfTableEntries
));
202 SmmConfigurationTable64
= (EFI_CONFIGURATION_TABLE64
*)(UINTN
)Smst64
->SmmConfigurationTable
;
203 NumberOfTableEntries
= (UINTN
)Smst64
->NumberOfTableEntries
;
204 for (Index
= 0; Index
< NumberOfTableEntries
; Index
++) {
205 if (CompareGuid (&SmmConfigurationTable64
[Index
].VendorGuid
, VendorGuid
)) {
206 return (VOID
*)(UINTN
)SmmConfigurationTable64
[Index
].VendorTable
;
212 DEBUG ((DEBUG_INFO
, "InitCommunicationContext - SmmConfigurationTable: %x\n", Smst
->SmmConfigurationTable
));
213 DEBUG ((DEBUG_INFO
, "InitCommunicationContext - NumberOfTableEntries: %x\n", Smst
->NumberOfTableEntries
));
214 SmmConfigurationTable
= Smst
->SmmConfigurationTable
;
215 NumberOfTableEntries
= Smst
->NumberOfTableEntries
;
216 for (Index
= 0; Index
< NumberOfTableEntries
; Index
++) {
217 if (CompareGuid (&SmmConfigurationTable
[Index
].VendorGuid
, VendorGuid
)) {
218 return (VOID
*)SmmConfigurationTable
[Index
].VendorTable
;
227 Init SMM communication context.
230 InitCommunicationContext (
234 EFI_SMRAM_DESCRIPTOR
*SmramDescriptor
;
235 SMM_S3_RESUME_STATE
*SmmS3ResumeState
;
237 EFI_SMM_COMMUNICATION_CONTEXT
*SmmCommunicationContext
;
239 GuidHob
= GetFirstGuidHob (&gEfiAcpiVariableGuid
);
240 ASSERT (GuidHob
!= NULL
);
241 SmramDescriptor
= (EFI_SMRAM_DESCRIPTOR
*)GET_GUID_HOB_DATA (GuidHob
);
242 SmmS3ResumeState
= (SMM_S3_RESUME_STATE
*)(UINTN
)SmramDescriptor
->CpuStart
;
244 DEBUG ((DEBUG_INFO
, "InitCommunicationContext - SmmS3ResumeState: %x\n", SmmS3ResumeState
));
245 DEBUG ((DEBUG_INFO
, "InitCommunicationContext - Smst: %x\n", SmmS3ResumeState
->Smst
));
247 SmmCommunicationContext
= (EFI_SMM_COMMUNICATION_CONTEXT
*)InternalSmstGetVendorTableByGuid (
248 SmmS3ResumeState
->Signature
,
249 (EFI_SMM_SYSTEM_TABLE2
*)(UINTN
)SmmS3ResumeState
->Smst
,
250 &gEfiPeiSmmCommunicationPpiGuid
252 ASSERT (SmmCommunicationContext
!= NULL
);
254 SetCommunicationContext (SmmCommunicationContext
);
260 Communicates with a registered handler.
262 This function provides a service to send and receive messages from a registered UEFI service.
264 @param[in] This The EFI_PEI_SMM_COMMUNICATION_PPI instance.
265 @param[in, out] CommBuffer A pointer to the buffer to convey into SMRAM.
266 @param[in, out] CommSize The size of the data buffer being passed in.On exit, the size of data
267 being returned. Zero if the handler does not wish to reply with any data.
269 @retval EFI_SUCCESS The message was successfully posted.
270 @retval EFI_INVALID_PARAMETER The CommBuffer was NULL.
271 @retval EFI_NOT_STARTED The service is NOT started.
276 IN CONST EFI_PEI_SMM_COMMUNICATION_PPI
*This
,
277 IN OUT VOID
*CommBuffer
,
278 IN OUT UINTN
*CommSize
282 PEI_SMM_CONTROL_PPI
*SmmControl
;
283 PEI_SMM_ACCESS_PPI
*SmmAccess
;
286 EFI_SMM_COMMUNICATION_CONTEXT
*SmmCommunicationContext
;
288 DEBUG ((DEBUG_INFO
, "PiSmmCommunicationPei Communicate Enter\n"));
290 if (CommBuffer
== NULL
) {
291 return EFI_INVALID_PARAMETER
;
295 // Get needed resource
297 Status
= PeiServicesLocatePpi (
298 &gPeiSmmControlPpiGuid
,
303 if (EFI_ERROR (Status
)) {
304 return EFI_NOT_STARTED
;
307 Status
= PeiServicesLocatePpi (
308 &gPeiSmmAccessPpiGuid
,
313 if (EFI_ERROR (Status
)) {
314 return EFI_NOT_STARTED
;
318 // Check SMRAM locked, it should be done after SMRAM lock.
320 if (!SmmAccess
->LockState
) {
321 DEBUG ((DEBUG_INFO
, "PiSmmCommunicationPei LockState - %x\n", (UINTN
)SmmAccess
->LockState
));
322 return EFI_NOT_STARTED
;
325 SmmCommunicationContext
= GetCommunicationContext ();
326 DEBUG ((DEBUG_INFO
, "PiSmmCommunicationPei BufferPtrAddress - 0x%016lx, BufferPtr: 0x%016lx\n", SmmCommunicationContext
->BufferPtrAddress
, *(EFI_PHYSICAL_ADDRESS
*)(UINTN
)SmmCommunicationContext
->BufferPtrAddress
));
329 // No need to check if BufferPtr is 0, because it is in PEI phase.
331 *(EFI_PHYSICAL_ADDRESS
*)(UINTN
)SmmCommunicationContext
->BufferPtrAddress
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)CommBuffer
;
332 DEBUG ((DEBUG_INFO
, "PiSmmCommunicationPei CommBuffer - %x\n", (UINTN
)CommBuffer
));
337 SmiCommand
= (UINT8
)SmmCommunicationContext
->SwSmiNumber
;
338 Size
= sizeof (SmiCommand
);
339 Status
= SmmControl
->Trigger (
340 (EFI_PEI_SERVICES
**)GetPeiServicesTablePointer (),
347 ASSERT_EFI_ERROR (Status
);
350 // Setting BufferPtr to 0 means this transaction is done.
352 *(EFI_PHYSICAL_ADDRESS
*)(UINTN
)SmmCommunicationContext
->BufferPtrAddress
= 0;
354 DEBUG ((DEBUG_INFO
, "PiSmmCommunicationPei Communicate Exit\n"));
360 Entry Point for PI SMM communication PEIM.
362 @param FileHandle Handle of the file being invoked.
363 @param PeiServices Pointer to PEI Services table.
366 @return Others Some error occurs.
370 PiSmmCommunicationPeiEntryPoint (
371 IN EFI_PEI_FILE_HANDLE FileHandle
,
372 IN CONST EFI_PEI_SERVICES
**PeiServices
376 PEI_SMM_ACCESS_PPI
*SmmAccess
;
377 EFI_BOOT_MODE BootMode
;
380 BootMode
= GetBootModeHob ();
381 if (BootMode
!= BOOT_ON_S3_RESUME
) {
382 return EFI_UNSUPPORTED
;
385 Status
= PeiServicesLocatePpi (
386 &gPeiSmmAccessPpiGuid
,
391 if (EFI_ERROR (Status
)) {
392 return EFI_NOT_STARTED
;
396 // Check SMRAM locked, it should be done before SMRAM lock.
398 if (SmmAccess
->LockState
) {
399 DEBUG ((DEBUG_INFO
, "PiSmmCommunicationPei LockState - %x\n", (UINTN
)SmmAccess
->LockState
));
400 return EFI_ACCESS_DENIED
;
406 for (Index
= 0; !EFI_ERROR (Status
); Index
++) {
407 Status
= SmmAccess
->Open ((EFI_PEI_SERVICES
**)GetPeiServicesTablePointer (), SmmAccess
, Index
);
410 InitCommunicationContext ();
412 PeiServicesInstallPpi (&mPpiList
);
414 return RETURN_SUCCESS
;