2 SMM Base Helper SMM driver.
4 This driver is the counterpart of the SMM Base On SMM Base2 Thunk driver. It
5 provides helping services in SMM to the SMM Base On SMM Base2 Thunk driver.
7 Copyright (c) 2009 - 2010, Intel Corporation
8 All rights reserved. This program and the accompanying materials
9 are licensed and made available under the terms and conditions of the BSD License
10 which accompanies this distribution. The full text of the license may be found at
11 http://opensource.org/licenses/bsd-license.php
13 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
14 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
19 #include <Library/DebugLib.h>
20 #include <Library/UefiBootServicesTableLib.h>
21 #include <Library/SmmServicesTableLib.h>
22 #include <Library/BaseLib.h>
23 #include <Library/BaseMemoryLib.h>
24 #include <Library/PeCoffLib.h>
25 #include <Library/DevicePathLib.h>
26 #include <Library/CacheMaintenanceLib.h>
27 #include <Library/MemoryAllocationLib.h>
28 #include <Guid/SmmBaseThunkCommunication.h>
29 #include <Protocol/SmmBaseHelperReady.h>
30 #include <Protocol/SmmCpu.h>
31 #include <Protocol/LoadedImage.h>
32 #include <Protocol/SmmCpuSaveState.h>
33 #include <Protocol/MpService.h>
36 /// Structure for tracking paired information of registered Framework SMI handler
37 /// and correpsonding dispatch handle for SMI handler thunk.
41 EFI_HANDLE DispatchHandle
;
42 EFI_HANDLE SmmImageHandle
;
43 EFI_SMM_CALLBACK_ENTRY_POINT CallbackAddress
;
48 /// PI SMM CPU Save State register index
50 EFI_SMM_SAVE_STATE_REGISTER Register
;
52 /// Offset in Framework SMST
55 } CPU_SAVE_STATE_CONVERSION
;
57 #define CPU_SAVE_STATE_GET_OFFSET(Field) (UINTN)(&(((EFI_SMM_CPU_SAVE_STATE *) 0)->Ia32SaveState.Field))
60 EFI_HANDLE mDispatchHandle
;
61 EFI_SMM_CPU_PROTOCOL
*mSmmCpu
;
62 EFI_GUID mEfiSmmCpuIoGuid
= EFI_SMM_CPU_IO_GUID
;
63 EFI_SMM_BASE_HELPER_READY_PROTOCOL
*mSmmBaseHelperReady
;
64 EFI_SMM_SYSTEM_TABLE
*mFrameworkSmst
;
65 UINTN mNumberOfProcessors
;
67 LIST_ENTRY mCallbackInfoListHead
= INITIALIZE_LIST_HEAD_VARIABLE (mCallbackInfoListHead
);
69 CPU_SAVE_STATE_CONVERSION mCpuSaveStateConvTable
[] = {
70 {EFI_SMM_SAVE_STATE_REGISTER_LDTBASE
, CPU_SAVE_STATE_GET_OFFSET(LDTBase
)},
71 {EFI_SMM_SAVE_STATE_REGISTER_ES
, CPU_SAVE_STATE_GET_OFFSET(ES
)},
72 {EFI_SMM_SAVE_STATE_REGISTER_CS
, CPU_SAVE_STATE_GET_OFFSET(CS
)},
73 {EFI_SMM_SAVE_STATE_REGISTER_SS
, CPU_SAVE_STATE_GET_OFFSET(SS
)},
74 {EFI_SMM_SAVE_STATE_REGISTER_DS
, CPU_SAVE_STATE_GET_OFFSET(DS
)},
75 {EFI_SMM_SAVE_STATE_REGISTER_FS
, CPU_SAVE_STATE_GET_OFFSET(FS
)},
76 {EFI_SMM_SAVE_STATE_REGISTER_GS
, CPU_SAVE_STATE_GET_OFFSET(GS
)},
77 {EFI_SMM_SAVE_STATE_REGISTER_TR_SEL
, CPU_SAVE_STATE_GET_OFFSET(TR
)},
78 {EFI_SMM_SAVE_STATE_REGISTER_DR7
, CPU_SAVE_STATE_GET_OFFSET(DR7
)},
79 {EFI_SMM_SAVE_STATE_REGISTER_DR6
, CPU_SAVE_STATE_GET_OFFSET(DR6
)},
80 {EFI_SMM_SAVE_STATE_REGISTER_RAX
, CPU_SAVE_STATE_GET_OFFSET(EAX
)},
81 {EFI_SMM_SAVE_STATE_REGISTER_RBX
, CPU_SAVE_STATE_GET_OFFSET(EBX
)},
82 {EFI_SMM_SAVE_STATE_REGISTER_RCX
, CPU_SAVE_STATE_GET_OFFSET(ECX
)},
83 {EFI_SMM_SAVE_STATE_REGISTER_RDX
, CPU_SAVE_STATE_GET_OFFSET(EDX
)},
84 {EFI_SMM_SAVE_STATE_REGISTER_RSP
, CPU_SAVE_STATE_GET_OFFSET(ESP
)},
85 {EFI_SMM_SAVE_STATE_REGISTER_RBP
, CPU_SAVE_STATE_GET_OFFSET(EBP
)},
86 {EFI_SMM_SAVE_STATE_REGISTER_RSI
, CPU_SAVE_STATE_GET_OFFSET(ESI
)},
87 {EFI_SMM_SAVE_STATE_REGISTER_RDI
, CPU_SAVE_STATE_GET_OFFSET(EDI
)},
88 {EFI_SMM_SAVE_STATE_REGISTER_RIP
, CPU_SAVE_STATE_GET_OFFSET(EIP
)},
89 {EFI_SMM_SAVE_STATE_REGISTER_RFLAGS
, CPU_SAVE_STATE_GET_OFFSET(EFLAGS
)},
90 {EFI_SMM_SAVE_STATE_REGISTER_CR0
, CPU_SAVE_STATE_GET_OFFSET(CR0
)},
91 {EFI_SMM_SAVE_STATE_REGISTER_CR3
, CPU_SAVE_STATE_GET_OFFSET(CR3
)}
95 Framework SMST SmmInstallConfigurationTable() Thunk.
97 This thunk calls the PI SMM SmmInstallConfigurationTable() and then update the configuration
98 table related fields in the Framework SMST because the PI SMM SmmInstallConfigurationTable()
99 function may modify these fields.
101 @param[in] SystemTable A pointer to the SMM System Table.
102 @param[in] Guid A pointer to the GUID for the entry to add, update, or remove.
103 @param[in] Table A pointer to the buffer of the table to add.
104 @param[in] TableSize The size of the table to install.
106 @retval EFI_SUCCESS The (Guid, Table) pair was added, updated, or removed.
107 @retval EFI_INVALID_PARAMETER Guid is not valid.
108 @retval EFI_NOT_FOUND An attempt was made to delete a non-existent entry.
109 @retval EFI_OUT_OF_RESOURCES There is not enough memory available to complete the operation.
113 SmmInstallConfigurationTable (
114 IN EFI_SMM_SYSTEM_TABLE
*SystemTable
,
122 Status
= gSmst
->SmmInstallConfigurationTable (gSmst
, Guid
, Table
, TableSize
);
123 if (!EFI_ERROR (Status
)) {
124 mFrameworkSmst
->NumberOfTableEntries
= gSmst
->NumberOfTableEntries
;
125 mFrameworkSmst
->SmmConfigurationTable
= gSmst
->SmmConfigurationTable
;
131 Construct a Framework SMST based on the PI SMM SMST.
133 @return Pointer to the constructed Framework SMST.
135 EFI_SMM_SYSTEM_TABLE
*
136 ConstructFrameworkSmst (
140 EFI_SMM_SYSTEM_TABLE
*FrameworkSmst
;
142 FrameworkSmst
= (EFI_SMM_SYSTEM_TABLE
*)AllocatePool (sizeof (EFI_SMM_SYSTEM_TABLE
));
143 ASSERT (FrameworkSmst
!= NULL
);
146 /// Copy same things from PI SMST to Framework SMST
148 CopyMem (FrameworkSmst
, gSmst
, (UINTN
)(&((EFI_SMM_SYSTEM_TABLE
*)0)->SmmIo
));
150 &FrameworkSmst
->SmmIo
,
152 sizeof (EFI_SMM_SYSTEM_TABLE
) - (UINTN
)(&((EFI_SMM_SYSTEM_TABLE
*)0)->SmmIo
)
156 /// Update Framework SMST
158 FrameworkSmst
->Hdr
.Revision
= EFI_SMM_SYSTEM_TABLE_REVISION
;
159 CopyGuid (&FrameworkSmst
->EfiSmmCpuIoGuid
, &mEfiSmmCpuIoGuid
);
161 FrameworkSmst
->CpuSaveState
= (EFI_SMM_CPU_SAVE_STATE
*)AllocateZeroPool (mNumberOfProcessors
* sizeof (EFI_SMM_CPU_SAVE_STATE
));
162 ASSERT (FrameworkSmst
->CpuSaveState
!= NULL
);
165 /// Do not support floating point state now
167 FrameworkSmst
->CpuOptionalFloatingPointState
= NULL
;
169 FrameworkSmst
->SmmInstallConfigurationTable
= SmmInstallConfigurationTable
;
171 return FrameworkSmst
;
175 Load a given Framework SMM driver into SMRAM and invoke its entry point.
177 @param[in] FilePath Location of the image to be installed as the handler.
178 @param[in] SourceBuffer Optional source buffer in case the image file
180 @param[in] SourceSize Size of the source image file, if in memory.
181 @param[out] ImageHandle The handle that the base driver uses to decode
182 the handler. Unique among SMM handlers only,
183 not unique across DXE/EFI.
185 @retval EFI_SUCCESS The operation was successful.
186 @retval EFI_OUT_OF_RESOURCES There were no additional SMRAM resources to load the handler
187 @retval EFI_UNSUPPORTED Can not find its copy in normal memory.
188 @retval EFI_INVALID_PARAMETER The handlers was not the correct image type
192 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
193 IN VOID
*SourceBuffer
,
195 OUT EFI_HANDLE
*ImageHandle
200 EFI_PHYSICAL_ADDRESS Buffer
;
201 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
202 EFI_HANDLE PesudoImageHandle
;
205 EFI_HANDLE
*HandleBuffer
;
206 EFI_LOADED_IMAGE_PROTOCOL
*LoadedImage
;
207 EFI_DEVICE_PATH
*LoadedImageDevicePath
;
208 UINTN DevicePathSize
;
210 if (FilePath
== NULL
|| ImageHandle
== NULL
) {
211 return EFI_INVALID_PARAMETER
;
215 /// Assume Framework SMM driver has an image copy in memory before registering itself into SMRAM.
216 /// Currently only supports load Framework SMM driver from existing image copy in memory.
217 /// Load PE32 Image Protocol can be used to support loading Framework SMM driver directly from FV.
219 if (SourceBuffer
== NULL
) {
220 Status
= gBS
->LocateHandleBuffer (
222 &gEfiLoadedImageDevicePathProtocolGuid
,
227 if (EFI_ERROR (Status
)) {
228 return EFI_UNSUPPORTED
;
231 DevicePathSize
= GetDevicePathSize (FilePath
);
233 for (Index
= 0; Index
< NumHandles
; Index
++) {
234 Status
= gBS
->HandleProtocol (
236 &gEfiLoadedImageDevicePathProtocolGuid
,
237 (VOID
**)&LoadedImageDevicePath
239 ASSERT_EFI_ERROR (Status
);
241 if (GetDevicePathSize (LoadedImageDevicePath
) == DevicePathSize
&&
242 CompareMem (LoadedImageDevicePath
, FilePath
, DevicePathSize
) == 0) {
247 if (Index
< NumHandles
) {
248 Status
= gBS
->HandleProtocol (
250 &gEfiLoadedImageProtocolGuid
,
251 (VOID
**)&LoadedImage
253 ASSERT_EFI_ERROR (Status
);
255 SourceBuffer
= LoadedImage
->ImageBase
;
256 gBS
->FreePool (HandleBuffer
);
258 gBS
->FreePool (HandleBuffer
);
259 return EFI_UNSUPPORTED
;
263 ImageContext
.Handle
= SourceBuffer
;
264 ImageContext
.ImageRead
= PeCoffLoaderImageReadFromMemory
;
267 /// Get information about the image being loaded
269 Status
= PeCoffLoaderGetImageInfo (&ImageContext
);
270 if (EFI_ERROR (Status
)) {
275 /// Allocate buffer for loading image into SMRAM
277 PageCount
= (UINTN
)EFI_SIZE_TO_PAGES (ImageContext
.ImageSize
+ ImageContext
.SectionAlignment
);
278 Status
= gSmst
->SmmAllocatePages (AllocateAnyPages
, EfiRuntimeServicesCode
, PageCount
, &Buffer
);
279 if (EFI_ERROR (Status
)) {
283 ImageContext
.ImageAddress
= (PHYSICAL_ADDRESS
)Buffer
;
286 /// Align buffer on section boundry
288 ImageContext
.ImageAddress
+= ImageContext
.SectionAlignment
- 1;
289 ImageContext
.ImageAddress
&= ~(ImageContext
.SectionAlignment
- 1);
292 /// Load the image into SMRAM
294 Status
= PeCoffLoaderLoadImage (&ImageContext
);
295 if (EFI_ERROR (Status
)) {
300 /// Relocate the image in our new buffer
302 Status
= PeCoffLoaderRelocateImage (&ImageContext
);
303 if (EFI_ERROR (Status
)) {
308 /// Flush the instruction cache so the image data are written before we execute it
310 InvalidateInstructionCacheRange ((VOID
*)(UINTN
) ImageContext
.ImageAddress
, (UINTN
) ImageContext
.ImageSize
);
313 /// Update MP state in Framework SMST before transferring control to Framework SMM driver entry point
314 /// in case it may invoke AP
316 mFrameworkSmst
->CurrentlyExecutingCpu
= gSmst
->CurrentlyExecutingCpu
;
319 /// For Framework SMM, ImageHandle does not have to be a UEFI image handle. The only requirement is that the
320 /// ImageHandle is a unique value. Use image base address as the unique value.
322 PesudoImageHandle
= (EFI_HANDLE
)(UINTN
)ImageContext
.ImageAddress
;
324 Status
= ((EFI_IMAGE_ENTRY_POINT
)(UINTN
)ImageContext
.EntryPoint
) (PesudoImageHandle
, gST
);
325 if (!EFI_ERROR (Status
)) {
326 *ImageHandle
= PesudoImageHandle
;
331 FreePages ((VOID
*)(UINTN
)Buffer
, PageCount
);
336 Thunk service of EFI_SMM_BASE_PROTOCOL.Register().
338 @param[in, out] FunctionData Pointer to SMMBASE_FUNCTION_DATA.
342 IN OUT SMMBASE_FUNCTION_DATA
*FunctionData
347 if (FunctionData
->Args
.Register
.LegacyIA32Binary
) {
348 Status
= EFI_UNSUPPORTED
;
351 FunctionData
->Args
.Register
.FilePath
,
352 FunctionData
->Args
.Register
.SourceBuffer
,
353 FunctionData
->Args
.Register
.SourceSize
,
354 FunctionData
->Args
.Register
.ImageHandle
357 FunctionData
->Status
= Status
;
361 Thunk service of EFI_SMM_BASE_PROTOCOL.UnRegister().
363 @param[in, out] FunctionData Pointer to SMMBASE_FUNCTION_DATA.
367 IN OUT SMMBASE_FUNCTION_DATA
*FunctionData
371 /// Unregister not supported now
373 FunctionData
->Status
= EFI_UNSUPPORTED
;
377 Search for Framework SMI handler information according to specific PI SMM dispatch handle.
379 @param[in] DispatchHandle The unique handle assigned by SmiHandlerRegister().
381 @return Pointer to CALLBACK_INFO. If NULL, no callback info record is found.
385 IN EFI_HANDLE DispatchHandle
390 Node
= GetFirstNode (&mCallbackInfoListHead
);
391 while (!IsNull (&mCallbackInfoListHead
, Node
)) {
392 if (((CALLBACK_INFO
*)Node
)->DispatchHandle
== DispatchHandle
) {
393 return (CALLBACK_INFO
*)Node
;
395 Node
= GetNextNode (&mCallbackInfoListHead
, Node
);
401 Callback thunk for Framework SMI handler.
403 This thunk functions calls the Framework SMI handler and converts the return value
404 defined from Framework SMI handlers to a correpsonding return value defined by PI SMM.
406 @param[in] DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
407 @param[in] Context Points to an optional handler context which was specified when the
408 handler was registered.
409 @param[in,out] CommBuffer A pointer to a collection of data in memory that will
410 be conveyed from a non-SMM environment into an SMM environment.
411 @param[in,out] CommBufferSize The size of the CommBuffer.
413 @retval EFI_SUCCESS The interrupt was handled and quiesced. No other handlers
414 should still be called.
415 @retval EFI_WARN_INTERRUPT_SOURCE_QUIESCED The interrupt has been quiesced but other handlers should
417 @retval EFI_WARN_INTERRUPT_SOURCE_PENDING The interrupt is still pending and other handlers should still
419 @retval EFI_INTERRUPT_PENDING The interrupt could not be quiesced.
424 IN EFI_HANDLE DispatchHandle
,
425 IN CONST VOID
*Context OPTIONAL
,
426 IN OUT VOID
*CommBuffer OPTIONAL
,
427 IN OUT UINTN
*CommBufferSize OPTIONAL
431 CALLBACK_INFO
*CallbackInfo
;
434 EFI_SMM_CPU_STATE
*State
;
435 EFI_SMI_CPU_SAVE_STATE
*SaveState
;
438 /// Before transferring the control into the Framework SMI handler, update CPU Save States
439 /// and MP states in the Framework SMST.
442 for (CpuIndex
= 0; CpuIndex
< mNumberOfProcessors
; CpuIndex
++) {
443 State
= (EFI_SMM_CPU_STATE
*)gSmst
->CpuSaveState
[CpuIndex
];
444 SaveState
= &mFrameworkSmst
->CpuSaveState
[CpuIndex
].Ia32SaveState
;
446 if (State
->x86
.SMMRevId
< EFI_SMM_MIN_REV_ID_x64
) {
447 SaveState
->SMBASE
= State
->x86
.SMBASE
;
448 SaveState
->SMMRevId
= State
->x86
.SMMRevId
;
449 SaveState
->IORestart
= State
->x86
.IORestart
;
450 SaveState
->AutoHALTRestart
= State
->x86
.AutoHALTRestart
;
452 SaveState
->SMBASE
= State
->x64
.SMBASE
;
453 SaveState
->SMMRevId
= State
->x64
.SMMRevId
;
454 SaveState
->IORestart
= State
->x64
.IORestart
;
455 SaveState
->AutoHALTRestart
= State
->x64
.AutoHALTRestart
;
458 for (Index
= 0; Index
< sizeof (mCpuSaveStateConvTable
) / sizeof (CPU_SAVE_STATE_CONVERSION
); Index
++) {
460 /// Try to use SMM CPU Protocol to access CPU save states if possible
462 Status
= mSmmCpu
->ReadSaveState (
464 (UINTN
)sizeof (UINT32
),
465 mCpuSaveStateConvTable
[Index
].Register
,
467 ((UINT8
*)SaveState
) + mCpuSaveStateConvTable
[Index
].Offset
469 ASSERT_EFI_ERROR (Status
);
473 mFrameworkSmst
->CurrentlyExecutingCpu
= gSmst
->CurrentlyExecutingCpu
;
476 /// Search for Framework SMI handler information
478 CallbackInfo
= GetCallbackInfo (DispatchHandle
);
479 ASSERT (CallbackInfo
!= NULL
);
482 /// Thunk into original Framwork SMI handler
484 Status
= (CallbackInfo
->CallbackAddress
) (
485 CallbackInfo
->SmmImageHandle
,
490 /// Save CPU Save States in case any of them was modified
492 for (CpuIndex
= 0; CpuIndex
< mNumberOfProcessors
; CpuIndex
++) {
493 for (Index
= 0; Index
< sizeof (mCpuSaveStateConvTable
) / sizeof (CPU_SAVE_STATE_CONVERSION
); Index
++) {
494 Status
= mSmmCpu
->WriteSaveState (
496 (UINTN
)sizeof (UINT32
),
497 mCpuSaveStateConvTable
[Index
].Register
,
499 ((UINT8
*)&mFrameworkSmst
->CpuSaveState
[CpuIndex
].Ia32SaveState
) +
500 mCpuSaveStateConvTable
[Index
].Offset
506 /// Conversion of returned status code
509 case EFI_HANDLER_SUCCESS
:
510 Status
= EFI_WARN_INTERRUPT_SOURCE_QUIESCED
;
512 case EFI_HANDLER_CRITICAL_EXIT
:
513 case EFI_HANDLER_SOURCE_QUIESCED
:
514 Status
= EFI_SUCCESS
;
516 case EFI_HANDLER_SOURCE_PENDING
:
517 Status
= EFI_WARN_INTERRUPT_SOURCE_PENDING
;
524 Thunk service of EFI_SMM_BASE_PROTOCOL.RegisterCallback().
526 @param[in, out] FunctionData Pointer to SMMBASE_FUNCTION_DATA.
530 IN OUT SMMBASE_FUNCTION_DATA
*FunctionData
533 CALLBACK_INFO
*Buffer
;
536 /// Note that MakeLast and FloatingPointSave options are not supported in PI SMM
540 /// Allocate buffer for callback thunk information
542 Buffer
= (CALLBACK_INFO
*)AllocatePool (sizeof (CALLBACK_INFO
));
543 if (Buffer
== NULL
) {
544 FunctionData
->Status
= EFI_OUT_OF_RESOURCES
;
549 /// Fill SmmImageHandle and CallbackAddress into the thunk
551 Buffer
->SmmImageHandle
= FunctionData
->Args
.RegisterCallback
.SmmImageHandle
;
552 Buffer
->CallbackAddress
= FunctionData
->Args
.RegisterCallback
.CallbackAddress
;
555 /// Register the thunk code as a root SMI handler
557 FunctionData
->Status
= gSmst
->SmiHandlerRegister (
560 &Buffer
->DispatchHandle
562 if (EFI_ERROR (FunctionData
->Status
)) {
568 /// Save this callback info
570 InsertTailList (&mCallbackInfoListHead
, &Buffer
->Link
);
575 Thunk service of EFI_SMM_BASE_PROTOCOL.SmmAllocatePool().
577 @param[in, out] FunctionData Pointer to SMMBASE_FUNCTION_DATA.
581 IN OUT SMMBASE_FUNCTION_DATA
*FunctionData
584 FunctionData
->Status
= gSmst
->SmmAllocatePool (
585 FunctionData
->Args
.AllocatePool
.PoolType
,
586 FunctionData
->Args
.AllocatePool
.Size
,
587 FunctionData
->Args
.AllocatePool
.Buffer
592 Thunk service of EFI_SMM_BASE_PROTOCOL.SmmFreePool().
594 @param[in, out] FunctionData Pointer to SMMBASE_FUNCTION_DATA.
598 IN OUT SMMBASE_FUNCTION_DATA
*FunctionData
601 FreePool (FunctionData
->Args
.FreePool
.Buffer
);
602 FunctionData
->Status
= EFI_SUCCESS
;
606 Thunk service of EFI_SMM_BASE_PROTOCOL.Communicate().
608 @param[in, out] FunctionData Pointer to SMMBASE_FUNCTION_DATA.
612 IN OUT SMMBASE_FUNCTION_DATA
*FunctionData
616 CALLBACK_INFO
*CallbackInfo
;
618 if (FunctionData
->Args
.Communicate
.CommunicationBuffer
== NULL
) {
619 FunctionData
->Status
= EFI_INVALID_PARAMETER
;
623 Node
= GetFirstNode (&mCallbackInfoListHead
);
624 while (!IsNull (&mCallbackInfoListHead
, Node
)) {
625 CallbackInfo
= (CALLBACK_INFO
*)Node
;
627 if (FunctionData
->Args
.Communicate
.ImageHandle
== CallbackInfo
->SmmImageHandle
) {
629 /// Thunk into original Framwork SMI handler
631 (CallbackInfo
->CallbackAddress
) (
632 CallbackInfo
->SmmImageHandle
,
633 FunctionData
->Args
.Communicate
.CommunicationBuffer
,
634 FunctionData
->Args
.Communicate
.SourceSize
637 /// The message was successfully posted.
639 FunctionData
->Status
= EFI_SUCCESS
;
642 Node
= GetNextNode (&mCallbackInfoListHead
, Node
);
645 FunctionData
->Status
= EFI_INVALID_PARAMETER
;
649 Communication service SMI Handler entry.
651 This SMI handler provides services for the SMM Base Thunk driver.
653 @param[in] DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
654 @param[in] Context Points to an optional handler context which was specified when the
655 handler was registered.
656 @param[in,out] CommBuffer A pointer to a collection of data in memory that will
657 be conveyed from a non-SMM environment into an SMM environment.
658 @param[in,out] CommBufferSize The size of the CommBuffer.
660 @retval EFI_SUCCESS The interrupt was handled and quiesced. No other handlers
661 should still be called.
662 @retval EFI_WARN_INTERRUPT_SOURCE_QUIESCED The interrupt has been quiesced but other handlers should
664 @retval EFI_WARN_INTERRUPT_SOURCE_PENDING The interrupt is still pending and other handlers should still
666 @retval EFI_INTERRUPT_PENDING The interrupt could not be quiesced.
671 IN EFI_HANDLE DispatchHandle
,
672 IN CONST VOID
*RegisterContext
,
673 IN OUT VOID
*CommBuffer
,
674 IN OUT UINTN
*CommBufferSize
677 SMMBASE_FUNCTION_DATA
*FunctionData
;
679 ASSERT (CommBuffer
!= NULL
);
680 ASSERT (*CommBufferSize
== sizeof (SMMBASE_FUNCTION_DATA
));
682 FunctionData
= (SMMBASE_FUNCTION_DATA
*)CommBuffer
;
684 switch (FunctionData
->Function
) {
685 case SMMBASE_REGISTER
:
686 Register (FunctionData
);
688 case SMMBASE_UNREGISTER
:
689 UnRegister (FunctionData
);
691 case SMMBASE_REGISTER_CALLBACK
:
692 RegisterCallback (FunctionData
);
694 case SMMBASE_ALLOCATE_POOL
:
695 HelperAllocatePool (FunctionData
);
697 case SMMBASE_FREE_POOL
:
698 HelperFreePool (FunctionData
);
700 case SMMBASE_COMMUNICATE
:
701 HelperCommunicate (FunctionData
);
705 FunctionData
->Status
= EFI_UNSUPPORTED
;
711 Entry point function of the SMM Base Helper SMM driver.
713 @param[in] ImageHandle The firmware allocated handle for the EFI image.
714 @param[in] SystemTable A pointer to the EFI System Table.
716 @retval EFI_SUCCESS The entry point is executed successfully.
717 @retval other Some error occurs when executing this entry point.
722 IN EFI_HANDLE ImageHandle
,
723 IN EFI_SYSTEM_TABLE
*SystemTable
727 EFI_MP_SERVICES_PROTOCOL
*MpServices
;
728 EFI_HANDLE Handle
= NULL
;
729 UINTN NumberOfEnabledProcessors
;
732 /// Locate SMM CPU Protocol which is used later to retrieve/update CPU Save States
734 Status
= gSmst
->SmmLocateProtocol (&gEfiSmmCpuProtocolGuid
, NULL
, (VOID
**) &mSmmCpu
);
735 ASSERT_EFI_ERROR (Status
);
738 // Get MP Services Protocol
740 Status
= SystemTable
->BootServices
->LocateProtocol (&gEfiMpServiceProtocolGuid
, NULL
, (VOID
**)&MpServices
);
741 ASSERT_EFI_ERROR (Status
);
744 // Use MP Services Protocol to retrieve the number of processors and number of enabled processors
746 Status
= MpServices
->GetNumberOfProcessors (MpServices
, &mNumberOfProcessors
, &NumberOfEnabledProcessors
);
747 ASSERT_EFI_ERROR (Status
);
750 /// Interface structure of SMM BASE Helper Ready Protocol is allocated from UEFI pool
751 /// instead of SMM pool so that SMM Base Thunk driver can access it in Non-SMM mode.
753 Status
= gBS
->AllocatePool (
755 sizeof (EFI_SMM_BASE_HELPER_READY_PROTOCOL
),
756 (VOID
**)&mSmmBaseHelperReady
758 ASSERT_EFI_ERROR (Status
);
761 /// Construct Framework SMST from PI SMST
763 mFrameworkSmst
= ConstructFrameworkSmst ();
764 mSmmBaseHelperReady
->FrameworkSmst
= mFrameworkSmst
;
765 mSmmBaseHelperReady
->ServiceEntry
= SmmHandlerEntry
;
768 /// Register SMM Base Helper services for SMM Base Thunk driver
770 Status
= gSmst
->SmiHandlerRegister (SmmHandlerEntry
, &gEfiSmmBaseThunkCommunicationGuid
, &mDispatchHandle
);
771 ASSERT_EFI_ERROR (Status
);
774 /// Install EFI SMM Base Helper Protocol in the UEFI handle database
776 Status
= gBS
->InstallProtocolInterface (
778 &gEfiSmmBaseHelperReadyProtocolGuid
,
779 EFI_NATIVE_INTERFACE
,
782 ASSERT_EFI_ERROR (Status
);