2 PiSmmCommunication PEI Driver.
4 Copyright (c) 2010 - 2015, 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 | EFI_SMM_COMMUNICATION_ACPI_TABLE | |
55 | SwSmiNumber | <- AcpiTable |
56 | BufferPtrAddress |--- |
57 +----------------------------------+ | |
59 +----------------------------------+<---------------
60 | Communication Buffer Pointer | <- AcpiNvs
61 +----------------------------------+---
63 +----------------------------------+<--
64 | EFI_SMM_COMMUNICATE_HEADER |
65 | HeaderGuid | <- DRAM
67 +----------------------------------+
71 #if defined (MDE_CPU_IA32)
74 UINT64 SmmFirmwareVendor
;
75 UINT64 SmmFirmwareRevision
;
76 UINT64 SmmInstallConfigurationTable
;
81 UINT64 SmmAllocatePool
;
83 UINT64 SmmAllocatePages
;
85 UINT64 SmmStartupThisAp
;
86 UINT64 CurrentlyExecutingCpu
;
88 UINT64 CpuSaveStateSize
;
90 UINT64 NumberOfTableEntries
;
91 UINT64 SmmConfigurationTable
;
92 } EFI_SMM_SYSTEM_TABLE2_64
;
97 } EFI_CONFIGURATION_TABLE64
;
100 #if defined (MDE_CPU_X64)
101 typedef EFI_SMM_SYSTEM_TABLE2 EFI_SMM_SYSTEM_TABLE2_64
;
102 typedef EFI_CONFIGURATION_TABLE EFI_CONFIGURATION_TABLE64
;
106 Communicates with a registered handler.
108 This function provides a service to send and receive messages from a registered UEFI service.
110 @param[in] This The EFI_PEI_SMM_COMMUNICATION_PPI instance.
111 @param[in, out] CommBuffer A pointer to the buffer to convey into SMRAM.
112 @param[in, out] CommSize The size of the data buffer being passed in.On exit, the size of data
113 being returned. Zero if the handler does not wish to reply with any data.
115 @retval EFI_SUCCESS The message was successfully posted.
116 @retval EFI_INVALID_PARAMETER The CommBuffer was NULL.
117 @retval EFI_NOT_STARTED The service is NOT started.
122 IN CONST EFI_PEI_SMM_COMMUNICATION_PPI
*This
,
123 IN OUT VOID
*CommBuffer
,
124 IN OUT UINTN
*CommSize
127 EFI_PEI_SMM_COMMUNICATION_PPI mSmmCommunicationPpi
= { Communicate
};
129 EFI_PEI_PPI_DESCRIPTOR mPpiList
= {
130 (EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
131 &gEfiPeiSmmCommunicationPpiGuid
,
132 &mSmmCommunicationPpi
136 Get SMM communication context.
138 @return SMM communication context.
140 EFI_SMM_COMMUNICATION_CONTEXT
*
141 GetCommunicationContext (
145 EFI_HOB_GUID_TYPE
*GuidHob
;
146 EFI_SMM_COMMUNICATION_CONTEXT
*SmmCommunicationContext
;
148 GuidHob
= GetFirstGuidHob (&gEfiPeiSmmCommunicationPpiGuid
);
149 ASSERT (GuidHob
!= NULL
);
151 SmmCommunicationContext
= (EFI_SMM_COMMUNICATION_CONTEXT
*)GET_GUID_HOB_DATA (GuidHob
);
153 return SmmCommunicationContext
;
157 Set SMM communication context.
159 @param SmmCommunicationContext SMM communication context.
162 SetCommunicationContext (
163 IN EFI_SMM_COMMUNICATION_CONTEXT
*SmmCommunicationContext
166 EFI_PEI_HOB_POINTERS Hob
;
169 BufferSize
= sizeof (*SmmCommunicationContext
);
170 Hob
.Raw
= BuildGuidHob (
171 &gEfiPeiSmmCommunicationPpiGuid
,
176 CopyMem ((VOID
*)Hob
.Raw
, SmmCommunicationContext
, sizeof(*SmmCommunicationContext
));
180 Get VendorTable by VendorGuid in Smst.
182 @param Signature Signature of SMM_S3_RESUME_STATE
183 @param Smst SMM system table
184 @param VendorGuid vendor guid
186 @return vendor table.
189 InternalSmstGetVendorTableByGuid (
191 IN EFI_SMM_SYSTEM_TABLE2
*Smst
,
192 IN EFI_GUID
*VendorGuid
195 EFI_CONFIGURATION_TABLE
*SmmConfigurationTable
;
196 UINTN NumberOfTableEntries
;
198 EFI_SMM_SYSTEM_TABLE2_64
*Smst64
;
199 EFI_CONFIGURATION_TABLE64
*SmmConfigurationTable64
;
201 if ((sizeof(UINTN
) == sizeof(UINT32
)) && (Signature
== SMM_S3_RESUME_SMM_64
)) {
205 Smst64
= (EFI_SMM_SYSTEM_TABLE2_64
*)Smst
;
206 DEBUG ((EFI_D_INFO
, "InitCommunicationContext - SmmConfigurationTable: %x\n", Smst64
->SmmConfigurationTable
));
207 DEBUG ((EFI_D_INFO
, "InitCommunicationContext - NumberOfTableEntries: %x\n", Smst64
->NumberOfTableEntries
));
208 SmmConfigurationTable64
= (EFI_CONFIGURATION_TABLE64
*)(UINTN
)Smst64
->SmmConfigurationTable
;
209 NumberOfTableEntries
= (UINTN
)Smst64
->NumberOfTableEntries
;
210 for (Index
= 0; Index
< NumberOfTableEntries
; Index
++) {
211 if (CompareGuid (&SmmConfigurationTable64
[Index
].VendorGuid
, VendorGuid
)) {
212 return (VOID
*)(UINTN
)SmmConfigurationTable64
[Index
].VendorTable
;
217 DEBUG ((EFI_D_INFO
, "InitCommunicationContext - SmmConfigurationTable: %x\n", Smst
->SmmConfigurationTable
));
218 DEBUG ((EFI_D_INFO
, "InitCommunicationContext - NumberOfTableEntries: %x\n", Smst
->NumberOfTableEntries
));
219 SmmConfigurationTable
= Smst
->SmmConfigurationTable
;
220 NumberOfTableEntries
= Smst
->NumberOfTableEntries
;
221 for (Index
= 0; Index
< NumberOfTableEntries
; Index
++) {
222 if (CompareGuid (&SmmConfigurationTable
[Index
].VendorGuid
, VendorGuid
)) {
223 return (VOID
*)SmmConfigurationTable
[Index
].VendorTable
;
231 Init SMM communication context.
234 InitCommunicationContext (
238 EFI_SMRAM_DESCRIPTOR
*SmramDescriptor
;
239 SMM_S3_RESUME_STATE
*SmmS3ResumeState
;
241 EFI_SMM_COMMUNICATION_CONTEXT
*SmmCommunicationContext
;
243 GuidHob
= GetFirstGuidHob (&gEfiAcpiVariableGuid
);
244 ASSERT (GuidHob
!= NULL
);
245 SmramDescriptor
= (EFI_SMRAM_DESCRIPTOR
*) GET_GUID_HOB_DATA (GuidHob
);
246 SmmS3ResumeState
= (SMM_S3_RESUME_STATE
*)(UINTN
)SmramDescriptor
->CpuStart
;
248 DEBUG ((EFI_D_INFO
, "InitCommunicationContext - SmmS3ResumeState: %x\n", SmmS3ResumeState
));
249 DEBUG ((EFI_D_INFO
, "InitCommunicationContext - Smst: %x\n", SmmS3ResumeState
->Smst
));
251 SmmCommunicationContext
= (EFI_SMM_COMMUNICATION_CONTEXT
*)InternalSmstGetVendorTableByGuid (
252 SmmS3ResumeState
->Signature
,
253 (EFI_SMM_SYSTEM_TABLE2
*)(UINTN
)SmmS3ResumeState
->Smst
,
254 &gEfiPeiSmmCommunicationPpiGuid
256 ASSERT (SmmCommunicationContext
!= NULL
);
258 SetCommunicationContext (SmmCommunicationContext
);
264 Communicates with a registered handler.
266 This function provides a service to send and receive messages from a registered UEFI service.
268 @param[in] This The EFI_PEI_SMM_COMMUNICATION_PPI instance.
269 @param[in, out] CommBuffer A pointer to the buffer to convey into SMRAM.
270 @param[in, out] CommSize The size of the data buffer being passed in.On exit, the size of data
271 being returned. Zero if the handler does not wish to reply with any data.
273 @retval EFI_SUCCESS The message was successfully posted.
274 @retval EFI_INVALID_PARAMETER The CommBuffer was NULL.
275 @retval EFI_NOT_STARTED The service is NOT started.
280 IN CONST EFI_PEI_SMM_COMMUNICATION_PPI
*This
,
281 IN OUT VOID
*CommBuffer
,
282 IN OUT UINTN
*CommSize
286 PEI_SMM_CONTROL_PPI
*SmmControl
;
287 PEI_SMM_ACCESS_PPI
*SmmAccess
;
290 EFI_SMM_COMMUNICATION_CONTEXT
*SmmCommunicationContext
;
292 DEBUG ((EFI_D_INFO
, "PiSmmCommunicationPei Communicate Enter\n"));
294 if (CommBuffer
== NULL
) {
295 return EFI_INVALID_PARAMETER
;
299 // Get needed resource
301 Status
= PeiServicesLocatePpi (
302 &gPeiSmmControlPpiGuid
,
307 if (EFI_ERROR (Status
)) {
308 return EFI_NOT_STARTED
;
311 Status
= PeiServicesLocatePpi (
312 &gPeiSmmAccessPpiGuid
,
317 if (EFI_ERROR (Status
)) {
318 return EFI_NOT_STARTED
;
322 // Check SMRAM locked, it should be done after SMRAM lock.
324 if (!SmmAccess
->LockState
) {
325 DEBUG ((EFI_D_INFO
, "PiSmmCommunicationPei LockState - %x\n", (UINTN
)SmmAccess
->LockState
));
326 return EFI_NOT_STARTED
;
329 SmmCommunicationContext
= GetCommunicationContext ();
330 DEBUG ((EFI_D_INFO
, "PiSmmCommunicationPei BufferPtrAddress - 0x%016lx, BufferPtr: 0x%016lx\n", SmmCommunicationContext
->BufferPtrAddress
, *(EFI_PHYSICAL_ADDRESS
*)(UINTN
)SmmCommunicationContext
->BufferPtrAddress
));
333 // No need to check if BufferPtr is 0, because it is in PEI phase.
335 *(EFI_PHYSICAL_ADDRESS
*)(UINTN
)SmmCommunicationContext
->BufferPtrAddress
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)CommBuffer
;
336 DEBUG ((EFI_D_INFO
, "PiSmmCommunicationPei CommBuffer - %x\n", (UINTN
)CommBuffer
));
341 SmiCommand
= (UINT8
)SmmCommunicationContext
->SwSmiNumber
;
342 Size
= sizeof(SmiCommand
);
343 Status
= SmmControl
->Trigger (
344 (EFI_PEI_SERVICES
**)GetPeiServicesTablePointer (),
351 ASSERT_EFI_ERROR (Status
);
354 // Setting BufferPtr to 0 means this transaction is done.
356 *(EFI_PHYSICAL_ADDRESS
*)(UINTN
)SmmCommunicationContext
->BufferPtrAddress
= 0;
358 DEBUG ((EFI_D_INFO
, "PiSmmCommunicationPei Communicate Exit\n"));
364 Entry Point for PI SMM communication PEIM.
366 @param FileHandle Handle of the file being invoked.
367 @param PeiServices Pointer to PEI Services table.
370 @return Others Some error occurs.
374 PiSmmCommunicationPeiEntryPoint (
375 IN EFI_PEI_FILE_HANDLE FileHandle
,
376 IN CONST EFI_PEI_SERVICES
**PeiServices
380 PEI_SMM_ACCESS_PPI
*SmmAccess
;
381 EFI_BOOT_MODE BootMode
;
384 BootMode
= GetBootModeHob ();
385 if (BootMode
!= BOOT_ON_S3_RESUME
) {
386 return EFI_UNSUPPORTED
;
389 Status
= PeiServicesLocatePpi (
390 &gPeiSmmAccessPpiGuid
,
395 if (EFI_ERROR (Status
)) {
396 return EFI_NOT_STARTED
;
400 // Check SMRAM locked, it should be done before SMRAM lock.
402 if (SmmAccess
->LockState
) {
403 DEBUG ((EFI_D_INFO
, "PiSmmCommunicationPei LockState - %x\n", (UINTN
)SmmAccess
->LockState
));
404 return EFI_ACCESS_DENIED
;
410 for (Index
= 0; !EFI_ERROR (Status
); Index
++) {
411 Status
= SmmAccess
->Open ((EFI_PEI_SERVICES
**)GetPeiServicesTablePointer (), SmmAccess
, Index
);
414 InitCommunicationContext ();
416 PeiServicesInstallPpi (&mPpiList
);
418 return RETURN_SUCCESS
;