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 ((EFI_D_INFO
, "InitCommunicationContext - SmmConfigurationTable: %x\n", Smst64
->SmmConfigurationTable
));
201 DEBUG ((EFI_D_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
;
211 DEBUG ((EFI_D_INFO
, "InitCommunicationContext - SmmConfigurationTable: %x\n", Smst
->SmmConfigurationTable
));
212 DEBUG ((EFI_D_INFO
, "InitCommunicationContext - NumberOfTableEntries: %x\n", Smst
->NumberOfTableEntries
));
213 SmmConfigurationTable
= Smst
->SmmConfigurationTable
;
214 NumberOfTableEntries
= Smst
->NumberOfTableEntries
;
215 for (Index
= 0; Index
< NumberOfTableEntries
; Index
++) {
216 if (CompareGuid (&SmmConfigurationTable
[Index
].VendorGuid
, VendorGuid
)) {
217 return (VOID
*)SmmConfigurationTable
[Index
].VendorTable
;
225 Init SMM communication context.
228 InitCommunicationContext (
232 EFI_SMRAM_DESCRIPTOR
*SmramDescriptor
;
233 SMM_S3_RESUME_STATE
*SmmS3ResumeState
;
235 EFI_SMM_COMMUNICATION_CONTEXT
*SmmCommunicationContext
;
237 GuidHob
= GetFirstGuidHob (&gEfiAcpiVariableGuid
);
238 ASSERT (GuidHob
!= NULL
);
239 SmramDescriptor
= (EFI_SMRAM_DESCRIPTOR
*) GET_GUID_HOB_DATA (GuidHob
);
240 SmmS3ResumeState
= (SMM_S3_RESUME_STATE
*)(UINTN
)SmramDescriptor
->CpuStart
;
242 DEBUG ((EFI_D_INFO
, "InitCommunicationContext - SmmS3ResumeState: %x\n", SmmS3ResumeState
));
243 DEBUG ((EFI_D_INFO
, "InitCommunicationContext - Smst: %x\n", SmmS3ResumeState
->Smst
));
245 SmmCommunicationContext
= (EFI_SMM_COMMUNICATION_CONTEXT
*)InternalSmstGetVendorTableByGuid (
246 SmmS3ResumeState
->Signature
,
247 (EFI_SMM_SYSTEM_TABLE2
*)(UINTN
)SmmS3ResumeState
->Smst
,
248 &gEfiPeiSmmCommunicationPpiGuid
250 ASSERT (SmmCommunicationContext
!= NULL
);
252 SetCommunicationContext (SmmCommunicationContext
);
258 Communicates with a registered handler.
260 This function provides a service to send and receive messages from a registered UEFI service.
262 @param[in] This The EFI_PEI_SMM_COMMUNICATION_PPI instance.
263 @param[in, out] CommBuffer A pointer to the buffer to convey into SMRAM.
264 @param[in, out] CommSize The size of the data buffer being passed in.On exit, the size of data
265 being returned. Zero if the handler does not wish to reply with any data.
267 @retval EFI_SUCCESS The message was successfully posted.
268 @retval EFI_INVALID_PARAMETER The CommBuffer was NULL.
269 @retval EFI_NOT_STARTED The service is NOT started.
274 IN CONST EFI_PEI_SMM_COMMUNICATION_PPI
*This
,
275 IN OUT VOID
*CommBuffer
,
276 IN OUT UINTN
*CommSize
280 PEI_SMM_CONTROL_PPI
*SmmControl
;
281 PEI_SMM_ACCESS_PPI
*SmmAccess
;
284 EFI_SMM_COMMUNICATION_CONTEXT
*SmmCommunicationContext
;
286 DEBUG ((EFI_D_INFO
, "PiSmmCommunicationPei Communicate Enter\n"));
288 if (CommBuffer
== NULL
) {
289 return EFI_INVALID_PARAMETER
;
293 // Get needed resource
295 Status
= PeiServicesLocatePpi (
296 &gPeiSmmControlPpiGuid
,
301 if (EFI_ERROR (Status
)) {
302 return EFI_NOT_STARTED
;
305 Status
= PeiServicesLocatePpi (
306 &gPeiSmmAccessPpiGuid
,
311 if (EFI_ERROR (Status
)) {
312 return EFI_NOT_STARTED
;
316 // Check SMRAM locked, it should be done after SMRAM lock.
318 if (!SmmAccess
->LockState
) {
319 DEBUG ((EFI_D_INFO
, "PiSmmCommunicationPei LockState - %x\n", (UINTN
)SmmAccess
->LockState
));
320 return EFI_NOT_STARTED
;
323 SmmCommunicationContext
= GetCommunicationContext ();
324 DEBUG ((EFI_D_INFO
, "PiSmmCommunicationPei BufferPtrAddress - 0x%016lx, BufferPtr: 0x%016lx\n", SmmCommunicationContext
->BufferPtrAddress
, *(EFI_PHYSICAL_ADDRESS
*)(UINTN
)SmmCommunicationContext
->BufferPtrAddress
));
327 // No need to check if BufferPtr is 0, because it is in PEI phase.
329 *(EFI_PHYSICAL_ADDRESS
*)(UINTN
)SmmCommunicationContext
->BufferPtrAddress
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)CommBuffer
;
330 DEBUG ((EFI_D_INFO
, "PiSmmCommunicationPei CommBuffer - %x\n", (UINTN
)CommBuffer
));
335 SmiCommand
= (UINT8
)SmmCommunicationContext
->SwSmiNumber
;
336 Size
= sizeof(SmiCommand
);
337 Status
= SmmControl
->Trigger (
338 (EFI_PEI_SERVICES
**)GetPeiServicesTablePointer (),
345 ASSERT_EFI_ERROR (Status
);
348 // Setting BufferPtr to 0 means this transaction is done.
350 *(EFI_PHYSICAL_ADDRESS
*)(UINTN
)SmmCommunicationContext
->BufferPtrAddress
= 0;
352 DEBUG ((EFI_D_INFO
, "PiSmmCommunicationPei Communicate Exit\n"));
358 Entry Point for PI SMM communication PEIM.
360 @param FileHandle Handle of the file being invoked.
361 @param PeiServices Pointer to PEI Services table.
364 @return Others Some error occurs.
368 PiSmmCommunicationPeiEntryPoint (
369 IN EFI_PEI_FILE_HANDLE FileHandle
,
370 IN CONST EFI_PEI_SERVICES
**PeiServices
374 PEI_SMM_ACCESS_PPI
*SmmAccess
;
375 EFI_BOOT_MODE BootMode
;
378 BootMode
= GetBootModeHob ();
379 if (BootMode
!= BOOT_ON_S3_RESUME
) {
380 return EFI_UNSUPPORTED
;
383 Status
= PeiServicesLocatePpi (
384 &gPeiSmmAccessPpiGuid
,
389 if (EFI_ERROR (Status
)) {
390 return EFI_NOT_STARTED
;
394 // Check SMRAM locked, it should be done before SMRAM lock.
396 if (SmmAccess
->LockState
) {
397 DEBUG ((EFI_D_INFO
, "PiSmmCommunicationPei LockState - %x\n", (UINTN
)SmmAccess
->LockState
));
398 return EFI_ACCESS_DENIED
;
404 for (Index
= 0; !EFI_ERROR (Status
); Index
++) {
405 Status
= SmmAccess
->Open ((EFI_PEI_SERVICES
**)GetPeiServicesTablePointer (), SmmAccess
, Index
);
408 InitCommunicationContext ();
410 PeiServicesInstallPpi (&mPpiList
);
412 return RETURN_SUCCESS
;