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 <Guid/SmmBaseThunkCommunication.h>
28 #include <Protocol/SmmBaseHelperReady.h>
29 #include <Protocol/SmmCpu.h>
30 #include <Protocol/LoadedImage.h>
31 #include <Protocol/SmmCpuSaveState.h>
34 /// Structure for tracking paired information of registered Framework SMI handler
35 /// and correpsonding dispatch handle for SMI handler thunk.
39 EFI_HANDLE DispatchHandle
;
40 EFI_HANDLE SmmImageHandle
;
41 EFI_SMM_CALLBACK_ENTRY_POINT CallbackAddress
;
46 /// PI SMM CPU Save State register index
48 EFI_SMM_SAVE_STATE_REGISTER Register
;
50 /// Offset in Framework SMST
53 } CPU_SAVE_STATE_CONVERSION
;
55 #define CPU_SAVE_STATE_GET_OFFSET(Field) (UINTN)(&(((EFI_SMM_CPU_SAVE_STATE *) 0)->Ia32SaveState.Field))
58 EFI_HANDLE mDispatchHandle
;
59 EFI_SMM_CPU_PROTOCOL
*mSmmCpu
;
60 EFI_GUID mEfiSmmCpuIoGuid
= EFI_SMM_CPU_IO_GUID
;
61 EFI_SMM_BASE_HELPER_READY_PROTOCOL
*mSmmBaseHelperReady
;
62 EFI_SMM_SYSTEM_TABLE
*mFrameworkSmst
;
64 LIST_ENTRY mCallbackInfoListHead
= INITIALIZE_LIST_HEAD_VARIABLE (mCallbackInfoListHead
);
66 CPU_SAVE_STATE_CONVERSION mCpuSaveStateConvTable
[] = {
67 {EFI_SMM_SAVE_STATE_REGISTER_LDTBASE
, CPU_SAVE_STATE_GET_OFFSET(LDTBase
)},
68 {EFI_SMM_SAVE_STATE_REGISTER_ES
, CPU_SAVE_STATE_GET_OFFSET(ES
)},
69 {EFI_SMM_SAVE_STATE_REGISTER_CS
, CPU_SAVE_STATE_GET_OFFSET(CS
)},
70 {EFI_SMM_SAVE_STATE_REGISTER_SS
, CPU_SAVE_STATE_GET_OFFSET(SS
)},
71 {EFI_SMM_SAVE_STATE_REGISTER_DS
, CPU_SAVE_STATE_GET_OFFSET(DS
)},
72 {EFI_SMM_SAVE_STATE_REGISTER_FS
, CPU_SAVE_STATE_GET_OFFSET(FS
)},
73 {EFI_SMM_SAVE_STATE_REGISTER_GS
, CPU_SAVE_STATE_GET_OFFSET(GS
)},
74 {EFI_SMM_SAVE_STATE_REGISTER_TR_SEL
, CPU_SAVE_STATE_GET_OFFSET(TR
)},
75 {EFI_SMM_SAVE_STATE_REGISTER_DR7
, CPU_SAVE_STATE_GET_OFFSET(DR7
)},
76 {EFI_SMM_SAVE_STATE_REGISTER_DR6
, CPU_SAVE_STATE_GET_OFFSET(DR6
)},
77 {EFI_SMM_SAVE_STATE_REGISTER_RAX
, CPU_SAVE_STATE_GET_OFFSET(EAX
)},
78 {EFI_SMM_SAVE_STATE_REGISTER_RBX
, CPU_SAVE_STATE_GET_OFFSET(EBX
)},
79 {EFI_SMM_SAVE_STATE_REGISTER_RCX
, CPU_SAVE_STATE_GET_OFFSET(ECX
)},
80 {EFI_SMM_SAVE_STATE_REGISTER_RDX
, CPU_SAVE_STATE_GET_OFFSET(EDX
)},
81 {EFI_SMM_SAVE_STATE_REGISTER_RSP
, CPU_SAVE_STATE_GET_OFFSET(ESP
)},
82 {EFI_SMM_SAVE_STATE_REGISTER_RBP
, CPU_SAVE_STATE_GET_OFFSET(EBP
)},
83 {EFI_SMM_SAVE_STATE_REGISTER_RSI
, CPU_SAVE_STATE_GET_OFFSET(ESI
)},
84 {EFI_SMM_SAVE_STATE_REGISTER_RDI
, CPU_SAVE_STATE_GET_OFFSET(EDI
)},
85 {EFI_SMM_SAVE_STATE_REGISTER_RIP
, CPU_SAVE_STATE_GET_OFFSET(EIP
)},
86 {EFI_SMM_SAVE_STATE_REGISTER_RFLAGS
, CPU_SAVE_STATE_GET_OFFSET(EFLAGS
)},
87 {EFI_SMM_SAVE_STATE_REGISTER_CR0
, CPU_SAVE_STATE_GET_OFFSET(CR0
)},
88 {EFI_SMM_SAVE_STATE_REGISTER_CR3
, CPU_SAVE_STATE_GET_OFFSET(CR3
)}
92 Framework SMST SmmInstallConfigurationTable() Thunk.
94 This thunk calls the PI SMM SmmInstallConfigurationTable() and then update the configuration
95 table related fields in the Framework SMST because the PI SMM SmmInstallConfigurationTable()
96 function may modify these fields.
98 @param[in] SystemTable A pointer to the SMM System Table.
99 @param[in] Guid A pointer to the GUID for the entry to add, update, or remove.
100 @param[in] Table A pointer to the buffer of the table to add.
101 @param[in] TableSize The size of the table to install.
103 @retval EFI_SUCCESS The (Guid, Table) pair was added, updated, or removed.
104 @retval EFI_INVALID_PARAMETER Guid is not valid.
105 @retval EFI_NOT_FOUND An attempt was made to delete a non-existent entry.
106 @retval EFI_OUT_OF_RESOURCES There is not enough memory available to complete the operation.
110 SmmInstallConfigurationTable (
111 IN EFI_SMM_SYSTEM_TABLE
*SystemTable
,
119 Status
= gSmst
->SmmInstallConfigurationTable (gSmst
, Guid
, Table
, TableSize
);
120 if (!EFI_ERROR (Status
)) {
121 mFrameworkSmst
->NumberOfTableEntries
= gSmst
->NumberOfTableEntries
;
122 mFrameworkSmst
->SmmConfigurationTable
= gSmst
->SmmConfigurationTable
;
128 Construct a Framework SMST based on the PI SMM SMST.
130 @return Pointer to the constructed Framework SMST.
132 EFI_SMM_SYSTEM_TABLE
*
133 ConstructFrameworkSmst (
138 EFI_SMM_SYSTEM_TABLE
*FrameworkSmst
;
140 Status
= gSmst
->SmmAllocatePool (
141 EfiRuntimeServicesData
,
142 sizeof (EFI_SMM_SYSTEM_TABLE
),
143 (VOID
**)&FrameworkSmst
145 ASSERT_EFI_ERROR (Status
);
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 Status
= gSmst
->SmmAllocatePool (
164 EfiRuntimeServicesData
,
165 gSmst
->NumberOfCpus
* sizeof (EFI_SMM_CPU_SAVE_STATE
),
166 (VOID
**)&FrameworkSmst
->CpuSaveState
168 ASSERT_EFI_ERROR (Status
);
169 ZeroMem (FrameworkSmst
->CpuSaveState
, gSmst
->NumberOfCpus
* sizeof (EFI_SMM_CPU_SAVE_STATE
));
172 /// Do not support floating point state now
174 FrameworkSmst
->CpuOptionalFloatingPointState
= NULL
;
176 FrameworkSmst
->SmmInstallConfigurationTable
= SmmInstallConfigurationTable
;
178 return FrameworkSmst
;
182 Load a given Framework SMM driver into SMRAM and invoke its entry point.
184 @param[in] FilePath Location of the image to be installed as the handler.
185 @param[in] SourceBuffer Optional source buffer in case the image file
187 @param[in] SourceSize Size of the source image file, if in memory.
188 @param[out] ImageHandle The handle that the base driver uses to decode
189 the handler. Unique among SMM handlers only,
190 not unique across DXE/EFI.
192 @retval EFI_SUCCESS The operation was successful.
193 @retval EFI_OUT_OF_RESOURCES There were no additional SMRAM resources to load the handler
194 @retval EFI_UNSUPPORTED Can not find its copy in normal memory.
195 @retval EFI_INVALID_PARAMETER The handlers was not the correct image type
199 IN EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
200 IN VOID
*SourceBuffer
,
202 OUT EFI_HANDLE
*ImageHandle
207 EFI_PHYSICAL_ADDRESS Buffer
;
208 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
209 EFI_HANDLE PesudoImageHandle
;
212 EFI_HANDLE
*HandleBuffer
;
213 EFI_LOADED_IMAGE_PROTOCOL
*LoadedImage
;
214 EFI_DEVICE_PATH
*LoadedImageDevicePath
;
215 UINTN DevicePathSize
;
217 if (FilePath
== NULL
|| ImageHandle
== NULL
) {
218 return EFI_INVALID_PARAMETER
;
222 /// Assume Framework SMM driver has an image copy in memory before registering itself into SMRAM.
223 /// Currently only supports load Framework SMM driver from existing image copy in memory.
224 /// Load PE32 Image Protocol can be used to support loading Framework SMM driver directly from FV.
226 if (SourceBuffer
== NULL
) {
227 Status
= gBS
->LocateHandleBuffer (
229 &gEfiLoadedImageDevicePathProtocolGuid
,
234 if (EFI_ERROR (Status
)) {
235 return EFI_UNSUPPORTED
;
238 DevicePathSize
= GetDevicePathSize (FilePath
);
240 for (Index
= 0; Index
< NumHandles
; Index
++) {
241 Status
= gBS
->HandleProtocol (
243 &gEfiLoadedImageDevicePathProtocolGuid
,
244 (VOID
**)&LoadedImageDevicePath
246 ASSERT_EFI_ERROR (Status
);
248 if (GetDevicePathSize (LoadedImageDevicePath
) == DevicePathSize
&&
249 CompareMem (LoadedImageDevicePath
, FilePath
, DevicePathSize
) == 0) {
254 if (Index
< NumHandles
) {
255 Status
= gBS
->HandleProtocol (
257 &gEfiLoadedImageProtocolGuid
,
258 (VOID
**)&LoadedImage
260 ASSERT_EFI_ERROR (Status
);
262 SourceBuffer
= LoadedImage
->ImageBase
;
263 gBS
->FreePool (HandleBuffer
);
265 gBS
->FreePool (HandleBuffer
);
266 return EFI_UNSUPPORTED
;
270 ImageContext
.Handle
= SourceBuffer
;
271 ImageContext
.ImageRead
= PeCoffLoaderImageReadFromMemory
;
274 /// Get information about the image being loaded
276 Status
= PeCoffLoaderGetImageInfo (&ImageContext
);
277 if (EFI_ERROR (Status
)) {
282 /// Allocate buffer for loading image into SMRAM
284 PageCount
= (UINTN
)EFI_SIZE_TO_PAGES (ImageContext
.ImageSize
+ ImageContext
.SectionAlignment
);
285 Status
= gSmst
->SmmAllocatePages (AllocateAnyPages
, EfiRuntimeServicesCode
, PageCount
, &Buffer
);
286 if (EFI_ERROR (Status
)) {
290 ImageContext
.ImageAddress
= (PHYSICAL_ADDRESS
)Buffer
;
293 /// Align buffer on section boundry
295 ImageContext
.ImageAddress
+= ImageContext
.SectionAlignment
- 1;
296 ImageContext
.ImageAddress
&= ~(ImageContext
.SectionAlignment
- 1);
299 /// Load the image into SMRAM
301 Status
= PeCoffLoaderLoadImage (&ImageContext
);
302 if (EFI_ERROR (Status
)) {
307 /// Relocate the image in our new buffer
309 Status
= PeCoffLoaderRelocateImage (&ImageContext
);
310 if (EFI_ERROR (Status
)) {
315 /// Flush the instruction cache so the image data are written before we execute it
317 InvalidateInstructionCacheRange ((VOID
*)(UINTN
) ImageContext
.ImageAddress
, (UINTN
) ImageContext
.ImageSize
);
320 /// Update MP state in Framework SMST before transferring control to Framework SMM driver entry point
321 /// in case it may invoke AP
323 mFrameworkSmst
->CurrentlyExecutingCpu
= gSmst
->CurrentlyExecutingCpu
;
326 /// For Framework SMM, ImageHandle does not have to be a UEFI image handle. The only requirement is that the
327 /// ImageHandle is a unique value. Use image base address as the unique value.
329 PesudoImageHandle
= (EFI_HANDLE
)(UINTN
)ImageContext
.ImageAddress
;
331 Status
= ((EFI_IMAGE_ENTRY_POINT
)(UINTN
)ImageContext
.EntryPoint
) (PesudoImageHandle
, gST
);
332 if (!EFI_ERROR (Status
)) {
333 *ImageHandle
= PesudoImageHandle
;
338 gSmst
->SmmFreePages (Buffer
, PageCount
);
343 Thunk service of EFI_SMM_BASE_PROTOCOL.Register().
345 @param[in, out] FunctionData Pointer to SMMBASE_FUNCTION_DATA.
349 IN OUT SMMBASE_FUNCTION_DATA
*FunctionData
354 if (FunctionData
->Args
.Register
.LegacyIA32Binary
) {
355 Status
= EFI_UNSUPPORTED
;
358 FunctionData
->Args
.Register
.FilePath
,
359 FunctionData
->Args
.Register
.SourceBuffer
,
360 FunctionData
->Args
.Register
.SourceSize
,
361 FunctionData
->Args
.Register
.ImageHandle
364 FunctionData
->Status
= Status
;
368 Thunk service of EFI_SMM_BASE_PROTOCOL.UnRegister().
370 @param[in, out] FunctionData Pointer to SMMBASE_FUNCTION_DATA.
374 IN OUT SMMBASE_FUNCTION_DATA
*FunctionData
378 /// Unregister not supported now
380 FunctionData
->Status
= EFI_UNSUPPORTED
;
384 Search for Framework SMI handler information according to specific PI SMM dispatch handle.
386 @param[in] DispatchHandle The unique handle assigned by SmiHandlerRegister().
388 @return Pointer to CALLBACK_INFO. If NULL, no callback info record is found.
392 IN EFI_HANDLE DispatchHandle
397 Node
= GetFirstNode (&mCallbackInfoListHead
);
398 while (!IsNull (&mCallbackInfoListHead
, Node
)) {
399 if (((CALLBACK_INFO
*)Node
)->DispatchHandle
== DispatchHandle
) {
400 return (CALLBACK_INFO
*)Node
;
402 Node
= GetNextNode (&mCallbackInfoListHead
, Node
);
408 Callback thunk for Framework SMI handler.
410 This thunk functions calls the Framework SMI handler and converts the return value
411 defined from Framework SMI handlers to a correpsonding return value defined by PI SMM.
413 @param[in] DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
414 @param[in] Context Points to an optional handler context which was specified when the
415 handler was registered.
416 @param[in,out] CommBuffer A pointer to a collection of data in memory that will
417 be conveyed from a non-SMM environment into an SMM environment.
418 @param[in,out] CommBufferSize The size of the CommBuffer.
420 @retval EFI_SUCCESS The interrupt was handled and quiesced. No other handlers
421 should still be called.
422 @retval EFI_WARN_INTERRUPT_SOURCE_QUIESCED The interrupt has been quiesced but other handlers should
424 @retval EFI_WARN_INTERRUPT_SOURCE_PENDING The interrupt is still pending and other handlers should still
426 @retval EFI_INTERRUPT_PENDING The interrupt could not be quiesced.
431 IN EFI_HANDLE DispatchHandle
,
432 IN CONST VOID
*Context OPTIONAL
,
433 IN OUT VOID
*CommBuffer OPTIONAL
,
434 IN OUT UINTN
*CommBufferSize OPTIONAL
438 CALLBACK_INFO
*CallbackInfo
;
441 EFI_SMM_CPU_STATE
*State
;
442 EFI_SMI_CPU_SAVE_STATE
*SaveState
;
445 /// Before transferring the control into the Framework SMI handler, update CPU Save States
446 /// and MP states in the Framework SMST.
449 for (CpuIndex
= 0; CpuIndex
< gSmst
->NumberOfCpus
; CpuIndex
++) {
450 State
= (EFI_SMM_CPU_STATE
*)gSmst
->CpuSaveState
[CpuIndex
];
451 SaveState
= &mFrameworkSmst
->CpuSaveState
[CpuIndex
].Ia32SaveState
;
453 if (State
->x86
.SMMRevId
< EFI_SMM_MIN_REV_ID_x64
) {
454 SaveState
->SMBASE
= State
->x86
.SMBASE
;
455 SaveState
->SMMRevId
= State
->x86
.SMMRevId
;
456 SaveState
->IORestart
= State
->x86
.IORestart
;
457 SaveState
->AutoHALTRestart
= State
->x86
.AutoHALTRestart
;
459 SaveState
->SMBASE
= State
->x64
.SMBASE
;
460 SaveState
->SMMRevId
= State
->x64
.SMMRevId
;
461 SaveState
->IORestart
= State
->x64
.IORestart
;
462 SaveState
->AutoHALTRestart
= State
->x64
.AutoHALTRestart
;
465 for (Index
= 0; Index
< sizeof (mCpuSaveStateConvTable
) / sizeof (CPU_SAVE_STATE_CONVERSION
); Index
++) {
467 /// Try to use SMM CPU Protocol to access CPU save states if possible
469 Status
= mSmmCpu
->ReadSaveState (
471 (UINTN
)sizeof (UINT32
),
472 mCpuSaveStateConvTable
[Index
].Register
,
474 ((UINT8
*)SaveState
) + mCpuSaveStateConvTable
[Index
].Offset
476 ASSERT_EFI_ERROR (Status
);
480 mFrameworkSmst
->CurrentlyExecutingCpu
= gSmst
->CurrentlyExecutingCpu
;
483 /// Search for Framework SMI handler information
485 CallbackInfo
= GetCallbackInfo (DispatchHandle
);
486 ASSERT (CallbackInfo
!= NULL
);
489 /// Thunk into original Framwork SMI handler
491 Status
= (CallbackInfo
->CallbackAddress
) (
492 CallbackInfo
->SmmImageHandle
,
497 /// Save CPU Save States in case any of them was modified
499 for (CpuIndex
= 0; CpuIndex
< gSmst
->NumberOfCpus
; CpuIndex
++) {
500 for (Index
= 0; Index
< sizeof (mCpuSaveStateConvTable
) / sizeof (CPU_SAVE_STATE_CONVERSION
); Index
++) {
501 Status
= mSmmCpu
->WriteSaveState (
503 (UINTN
)sizeof (UINT32
),
504 mCpuSaveStateConvTable
[Index
].Register
,
506 ((UINT8
*)&mFrameworkSmst
->CpuSaveState
[CpuIndex
].Ia32SaveState
) +
507 mCpuSaveStateConvTable
[Index
].Offset
513 /// Conversion of returned status code
516 case EFI_HANDLER_SUCCESS
:
517 Status
= EFI_WARN_INTERRUPT_SOURCE_QUIESCED
;
519 case EFI_HANDLER_CRITICAL_EXIT
:
520 case EFI_HANDLER_SOURCE_QUIESCED
:
521 Status
= EFI_SUCCESS
;
523 case EFI_HANDLER_SOURCE_PENDING
:
524 Status
= EFI_WARN_INTERRUPT_SOURCE_PENDING
;
531 Thunk service of EFI_SMM_BASE_PROTOCOL.RegisterCallback().
533 @param[in, out] FunctionData Pointer to SMMBASE_FUNCTION_DATA.
537 IN OUT SMMBASE_FUNCTION_DATA
*FunctionData
541 CALLBACK_INFO
*Buffer
;
544 /// Note that MakeLast and FloatingPointSave options are not supported in PI SMM
548 /// Allocate buffer for callback thunk information
550 Status
= gSmst
->SmmAllocatePool (
551 EfiRuntimeServicesCode
,
552 sizeof (CALLBACK_INFO
),
555 if (!EFI_ERROR (Status
)) {
557 /// Fill SmmImageHandle and CallbackAddress into the thunk
559 Buffer
->SmmImageHandle
= FunctionData
->Args
.RegisterCallback
.SmmImageHandle
;
560 Buffer
->CallbackAddress
= FunctionData
->Args
.RegisterCallback
.CallbackAddress
;
563 /// Register the thunk code as a root SMI handler
565 Status
= gSmst
->SmiHandlerRegister (
568 &Buffer
->DispatchHandle
570 if (!EFI_ERROR (Status
)) {
572 /// Save this callback info
574 InsertTailList (&mCallbackInfoListHead
, &Buffer
->Link
);
576 gSmst
->SmmFreePool (Buffer
);
579 FunctionData
->Status
= Status
;
584 Thunk service of EFI_SMM_BASE_PROTOCOL.SmmAllocatePool().
586 @param[in, out] FunctionData Pointer to SMMBASE_FUNCTION_DATA.
590 IN OUT SMMBASE_FUNCTION_DATA
*FunctionData
593 FunctionData
->Status
= gSmst
->SmmAllocatePool (
594 FunctionData
->Args
.AllocatePool
.PoolType
,
595 FunctionData
->Args
.AllocatePool
.Size
,
596 FunctionData
->Args
.AllocatePool
.Buffer
601 Thunk service of EFI_SMM_BASE_PROTOCOL.SmmFreePool().
603 @param[in, out] FunctionData Pointer to SMMBASE_FUNCTION_DATA.
607 IN OUT SMMBASE_FUNCTION_DATA
*FunctionData
610 FunctionData
->Status
= gSmst
->SmmFreePool (
611 FunctionData
->Args
.FreePool
.Buffer
616 Communication service SMI Handler entry.
618 This SMI handler provides services for the SMM Base Thunk driver.
620 @param[in] DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
621 @param[in] Context Points to an optional handler context which was specified when the
622 handler was registered.
623 @param[in,out] CommBuffer A pointer to a collection of data in memory that will
624 be conveyed from a non-SMM environment into an SMM environment.
625 @param[in,out] CommBufferSize The size of the CommBuffer.
627 @retval EFI_SUCCESS The interrupt was handled and quiesced. No other handlers
628 should still be called.
629 @retval EFI_WARN_INTERRUPT_SOURCE_QUIESCED The interrupt has been quiesced but other handlers should
631 @retval EFI_WARN_INTERRUPT_SOURCE_PENDING The interrupt is still pending and other handlers should still
633 @retval EFI_INTERRUPT_PENDING The interrupt could not be quiesced.
638 IN EFI_HANDLE DispatchHandle
,
639 IN CONST VOID
*RegisterContext
,
640 IN OUT VOID
*CommBuffer
,
641 IN OUT UINTN
*CommBufferSize
644 SMMBASE_FUNCTION_DATA
*FunctionData
;
646 ASSERT (CommBuffer
!= NULL
);
647 ASSERT (*CommBufferSize
== sizeof (SMMBASE_FUNCTION_DATA
));
649 FunctionData
= (SMMBASE_FUNCTION_DATA
*)CommBuffer
;
651 switch (FunctionData
->Function
) {
652 case SMMBASE_REGISTER
:
653 Register (FunctionData
);
655 case SMMBASE_UNREGISTER
:
656 UnRegister (FunctionData
);
658 case SMMBASE_REGISTER_CALLBACK
:
659 RegisterCallback (FunctionData
);
661 case SMMBASE_ALLOCATE_POOL
:
662 HelperAllocatePool (FunctionData
);
664 case SMMBASE_FREE_POOL
:
665 HelperFreePool (FunctionData
);
669 FunctionData
->Status
= EFI_UNSUPPORTED
;
675 Entry point function of the SMM Base Helper SMM driver.
677 @param[in] ImageHandle The firmware allocated handle for the EFI image.
678 @param[in] SystemTable A pointer to the EFI System Table.
680 @retval EFI_SUCCESS The entry point is executed successfully.
681 @retval other Some error occurs when executing this entry point.
686 IN EFI_HANDLE ImageHandle
,
687 IN EFI_SYSTEM_TABLE
*SystemTable
691 EFI_HANDLE Handle
= NULL
;
694 /// Locate SMM CPU Protocol which is used later to retrieve/update CPU Save States
696 Status
= gSmst
->SmmLocateProtocol (&gEfiSmmCpuProtocolGuid
, NULL
, (VOID
**) &mSmmCpu
);
697 ASSERT_EFI_ERROR (Status
);
700 /// Interface structure of SMM BASE Helper Ready Protocol is allocated from UEFI pool
701 /// instead of SMM pool so that SMM Base Thunk driver can access it in Non-SMM mode.
703 Status
= gBS
->AllocatePool (
705 sizeof (EFI_SMM_BASE_HELPER_READY_PROTOCOL
),
706 (VOID
**)&mSmmBaseHelperReady
708 ASSERT_EFI_ERROR (Status
);
711 /// Construct Framework SMST from PI SMST
713 mFrameworkSmst
= ConstructFrameworkSmst ();
714 mSmmBaseHelperReady
->FrameworkSmst
= mFrameworkSmst
;
715 mSmmBaseHelperReady
->ServiceEntry
= SmmHandlerEntry
;
718 /// Register SMM Base Helper services for SMM Base Thunk driver
720 Status
= gSmst
->SmiHandlerRegister (SmmHandlerEntry
, &gEfiSmmBaseThunkCommunicationGuid
, &mDispatchHandle
);
721 ASSERT_EFI_ERROR (Status
);
724 /// Install EFI SMM Base Helper Protocol in the UEFI handle database
726 Status
= gBS
->InstallProtocolInterface (
728 &gEfiSmmBaseHelperReadyProtocolGuid
,
729 EFI_NATIVE_INTERFACE
,
732 ASSERT_EFI_ERROR (Status
);