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
12 All rights reserved. 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>
39 // SMM Base Protocol function ptoyotypes
44 IN EFI_SMM_BASE_PROTOCOL
*This
,
45 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
46 IN VOID
*SourceBuffer
,
48 OUT EFI_HANDLE
*ImageHandle
,
49 IN BOOLEAN LegacyIA32Binary
55 IN EFI_SMM_BASE_PROTOCOL
*This
,
56 IN EFI_HANDLE ImageHandle
62 IN EFI_SMM_BASE_PROTOCOL
*This
,
63 IN EFI_HANDLE ImageHandle
,
64 IN OUT VOID
*CommunicationBuffer
,
65 IN OUT UINTN
*BufferSize
70 SmmBaseRegisterCallback (
71 IN EFI_SMM_BASE_PROTOCOL
*This
,
72 IN EFI_HANDLE SmmImageHandle
,
73 IN EFI_SMM_CALLBACK_ENTRY_POINT CallbackAddress
,
75 IN BOOLEAN FloatingPointSave
81 IN EFI_SMM_BASE_PROTOCOL
*This
,
87 SmmBaseSmmAllocatePool (
88 IN EFI_SMM_BASE_PROTOCOL
*This
,
89 IN EFI_MEMORY_TYPE PoolType
,
97 IN EFI_SMM_BASE_PROTOCOL
*This
,
103 SmmBaseGetSmstLocation (
104 IN EFI_SMM_BASE_PROTOCOL
*This
,
105 OUT EFI_SMM_SYSTEM_TABLE
**Smst
109 /// SMM Base Protocol instance
111 EFI_SMM_BASE_PROTOCOL mSmmBase
= {
115 SmmBaseRegisterCallback
,
117 SmmBaseSmmAllocatePool
,
119 SmmBaseGetSmstLocation
122 SMMBASETHUNK_COMMUNICATION_DATA mCommunicationData
= {
123 EFI_SMM_BASE_THUNK_COMMUNICATION_GUID
,
124 sizeof (SMMBASE_FUNCTION_DATA
)
127 EFI_HANDLE mSmmBaseHandle
= NULL
;
128 EFI_SMM_BASE2_PROTOCOL
*mSmmBase2
= NULL
;
129 EFI_SMM_COMMUNICATION_PROTOCOL
*mSmmCommunication
= NULL
;
130 EFI_SMM_BASE_HELPER_READY_PROTOCOL
*mSmmBaseHelperReady
= NULL
;
133 Determine if in SMM mode.
135 @retval TRUE In SMM mode.
136 @retval FALSE Not in SMM mode.
146 Status
= mSmmBase2
->InSmm (mSmmBase2
, &InSmm
);
147 ASSERT_EFI_ERROR (Status
);
152 Invoke services provided by SMM Base Helper SMM driver.
155 SmmBaseHelperService (
161 mCommunicationData
.FunctionData
.Status
= EFI_UNSUPPORTED
;
165 /// If in SMM mode, directly call services in SMM Base Helper.
167 if (mSmmBaseHelperReady
== NULL
) {
172 DataSize
= (UINTN
)(sizeof (SMMBASE_FUNCTION_DATA
));
173 mSmmBaseHelperReady
->ServiceEntry (
176 &mCommunicationData
.FunctionData
,
181 /// If in non-SMM mode, call services in SMM Base Helper via SMM Communication Protocol.
183 if (mSmmCommunication
== NULL
) {
188 DataSize
= (UINTN
)(sizeof (mCommunicationData
));
189 mSmmCommunication
->Communicate (
198 Register a given driver into SMRAM. This is the equivalent of performing
199 the LoadImage/StartImage into System Management Mode.
201 @param[in] This Protocol instance pointer.
202 @param[in] FilePath Location of the image to be installed as the handler.
203 @param[in] SourceBuffer Optional source buffer in case the image file
205 @param[in] SourceSize Size of the source image file, if in memory.
206 @param[out] ImageHandle The handle that the base driver uses to decode
207 the handler. Unique among SMM handlers only,
208 not unique across DXE/EFI.
209 @param[in] LegacyIA32Binary An optional parameter specifying that the associated
210 file is a real-mode IA-32 binary.
212 @retval EFI_SUCCESS The operation was successful.
213 @retval EFI_OUT_OF_RESOURCES There were no additional SMRAM resources to load the handler
214 @retval EFI_UNSUPPORTED This platform does not support 16-bit handlers.
215 @retval EFI_UNSUPPORTED Platform is in runtime.
216 @retval EFI_INVALID_PARAMETER The handlers was not the correct image type
221 IN EFI_SMM_BASE_PROTOCOL
*This
,
222 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
223 IN VOID
*SourceBuffer
,
225 OUT EFI_HANDLE
*ImageHandle
,
226 IN BOOLEAN LegacyIA32Binary
229 if (LegacyIA32Binary
) {
230 return EFI_UNSUPPORTED
;
233 mCommunicationData
.FunctionData
.Function
= SMMBASE_REGISTER
;
234 mCommunicationData
.FunctionData
.Args
.Register
.FilePath
= FilePath
;
235 mCommunicationData
.FunctionData
.Args
.Register
.SourceBuffer
= SourceBuffer
;
236 mCommunicationData
.FunctionData
.Args
.Register
.SourceSize
= SourceSize
;
237 mCommunicationData
.FunctionData
.Args
.Register
.ImageHandle
= ImageHandle
;
238 mCommunicationData
.FunctionData
.Args
.Register
.LegacyIA32Binary
= LegacyIA32Binary
;
240 SmmBaseHelperService ();
241 return mCommunicationData
.FunctionData
.Status
;
245 Removes a handler from execution within SMRAM. This is the equivalent of performing
246 the UnloadImage in System Management Mode.
248 @param[in] This Protocol instance pointer.
249 @param[in] ImageHandle The handler to be removed.
251 @retval EFI_SUCCESS The operation was successful
252 @retval EFI_INVALID_PARAMETER The handler did not exist
253 @retval EFI_UNSUPPORTED Platform is in runtime.
258 IN EFI_SMM_BASE_PROTOCOL
*This
,
259 IN EFI_HANDLE ImageHandle
262 mCommunicationData
.FunctionData
.Function
= SMMBASE_UNREGISTER
;
263 mCommunicationData
.FunctionData
.Args
.UnRegister
.ImageHandle
= ImageHandle
;
265 SmmBaseHelperService ();
266 return mCommunicationData
.FunctionData
.Status
;
270 The SMM Inter-module Communicate Service Communicate() function
271 provides a service to send/receive messages from a registered
272 EFI service. The BASE protocol driver is responsible for doing
273 any of the copies such that the data lives in boot-service-accessible RAM.
275 @param[in] This Protocol instance pointer.
276 @param[in] ImageHandle The handle of the registered driver.
277 @param[in,out] CommunicationBuffer Pointer to the buffer to convey into SMRAM.
278 @param[in,out] BufferSize The size of the data buffer being passed in.
279 On exit, the size of data being returned.
280 Zero if the handler does not wish to reply with any data.
282 @retval EFI_SUCCESS The message was successfully posted
283 @retval EFI_INVALID_PARAMETER The buffer was NULL
288 IN EFI_SMM_BASE_PROTOCOL
*This
,
289 IN EFI_HANDLE ImageHandle
,
290 IN OUT VOID
*CommunicationBuffer
,
291 IN OUT UINTN
*BufferSize
294 if (mSmmCommunication
== NULL
) {
296 return EFI_UNSUPPORTED
;
299 return mSmmCommunication
->Communicate (
307 Register a callback to execute within SMM.
308 This allows receipt of messages created with EFI_SMM_BASE_PROTOCOL.Communicate().
310 @param[in] This Protocol instance pointer.
311 @param[in] SmmImageHandle Handle of the callback service.
312 @param[in] CallbackAddress Address of the callback service.
313 @param[in] MakeLast If present, will stipulate that the handler is posted to
314 be executed last in the dispatch table.
315 @param[in] FloatingPointSave An optional parameter that informs the
316 EFI_SMM_ACCESS_PROTOCOL Driver core if it needs to save
317 the floating point register state. If any handler
318 require this, the state will be saved for all handlers.
320 @retval EFI_SUCCESS The operation was successful
321 @retval EFI_OUT_OF_RESOURCES Not enough space in the dispatch queue
322 @retval EFI_UNSUPPORTED Platform is in runtime.
323 @retval EFI_UNSUPPORTED The caller is not in SMM.
327 SmmBaseRegisterCallback (
328 IN EFI_SMM_BASE_PROTOCOL
*This
,
329 IN EFI_HANDLE SmmImageHandle
,
330 IN EFI_SMM_CALLBACK_ENTRY_POINT CallbackAddress
,
332 IN BOOLEAN FloatingPointSave
336 return EFI_UNSUPPORTED
;
339 mCommunicationData
.FunctionData
.Function
= SMMBASE_REGISTER_CALLBACK
;
340 mCommunicationData
.FunctionData
.Args
.RegisterCallback
.SmmImageHandle
= SmmImageHandle
;
341 mCommunicationData
.FunctionData
.Args
.RegisterCallback
.CallbackAddress
= CallbackAddress
;
342 mCommunicationData
.FunctionData
.Args
.RegisterCallback
.MakeLast
= MakeLast
;
343 mCommunicationData
.FunctionData
.Args
.RegisterCallback
.FloatingPointSave
= FloatingPointSave
;
345 SmmBaseHelperService();
346 return mCommunicationData
.FunctionData
.Status
;
350 This routine tells caller if execution context is SMM or not.
352 @param[in] This Protocol instance pointer.
353 @param[out] InSmm Whether the caller is inside SMM for IA-32
354 or servicing a PMI for the Itanium processor
357 @retval EFI_SUCCESS The operation was successful
358 @retval EFI_INVALID_PARAMETER InSmm was NULL.
363 IN EFI_SMM_BASE_PROTOCOL
*This
,
367 return mSmmBase2
->InSmm (mSmmBase2
, InSmm
);
371 The SmmAllocatePool() function allocates a memory region of Size bytes from memory of
372 type PoolType and returns the address of the allocated memory in the location referenced
373 by Buffer. This function allocates pages from EFI SMRAM Memory as needed to grow the
374 requested pool type. All allocations are eight-byte aligned.
376 @param[in] This Protocol instance pointer.
377 @param[in] PoolType The type of pool to allocate.
378 The only supported type is EfiRuntimeServicesData;
379 the interface will internally map this runtime request to
380 SMRAM for IA-32 and leave as this type for the Itanium
381 processor family. Other types can be ignored.
382 @param[in] Size The number of bytes to allocate from the pool.
383 @param[out] Buffer A pointer to a pointer to the allocated buffer if the call
384 succeeds; undefined otherwise.
386 @retval EFI_SUCCESS The requested number of bytes was allocated.
387 @retval EFI_OUT_OF_RESOURCES The pool requested could not be allocated.
388 @retval EFI_UNSUPPORTED Platform is in runtime.
392 SmmBaseSmmAllocatePool (
393 IN EFI_SMM_BASE_PROTOCOL
*This
,
394 IN EFI_MEMORY_TYPE PoolType
,
399 mCommunicationData
.FunctionData
.Function
= SMMBASE_ALLOCATE_POOL
;
400 mCommunicationData
.FunctionData
.Args
.AllocatePool
.PoolType
= PoolType
;
401 mCommunicationData
.FunctionData
.Args
.AllocatePool
.Size
= Size
;
402 mCommunicationData
.FunctionData
.Args
.AllocatePool
.Buffer
= Buffer
;
404 SmmBaseHelperService ();
405 return mCommunicationData
.FunctionData
.Status
;
409 The SmmFreePool() function returns the memory specified by Buffer to the system.
410 On return, the memory's type is EFI SMRAM Memory. The Buffer that is freed must
411 have been allocated by SmmAllocatePool().
413 @param[in] This Protocol instance pointer.
414 @param[in] Buffer Pointer to the buffer allocation.
416 @retval EFI_SUCCESS The memory was returned to the system.
417 @retval EFI_INVALID_PARAMETER Buffer was invalid.
418 @retval EFI_UNSUPPORTED Platform is in runtime.
423 IN EFI_SMM_BASE_PROTOCOL
*This
,
427 mCommunicationData
.FunctionData
.Function
= SMMBASE_FREE_POOL
;
428 mCommunicationData
.FunctionData
.Args
.FreePool
.Buffer
= Buffer
;
430 SmmBaseHelperService ();
431 return mCommunicationData
.FunctionData
.Status
;
435 The GetSmstLocation() function returns the location of the System Management
436 Service Table. The use of the API is such that a driver can discover the
437 location of the SMST in its entry point and then cache it in some driver
438 global variable so that the SMST can be invoked in subsequent callbacks.
440 @param[in] This Protocol instance pointer.
441 @param[in] Smst Pointer to the SMST.
443 @retval EFI_SUCCESS The operation was successful
444 @retval EFI_INVALID_PARAMETER Smst was invalid.
445 @retval EFI_UNSUPPORTED Not in SMM.
449 SmmBaseGetSmstLocation (
450 IN EFI_SMM_BASE_PROTOCOL
*This
,
451 OUT EFI_SMM_SYSTEM_TABLE
**Smst
454 if (mSmmBaseHelperReady
== NULL
) {
456 return EFI_UNSUPPORTED
;
460 return EFI_UNSUPPORTED
;
464 return EFI_INVALID_PARAMETER
;
467 *Smst
= mSmmBaseHelperReady
->FrameworkSmst
;
472 Notification function of EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE
474 This is a notification function registered on EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event.
475 It convers pointer to new virtual address.
477 @param Event Event whose notification function is being invoked
478 @param Context Pointer to the notification function's context
482 SmmBaseAddressChangeEvent (
487 if (mSmmCommunication
!= NULL
) {
488 EfiConvertPointer (0x0, (VOID
**) &mSmmCommunication
);
493 Entry Point for SMM Base Protocol on SMM Base2 Protocol Thunk driver.
495 @param[in] ImageHandle Image handle of this driver.
496 @param[in] SystemTable A Pointer to the EFI System Table.
498 @retval EFI_SUCCESS The entry point is executed successfully.
503 IN EFI_HANDLE ImageHandle
,
504 IN EFI_SYSTEM_TABLE
*SystemTable
511 // Assume only one instance of SMM Base2 Protocol in the system
512 // Locate SMM Base2 Protocol
514 Status
= gBS
->LocateProtocol (&gEfiSmmBase2ProtocolGuid
, NULL
, (VOID
**) &mSmmBase2
);
515 ASSERT_EFI_ERROR (Status
);
518 // Assume only one instance of SMM Communication Protocol in the system
519 // Locate SMM Communication Protocol
521 gBS
->LocateProtocol (&gEfiSmmCommunicationProtocolGuid
, NULL
, (VOID
**) &mSmmCommunication
);
522 ASSERT_EFI_ERROR (Status
);
525 // Assume only one instance of SMM Base Helper Ready Protocol in the system
526 // Locate SMM Base Helper Ready Protocol
528 Status
= gBS
->LocateProtocol (&gEfiSmmBaseHelperReadyProtocolGuid
, NULL
, (VOID
**) &mSmmBaseHelperReady
);
529 ASSERT_EFI_ERROR (Status
);
532 // Create event on SetVirtualAddressMap() to convert mSmmCommunication from a physical address to a virtual address
534 Status
= gBS
->CreateEventEx (
537 SmmBaseAddressChangeEvent
,
539 &gEfiEventVirtualAddressChangeGuid
,
542 ASSERT_EFI_ERROR (Status
);
545 // Publish Framework SMM BASE Protocol immediately after SMM Base2 Protocol is installed to
546 // make SMM Base Protocol.InSmm() available as early as possible.
548 Status
= gBS
->InstallMultipleProtocolInterfaces (
550 &gEfiSmmBaseProtocolGuid
, &mSmmBase
,
553 ASSERT_EFI_ERROR (Status
);