2 SMM Base Protocol on SMM Base2 Protocol Thunk driver.
4 This driver co-operates with SMM Base Helper SMM driver to provide SMM Base Protocol
5 based on SMM Base2 Protocol.
7 This thunk driver is expected to be loaded before PI SMM IPL driver so that
8 SMM BASE Protocol can be published immediately after SMM Base2 Protocol is installed to
9 make SMM Base Protocol.InSmm() as early as possible.
11 Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
12 This program and the accompanying materials
13 are licensed and made available under the terms and conditions of the BSD License
14 which accompanies this distribution. The full text of the license may be found at
15 http://opensource.org/licenses/bsd-license.php
17 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
18 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
23 #include <FrameworkSmm.h>
25 #include <Protocol/SmmBase2.h>
26 #include <Protocol/SmmCommunication.h>
27 #include <Protocol/SmmBaseHelperReady.h>
29 #include <Guid/SmmBaseThunkCommunication.h>
30 #include <Guid/EventGroup.h>
32 #include <Library/DebugLib.h>
33 #include <Library/UefiBootServicesTableLib.h>
34 #include <Library/UefiDriverEntryPoint.h>
35 #include <Library/UefiLib.h>
36 #include <Library/UefiRuntimeLib.h>
38 SMMBASETHUNK_COMMUNICATION_DATA mCommunicationData
= {
39 EFI_SMM_BASE_THUNK_COMMUNICATION_GUID
,
40 sizeof (SMMBASE_FUNCTION_DATA
)
43 EFI_HANDLE mSmmBaseHandle
= NULL
;
44 EFI_SMM_BASE2_PROTOCOL
*mSmmBase2
= NULL
;
45 EFI_SMM_COMMUNICATION_PROTOCOL
*mSmmCommunication
= NULL
;
46 EFI_SMM_BASE_HELPER_READY_PROTOCOL
*mSmmBaseHelperReady
= NULL
;
47 BOOLEAN mAtRuntime
= FALSE
;
50 Determine if in SMM mode.
52 @retval TRUE In SMM mode.
53 @retval FALSE Not in SMM mode.
63 Status
= mSmmBase2
->InSmm (mSmmBase2
, &InSmm
);
64 ASSERT_EFI_ERROR (Status
);
69 Invoke services provided by SMM Base Helper SMM driver.
72 SmmBaseHelperService (
78 mCommunicationData
.FunctionData
.Status
= EFI_UNSUPPORTED
;
79 mCommunicationData
.FunctionData
.SmmBaseImageHandle
= mSmmBaseHandle
;
81 if ((mCommunicationData
.FunctionData
.Function
!= SmmBaseFunctionCommunicate
) && IsInSmm()) {
83 /// If in SMM mode, directly call services in SMM Base Helper.
85 DataSize
= (UINTN
)(sizeof (SMMBASE_FUNCTION_DATA
));
86 mSmmBaseHelperReady
->ServiceEntry (
89 &mCommunicationData
.FunctionData
,
94 /// Call services in SMM Base Helper via SMM Communication Protocol.
96 DataSize
= (UINTN
)(sizeof (mCommunicationData
));
97 mSmmCommunication
->Communicate (
106 Register a given driver into SMRAM. This is the equivalent of performing
107 the LoadImage/StartImage into System Management Mode.
109 @param[in] This Protocol instance pointer.
110 @param[in] FilePath Location of the image to be installed as the handler.
111 @param[in] SourceBuffer Optional source buffer in case the image file
113 @param[in] SourceSize Size of the source image file, if in memory.
114 @param[out] ImageHandle The handle that the base driver uses to decode
115 the handler. Unique among SMM handlers only,
116 not unique across DXE/EFI.
117 @param[in] LegacyIA32Binary An optional parameter specifying that the associated
118 file is a real-mode IA-32 binary.
120 @retval EFI_SUCCESS The operation was successful.
121 @retval EFI_OUT_OF_RESOURCES There were no additional SMRAM resources to load the handler
122 @retval EFI_UNSUPPORTED This platform does not support 16-bit handlers.
123 @retval EFI_UNSUPPORTED Platform is in runtime.
124 @retval EFI_INVALID_PARAMETER The handlers was not the correct image type
129 IN EFI_SMM_BASE_PROTOCOL
*This
,
130 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
131 IN VOID
*SourceBuffer
,
133 OUT EFI_HANDLE
*ImageHandle
,
134 IN BOOLEAN LegacyIA32Binary
137 if (mAtRuntime
|| LegacyIA32Binary
) {
138 return EFI_UNSUPPORTED
;
141 mCommunicationData
.FunctionData
.Function
= SmmBaseFunctionRegister
;
142 mCommunicationData
.FunctionData
.Args
.Register
.FilePath
= FilePath
;
143 mCommunicationData
.FunctionData
.Args
.Register
.SourceBuffer
= SourceBuffer
;
144 mCommunicationData
.FunctionData
.Args
.Register
.SourceSize
= SourceSize
;
145 mCommunicationData
.FunctionData
.Args
.Register
.ImageHandle
= ImageHandle
;
146 mCommunicationData
.FunctionData
.Args
.Register
.LegacyIA32Binary
= LegacyIA32Binary
;
148 SmmBaseHelperService ();
149 return mCommunicationData
.FunctionData
.Status
;
153 Removes a handler from execution within SMRAM. This is the equivalent of performing
154 the UnloadImage in System Management Mode.
156 @param[in] This Protocol instance pointer.
157 @param[in] ImageHandle The handler to be removed.
159 @retval EFI_SUCCESS The operation was successful
160 @retval EFI_INVALID_PARAMETER The handler did not exist
161 @retval EFI_UNSUPPORTED Platform is in runtime.
166 IN EFI_SMM_BASE_PROTOCOL
*This
,
167 IN EFI_HANDLE ImageHandle
171 return EFI_UNSUPPORTED
;
174 mCommunicationData
.FunctionData
.Function
= SmmBaseFunctionUnregister
;
175 mCommunicationData
.FunctionData
.Args
.UnRegister
.ImageHandle
= ImageHandle
;
177 SmmBaseHelperService ();
178 return mCommunicationData
.FunctionData
.Status
;
182 The SMM Inter-module Communicate Service Communicate() function
183 provides a service to send/receive messages from a registered
184 EFI service. The BASE protocol driver is responsible for doing
185 any of the copies such that the data lives in boot-service-accessible RAM.
187 @param[in] This Protocol instance pointer.
188 @param[in] ImageHandle The handle of the registered driver.
189 @param[in, out] CommunicationBuffer Pointer to the buffer to convey into SMRAM.
190 @param[in, out] BufferSize The size of the data buffer being passed in.
191 On exit, the size of data being returned.
192 Zero if the handler does not wish to reply with any data.
194 @retval EFI_SUCCESS The message was successfully posted
195 @retval EFI_INVALID_PARAMETER The buffer was NULL
200 IN EFI_SMM_BASE_PROTOCOL
*This
,
201 IN EFI_HANDLE ImageHandle
,
202 IN OUT VOID
*CommunicationBuffer
,
203 IN OUT UINTN
*BufferSize
207 /// Note this is a runtime interface
210 if (CommunicationBuffer
== NULL
|| BufferSize
== NULL
) {
211 return EFI_INVALID_PARAMETER
;
214 mCommunicationData
.FunctionData
.Function
= SmmBaseFunctionCommunicate
;
215 mCommunicationData
.FunctionData
.Args
.Communicate
.ImageHandle
= ImageHandle
;
216 mCommunicationData
.FunctionData
.Args
.Communicate
.CommunicationBuffer
= CommunicationBuffer
;
217 mCommunicationData
.FunctionData
.Args
.Communicate
.SourceSize
= BufferSize
;
219 SmmBaseHelperService ();
220 return mCommunicationData
.FunctionData
.Status
;
224 Register a callback to execute within SMM.
225 This allows receipt of messages created with EFI_SMM_BASE_PROTOCOL.Communicate().
227 @param[in] This Protocol instance pointer.
228 @param[in] SmmImageHandle Handle of the callback service.
229 @param[in] CallbackAddress Address of the callback service.
230 @param[in] MakeLast If present, will stipulate that the handler is posted to
231 be executed last in the dispatch table.
232 @param[in] FloatingPointSave An optional parameter that informs the
233 EFI_SMM_ACCESS_PROTOCOL Driver core if it needs to save
234 the floating point register state. If any handler
235 require this, the state will be saved for all handlers.
237 @retval EFI_SUCCESS The operation was successful
238 @retval EFI_OUT_OF_RESOURCES Not enough space in the dispatch queue
239 @retval EFI_UNSUPPORTED Platform is in runtime.
240 @retval EFI_UNSUPPORTED The caller is not in SMM.
244 SmmBaseRegisterCallback (
245 IN EFI_SMM_BASE_PROTOCOL
*This
,
246 IN EFI_HANDLE SmmImageHandle
,
247 IN EFI_SMM_CALLBACK_ENTRY_POINT CallbackAddress
,
249 IN BOOLEAN FloatingPointSave
253 return EFI_UNSUPPORTED
;
256 mCommunicationData
.FunctionData
.Function
= SmmBaseFunctionRegisterCallback
;
257 mCommunicationData
.FunctionData
.Args
.RegisterCallback
.SmmImageHandle
= SmmImageHandle
;
258 mCommunicationData
.FunctionData
.Args
.RegisterCallback
.CallbackAddress
= CallbackAddress
;
259 mCommunicationData
.FunctionData
.Args
.RegisterCallback
.MakeLast
= MakeLast
;
260 mCommunicationData
.FunctionData
.Args
.RegisterCallback
.FloatingPointSave
= FloatingPointSave
;
262 SmmBaseHelperService();
263 return mCommunicationData
.FunctionData
.Status
;
267 This routine tells caller if execution context is SMM or not.
269 @param[in] This Protocol instance pointer.
270 @param[out] InSmm Whether the caller is inside SMM for IA-32
271 or servicing a PMI for the Itanium processor
274 @retval EFI_SUCCESS The operation was successful
275 @retval EFI_INVALID_PARAMETER InSmm was NULL.
280 IN EFI_SMM_BASE_PROTOCOL
*This
,
284 return mSmmBase2
->InSmm (mSmmBase2
, InSmm
);
288 The SmmAllocatePool() function allocates a memory region of Size bytes from memory of
289 type PoolType and returns the address of the allocated memory in the location referenced
290 by Buffer. This function allocates pages from EFI SMRAM Memory as needed to grow the
291 requested pool type. All allocations are eight-byte aligned.
293 @param[in] This Protocol instance pointer.
294 @param[in] PoolType The type of pool to allocate.
295 The only supported type is EfiRuntimeServicesData;
296 the interface will internally map this runtime request to
297 SMRAM for IA-32 and leave as this type for the Itanium
298 processor family. Other types can be ignored.
299 @param[in] Size The number of bytes to allocate from the pool.
300 @param[out] Buffer A pointer to a pointer to the allocated buffer if the call
301 succeeds; undefined otherwise.
303 @retval EFI_SUCCESS The requested number of bytes was allocated.
304 @retval EFI_OUT_OF_RESOURCES The pool requested could not be allocated.
305 @retval EFI_UNSUPPORTED Platform is in runtime.
309 SmmBaseSmmAllocatePool (
310 IN EFI_SMM_BASE_PROTOCOL
*This
,
311 IN EFI_MEMORY_TYPE PoolType
,
317 return EFI_UNSUPPORTED
;
320 mCommunicationData
.FunctionData
.Function
= SmmBaseFunctionAllocatePool
;
321 mCommunicationData
.FunctionData
.Args
.AllocatePool
.PoolType
= PoolType
;
322 mCommunicationData
.FunctionData
.Args
.AllocatePool
.Size
= Size
;
323 mCommunicationData
.FunctionData
.Args
.AllocatePool
.Buffer
= Buffer
;
325 SmmBaseHelperService ();
326 return mCommunicationData
.FunctionData
.Status
;
330 The SmmFreePool() function returns the memory specified by Buffer to the system.
331 On return, the memory's type is EFI SMRAM Memory. The Buffer that is freed must
332 have been allocated by SmmAllocatePool().
334 @param[in] This Protocol instance pointer.
335 @param[in] Buffer Pointer to the buffer allocation.
337 @retval EFI_SUCCESS The memory was returned to the system.
338 @retval EFI_INVALID_PARAMETER Buffer was invalid.
339 @retval EFI_UNSUPPORTED Platform is in runtime.
344 IN EFI_SMM_BASE_PROTOCOL
*This
,
349 return EFI_UNSUPPORTED
;
352 mCommunicationData
.FunctionData
.Function
= SmmBaseFunctionFreePool
;
353 mCommunicationData
.FunctionData
.Args
.FreePool
.Buffer
= Buffer
;
355 SmmBaseHelperService ();
356 return mCommunicationData
.FunctionData
.Status
;
360 The GetSmstLocation() function returns the location of the System Management
361 Service Table. The use of the API is such that a driver can discover the
362 location of the SMST in its entry point and then cache it in some driver
363 global variable so that the SMST can be invoked in subsequent callbacks.
365 @param[in] This Protocol instance pointer.
366 @param[out] Smst Pointer to the SMST.
368 @retval EFI_SUCCESS The operation was successful
369 @retval EFI_INVALID_PARAMETER Smst was invalid.
370 @retval EFI_UNSUPPORTED Not in SMM.
374 SmmBaseGetSmstLocation (
375 IN EFI_SMM_BASE_PROTOCOL
*This
,
376 OUT EFI_SMM_SYSTEM_TABLE
**Smst
380 return EFI_UNSUPPORTED
;
384 return EFI_INVALID_PARAMETER
;
387 *Smst
= mSmmBaseHelperReady
->FrameworkSmst
;
392 Notification function of EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE
394 This is a notification function registered on EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event.
395 It convers pointer to new virtual address.
397 @param Event Event whose notification function is being invoked
398 @param Context Pointer to the notification function's context
402 SmmBaseAddressChangeEvent (
407 EfiConvertPointer (0x0, (VOID
**) &mSmmCommunication
);
411 /// SMM Base Protocol instance
413 EFI_SMM_BASE_PROTOCOL mSmmBase
= {
417 SmmBaseRegisterCallback
,
419 SmmBaseSmmAllocatePool
,
421 SmmBaseGetSmstLocation
425 Notification function on Exit Boot Services Event.
427 This function sets a flag indicating it is in Runtime phase.
429 @param Event Event whose notification function is being invoked
430 @param Context Pointer to the notification function's context
434 SmmBaseExitBootServicesEventNotify (
443 Entry Point for SMM Base Protocol on SMM Base2 Protocol Thunk driver.
445 @param[in] ImageHandle Image handle of this driver.
446 @param[in] SystemTable A Pointer to the EFI System Table.
448 @retval EFI_SUCCESS The entry point is executed successfully.
453 IN EFI_HANDLE ImageHandle
,
454 IN EFI_SYSTEM_TABLE
*SystemTable
460 mSmmBaseHandle
= ImageHandle
;
463 // Assume only one instance of SMM Base2 Protocol in the system
464 // Locate SMM Base2 Protocol
466 Status
= gBS
->LocateProtocol (&gEfiSmmBase2ProtocolGuid
, NULL
, (VOID
**) &mSmmBase2
);
467 ASSERT_EFI_ERROR (Status
);
470 // Assume only one instance of SMM Communication Protocol in the system
471 // Locate SMM Communication Protocol
473 Status
= gBS
->LocateProtocol (&gEfiSmmCommunicationProtocolGuid
, NULL
, (VOID
**) &mSmmCommunication
);
474 ASSERT_EFI_ERROR (Status
);
477 // Assume only one instance of SMM Base Helper Ready Protocol in the system
478 // Locate SMM Base Helper Ready Protocol
480 Status
= gBS
->LocateProtocol (&gEfiSmmBaseHelperReadyProtocolGuid
, NULL
, (VOID
**) &mSmmBaseHelperReady
);
481 ASSERT_EFI_ERROR (Status
);
484 // Create event notification on Exit Boot Services event.
486 Status
= gBS
->CreateEventEx (
489 SmmBaseExitBootServicesEventNotify
,
491 &gEfiEventExitBootServicesGuid
,
494 ASSERT_EFI_ERROR (Status
);
497 // Create event on SetVirtualAddressMap() to convert mSmmCommunication from a physical address to a virtual address
499 Status
= gBS
->CreateEventEx (
502 SmmBaseAddressChangeEvent
,
504 &gEfiEventVirtualAddressChangeGuid
,
507 ASSERT_EFI_ERROR (Status
);
510 // Publish Framework SMM BASE Protocol immediately after SMM Base2 Protocol is installed to
511 // make SMM Base Protocol.InSmm() available as early as possible.
513 Status
= gBS
->InstallMultipleProtocolInterfaces (
515 &gEfiSmmBaseProtocolGuid
, &mSmmBase
,
518 ASSERT_EFI_ERROR (Status
);