2 PiSmmCommunication PEI Driver.
4 Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 #include <Library/PeiServicesTablePointerLib.h>
19 #include <Library/PeiServicesLib.h>
20 #include <Library/BaseLib.h>
21 #include <Library/BaseMemoryLib.h>
22 #include <Library/HobLib.h>
23 #include <Library/DebugLib.h>
24 #include <Protocol/SmmCommunication.h>
25 #include <Ppi/SmmCommunication.h>
26 #include <Ppi/SmmAccess.h>
27 #include <Ppi/SmmControl.h>
28 #include <Guid/AcpiS3Context.h>
30 #include "PiSmmCommunicationPrivate.h"
33 the whole picture is below:
35 +----------------------------------+
37 | SmramDescriptor | <- DRAM
39 +----------------------------------+ |
41 +----------------------------------+<--
42 | SMM_S3_RESUME_STATE |
43 | Signature | <- SMRAM
45 +----------------------------------+ |
47 +----------------------------------+<--
48 | EFI_SMM_SYSTEM_TABLE2 |
49 | NumberOfTableEntries | <- SMRAM
50 | SmmConfigurationTable |---
51 +----------------------------------+ |
53 +----------------------------------+<--
54 | EFI_SMM_COMMUNICATION_CONTEXT |
55 | SwSmiNumber | <- SMRAM
56 | BufferPtrAddress |----------------
57 +----------------------------------+ |
59 +----------------------------------+ |
60 | EFI_SMM_COMMUNICATION_ACPI_TABLE | |
61 | SwSmiNumber | <- AcpiTable |
62 | BufferPtrAddress |--- |
63 +----------------------------------+ | |
65 +----------------------------------+<---------------
66 | Communication Buffer Pointer | <- AcpiNvs
67 +----------------------------------+---
69 +----------------------------------+<--
70 | EFI_SMM_COMMUNICATE_HEADER |
71 | HeaderGuid | <- DRAM
73 +----------------------------------+
77 #if defined (MDE_CPU_IA32)
80 UINT64 SmmFirmwareVendor
;
81 UINT64 SmmFirmwareRevision
;
82 UINT64 SmmInstallConfigurationTable
;
87 UINT64 SmmAllocatePool
;
89 UINT64 SmmAllocatePages
;
91 UINT64 SmmStartupThisAp
;
92 UINT64 CurrentlyExecutingCpu
;
94 UINT64 CpuSaveStateSize
;
96 UINT64 NumberOfTableEntries
;
97 UINT64 SmmConfigurationTable
;
98 } EFI_SMM_SYSTEM_TABLE2_64
;
103 } EFI_CONFIGURATION_TABLE64
;
106 #if defined (MDE_CPU_X64)
107 typedef EFI_SMM_SYSTEM_TABLE2 EFI_SMM_SYSTEM_TABLE2_64
;
108 typedef EFI_CONFIGURATION_TABLE EFI_CONFIGURATION_TABLE64
;
112 Communicates with a registered handler.
114 This function provides a service to send and receive messages from a registered UEFI service.
116 @param[in] This The EFI_PEI_SMM_COMMUNICATION_PPI instance.
117 @param[in, out] CommBuffer A pointer to the buffer to convey into SMRAM.
118 @param[in, out] CommSize The size of the data buffer being passed in.On exit, the size of data
119 being returned. Zero if the handler does not wish to reply with any data.
121 @retval EFI_SUCCESS The message was successfully posted.
122 @retval EFI_INVALID_PARAMETER The CommBuffer was NULL.
123 @retval EFI_NOT_STARTED The service is NOT started.
128 IN CONST EFI_PEI_SMM_COMMUNICATION_PPI
*This
,
129 IN OUT VOID
*CommBuffer
,
130 IN OUT UINTN
*CommSize
133 EFI_PEI_SMM_COMMUNICATION_PPI mSmmCommunicationPpi
= { Communicate
};
135 EFI_PEI_PPI_DESCRIPTOR mPpiList
= {
136 (EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
137 &gEfiPeiSmmCommunicationPpiGuid
,
138 &mSmmCommunicationPpi
142 Get SMM communication context.
144 @return SMM communication context.
146 EFI_SMM_COMMUNICATION_CONTEXT
*
147 GetCommunicationContext (
151 EFI_HOB_GUID_TYPE
*GuidHob
;
152 EFI_SMM_COMMUNICATION_CONTEXT
*SmmCommunicationContext
;
154 GuidHob
= GetFirstGuidHob (&gEfiPeiSmmCommunicationPpiGuid
);
155 ASSERT (GuidHob
!= NULL
);
157 SmmCommunicationContext
= (EFI_SMM_COMMUNICATION_CONTEXT
*)GET_GUID_HOB_DATA (GuidHob
);
159 return SmmCommunicationContext
;
163 Set SMM communication context.
165 @param SmmCommunicationContext SMM communication context.
168 SetCommunicationContext (
169 IN EFI_SMM_COMMUNICATION_CONTEXT
*SmmCommunicationContext
172 EFI_PEI_HOB_POINTERS Hob
;
175 BufferSize
= sizeof (*SmmCommunicationContext
);
176 Hob
.Raw
= BuildGuidHob (
177 &gEfiPeiSmmCommunicationPpiGuid
,
182 CopyMem ((VOID
*)Hob
.Raw
, SmmCommunicationContext
, sizeof(*SmmCommunicationContext
));
186 Get VendorTable by VendorGuid in Smst.
188 @param Signature Signature of SMM_S3_RESUME_STATE
189 @param Smst SMM system table
190 @param VendorGuid vendor guid
192 @return vendor table.
195 InternalSmstGetVendorTableByGuid (
197 IN EFI_SMM_SYSTEM_TABLE2
*Smst
,
198 IN EFI_GUID
*VendorGuid
201 EFI_CONFIGURATION_TABLE
*SmmConfigurationTable
;
202 UINTN NumberOfTableEntries
;
204 EFI_SMM_SYSTEM_TABLE2_64
*Smst64
;
205 EFI_CONFIGURATION_TABLE64
*SmmConfigurationTable64
;
207 if ((sizeof(UINTN
) == sizeof(UINT32
)) && (Signature
== SMM_S3_RESUME_SMM_64
)) {
211 Smst64
= (EFI_SMM_SYSTEM_TABLE2_64
*)Smst
;
212 DEBUG ((EFI_D_INFO
, "InitCommunicationContext - SmmConfigurationTable: %x\n", Smst64
->SmmConfigurationTable
));
213 DEBUG ((EFI_D_INFO
, "InitCommunicationContext - NumberOfTableEntries: %x\n", Smst64
->NumberOfTableEntries
));
214 SmmConfigurationTable64
= (EFI_CONFIGURATION_TABLE64
*)(UINTN
)Smst64
->SmmConfigurationTable
;
215 NumberOfTableEntries
= (UINTN
)Smst64
->NumberOfTableEntries
;
216 for (Index
= 0; Index
< NumberOfTableEntries
; Index
++) {
217 if (CompareGuid (&SmmConfigurationTable64
[Index
].VendorGuid
, VendorGuid
)) {
218 return (VOID
*)(UINTN
)SmmConfigurationTable64
[Index
].VendorTable
;
223 DEBUG ((EFI_D_INFO
, "InitCommunicationContext - SmmConfigurationTable: %x\n", Smst
->SmmConfigurationTable
));
224 DEBUG ((EFI_D_INFO
, "InitCommunicationContext - NumberOfTableEntries: %x\n", Smst
->NumberOfTableEntries
));
225 SmmConfigurationTable
= Smst
->SmmConfigurationTable
;
226 NumberOfTableEntries
= Smst
->NumberOfTableEntries
;
227 for (Index
= 0; Index
< NumberOfTableEntries
; Index
++) {
228 if (CompareGuid (&SmmConfigurationTable
[Index
].VendorGuid
, VendorGuid
)) {
229 return (VOID
*)SmmConfigurationTable
[Index
].VendorTable
;
237 Init SMM communication context.
240 InitCommunicationContext (
244 EFI_SMRAM_DESCRIPTOR
*SmramDescriptor
;
245 SMM_S3_RESUME_STATE
*SmmS3ResumeState
;
247 EFI_SMM_COMMUNICATION_CONTEXT
*SmmCommunicationContext
;
249 GuidHob
= GetFirstGuidHob (&gEfiAcpiVariableGuid
);
250 ASSERT (GuidHob
!= NULL
);
251 SmramDescriptor
= (EFI_SMRAM_DESCRIPTOR
*) GET_GUID_HOB_DATA (GuidHob
);
252 SmmS3ResumeState
= (SMM_S3_RESUME_STATE
*)(UINTN
)SmramDescriptor
->CpuStart
;
254 DEBUG ((EFI_D_INFO
, "InitCommunicationContext - SmmS3ResumeState: %x\n", SmmS3ResumeState
));
255 DEBUG ((EFI_D_INFO
, "InitCommunicationContext - Smst: %x\n", SmmS3ResumeState
->Smst
));
257 SmmCommunicationContext
= (EFI_SMM_COMMUNICATION_CONTEXT
*)InternalSmstGetVendorTableByGuid (
258 SmmS3ResumeState
->Signature
,
259 (EFI_SMM_SYSTEM_TABLE2
*)(UINTN
)SmmS3ResumeState
->Smst
,
260 &gEfiPeiSmmCommunicationPpiGuid
262 ASSERT (SmmCommunicationContext
!= NULL
);
264 SetCommunicationContext (SmmCommunicationContext
);
270 Communicates with a registered handler.
272 This function provides a service to send and receive messages from a registered UEFI service.
274 @param[in] This The EFI_PEI_SMM_COMMUNICATION_PPI instance.
275 @param[in, out] CommBuffer A pointer to the buffer to convey into SMRAM.
276 @param[in, out] CommSize The size of the data buffer being passed in.On exit, the size of data
277 being returned. Zero if the handler does not wish to reply with any data.
279 @retval EFI_SUCCESS The message was successfully posted.
280 @retval EFI_INVALID_PARAMETER The CommBuffer was NULL.
281 @retval EFI_NOT_STARTED The service is NOT started.
286 IN CONST EFI_PEI_SMM_COMMUNICATION_PPI
*This
,
287 IN OUT VOID
*CommBuffer
,
288 IN OUT UINTN
*CommSize
292 PEI_SMM_CONTROL_PPI
*SmmControl
;
293 PEI_SMM_ACCESS_PPI
*SmmAccess
;
296 EFI_SMM_COMMUNICATION_CONTEXT
*SmmCommunicationContext
;
298 DEBUG ((EFI_D_INFO
, "PiSmmCommunicationPei Communicate Enter\n"));
300 if (CommBuffer
== NULL
) {
301 return EFI_INVALID_PARAMETER
;
305 // Get needed resource
307 Status
= PeiServicesLocatePpi (
308 &gPeiSmmControlPpiGuid
,
313 if (EFI_ERROR (Status
)) {
314 return EFI_NOT_STARTED
;
317 Status
= PeiServicesLocatePpi (
318 &gPeiSmmAccessPpiGuid
,
323 if (EFI_ERROR (Status
)) {
324 return EFI_NOT_STARTED
;
328 // Check SMRAM locked, it should be done after SMRAM lock.
330 if (!SmmAccess
->LockState
) {
331 DEBUG ((EFI_D_INFO
, "PiSmmCommunicationPei LockState - %x\n", (UINTN
)SmmAccess
->LockState
));
332 return EFI_NOT_STARTED
;
335 SmmCommunicationContext
= GetCommunicationContext ();
336 DEBUG ((EFI_D_INFO
, "PiSmmCommunicationPei BufferPtrAddress - 0x%016lx, BufferPtr: 0x%016lx\n", SmmCommunicationContext
->BufferPtrAddress
, *(EFI_PHYSICAL_ADDRESS
*)(UINTN
)SmmCommunicationContext
->BufferPtrAddress
));
339 // No need to check if BufferPtr is 0, because it is in PEI phase.
341 *(EFI_PHYSICAL_ADDRESS
*)(UINTN
)SmmCommunicationContext
->BufferPtrAddress
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)CommBuffer
;
342 DEBUG ((EFI_D_INFO
, "PiSmmCommunicationPei CommBuffer - %x\n", (UINTN
)CommBuffer
));
347 SmiCommand
= (UINT8
)SmmCommunicationContext
->SwSmiNumber
;
348 Size
= sizeof(SmiCommand
);
349 Status
= SmmControl
->Trigger (
350 (EFI_PEI_SERVICES
**)GetPeiServicesTablePointer (),
357 ASSERT_EFI_ERROR (Status
);
360 // Setting BufferPtr to 0 means this transaction is done.
362 *(EFI_PHYSICAL_ADDRESS
*)(UINTN
)SmmCommunicationContext
->BufferPtrAddress
= 0;
364 DEBUG ((EFI_D_INFO
, "PiSmmCommunicationPei Communicate Exit\n"));
370 Entry Point for PI SMM communication PEIM.
372 @param FileHandle Handle of the file being invoked.
373 @param PeiServices Pointer to PEI Services table.
376 @return Others Some error occurs.
380 PiSmmCommunicationPeiEntryPoint (
381 IN EFI_PEI_FILE_HANDLE FileHandle
,
382 IN CONST EFI_PEI_SERVICES
**PeiServices
386 PEI_SMM_ACCESS_PPI
*SmmAccess
;
387 EFI_BOOT_MODE BootMode
;
390 BootMode
= GetBootModeHob ();
391 if (BootMode
!= BOOT_ON_S3_RESUME
) {
392 return EFI_UNSUPPORTED
;
395 Status
= PeiServicesLocatePpi (
396 &gPeiSmmAccessPpiGuid
,
401 if (EFI_ERROR (Status
)) {
402 return EFI_NOT_STARTED
;
406 // Check SMRAM locked, it should be done before SMRAM lock.
408 if (SmmAccess
->LockState
) {
409 DEBUG ((EFI_D_INFO
, "PiSmmCommunicationPei LockState - %x\n", (UINTN
)SmmAccess
->LockState
));
410 return EFI_ACCESS_DENIED
;
416 for (Index
= 0; !EFI_ERROR (Status
); Index
++) {
417 Status
= SmmAccess
->Open ((EFI_PEI_SERVICES
**)GetPeiServicesTablePointer (), SmmAccess
, Index
);
420 InitCommunicationContext ();
422 PeiServicesInstallPpi (&mPpiList
);
424 return RETURN_SUCCESS
;