]> git.proxmox.com Git - mirror_edk2.git/blob - EdkCompatibilityPkg/Compatibility/SmmBaseHelper/SmmBaseHelper.c
381f6ae2edbf9bda8e70b4641f7bb1a17465513f
[mirror_edk2.git] / EdkCompatibilityPkg / Compatibility / SmmBaseHelper / SmmBaseHelper.c
1 /** @file
2 SMM Base Helper SMM driver.
3
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.
6
7 Copyright (c) 2009, 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
12
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.
15
16 **/
17
18 #include "SmmBaseHelper.h"
19
20 EFI_HANDLE mDispatchHandle;
21 EFI_SMM_CPU_PROTOCOL *mSmmCpu;
22 EFI_GUID mEfiSmmCpuIoGuid = EFI_SMM_CPU_IO_GUID;
23 EFI_SMM_BASE_HELPER_READY_PROTOCOL *mSmmBaseHelperReady;
24 EFI_SMM_SYSTEM_TABLE *mFrameworkSmst;
25
26 LIST_ENTRY mCallbackInfoListHead = INITIALIZE_LIST_HEAD_VARIABLE (mCallbackInfoListHead);
27
28 CPU_SAVE_STATE_CONVERSION mCpuSaveStateConvTable[] = {
29 {EFI_SMM_SAVE_STATE_REGISTER_LDTBASE , CPU_SAVE_STATE_GET_OFFSET(LDTBase)},
30 {EFI_SMM_SAVE_STATE_REGISTER_ES , CPU_SAVE_STATE_GET_OFFSET(ES)},
31 {EFI_SMM_SAVE_STATE_REGISTER_CS , CPU_SAVE_STATE_GET_OFFSET(CS)},
32 {EFI_SMM_SAVE_STATE_REGISTER_SS , CPU_SAVE_STATE_GET_OFFSET(SS)},
33 {EFI_SMM_SAVE_STATE_REGISTER_DS , CPU_SAVE_STATE_GET_OFFSET(DS)},
34 {EFI_SMM_SAVE_STATE_REGISTER_FS , CPU_SAVE_STATE_GET_OFFSET(FS)},
35 {EFI_SMM_SAVE_STATE_REGISTER_GS , CPU_SAVE_STATE_GET_OFFSET(GS)},
36 {EFI_SMM_SAVE_STATE_REGISTER_TR_SEL , CPU_SAVE_STATE_GET_OFFSET(TR)},
37 {EFI_SMM_SAVE_STATE_REGISTER_DR7 , CPU_SAVE_STATE_GET_OFFSET(DR7)},
38 {EFI_SMM_SAVE_STATE_REGISTER_DR6 , CPU_SAVE_STATE_GET_OFFSET(DR6)},
39 {EFI_SMM_SAVE_STATE_REGISTER_RAX , CPU_SAVE_STATE_GET_OFFSET(EAX)},
40 {EFI_SMM_SAVE_STATE_REGISTER_RBX , CPU_SAVE_STATE_GET_OFFSET(EBX)},
41 {EFI_SMM_SAVE_STATE_REGISTER_RCX , CPU_SAVE_STATE_GET_OFFSET(ECX)},
42 {EFI_SMM_SAVE_STATE_REGISTER_RDX , CPU_SAVE_STATE_GET_OFFSET(EDX)},
43 {EFI_SMM_SAVE_STATE_REGISTER_RSP , CPU_SAVE_STATE_GET_OFFSET(ESP)},
44 {EFI_SMM_SAVE_STATE_REGISTER_RBP , CPU_SAVE_STATE_GET_OFFSET(EBP)},
45 {EFI_SMM_SAVE_STATE_REGISTER_RSI , CPU_SAVE_STATE_GET_OFFSET(ESI)},
46 {EFI_SMM_SAVE_STATE_REGISTER_RDI , CPU_SAVE_STATE_GET_OFFSET(EDI)},
47 {EFI_SMM_SAVE_STATE_REGISTER_RIP , CPU_SAVE_STATE_GET_OFFSET(EIP)},
48 {EFI_SMM_SAVE_STATE_REGISTER_RFLAGS , CPU_SAVE_STATE_GET_OFFSET(EFLAGS)},
49 {EFI_SMM_SAVE_STATE_REGISTER_CR0 , CPU_SAVE_STATE_GET_OFFSET(CR0)},
50 {EFI_SMM_SAVE_STATE_REGISTER_CR3 , CPU_SAVE_STATE_GET_OFFSET(CR3)}
51 };
52
53 /**
54 Framework SMST SmmInstallConfigurationTable() Thunk.
55
56 This thunk calls the PI SMM SmmInstallConfigurationTable() and then update the configuration
57 table related fields in the Framework SMST because the PI SMM SmmInstallConfigurationTable()
58 function may modify these fields.
59
60 @param[in] SystemTable A pointer to the SMM System Table.
61 @param[in] Guid A pointer to the GUID for the entry to add, update, or remove.
62 @param[in] Table A pointer to the buffer of the table to add.
63 @param[in] TableSize The size of the table to install.
64
65 @retval EFI_SUCCESS The (Guid, Table) pair was added, updated, or removed.
66 @retval EFI_INVALID_PARAMETER Guid is not valid.
67 @retval EFI_NOT_FOUND An attempt was made to delete a non-existent entry.
68 @retval EFI_OUT_OF_RESOURCES There is not enough memory available to complete the operation.
69 **/
70 EFI_STATUS
71 EFIAPI
72 SmmInstallConfigurationTable (
73 IN EFI_SMM_SYSTEM_TABLE *SystemTable,
74 IN EFI_GUID *Guid,
75 IN VOID *Table,
76 IN UINTN TableSize
77 )
78 {
79 EFI_STATUS Status;
80
81 Status = gSmst->SmmInstallConfigurationTable (gSmst, Guid, Table, TableSize);
82 if (!EFI_ERROR (Status)) {
83 mFrameworkSmst->NumberOfTableEntries = gSmst->NumberOfTableEntries;
84 mFrameworkSmst->SmmConfigurationTable = gSmst->SmmConfigurationTable;
85 }
86 return Status;
87 }
88
89 /**
90 Construct a Framework SMST based on the PI SMM SMST.
91
92 @return Pointer to the constructed Framework SMST.
93 **/
94 EFI_SMM_SYSTEM_TABLE *
95 ConstructFrameworkSmst (
96 VOID
97 )
98 {
99 EFI_STATUS Status;
100 EFI_SMM_SYSTEM_TABLE *FrameworkSmst;
101
102 Status = gSmst->SmmAllocatePool (
103 EfiRuntimeServicesData,
104 sizeof (EFI_SMM_SYSTEM_TABLE),
105 (VOID **)&FrameworkSmst
106 );
107 ASSERT_EFI_ERROR (Status);
108
109 ///
110 /// Copy same things from PI SMST to Framework SMST
111 ///
112 CopyMem (FrameworkSmst, gSmst, (UINTN)(&((EFI_SMM_SYSTEM_TABLE *)0)->SmmIo));
113 CopyMem (
114 &FrameworkSmst->SmmIo,
115 &gSmst->SmmIo,
116 sizeof (EFI_SMM_SYSTEM_TABLE) - (UINTN)(&((EFI_SMM_SYSTEM_TABLE *)0)->SmmIo)
117 );
118
119 ///
120 /// Update Framework SMST
121 ///
122 FrameworkSmst->Hdr.Revision = EFI_SMM_SYSTEM_TABLE_REVISION;
123 CopyGuid (&FrameworkSmst->EfiSmmCpuIoGuid, &mEfiSmmCpuIoGuid);
124
125 Status = gSmst->SmmAllocatePool (
126 EfiRuntimeServicesData,
127 gSmst->NumberOfCpus * sizeof (EFI_SMI_CPU_SAVE_STATE),
128 (VOID **)&FrameworkSmst->CpuSaveState
129 );
130 ASSERT_EFI_ERROR (Status);
131 ZeroMem (FrameworkSmst->CpuSaveState, gSmst->NumberOfCpus * sizeof (EFI_SMI_CPU_SAVE_STATE));
132
133 ///
134 /// Do not support floating point state now
135 ///
136 FrameworkSmst->CpuOptionalFloatingPointState = NULL;
137
138 FrameworkSmst->SmmInstallConfigurationTable = SmmInstallConfigurationTable;
139
140 return FrameworkSmst;
141 }
142
143 /**
144 Load a given Framework SMM driver into SMRAM and invoke its entry point.
145
146 @param[in] FilePath Location of the image to be installed as the handler.
147 @param[in] SourceBuffer Optional source buffer in case the image file
148 is in memory.
149 @param[in] SourceSize Size of the source image file, if in memory.
150 @param[out] ImageHandle The handle that the base driver uses to decode
151 the handler. Unique among SMM handlers only,
152 not unique across DXE/EFI.
153
154 @retval EFI_SUCCESS The operation was successful.
155 @retval EFI_OUT_OF_RESOURCES There were no additional SMRAM resources to load the handler
156 @retval EFI_UNSUPPORTED Can not find its copy in normal memory.
157 @retval EFI_INVALID_PARAMETER The handlers was not the correct image type
158 **/
159 EFI_STATUS
160 LoadImage (
161 IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
162 IN VOID *SourceBuffer,
163 IN UINTN SourceSize,
164 OUT EFI_HANDLE *ImageHandle
165 )
166 {
167 EFI_STATUS Status;
168 UINTN PageCount;
169 EFI_PHYSICAL_ADDRESS Buffer;
170 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
171 EFI_HANDLE PesudoImageHandle;
172 UINTN NumHandles;
173 UINTN Index;
174 EFI_HANDLE *HandleBuffer;
175 EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
176 EFI_DEVICE_PATH *LoadedImageDevicePath;
177 UINTN DevicePathSize;
178
179 if (FilePath == NULL || ImageHandle == NULL) {
180 return EFI_INVALID_PARAMETER;
181 }
182
183 ///
184 /// Assume Framework SMM driver has an image copy in memory before registering itself into SMRAM.
185 /// Currently only supports load Framework SMM driver from existing image copy in memory.
186 /// Load PE32 Image Protocol can be used to support loading Framework SMM driver directly from FV.
187 ///
188 if (SourceBuffer == NULL) {
189 Status = gBS->LocateHandleBuffer (
190 ByProtocol,
191 &gEfiLoadedImageDevicePathProtocolGuid,
192 NULL,
193 &NumHandles,
194 &HandleBuffer
195 );
196 if (EFI_ERROR (Status)) {
197 return EFI_UNSUPPORTED;
198 }
199
200 DevicePathSize = GetDevicePathSize (FilePath);
201
202 for (Index = 0; Index < NumHandles; Index++) {
203 Status = gBS->HandleProtocol (
204 HandleBuffer[Index],
205 &gEfiLoadedImageDevicePathProtocolGuid,
206 (VOID **)&LoadedImageDevicePath
207 );
208 ASSERT_EFI_ERROR (Status);
209
210 if (GetDevicePathSize (LoadedImageDevicePath) == DevicePathSize &&
211 CompareMem (LoadedImageDevicePath, FilePath, DevicePathSize) == 0) {
212 break;
213 }
214 }
215
216 if (Index < NumHandles) {
217 Status = gBS->HandleProtocol (
218 HandleBuffer[Index],
219 &gEfiLoadedImageProtocolGuid,
220 (VOID **)&LoadedImage
221 );
222 ASSERT_EFI_ERROR (Status);
223
224 SourceBuffer = LoadedImage->ImageBase;
225 gBS->FreePool (HandleBuffer);
226 } else {
227 gBS->FreePool (HandleBuffer);
228 return EFI_UNSUPPORTED;
229 }
230 }
231
232 ImageContext.Handle = SourceBuffer;
233 ImageContext.ImageRead = PeCoffLoaderImageReadFromMemory;
234
235 ///
236 /// Get information about the image being loaded
237 ///
238 Status = PeCoffLoaderGetImageInfo (&ImageContext);
239 if (EFI_ERROR (Status)) {
240 return Status;
241 }
242
243 ///
244 /// Allocate buffer for loading image into SMRAM
245 ///
246 PageCount = (UINTN)EFI_SIZE_TO_PAGES (ImageContext.ImageSize + ImageContext.SectionAlignment);
247 Status = gSmst->SmmAllocatePages (AllocateAnyPages, EfiRuntimeServicesCode, PageCount, &Buffer);
248 if (EFI_ERROR (Status)) {
249 return Status;
250 }
251
252 ImageContext.ImageAddress = (PHYSICAL_ADDRESS)Buffer;
253
254 ///
255 /// Align buffer on section boundry
256 ///
257 ImageContext.ImageAddress += ImageContext.SectionAlignment - 1;
258 ImageContext.ImageAddress &= ~(ImageContext.SectionAlignment - 1);
259
260 ///
261 /// Load the image into SMRAM
262 ///
263 Status = PeCoffLoaderLoadImage (&ImageContext);
264 if (EFI_ERROR (Status)) {
265 goto Error;
266 }
267
268 ///
269 /// Relocate the image in our new buffer
270 ///
271 Status = PeCoffLoaderRelocateImage (&ImageContext);
272 if (EFI_ERROR (Status)) {
273 goto Error;
274 }
275
276 ///
277 /// Flush the instruction cache so the image data are written before we execute it
278 ///
279 InvalidateInstructionCacheRange ((VOID *)(UINTN) ImageContext.ImageAddress, (UINTN) ImageContext.ImageSize);
280
281 ///
282 /// Update MP state in Framework SMST before transferring control to Framework SMM driver entry point
283 /// in case it may invoke AP
284 ///
285 mFrameworkSmst->CurrentlyExecutingCpu = gSmst->CurrentlyExecutingCpu;
286
287 ///
288 /// For Framework SMM, ImageHandle does not have to be a UEFI image handle. The only requirement is that the
289 /// ImageHandle is a unique value. Use image base address as the unique value.
290 ///
291 PesudoImageHandle = (EFI_HANDLE)(UINTN)ImageContext.ImageAddress;
292
293 Status = ((EFI_IMAGE_ENTRY_POINT)(UINTN)ImageContext.EntryPoint) (PesudoImageHandle, gST);
294 if (!EFI_ERROR (Status)) {
295 *ImageHandle = PesudoImageHandle;
296 return EFI_SUCCESS;
297 }
298
299 Error:
300 gSmst->SmmFreePages (Buffer, PageCount);
301 return Status;
302 }
303
304 /**
305 Thunk service of EFI_SMM_BASE_PROTOCOL.Register().
306
307 @param[in] FunctionData Pointer to SMMBASE_FUNCTION_DATA.
308 */
309 VOID
310 Register (
311 IN OUT SMMBASE_FUNCTION_DATA *FunctionData
312 )
313 {
314 EFI_STATUS Status;
315
316 if (FunctionData->Args.Register.LegacyIA32Binary) {
317 Status = EFI_UNSUPPORTED;
318 } else {
319 Status = LoadImage (
320 FunctionData->Args.Register.FilePath,
321 FunctionData->Args.Register.SourceBuffer,
322 FunctionData->Args.Register.SourceSize,
323 FunctionData->Args.Register.ImageHandle
324 );
325 }
326 FunctionData->Status = Status;
327 }
328
329 /**
330 Thunk service of EFI_SMM_BASE_PROTOCOL.UnRegister().
331
332 @param[in] FunctionData Pointer to SMMBASE_FUNCTION_DATA.
333 */
334 VOID
335 UnRegister (
336 IN OUT SMMBASE_FUNCTION_DATA *FunctionData
337 )
338 {
339 ///
340 /// Unregister not supported now
341 ///
342 FunctionData->Status = EFI_UNSUPPORTED;
343 }
344
345 /**
346 Search for Framework SMI handler information according to specific PI SMM dispatch handle.
347
348 @param[in] DispatchHandle The unique handle assigned by SmiHandlerRegister().
349
350 @return Pointer to CALLBACK_INFO.
351 **/
352 CALLBACK_INFO *
353 GetCallbackInfo (
354 IN EFI_HANDLE DispatchHandle
355 )
356 {
357 LIST_ENTRY *Node;
358
359 Node = GetFirstNode (&mCallbackInfoListHead);
360 while (!IsNull (&mCallbackInfoListHead, Node)) {
361 if (((CALLBACK_INFO *)Node)->DispatchHandle == DispatchHandle) {
362 return (CALLBACK_INFO *)Node;
363 }
364 Node = GetNextNode (&mCallbackInfoListHead, Node);
365 }
366 return NULL;
367 }
368
369 /**
370 Callback thunk for Framework SMI handler.
371
372 This thunk functions calls the Framework SMI handler and converts the return value
373 defined from Framework SMI handlers to a correpsonding return value defined by PI SMM.
374
375 @param[in] DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
376 @param[in] Context Points to an optional handler context which was specified when the
377 handler was registered.
378 @param[in,out] CommBuffer A pointer to a collection of data in memory that will
379 be conveyed from a non-SMM environment into an SMM environment.
380 @param[in,out] CommBufferSize The size of the CommBuffer.
381
382 @retval EFI_SUCCESS The interrupt was handled and quiesced. No other handlers
383 should still be called.
384 @retval EFI_WARN_INTERRUPT_SOURCE_QUIESCED The interrupt has been quiesced but other handlers should
385 still be called.
386 @retval EFI_WARN_INTERRUPT_SOURCE_PENDING The interrupt is still pending and other handlers should still
387 be called.
388 @retval EFI_INTERRUPT_PENDING The interrupt could not be quiesced.
389 **/
390 EFI_STATUS
391 EFIAPI
392 CallbackThunk (
393 IN EFI_HANDLE DispatchHandle,
394 IN CONST VOID *Context OPTIONAL,
395 IN OUT VOID *CommBuffer OPTIONAL,
396 IN OUT UINTN *CommBufferSize OPTIONAL
397 )
398 {
399 EFI_STATUS Status;
400 CALLBACK_INFO *CallbackInfo;
401 UINTN Index;
402 UINTN CpuIndex;
403 EFI_SMM_CPU_STATE *State;
404 EFI_SMI_CPU_SAVE_STATE *SaveState;
405
406 ///
407 /// Before transferring the control into the Framework SMI handler, update CPU Save States
408 /// and MP states in the Framework SMST.
409 ///
410
411 for (CpuIndex = 0; CpuIndex < gSmst->NumberOfCpus; CpuIndex++) {
412 State = (EFI_SMM_CPU_STATE *)gSmst->CpuSaveState[CpuIndex];
413 SaveState = &mFrameworkSmst->CpuSaveState[CpuIndex].Ia32SaveState;
414
415 if (State->x86.SMMRevId < EFI_SMM_MIN_REV_ID_x64) {
416 SaveState->SMBASE = State->x86.SMBASE;
417 SaveState->SMMRevId = State->x86.SMMRevId;
418 SaveState->IORestart = State->x86.IORestart;
419 SaveState->AutoHALTRestart = State->x86.AutoHALTRestart;
420 } else {
421 SaveState->SMBASE = State->x64.SMBASE;
422 SaveState->SMMRevId = State->x64.SMMRevId;
423 SaveState->IORestart = State->x64.IORestart;
424 SaveState->AutoHALTRestart = State->x64.AutoHALTRestart;
425 }
426
427 for (Index = 0; Index < sizeof (mCpuSaveStateConvTable) / sizeof (CPU_SAVE_STATE_CONVERSION); Index++) {
428 ///
429 /// Try to use SMM CPU Protocol to access CPU save states if possible
430 ///
431 Status = mSmmCpu->ReadSaveState (
432 mSmmCpu,
433 EFI_SMM_SAVE_STATE_IO_WIDTH_UINT32,
434 mCpuSaveStateConvTable[Index].Register,
435 CpuIndex,
436 ((UINT8 *)SaveState) + mCpuSaveStateConvTable[Index].Offset
437 );
438 ASSERT_EFI_ERROR (Status);
439 }
440 }
441
442 mFrameworkSmst->CurrentlyExecutingCpu = gSmst->CurrentlyExecutingCpu;
443
444 ///
445 /// Search for Framework SMI handler information
446 ///
447 CallbackInfo = GetCallbackInfo (DispatchHandle);
448 ASSERT (CallbackInfo != NULL);
449
450 ///
451 /// Thunk into original Framwork SMI handler
452 ///
453 Status = (CallbackInfo->CallbackAddress) (
454 CallbackInfo->SmmImageHandle,
455 CommBuffer,
456 CommBufferSize
457 );
458 ///
459 /// Save CPU Save States in case any of them was modified
460 ///
461 for (CpuIndex = 0; CpuIndex < gSmst->NumberOfCpus; CpuIndex++) {
462 for (Index = 0; Index < sizeof (mCpuSaveStateConvTable) / sizeof (CPU_SAVE_STATE_CONVERSION); Index++) {
463 Status = mSmmCpu->WriteSaveState (
464 mSmmCpu,
465 EFI_SMM_SAVE_STATE_IO_WIDTH_UINT32,
466 mCpuSaveStateConvTable[Index].Register,
467 CpuIndex,
468 ((UINT8 *)&mFrameworkSmst->CpuSaveState[CpuIndex].Ia32SaveState) +
469 mCpuSaveStateConvTable[Index].Offset
470 );
471 }
472 }
473
474 ///
475 /// Conversion of returned status code
476 ///
477 switch (Status) {
478 case EFI_HANDLER_SUCCESS:
479 Status = EFI_WARN_INTERRUPT_SOURCE_QUIESCED;
480 break;
481 case EFI_HANDLER_CRITICAL_EXIT:
482 case EFI_HANDLER_SOURCE_QUIESCED:
483 Status = EFI_SUCCESS;
484 break;
485 case EFI_HANDLER_SOURCE_PENDING:
486 Status = EFI_WARN_INTERRUPT_SOURCE_PENDING;
487 break;
488 }
489 return Status;
490 }
491
492 /**
493 Thunk service of EFI_SMM_BASE_PROTOCOL.RegisterCallback().
494
495 @param[in] FunctionData Pointer to SMMBASE_FUNCTION_DATA.
496 */
497 VOID
498 RegisterCallback (
499 IN OUT SMMBASE_FUNCTION_DATA *FunctionData
500 )
501 {
502 EFI_STATUS Status;
503 CALLBACK_INFO *Buffer;
504
505 ///
506 /// Note that MakeLast and FloatingPointSave options are not supported in PI SMM
507 ///
508
509 ///
510 /// Allocate buffer for callback thunk information
511 ///
512 Status = gSmst->SmmAllocatePool (
513 EfiRuntimeServicesCode,
514 sizeof (CALLBACK_INFO),
515 (VOID **)&Buffer
516 );
517 if (!EFI_ERROR (Status)) {
518 ///
519 /// Fill SmmImageHandle and CallbackAddress into the thunk
520 ///
521 Buffer->SmmImageHandle = FunctionData->Args.RegisterCallback.SmmImageHandle;
522 Buffer->CallbackAddress = FunctionData->Args.RegisterCallback.CallbackAddress;
523
524 ///
525 /// Register the thunk code as a root SMI handler
526 ///
527 Status = gSmst->SmiHandlerRegister (
528 CallbackThunk,
529 NULL,
530 &Buffer->DispatchHandle
531 );
532 if (!EFI_ERROR (Status)) {
533 ///
534 /// Save this callback info
535 ///
536 InsertTailList (&mCallbackInfoListHead, &Buffer->Link);
537 } else {
538 gSmst->SmmFreePool (Buffer);
539 }
540 }
541 FunctionData->Status = Status;
542 }
543
544
545 /**
546 Thunk service of EFI_SMM_BASE_PROTOCOL.SmmAllocatePool().
547
548 @param[in] FunctionData Pointer to SMMBASE_FUNCTION_DATA.
549 */
550 VOID
551 HelperAllocatePool (
552 IN OUT SMMBASE_FUNCTION_DATA *FunctionData
553 )
554 {
555 FunctionData->Status = gSmst->SmmAllocatePool (
556 FunctionData->Args.AllocatePool.PoolType,
557 FunctionData->Args.AllocatePool.Size,
558 FunctionData->Args.AllocatePool.Buffer
559 );
560 }
561
562 /**
563 Thunk service of EFI_SMM_BASE_PROTOCOL.SmmFreePool().
564
565 @param[in] FunctionData Pointer to SMMBASE_FUNCTION_DATA.
566 */
567 VOID
568 HelperFreePool (
569 IN OUT SMMBASE_FUNCTION_DATA *FunctionData
570 )
571 {
572 FunctionData->Status = gSmst->SmmFreePool (
573 FunctionData->Args.FreePool.Buffer
574 );
575 }
576
577 /**
578 Communication service SMI Handler entry.
579
580 This SMI handler provides services for the SMM Base Thunk driver.
581
582 @param[in] DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
583 @param[in] Context Points to an optional handler context which was specified when the
584 handler was registered.
585 @param[in,out] CommBuffer A pointer to a collection of data in memory that will
586 be conveyed from a non-SMM environment into an SMM environment.
587 @param[in,out] CommBufferSize The size of the CommBuffer.
588
589 @retval EFI_SUCCESS The interrupt was handled and quiesced. No other handlers
590 should still be called.
591 @retval EFI_WARN_INTERRUPT_SOURCE_QUIESCED The interrupt has been quiesced but other handlers should
592 still be called.
593 @retval EFI_WARN_INTERRUPT_SOURCE_PENDING The interrupt is still pending and other handlers should still
594 be called.
595 @retval EFI_INTERRUPT_PENDING The interrupt could not be quiesced.
596 **/
597 EFI_STATUS
598 EFIAPI
599 SmmHandlerEntry (
600 IN EFI_HANDLE DispatchHandle,
601 IN CONST VOID *RegisterContext,
602 IN OUT VOID *CommBuffer,
603 IN OUT UINTN *CommBufferSize
604 )
605 {
606 SMMBASE_FUNCTION_DATA *FunctionData;
607
608 ASSERT (CommBuffer != NULL);
609 ASSERT (*CommBufferSize == sizeof (SMMBASE_FUNCTION_DATA));
610
611 FunctionData = (SMMBASE_FUNCTION_DATA *)CommBuffer;
612
613 switch (FunctionData->Function) {
614 case SMMBASE_REGISTER:
615 Register (FunctionData);
616 break;
617 case SMMBASE_UNREGISTER:
618 UnRegister (FunctionData);
619 break;
620 case SMMBASE_REGISTER_CALLBACK:
621 RegisterCallback (FunctionData);
622 break;
623 case SMMBASE_ALLOCATE_POOL:
624 HelperAllocatePool (FunctionData);
625 break;
626 case SMMBASE_FREE_POOL:
627 HelperFreePool (FunctionData);
628 break;
629 default:
630 ASSERT (FALSE);
631 FunctionData->Status = EFI_UNSUPPORTED;
632 }
633 return EFI_SUCCESS;
634 }
635
636 /**
637 Entry point function of the SMM Base Helper SMM driver.
638
639 @param[in] ImageHandle The firmware allocated handle for the EFI image.
640 @param[in] SystemTable A pointer to the EFI System Table.
641
642 @retval EFI_SUCCESS The entry point is executed successfully.
643 @retval other Some error occurs when executing this entry point.
644 **/
645 EFI_STATUS
646 EFIAPI
647 SmmBaseHelperMain (
648 IN EFI_HANDLE ImageHandle,
649 IN EFI_SYSTEM_TABLE *SystemTable
650 )
651 {
652 EFI_STATUS Status;
653 EFI_HANDLE Handle = NULL;
654
655 ///
656 /// Locate SMM CPU Protocol which is used later to update CPU Save States
657 ///
658 Status = gSmst->SmmLocateProtocol (&gEfiSmmCpuProtocolGuid, NULL, (VOID **) &mSmmCpu);
659 ASSERT_EFI_ERROR (Status);
660
661 ///
662 /// Interface structure of SMM BASE Helper Ready Protocol is allocated from UEFI pool
663 /// instead of SMM pool so that SMM Base Thunk driver can access it in Non-SMM mode.
664 ///
665 Status = gBS->AllocatePool (
666 EfiBootServicesData,
667 sizeof (EFI_SMM_BASE_HELPER_READY_PROTOCOL),
668 (VOID **)&mSmmBaseHelperReady
669 );
670 ASSERT_EFI_ERROR (Status);
671
672 ///
673 /// Construct Framework SMST from PI SMST
674 ///
675 mFrameworkSmst = ConstructFrameworkSmst ();
676 mSmmBaseHelperReady->FrameworkSmst = mFrameworkSmst;
677 mSmmBaseHelperReady->ServiceEntry = SmmHandlerEntry;
678
679 ///
680 /// Register SMM Base Helper services for SMM Base Thunk driver
681 ///
682 Status = gSmst->SmiHandlerRegister (SmmHandlerEntry, &gEfiSmmBaseThunkCommunicationGuid, &mDispatchHandle);
683 ASSERT_EFI_ERROR (Status);
684
685 ///
686 /// Install EFI SMM Base Helper Protocol in the UEFI handle database
687 ///
688 Status = gBS->InstallProtocolInterface (
689 &Handle,
690 &gEfiSmmBaseHelperReadyProtocolGuid,
691 EFI_NATIVE_INTERFACE,
692 mSmmBaseHelperReady
693 );
694 ASSERT_EFI_ERROR (Status);
695
696 return Status;
697 }
698