2 PiSmmCommunication SMM 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.
16 #include <Library/UefiDriverEntryPoint.h>
17 #include <Library/UefiBootServicesTableLib.h>
18 #include <Library/UefiRuntimeServicesTableLib.h>
19 #include <Library/SmmServicesTableLib.h>
20 #include <Library/BaseLib.h>
21 #include <Library/BaseMemoryLib.h>
22 #include <Library/HobLib.h>
23 #include <Library/DebugLib.h>
24 #include <Library/SmmMemLib.h>
25 #include <Library/PcdLib.h>
26 #include <Protocol/SmmSwDispatch2.h>
27 #include <Protocol/SmmReadyToLock.h>
28 #include <Protocol/SmmCommunication.h>
29 #include <Protocol/AcpiTable.h>
30 #include <Ppi/SmmCommunication.h>
31 #include <Guid/Acpi.h>
33 #include "PiSmmCommunicationPrivate.h"
35 EFI_SMM_COMMUNICATION_CONTEXT mSmmCommunicationContext
= {
36 SMM_COMMUNICATION_SIGNATURE
39 EFI_SMM_COMMUNICATION_ACPI_TABLE mSmmCommunicationAcpiTable
= {
42 EFI_ACPI_4_0_UEFI_ACPI_DATA_TABLE_SIGNATURE
,
43 sizeof (EFI_SMM_COMMUNICATION_ACPI_TABLE
),
50 0x0 // CreatorRevision
53 OFFSET_OF (EFI_SMM_COMMUNICATION_ACPI_TABLE
, SwSmiNumber
) // DataOffset
56 0x0 // BufferPtrAddress
60 Set SMM communication context.
63 SetCommunicationContext (
69 Status
= gSmst
->SmmInstallConfigurationTable (
71 &gEfiPeiSmmCommunicationPpiGuid
,
72 &mSmmCommunicationContext
,
73 sizeof(mSmmCommunicationContext
)
75 ASSERT_EFI_ERROR (Status
);
79 Dispatch function for a Software SMI handler.
81 @param DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
82 @param Context Points to an optional handler context which was specified when the
83 handler was registered.
84 @param CommBuffer A pointer to a collection of data in memory that will
85 be conveyed from a non-SMM environment into an SMM environment.
86 @param CommBufferSize The size of the CommBuffer.
88 @retval EFI_SUCCESS Command is handled successfully.
93 PiSmmCommunicationHandler (
94 IN EFI_HANDLE DispatchHandle
,
95 IN CONST VOID
*Context OPTIONAL
,
96 IN OUT VOID
*CommBuffer OPTIONAL
,
97 IN OUT UINTN
*CommBufferSize OPTIONAL
102 EFI_SMM_COMMUNICATE_HEADER
*CommunicateHeader
;
103 EFI_PHYSICAL_ADDRESS
*BufferPtrAddress
;
105 DEBUG ((EFI_D_INFO
, "PiSmmCommunicationHandler Enter\n"));
107 BufferPtrAddress
= (EFI_PHYSICAL_ADDRESS
*)(UINTN
)mSmmCommunicationContext
.BufferPtrAddress
;
108 CommunicateHeader
= (EFI_SMM_COMMUNICATE_HEADER
*)(UINTN
)*BufferPtrAddress
;
109 DEBUG ((EFI_D_INFO
, "PiSmmCommunicationHandler CommunicateHeader - %x\n", CommunicateHeader
));
110 if (CommunicateHeader
== NULL
) {
111 DEBUG ((EFI_D_INFO
, "PiSmmCommunicationHandler is NULL, needn't to call dispatch function\n"));
112 Status
= EFI_SUCCESS
;
114 if (!SmmIsBufferOutsideSmmValid ((UINTN
)CommunicateHeader
, OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER
, Data
))) {
115 DEBUG ((EFI_D_INFO
, "PiSmmCommunicationHandler CommunicateHeader invalid - 0x%x\n", CommunicateHeader
));
116 Status
= EFI_SUCCESS
;
120 CommSize
= (UINTN
)CommunicateHeader
->MessageLength
;
121 if (!SmmIsBufferOutsideSmmValid ((UINTN
)&CommunicateHeader
->Data
[0], CommSize
)) {
122 DEBUG ((EFI_D_INFO
, "PiSmmCommunicationHandler CommunicateData invalid - 0x%x\n", &CommunicateHeader
->Data
[0]));
123 Status
= EFI_SUCCESS
;
128 // Call dispatch function
130 DEBUG ((EFI_D_INFO
, "PiSmmCommunicationHandler Data - %x\n", &CommunicateHeader
->Data
[0]));
131 Status
= gSmst
->SmiManage (
132 &CommunicateHeader
->HeaderGuid
,
134 &CommunicateHeader
->Data
[0],
140 DEBUG ((EFI_D_INFO
, "PiSmmCommunicationHandler %r\n", Status
));
141 DEBUG ((EFI_D_INFO
, "PiSmmCommunicationHandler Exit\n"));
143 return (Status
== EFI_SUCCESS
) ? EFI_SUCCESS
: EFI_INTERRUPT_PENDING
;
147 Allocate EfiACPIMemoryNVS below 4G memory address.
149 This function allocates EfiACPIMemoryNVS below 4G memory address.
151 @param Size Size of memory to allocate.
153 @return Allocated address for output.
157 AllocateAcpiNvsMemoryBelow4G (
162 EFI_PHYSICAL_ADDRESS Address
;
166 Pages
= EFI_SIZE_TO_PAGES (Size
);
167 Address
= 0xffffffff;
169 Status
= gBS
->AllocatePages (
175 ASSERT_EFI_ERROR (Status
);
177 Buffer
= (VOID
*) (UINTN
) Address
;
178 ZeroMem (Buffer
, Size
);
184 Entry Point for PI SMM communication SMM driver.
186 @param[in] ImageHandle Image handle of this driver.
187 @param[in] SystemTable A Pointer to the EFI System Table.
190 @return Others Some error occurs.
194 PiSmmCommunicationSmmEntryPoint (
195 IN EFI_HANDLE ImageHandle
,
196 IN EFI_SYSTEM_TABLE
*SystemTable
200 EFI_SMM_SW_DISPATCH2_PROTOCOL
*SmmSwDispatch2
;
201 EFI_SMM_SW_REGISTER_CONTEXT SmmSwDispatchContext
;
202 EFI_HANDLE DispatchHandle
;
203 EFI_ACPI_TABLE_PROTOCOL
*AcpiTableProtocol
;
206 EFI_PHYSICAL_ADDRESS
*BufferPtrAddress
;
209 mSmmCommunicationAcpiTable
.UefiAcpiDataTable
.Header
.OemId
,
210 PcdGetPtr (PcdAcpiDefaultOemId
),
211 sizeof (mSmmCommunicationAcpiTable
.UefiAcpiDataTable
.Header
.OemId
)
213 OemTableId
= PcdGet64 (PcdAcpiDefaultOemTableId
);
214 CopyMem (&mSmmCommunicationAcpiTable
.UefiAcpiDataTable
.Header
.OemTableId
, &OemTableId
, sizeof (UINT64
));
215 mSmmCommunicationAcpiTable
.UefiAcpiDataTable
.Header
.OemRevision
= PcdGet32 (PcdAcpiDefaultOemRevision
);
216 mSmmCommunicationAcpiTable
.UefiAcpiDataTable
.Header
.CreatorId
= PcdGet32 (PcdAcpiDefaultCreatorId
);
217 mSmmCommunicationAcpiTable
.UefiAcpiDataTable
.Header
.CreatorRevision
= PcdGet32 (PcdAcpiDefaultCreatorRevision
);
220 // Register software SMI handler
222 Status
= gSmst
->SmmLocateProtocol (
223 &gEfiSmmSwDispatch2ProtocolGuid
,
225 (VOID
**)&SmmSwDispatch2
227 ASSERT_EFI_ERROR (Status
);
229 SmmSwDispatchContext
.SwSmiInputValue
= (UINTN
)-1;
230 Status
= SmmSwDispatch2
->Register (
232 PiSmmCommunicationHandler
,
233 &SmmSwDispatchContext
,
236 ASSERT_EFI_ERROR (Status
);
238 DEBUG ((EFI_D_INFO
, "SmmCommunication SwSmi: %x\n", (UINTN
)SmmSwDispatchContext
.SwSmiInputValue
));
243 Status
= gBS
->LocateProtocol (&gEfiAcpiTableProtocolGuid
, NULL
, (VOID
**) &AcpiTableProtocol
);
244 ASSERT_EFI_ERROR (Status
);
246 mSmmCommunicationAcpiTable
.SwSmiNumber
= (UINT32
)SmmSwDispatchContext
.SwSmiInputValue
;
247 BufferPtrAddress
= AllocateAcpiNvsMemoryBelow4G (sizeof(EFI_PHYSICAL_ADDRESS
));
248 ASSERT (BufferPtrAddress
!= NULL
);
249 DEBUG ((EFI_D_INFO
, "SmmCommunication BufferPtrAddress: 0x%016lx, BufferPtr: 0x%016lx\n", (EFI_PHYSICAL_ADDRESS
)(UINTN
)BufferPtrAddress
, *BufferPtrAddress
));
250 mSmmCommunicationAcpiTable
.BufferPtrAddress
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)BufferPtrAddress
;
251 CopyMem (&mSmmCommunicationAcpiTable
.UefiAcpiDataTable
.Identifier
, &gEfiSmmCommunicationProtocolGuid
, sizeof(gEfiSmmCommunicationProtocolGuid
));
253 Status
= AcpiTableProtocol
->InstallAcpiTable (
255 &mSmmCommunicationAcpiTable
,
256 sizeof(mSmmCommunicationAcpiTable
),
259 ASSERT_EFI_ERROR (Status
);
264 mSmmCommunicationContext
.SwSmiNumber
= (UINT32
)SmmSwDispatchContext
.SwSmiInputValue
;
265 mSmmCommunicationContext
.BufferPtrAddress
= mSmmCommunicationAcpiTable
.BufferPtrAddress
;
266 SetCommunicationContext ();