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>
34 #include <Protocol/LoadPe32Image.h>
37 /// Structure for tracking paired information of registered Framework SMI handler
38 /// and correpsonding dispatch handle for SMI handler thunk.
42 EFI_HANDLE DispatchHandle
;
43 EFI_HANDLE SmmImageHandle
;
44 EFI_SMM_CALLBACK_ENTRY_POINT CallbackAddress
;
49 /// PI SMM CPU Save State register index
51 EFI_SMM_SAVE_STATE_REGISTER Register
;
53 /// Offset in Framework SMST
56 } CPU_SAVE_STATE_CONVERSION
;
58 #define CPU_SAVE_STATE_GET_OFFSET(Field) (UINTN)(&(((EFI_SMM_CPU_SAVE_STATE *) 0)->Ia32SaveState.Field))
61 EFI_HANDLE mDispatchHandle
;
62 EFI_SMM_CPU_PROTOCOL
*mSmmCpu
;
63 EFI_PE32_IMAGE_PROTOCOL
*mLoadPe32Image
;
64 EFI_GUID mEfiSmmCpuIoGuid
= EFI_SMM_CPU_IO_GUID
;
65 EFI_SMM_BASE_HELPER_READY_PROTOCOL
*mSmmBaseHelperReady
;
66 EFI_SMM_SYSTEM_TABLE
*mFrameworkSmst
;
67 UINTN mNumberOfProcessors
;
69 LIST_ENTRY mCallbackInfoListHead
= INITIALIZE_LIST_HEAD_VARIABLE (mCallbackInfoListHead
);
71 CPU_SAVE_STATE_CONVERSION mCpuSaveStateConvTable
[] = {
72 {EFI_SMM_SAVE_STATE_REGISTER_LDTBASE
, CPU_SAVE_STATE_GET_OFFSET(LDTBase
)},
73 {EFI_SMM_SAVE_STATE_REGISTER_ES
, CPU_SAVE_STATE_GET_OFFSET(ES
)},
74 {EFI_SMM_SAVE_STATE_REGISTER_CS
, CPU_SAVE_STATE_GET_OFFSET(CS
)},
75 {EFI_SMM_SAVE_STATE_REGISTER_SS
, CPU_SAVE_STATE_GET_OFFSET(SS
)},
76 {EFI_SMM_SAVE_STATE_REGISTER_DS
, CPU_SAVE_STATE_GET_OFFSET(DS
)},
77 {EFI_SMM_SAVE_STATE_REGISTER_FS
, CPU_SAVE_STATE_GET_OFFSET(FS
)},
78 {EFI_SMM_SAVE_STATE_REGISTER_GS
, CPU_SAVE_STATE_GET_OFFSET(GS
)},
79 {EFI_SMM_SAVE_STATE_REGISTER_TR_SEL
, CPU_SAVE_STATE_GET_OFFSET(TR
)},
80 {EFI_SMM_SAVE_STATE_REGISTER_DR7
, CPU_SAVE_STATE_GET_OFFSET(DR7
)},
81 {EFI_SMM_SAVE_STATE_REGISTER_DR6
, CPU_SAVE_STATE_GET_OFFSET(DR6
)},
82 {EFI_SMM_SAVE_STATE_REGISTER_RAX
, CPU_SAVE_STATE_GET_OFFSET(EAX
)},
83 {EFI_SMM_SAVE_STATE_REGISTER_RBX
, CPU_SAVE_STATE_GET_OFFSET(EBX
)},
84 {EFI_SMM_SAVE_STATE_REGISTER_RCX
, CPU_SAVE_STATE_GET_OFFSET(ECX
)},
85 {EFI_SMM_SAVE_STATE_REGISTER_RDX
, CPU_SAVE_STATE_GET_OFFSET(EDX
)},
86 {EFI_SMM_SAVE_STATE_REGISTER_RSP
, CPU_SAVE_STATE_GET_OFFSET(ESP
)},
87 {EFI_SMM_SAVE_STATE_REGISTER_RBP
, CPU_SAVE_STATE_GET_OFFSET(EBP
)},
88 {EFI_SMM_SAVE_STATE_REGISTER_RSI
, CPU_SAVE_STATE_GET_OFFSET(ESI
)},
89 {EFI_SMM_SAVE_STATE_REGISTER_RDI
, CPU_SAVE_STATE_GET_OFFSET(EDI
)},
90 {EFI_SMM_SAVE_STATE_REGISTER_RIP
, CPU_SAVE_STATE_GET_OFFSET(EIP
)},
91 {EFI_SMM_SAVE_STATE_REGISTER_RFLAGS
, CPU_SAVE_STATE_GET_OFFSET(EFLAGS
)},
92 {EFI_SMM_SAVE_STATE_REGISTER_CR0
, CPU_SAVE_STATE_GET_OFFSET(CR0
)},
93 {EFI_SMM_SAVE_STATE_REGISTER_CR3
, CPU_SAVE_STATE_GET_OFFSET(CR3
)}
97 Framework SMST SmmInstallConfigurationTable() Thunk.
99 This thunk calls the PI SMM SmmInstallConfigurationTable() and then update the configuration
100 table related fields in the Framework SMST because the PI SMM SmmInstallConfigurationTable()
101 function may modify these fields.
103 @param[in] SystemTable A pointer to the SMM System Table.
104 @param[in] Guid A pointer to the GUID for the entry to add, update, or remove.
105 @param[in] Table A pointer to the buffer of the table to add.
106 @param[in] TableSize The size of the table to install.
108 @retval EFI_SUCCESS The (Guid, Table) pair was added, updated, or removed.
109 @retval EFI_INVALID_PARAMETER Guid is not valid.
110 @retval EFI_NOT_FOUND An attempt was made to delete a non-existent entry.
111 @retval EFI_OUT_OF_RESOURCES There is not enough memory available to complete the operation.
115 SmmInstallConfigurationTable (
116 IN EFI_SMM_SYSTEM_TABLE
*SystemTable
,
124 Status
= gSmst
->SmmInstallConfigurationTable (gSmst
, Guid
, Table
, TableSize
);
125 if (!EFI_ERROR (Status
)) {
126 mFrameworkSmst
->NumberOfTableEntries
= gSmst
->NumberOfTableEntries
;
127 mFrameworkSmst
->SmmConfigurationTable
= gSmst
->SmmConfigurationTable
;
133 Construct a Framework SMST based on the PI SMM SMST.
135 @return Pointer to the constructed Framework SMST.
137 EFI_SMM_SYSTEM_TABLE
*
138 ConstructFrameworkSmst (
142 EFI_SMM_SYSTEM_TABLE
*FrameworkSmst
;
144 FrameworkSmst
= (EFI_SMM_SYSTEM_TABLE
*)AllocatePool (sizeof (EFI_SMM_SYSTEM_TABLE
));
145 ASSERT (FrameworkSmst
!= NULL
);
148 /// Copy same things from PI SMST to Framework SMST
150 CopyMem (FrameworkSmst
, gSmst
, (UINTN
)(&((EFI_SMM_SYSTEM_TABLE
*)0)->SmmIo
));
152 &FrameworkSmst
->SmmIo
,
154 sizeof (EFI_SMM_SYSTEM_TABLE
) - (UINTN
)(&((EFI_SMM_SYSTEM_TABLE
*)0)->SmmIo
)
158 /// Update Framework SMST
160 FrameworkSmst
->Hdr
.Revision
= EFI_SMM_SYSTEM_TABLE_REVISION
;
161 CopyGuid (&FrameworkSmst
->EfiSmmCpuIoGuid
, &mEfiSmmCpuIoGuid
);
163 FrameworkSmst
->CpuSaveState
= (EFI_SMM_CPU_SAVE_STATE
*)AllocateZeroPool (mNumberOfProcessors
* sizeof (EFI_SMM_CPU_SAVE_STATE
));
164 ASSERT (FrameworkSmst
->CpuSaveState
!= NULL
);
167 /// Do not support floating point state now
169 FrameworkSmst
->CpuOptionalFloatingPointState
= NULL
;
171 FrameworkSmst
->SmmInstallConfigurationTable
= SmmInstallConfigurationTable
;
173 return FrameworkSmst
;
177 Load a given Framework SMM driver into SMRAM and invoke its entry point.
179 @param[in] ParentImageHandle Parent Image Handle.
180 @param[in] FilePath Location of the image to be installed as the handler.
181 @param[in] SourceBuffer Optional source buffer in case the image file
183 @param[in] SourceSize Size of the source image file, if in memory.
184 @param[out] ImageHandle The handle that the base driver uses to decode
185 the handler. Unique among SMM handlers only,
186 not unique across DXE/EFI.
188 @retval EFI_SUCCESS The operation was successful.
189 @retval EFI_OUT_OF_RESOURCES There were no additional SMRAM resources to load the handler
190 @retval EFI_UNSUPPORTED Can not find its copy in normal memory.
191 @retval EFI_INVALID_PARAMETER The handlers was not the correct image type
195 IN EFI_HANDLE ParentImageHandle
,
196 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
197 IN VOID
*SourceBuffer
,
199 OUT EFI_HANDLE
*ImageHandle
205 EFI_PHYSICAL_ADDRESS DstBuffer
;
207 if (FilePath
== NULL
|| ImageHandle
== NULL
) {
208 return EFI_INVALID_PARAMETER
;
213 OrgPageCount
= PageCount
;
214 DstBuffer
= (UINTN
)-1;
215 Status
= gSmst
->SmmAllocatePages (
217 EfiRuntimeServicesCode
,
221 if (EFI_ERROR (Status
)) {
225 Status
= mLoadPe32Image
->LoadPeImage (
235 EFI_LOAD_PE_IMAGE_ATTRIBUTE_NONE
237 if (EFI_ERROR (Status
)) {
238 FreePages ((VOID
*)(UINTN
)DstBuffer
, OrgPageCount
);
240 } while (Status
== EFI_BUFFER_TOO_SMALL
);
242 if (!EFI_ERROR (Status
)) {
244 /// Update MP state in Framework SMST before transferring control to Framework SMM driver entry point
245 /// in case it may invoke AP
247 mFrameworkSmst
->CurrentlyExecutingCpu
= gSmst
->CurrentlyExecutingCpu
;
249 Status
= gBS
->StartImage (*ImageHandle
, NULL
, NULL
);
250 if (EFI_ERROR (Status
)) {
251 mLoadPe32Image
->UnLoadPeImage (mLoadPe32Image
, *ImageHandle
);
253 FreePages ((VOID
*)(UINTN
)DstBuffer
, PageCount
);
262 Thunk service of EFI_SMM_BASE_PROTOCOL.Register().
264 @param[in, out] FunctionData Pointer to SMMBASE_FUNCTION_DATA.
268 IN OUT SMMBASE_FUNCTION_DATA
*FunctionData
273 if (FunctionData
->Args
.Register
.LegacyIA32Binary
) {
274 Status
= EFI_UNSUPPORTED
;
277 FunctionData
->SmmBaseImageHandle
,
278 FunctionData
->Args
.Register
.FilePath
,
279 FunctionData
->Args
.Register
.SourceBuffer
,
280 FunctionData
->Args
.Register
.SourceSize
,
281 FunctionData
->Args
.Register
.ImageHandle
284 FunctionData
->Status
= Status
;
288 Thunk service of EFI_SMM_BASE_PROTOCOL.UnRegister().
290 @param[in, out] FunctionData Pointer to SMMBASE_FUNCTION_DATA.
294 IN OUT SMMBASE_FUNCTION_DATA
*FunctionData
298 /// Unregister not supported now
300 FunctionData
->Status
= EFI_UNSUPPORTED
;
304 Search for Framework SMI handler information according to specific PI SMM dispatch handle.
306 @param[in] DispatchHandle The unique handle assigned by SmiHandlerRegister().
308 @return Pointer to CALLBACK_INFO. If NULL, no callback info record is found.
312 IN EFI_HANDLE DispatchHandle
317 Node
= GetFirstNode (&mCallbackInfoListHead
);
318 while (!IsNull (&mCallbackInfoListHead
, Node
)) {
319 if (((CALLBACK_INFO
*)Node
)->DispatchHandle
== DispatchHandle
) {
320 return (CALLBACK_INFO
*)Node
;
322 Node
= GetNextNode (&mCallbackInfoListHead
, Node
);
328 Callback thunk for Framework SMI handler.
330 This thunk functions calls the Framework SMI handler and converts the return value
331 defined from Framework SMI handlers to a correpsonding return value defined by PI SMM.
333 @param[in] DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
334 @param[in] Context Points to an optional handler context which was specified when the
335 handler was registered.
336 @param[in, out] CommBuffer A pointer to a collection of data in memory that will
337 be conveyed from a non-SMM environment into an SMM environment.
338 @param[in, out] CommBufferSize The size of the CommBuffer.
340 @retval EFI_SUCCESS The interrupt was handled and quiesced. No other handlers
341 should still be called.
342 @retval EFI_WARN_INTERRUPT_SOURCE_QUIESCED The interrupt has been quiesced but other handlers should
344 @retval EFI_WARN_INTERRUPT_SOURCE_PENDING The interrupt is still pending and other handlers should still
346 @retval EFI_INTERRUPT_PENDING The interrupt could not be quiesced.
351 IN EFI_HANDLE DispatchHandle
,
352 IN CONST VOID
*Context OPTIONAL
,
353 IN OUT VOID
*CommBuffer OPTIONAL
,
354 IN OUT UINTN
*CommBufferSize OPTIONAL
358 CALLBACK_INFO
*CallbackInfo
;
361 EFI_SMM_CPU_STATE
*State
;
362 EFI_SMI_CPU_SAVE_STATE
*SaveState
;
365 /// Before transferring the control into the Framework SMI handler, update CPU Save States
366 /// and MP states in the Framework SMST.
369 for (CpuIndex
= 0; CpuIndex
< mNumberOfProcessors
; CpuIndex
++) {
370 State
= (EFI_SMM_CPU_STATE
*)gSmst
->CpuSaveState
[CpuIndex
];
371 SaveState
= &mFrameworkSmst
->CpuSaveState
[CpuIndex
].Ia32SaveState
;
373 if (State
->x86
.SMMRevId
< EFI_SMM_MIN_REV_ID_x64
) {
374 SaveState
->SMBASE
= State
->x86
.SMBASE
;
375 SaveState
->SMMRevId
= State
->x86
.SMMRevId
;
376 SaveState
->IORestart
= State
->x86
.IORestart
;
377 SaveState
->AutoHALTRestart
= State
->x86
.AutoHALTRestart
;
379 SaveState
->SMBASE
= State
->x64
.SMBASE
;
380 SaveState
->SMMRevId
= State
->x64
.SMMRevId
;
381 SaveState
->IORestart
= State
->x64
.IORestart
;
382 SaveState
->AutoHALTRestart
= State
->x64
.AutoHALTRestart
;
385 for (Index
= 0; Index
< sizeof (mCpuSaveStateConvTable
) / sizeof (CPU_SAVE_STATE_CONVERSION
); Index
++) {
387 /// Try to use SMM CPU Protocol to access CPU save states if possible
389 Status
= mSmmCpu
->ReadSaveState (
391 (UINTN
)sizeof (UINT32
),
392 mCpuSaveStateConvTable
[Index
].Register
,
394 ((UINT8
*)SaveState
) + mCpuSaveStateConvTable
[Index
].Offset
396 ASSERT_EFI_ERROR (Status
);
400 mFrameworkSmst
->CurrentlyExecutingCpu
= gSmst
->CurrentlyExecutingCpu
;
403 /// Search for Framework SMI handler information
405 CallbackInfo
= GetCallbackInfo (DispatchHandle
);
406 ASSERT (CallbackInfo
!= NULL
);
409 /// Thunk into original Framwork SMI handler
411 Status
= (CallbackInfo
->CallbackAddress
) (
412 CallbackInfo
->SmmImageHandle
,
417 /// Save CPU Save States in case any of them was modified
419 for (CpuIndex
= 0; CpuIndex
< mNumberOfProcessors
; CpuIndex
++) {
420 for (Index
= 0; Index
< sizeof (mCpuSaveStateConvTable
) / sizeof (CPU_SAVE_STATE_CONVERSION
); Index
++) {
421 Status
= mSmmCpu
->WriteSaveState (
423 (UINTN
)sizeof (UINT32
),
424 mCpuSaveStateConvTable
[Index
].Register
,
426 ((UINT8
*)&mFrameworkSmst
->CpuSaveState
[CpuIndex
].Ia32SaveState
) +
427 mCpuSaveStateConvTable
[Index
].Offset
433 /// Conversion of returned status code
436 case EFI_HANDLER_SUCCESS
:
437 Status
= EFI_WARN_INTERRUPT_SOURCE_QUIESCED
;
439 case EFI_HANDLER_CRITICAL_EXIT
:
440 case EFI_HANDLER_SOURCE_QUIESCED
:
441 Status
= EFI_SUCCESS
;
443 case EFI_HANDLER_SOURCE_PENDING
:
444 Status
= EFI_WARN_INTERRUPT_SOURCE_PENDING
;
451 Thunk service of EFI_SMM_BASE_PROTOCOL.RegisterCallback().
453 @param[in, out] FunctionData Pointer to SMMBASE_FUNCTION_DATA.
457 IN OUT SMMBASE_FUNCTION_DATA
*FunctionData
460 CALLBACK_INFO
*Buffer
;
463 /// Note that MakeLast and FloatingPointSave options are not supported in PI SMM
467 /// Allocate buffer for callback thunk information
469 Buffer
= (CALLBACK_INFO
*)AllocatePool (sizeof (CALLBACK_INFO
));
470 if (Buffer
== NULL
) {
471 FunctionData
->Status
= EFI_OUT_OF_RESOURCES
;
476 /// Fill SmmImageHandle and CallbackAddress into the thunk
478 Buffer
->SmmImageHandle
= FunctionData
->Args
.RegisterCallback
.SmmImageHandle
;
479 Buffer
->CallbackAddress
= FunctionData
->Args
.RegisterCallback
.CallbackAddress
;
482 /// Register the thunk code as a root SMI handler
484 FunctionData
->Status
= gSmst
->SmiHandlerRegister (
487 &Buffer
->DispatchHandle
489 if (EFI_ERROR (FunctionData
->Status
)) {
495 /// Save this callback info
497 InsertTailList (&mCallbackInfoListHead
, &Buffer
->Link
);
502 Thunk service of EFI_SMM_BASE_PROTOCOL.SmmAllocatePool().
504 @param[in, out] FunctionData Pointer to SMMBASE_FUNCTION_DATA.
508 IN OUT SMMBASE_FUNCTION_DATA
*FunctionData
511 FunctionData
->Status
= gSmst
->SmmAllocatePool (
512 FunctionData
->Args
.AllocatePool
.PoolType
,
513 FunctionData
->Args
.AllocatePool
.Size
,
514 FunctionData
->Args
.AllocatePool
.Buffer
519 Thunk service of EFI_SMM_BASE_PROTOCOL.SmmFreePool().
521 @param[in, out] FunctionData Pointer to SMMBASE_FUNCTION_DATA.
525 IN OUT SMMBASE_FUNCTION_DATA
*FunctionData
528 FreePool (FunctionData
->Args
.FreePool
.Buffer
);
529 FunctionData
->Status
= EFI_SUCCESS
;
533 Thunk service of EFI_SMM_BASE_PROTOCOL.Communicate().
535 @param[in, out] FunctionData Pointer to SMMBASE_FUNCTION_DATA.
539 IN OUT SMMBASE_FUNCTION_DATA
*FunctionData
543 CALLBACK_INFO
*CallbackInfo
;
545 if (FunctionData
->Args
.Communicate
.CommunicationBuffer
== NULL
) {
546 FunctionData
->Status
= EFI_INVALID_PARAMETER
;
550 Node
= GetFirstNode (&mCallbackInfoListHead
);
551 while (!IsNull (&mCallbackInfoListHead
, Node
)) {
552 CallbackInfo
= (CALLBACK_INFO
*)Node
;
554 if (FunctionData
->Args
.Communicate
.ImageHandle
== CallbackInfo
->SmmImageHandle
) {
556 /// Thunk into original Framwork SMI handler
558 (CallbackInfo
->CallbackAddress
) (
559 CallbackInfo
->SmmImageHandle
,
560 FunctionData
->Args
.Communicate
.CommunicationBuffer
,
561 FunctionData
->Args
.Communicate
.SourceSize
564 /// The message was successfully posted.
566 FunctionData
->Status
= EFI_SUCCESS
;
569 Node
= GetNextNode (&mCallbackInfoListHead
, Node
);
572 FunctionData
->Status
= EFI_INVALID_PARAMETER
;
576 Communication service SMI Handler entry.
578 This SMI handler provides services for the SMM Base Thunk driver.
580 @param[in] DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
581 @param[in] RegisterContext Points to an optional handler context which was specified when the
582 handler was registered.
583 @param[in, out] CommBuffer A pointer to a collection of data in memory that will
584 be conveyed from a non-SMM environment into an SMM environment.
585 @param[in, out] CommBufferSize The size of the CommBuffer.
587 @retval EFI_SUCCESS The interrupt was handled and quiesced. No other handlers
588 should still be called.
589 @retval EFI_WARN_INTERRUPT_SOURCE_QUIESCED The interrupt has been quiesced but other handlers should
591 @retval EFI_WARN_INTERRUPT_SOURCE_PENDING The interrupt is still pending and other handlers should still
593 @retval EFI_INTERRUPT_PENDING The interrupt could not be quiesced.
598 IN EFI_HANDLE DispatchHandle
,
599 IN CONST VOID
*RegisterContext
,
600 IN OUT VOID
*CommBuffer
,
601 IN OUT UINTN
*CommBufferSize
604 SMMBASE_FUNCTION_DATA
*FunctionData
;
606 ASSERT (CommBuffer
!= NULL
);
607 ASSERT (*CommBufferSize
== sizeof (SMMBASE_FUNCTION_DATA
));
609 FunctionData
= (SMMBASE_FUNCTION_DATA
*)CommBuffer
;
611 switch (FunctionData
->Function
) {
612 case SmmBaseFunctionRegister
:
613 Register (FunctionData
);
615 case SmmBaseFunctionUnregister
:
616 UnRegister (FunctionData
);
618 case SmmBaseFunctionRegisterCallback
:
619 RegisterCallback (FunctionData
);
621 case SmmBaseFunctionAllocatePool
:
622 HelperAllocatePool (FunctionData
);
624 case SmmBaseFunctionFreePool
:
625 HelperFreePool (FunctionData
);
627 case SmmBaseFunctionCommunicate
:
628 HelperCommunicate (FunctionData
);
632 FunctionData
->Status
= EFI_UNSUPPORTED
;
638 Entry point function of the SMM Base Helper SMM driver.
640 @param[in] ImageHandle The firmware allocated handle for the EFI image.
641 @param[in] SystemTable A pointer to the EFI System Table.
643 @retval EFI_SUCCESS The entry point is executed successfully.
644 @retval other Some error occurs when executing this entry point.
649 IN EFI_HANDLE ImageHandle
,
650 IN EFI_SYSTEM_TABLE
*SystemTable
654 EFI_MP_SERVICES_PROTOCOL
*MpServices
;
656 UINTN NumberOfEnabledProcessors
;
660 /// Locate SMM CPU Protocol which is used later to retrieve/update CPU Save States
662 Status
= gSmst
->SmmLocateProtocol (&gEfiSmmCpuProtocolGuid
, NULL
, (VOID
**) &mSmmCpu
);
663 ASSERT_EFI_ERROR (Status
);
666 /// Locate PE32 Image Protocol which is used later to load Framework SMM driver
668 Status
= SystemTable
->BootServices
->LocateProtocol (&gEfiLoadPeImageProtocolGuid
, NULL
, (VOID
**) &mLoadPe32Image
);
669 ASSERT_EFI_ERROR (Status
);
672 // Get MP Services Protocol
674 Status
= SystemTable
->BootServices
->LocateProtocol (&gEfiMpServiceProtocolGuid
, NULL
, (VOID
**)&MpServices
);
675 ASSERT_EFI_ERROR (Status
);
678 // Use MP Services Protocol to retrieve the number of processors and number of enabled processors
680 Status
= MpServices
->GetNumberOfProcessors (MpServices
, &mNumberOfProcessors
, &NumberOfEnabledProcessors
);
681 ASSERT_EFI_ERROR (Status
);
684 /// Interface structure of SMM BASE Helper Ready Protocol is allocated from UEFI pool
685 /// instead of SMM pool so that SMM Base Thunk driver can access it in Non-SMM mode.
687 Status
= gBS
->AllocatePool (
689 sizeof (EFI_SMM_BASE_HELPER_READY_PROTOCOL
),
690 (VOID
**)&mSmmBaseHelperReady
692 ASSERT_EFI_ERROR (Status
);
695 /// Construct Framework SMST from PI SMST
697 mFrameworkSmst
= ConstructFrameworkSmst ();
698 mSmmBaseHelperReady
->FrameworkSmst
= mFrameworkSmst
;
699 mSmmBaseHelperReady
->ServiceEntry
= SmmHandlerEntry
;
702 /// Register SMM Base Helper services for SMM Base Thunk driver
704 Status
= gSmst
->SmiHandlerRegister (SmmHandlerEntry
, &gEfiSmmBaseThunkCommunicationGuid
, &mDispatchHandle
);
705 ASSERT_EFI_ERROR (Status
);
708 /// Install EFI SMM Base Helper Protocol in the UEFI handle database
710 Status
= gBS
->InstallProtocolInterface (
712 &gEfiSmmBaseHelperReadyProtocolGuid
,
713 EFI_NATIVE_INTERFACE
,
716 ASSERT_EFI_ERROR (Status
);