]> git.proxmox.com Git - mirror_edk2.git/blob - EdkCompatibilityPkg/Compatibility/SmmBaseHelper/SmmBaseHelper.c
Remove the implementation limitation in the SmmBaseHelper driver that it assumes...
[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 - 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
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 <PiSmm.h>
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>
35
36 ///
37 /// Structure for tracking paired information of registered Framework SMI handler
38 /// and correpsonding dispatch handle for SMI handler thunk.
39 ///
40 typedef struct {
41 LIST_ENTRY Link;
42 EFI_HANDLE DispatchHandle;
43 EFI_HANDLE SmmImageHandle;
44 EFI_SMM_CALLBACK_ENTRY_POINT CallbackAddress;
45 } CALLBACK_INFO;
46
47 typedef struct {
48 ///
49 /// PI SMM CPU Save State register index
50 ///
51 EFI_SMM_SAVE_STATE_REGISTER Register;
52 ///
53 /// Offset in Framework SMST
54 ///
55 UINTN Offset;
56 } CPU_SAVE_STATE_CONVERSION;
57
58 #define CPU_SAVE_STATE_GET_OFFSET(Field) (UINTN)(&(((EFI_SMM_CPU_SAVE_STATE *) 0)->Ia32SaveState.Field))
59
60
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;
68
69 LIST_ENTRY mCallbackInfoListHead = INITIALIZE_LIST_HEAD_VARIABLE (mCallbackInfoListHead);
70
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)}
94 };
95
96 /**
97 Framework SMST SmmInstallConfigurationTable() Thunk.
98
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.
102
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.
107
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.
112 **/
113 EFI_STATUS
114 EFIAPI
115 SmmInstallConfigurationTable (
116 IN EFI_SMM_SYSTEM_TABLE *SystemTable,
117 IN EFI_GUID *Guid,
118 IN VOID *Table,
119 IN UINTN TableSize
120 )
121 {
122 EFI_STATUS Status;
123
124 Status = gSmst->SmmInstallConfigurationTable (gSmst, Guid, Table, TableSize);
125 if (!EFI_ERROR (Status)) {
126 mFrameworkSmst->NumberOfTableEntries = gSmst->NumberOfTableEntries;
127 mFrameworkSmst->SmmConfigurationTable = gSmst->SmmConfigurationTable;
128 }
129 return Status;
130 }
131
132 /**
133 Construct a Framework SMST based on the PI SMM SMST.
134
135 @return Pointer to the constructed Framework SMST.
136 **/
137 EFI_SMM_SYSTEM_TABLE *
138 ConstructFrameworkSmst (
139 VOID
140 )
141 {
142 EFI_SMM_SYSTEM_TABLE *FrameworkSmst;
143
144 FrameworkSmst = (EFI_SMM_SYSTEM_TABLE *)AllocatePool (sizeof (EFI_SMM_SYSTEM_TABLE));
145 ASSERT (FrameworkSmst != NULL);
146
147 ///
148 /// Copy same things from PI SMST to Framework SMST
149 ///
150 CopyMem (FrameworkSmst, gSmst, (UINTN)(&((EFI_SMM_SYSTEM_TABLE *)0)->SmmIo));
151 CopyMem (
152 &FrameworkSmst->SmmIo,
153 &gSmst->SmmIo,
154 sizeof (EFI_SMM_SYSTEM_TABLE) - (UINTN)(&((EFI_SMM_SYSTEM_TABLE *)0)->SmmIo)
155 );
156
157 ///
158 /// Update Framework SMST
159 ///
160 FrameworkSmst->Hdr.Revision = EFI_SMM_SYSTEM_TABLE_REVISION;
161 CopyGuid (&FrameworkSmst->EfiSmmCpuIoGuid, &mEfiSmmCpuIoGuid);
162
163 FrameworkSmst->CpuSaveState = (EFI_SMM_CPU_SAVE_STATE *)AllocateZeroPool (mNumberOfProcessors * sizeof (EFI_SMM_CPU_SAVE_STATE));
164 ASSERT (FrameworkSmst->CpuSaveState != NULL);
165
166 ///
167 /// Do not support floating point state now
168 ///
169 FrameworkSmst->CpuOptionalFloatingPointState = NULL;
170
171 FrameworkSmst->SmmInstallConfigurationTable = SmmInstallConfigurationTable;
172
173 return FrameworkSmst;
174 }
175
176 /**
177 Load a given Framework SMM driver into SMRAM and invoke its entry point.
178
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
182 is in memory.
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.
187
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
192 **/
193 EFI_STATUS
194 LoadImage (
195 IN EFI_HANDLE ParentImageHandle,
196 IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
197 IN VOID *SourceBuffer,
198 IN UINTN SourceSize,
199 OUT EFI_HANDLE *ImageHandle
200 )
201 {
202 EFI_STATUS Status;
203 UINTN PageCount;
204 UINTN OrgPageCount;
205 EFI_PHYSICAL_ADDRESS DstBuffer;
206
207 if (FilePath == NULL || ImageHandle == NULL) {
208 return EFI_INVALID_PARAMETER;
209 }
210
211 PageCount = 1;
212 do {
213 OrgPageCount = PageCount;
214 DstBuffer = (UINTN)-1;
215 Status = gSmst->SmmAllocatePages (
216 AllocateMaxAddress,
217 EfiRuntimeServicesCode,
218 PageCount,
219 &DstBuffer
220 );
221 if (EFI_ERROR (Status)) {
222 return Status;
223 }
224
225 Status = mLoadPe32Image->LoadPeImage (
226 mLoadPe32Image,
227 ParentImageHandle,
228 FilePath,
229 SourceBuffer,
230 SourceSize,
231 DstBuffer,
232 &PageCount,
233 ImageHandle,
234 NULL,
235 EFI_LOAD_PE_IMAGE_ATTRIBUTE_NONE
236 );
237 if (EFI_ERROR (Status)) {
238 FreePages ((VOID *)(UINTN)DstBuffer, OrgPageCount);
239 }
240 } while (Status == EFI_BUFFER_TOO_SMALL);
241
242 if (!EFI_ERROR (Status)) {
243 ///
244 /// Update MP state in Framework SMST before transferring control to Framework SMM driver entry point
245 /// in case it may invoke AP
246 ///
247 mFrameworkSmst->CurrentlyExecutingCpu = gSmst->CurrentlyExecutingCpu;
248
249 Status = gBS->StartImage (*ImageHandle, NULL, NULL);
250 if (EFI_ERROR (Status)) {
251 mLoadPe32Image->UnLoadPeImage (mLoadPe32Image, *ImageHandle);
252 *ImageHandle = NULL;
253 FreePages ((VOID *)(UINTN)DstBuffer, PageCount);
254 }
255 }
256
257 return Status;
258 }
259
260
261 /**
262 Thunk service of EFI_SMM_BASE_PROTOCOL.Register().
263
264 @param[in, out] FunctionData Pointer to SMMBASE_FUNCTION_DATA.
265 **/
266 VOID
267 Register (
268 IN OUT SMMBASE_FUNCTION_DATA *FunctionData
269 )
270 {
271 EFI_STATUS Status;
272
273 if (FunctionData->Args.Register.LegacyIA32Binary) {
274 Status = EFI_UNSUPPORTED;
275 } else {
276 Status = LoadImage (
277 FunctionData->SmmBaseImageHandle,
278 FunctionData->Args.Register.FilePath,
279 FunctionData->Args.Register.SourceBuffer,
280 FunctionData->Args.Register.SourceSize,
281 FunctionData->Args.Register.ImageHandle
282 );
283 }
284 FunctionData->Status = Status;
285 }
286
287 /**
288 Thunk service of EFI_SMM_BASE_PROTOCOL.UnRegister().
289
290 @param[in, out] FunctionData Pointer to SMMBASE_FUNCTION_DATA.
291 **/
292 VOID
293 UnRegister (
294 IN OUT SMMBASE_FUNCTION_DATA *FunctionData
295 )
296 {
297 ///
298 /// Unregister not supported now
299 ///
300 FunctionData->Status = EFI_UNSUPPORTED;
301 }
302
303 /**
304 Search for Framework SMI handler information according to specific PI SMM dispatch handle.
305
306 @param[in] DispatchHandle The unique handle assigned by SmiHandlerRegister().
307
308 @return Pointer to CALLBACK_INFO. If NULL, no callback info record is found.
309 **/
310 CALLBACK_INFO *
311 GetCallbackInfo (
312 IN EFI_HANDLE DispatchHandle
313 )
314 {
315 LIST_ENTRY *Node;
316
317 Node = GetFirstNode (&mCallbackInfoListHead);
318 while (!IsNull (&mCallbackInfoListHead, Node)) {
319 if (((CALLBACK_INFO *)Node)->DispatchHandle == DispatchHandle) {
320 return (CALLBACK_INFO *)Node;
321 }
322 Node = GetNextNode (&mCallbackInfoListHead, Node);
323 }
324 return NULL;
325 }
326
327 /**
328 Callback thunk for Framework SMI handler.
329
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.
332
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.
339
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
343 still be called.
344 @retval EFI_WARN_INTERRUPT_SOURCE_PENDING The interrupt is still pending and other handlers should still
345 be called.
346 @retval EFI_INTERRUPT_PENDING The interrupt could not be quiesced.
347 **/
348 EFI_STATUS
349 EFIAPI
350 CallbackThunk (
351 IN EFI_HANDLE DispatchHandle,
352 IN CONST VOID *Context OPTIONAL,
353 IN OUT VOID *CommBuffer OPTIONAL,
354 IN OUT UINTN *CommBufferSize OPTIONAL
355 )
356 {
357 EFI_STATUS Status;
358 CALLBACK_INFO *CallbackInfo;
359 UINTN Index;
360 UINTN CpuIndex;
361 EFI_SMM_CPU_STATE *State;
362 EFI_SMI_CPU_SAVE_STATE *SaveState;
363
364 ///
365 /// Before transferring the control into the Framework SMI handler, update CPU Save States
366 /// and MP states in the Framework SMST.
367 ///
368
369 for (CpuIndex = 0; CpuIndex < mNumberOfProcessors; CpuIndex++) {
370 State = (EFI_SMM_CPU_STATE *)gSmst->CpuSaveState[CpuIndex];
371 SaveState = &mFrameworkSmst->CpuSaveState[CpuIndex].Ia32SaveState;
372
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;
378 } else {
379 SaveState->SMBASE = State->x64.SMBASE;
380 SaveState->SMMRevId = State->x64.SMMRevId;
381 SaveState->IORestart = State->x64.IORestart;
382 SaveState->AutoHALTRestart = State->x64.AutoHALTRestart;
383 }
384
385 for (Index = 0; Index < sizeof (mCpuSaveStateConvTable) / sizeof (CPU_SAVE_STATE_CONVERSION); Index++) {
386 ///
387 /// Try to use SMM CPU Protocol to access CPU save states if possible
388 ///
389 Status = mSmmCpu->ReadSaveState (
390 mSmmCpu,
391 (UINTN)sizeof (UINT32),
392 mCpuSaveStateConvTable[Index].Register,
393 CpuIndex,
394 ((UINT8 *)SaveState) + mCpuSaveStateConvTable[Index].Offset
395 );
396 ASSERT_EFI_ERROR (Status);
397 }
398 }
399
400 mFrameworkSmst->CurrentlyExecutingCpu = gSmst->CurrentlyExecutingCpu;
401
402 ///
403 /// Search for Framework SMI handler information
404 ///
405 CallbackInfo = GetCallbackInfo (DispatchHandle);
406 ASSERT (CallbackInfo != NULL);
407
408 ///
409 /// Thunk into original Framwork SMI handler
410 ///
411 Status = (CallbackInfo->CallbackAddress) (
412 CallbackInfo->SmmImageHandle,
413 CommBuffer,
414 CommBufferSize
415 );
416 ///
417 /// Save CPU Save States in case any of them was modified
418 ///
419 for (CpuIndex = 0; CpuIndex < mNumberOfProcessors; CpuIndex++) {
420 for (Index = 0; Index < sizeof (mCpuSaveStateConvTable) / sizeof (CPU_SAVE_STATE_CONVERSION); Index++) {
421 Status = mSmmCpu->WriteSaveState (
422 mSmmCpu,
423 (UINTN)sizeof (UINT32),
424 mCpuSaveStateConvTable[Index].Register,
425 CpuIndex,
426 ((UINT8 *)&mFrameworkSmst->CpuSaveState[CpuIndex].Ia32SaveState) +
427 mCpuSaveStateConvTable[Index].Offset
428 );
429 }
430 }
431
432 ///
433 /// Conversion of returned status code
434 ///
435 switch (Status) {
436 case EFI_HANDLER_SUCCESS:
437 Status = EFI_WARN_INTERRUPT_SOURCE_QUIESCED;
438 break;
439 case EFI_HANDLER_CRITICAL_EXIT:
440 case EFI_HANDLER_SOURCE_QUIESCED:
441 Status = EFI_SUCCESS;
442 break;
443 case EFI_HANDLER_SOURCE_PENDING:
444 Status = EFI_WARN_INTERRUPT_SOURCE_PENDING;
445 break;
446 }
447 return Status;
448 }
449
450 /**
451 Thunk service of EFI_SMM_BASE_PROTOCOL.RegisterCallback().
452
453 @param[in, out] FunctionData Pointer to SMMBASE_FUNCTION_DATA.
454 **/
455 VOID
456 RegisterCallback (
457 IN OUT SMMBASE_FUNCTION_DATA *FunctionData
458 )
459 {
460 CALLBACK_INFO *Buffer;
461
462 ///
463 /// Note that MakeLast and FloatingPointSave options are not supported in PI SMM
464 ///
465
466 ///
467 /// Allocate buffer for callback thunk information
468 ///
469 Buffer = (CALLBACK_INFO *)AllocatePool (sizeof (CALLBACK_INFO));
470 if (Buffer == NULL) {
471 FunctionData->Status = EFI_OUT_OF_RESOURCES;
472 return;
473 }
474
475 ///
476 /// Fill SmmImageHandle and CallbackAddress into the thunk
477 ///
478 Buffer->SmmImageHandle = FunctionData->Args.RegisterCallback.SmmImageHandle;
479 Buffer->CallbackAddress = FunctionData->Args.RegisterCallback.CallbackAddress;
480
481 ///
482 /// Register the thunk code as a root SMI handler
483 ///
484 FunctionData->Status = gSmst->SmiHandlerRegister (
485 CallbackThunk,
486 NULL,
487 &Buffer->DispatchHandle
488 );
489 if (EFI_ERROR (FunctionData->Status)) {
490 FreePool (Buffer);
491 return;
492 }
493
494 ///
495 /// Save this callback info
496 ///
497 InsertTailList (&mCallbackInfoListHead, &Buffer->Link);
498 }
499
500
501 /**
502 Thunk service of EFI_SMM_BASE_PROTOCOL.SmmAllocatePool().
503
504 @param[in, out] FunctionData Pointer to SMMBASE_FUNCTION_DATA.
505 **/
506 VOID
507 HelperAllocatePool (
508 IN OUT SMMBASE_FUNCTION_DATA *FunctionData
509 )
510 {
511 FunctionData->Status = gSmst->SmmAllocatePool (
512 FunctionData->Args.AllocatePool.PoolType,
513 FunctionData->Args.AllocatePool.Size,
514 FunctionData->Args.AllocatePool.Buffer
515 );
516 }
517
518 /**
519 Thunk service of EFI_SMM_BASE_PROTOCOL.SmmFreePool().
520
521 @param[in, out] FunctionData Pointer to SMMBASE_FUNCTION_DATA.
522 **/
523 VOID
524 HelperFreePool (
525 IN OUT SMMBASE_FUNCTION_DATA *FunctionData
526 )
527 {
528 FreePool (FunctionData->Args.FreePool.Buffer);
529 FunctionData->Status = EFI_SUCCESS;
530 }
531
532 /**
533 Thunk service of EFI_SMM_BASE_PROTOCOL.Communicate().
534
535 @param[in, out] FunctionData Pointer to SMMBASE_FUNCTION_DATA.
536 **/
537 VOID
538 HelperCommunicate (
539 IN OUT SMMBASE_FUNCTION_DATA *FunctionData
540 )
541 {
542 LIST_ENTRY *Node;
543 CALLBACK_INFO *CallbackInfo;
544
545 if (FunctionData->Args.Communicate.CommunicationBuffer == NULL) {
546 FunctionData->Status = EFI_INVALID_PARAMETER;
547 return;
548 }
549
550 Node = GetFirstNode (&mCallbackInfoListHead);
551 while (!IsNull (&mCallbackInfoListHead, Node)) {
552 CallbackInfo = (CALLBACK_INFO *)Node;
553
554 if (FunctionData->Args.Communicate.ImageHandle == CallbackInfo->SmmImageHandle) {
555 ///
556 /// Thunk into original Framwork SMI handler
557 ///
558 (CallbackInfo->CallbackAddress) (
559 CallbackInfo->SmmImageHandle,
560 FunctionData->Args.Communicate.CommunicationBuffer,
561 FunctionData->Args.Communicate.SourceSize
562 );
563 ///
564 /// The message was successfully posted.
565 ///
566 FunctionData->Status = EFI_SUCCESS;
567 return;
568 }
569 Node = GetNextNode (&mCallbackInfoListHead, Node);
570 }
571
572 FunctionData->Status = EFI_INVALID_PARAMETER;
573 }
574
575 /**
576 Communication service SMI Handler entry.
577
578 This SMI handler provides services for the SMM Base Thunk driver.
579
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.
586
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
590 still be called.
591 @retval EFI_WARN_INTERRUPT_SOURCE_PENDING The interrupt is still pending and other handlers should still
592 be called.
593 @retval EFI_INTERRUPT_PENDING The interrupt could not be quiesced.
594 **/
595 EFI_STATUS
596 EFIAPI
597 SmmHandlerEntry (
598 IN EFI_HANDLE DispatchHandle,
599 IN CONST VOID *RegisterContext,
600 IN OUT VOID *CommBuffer,
601 IN OUT UINTN *CommBufferSize
602 )
603 {
604 SMMBASE_FUNCTION_DATA *FunctionData;
605
606 ASSERT (CommBuffer != NULL);
607 ASSERT (*CommBufferSize == sizeof (SMMBASE_FUNCTION_DATA));
608
609 FunctionData = (SMMBASE_FUNCTION_DATA *)CommBuffer;
610
611 switch (FunctionData->Function) {
612 case SmmBaseFunctionRegister:
613 Register (FunctionData);
614 break;
615 case SmmBaseFunctionUnregister:
616 UnRegister (FunctionData);
617 break;
618 case SmmBaseFunctionRegisterCallback:
619 RegisterCallback (FunctionData);
620 break;
621 case SmmBaseFunctionAllocatePool:
622 HelperAllocatePool (FunctionData);
623 break;
624 case SmmBaseFunctionFreePool:
625 HelperFreePool (FunctionData);
626 break;
627 case SmmBaseFunctionCommunicate:
628 HelperCommunicate (FunctionData);
629 break;
630 default:
631 ASSERT (FALSE);
632 FunctionData->Status = EFI_UNSUPPORTED;
633 }
634 return EFI_SUCCESS;
635 }
636
637 /**
638 Entry point function of the SMM Base Helper SMM driver.
639
640 @param[in] ImageHandle The firmware allocated handle for the EFI image.
641 @param[in] SystemTable A pointer to the EFI System Table.
642
643 @retval EFI_SUCCESS The entry point is executed successfully.
644 @retval other Some error occurs when executing this entry point.
645 **/
646 EFI_STATUS
647 EFIAPI
648 SmmBaseHelperMain (
649 IN EFI_HANDLE ImageHandle,
650 IN EFI_SYSTEM_TABLE *SystemTable
651 )
652 {
653 EFI_STATUS Status;
654 EFI_MP_SERVICES_PROTOCOL *MpServices;
655 EFI_HANDLE Handle;
656 UINTN NumberOfEnabledProcessors;
657
658 Handle = NULL;
659 ///
660 /// Locate SMM CPU Protocol which is used later to retrieve/update CPU Save States
661 ///
662 Status = gSmst->SmmLocateProtocol (&gEfiSmmCpuProtocolGuid, NULL, (VOID **) &mSmmCpu);
663 ASSERT_EFI_ERROR (Status);
664
665 ///
666 /// Locate PE32 Image Protocol which is used later to load Framework SMM driver
667 ///
668 Status = SystemTable->BootServices->LocateProtocol (&gEfiLoadPeImageProtocolGuid, NULL, (VOID **) &mLoadPe32Image);
669 ASSERT_EFI_ERROR (Status);
670
671 //
672 // Get MP Services Protocol
673 //
674 Status = SystemTable->BootServices->LocateProtocol (&gEfiMpServiceProtocolGuid, NULL, (VOID **)&MpServices);
675 ASSERT_EFI_ERROR (Status);
676
677 //
678 // Use MP Services Protocol to retrieve the number of processors and number of enabled processors
679 //
680 Status = MpServices->GetNumberOfProcessors (MpServices, &mNumberOfProcessors, &NumberOfEnabledProcessors);
681 ASSERT_EFI_ERROR (Status);
682
683 ///
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.
686 ///
687 Status = gBS->AllocatePool (
688 EfiBootServicesData,
689 sizeof (EFI_SMM_BASE_HELPER_READY_PROTOCOL),
690 (VOID **)&mSmmBaseHelperReady
691 );
692 ASSERT_EFI_ERROR (Status);
693
694 ///
695 /// Construct Framework SMST from PI SMST
696 ///
697 mFrameworkSmst = ConstructFrameworkSmst ();
698 mSmmBaseHelperReady->FrameworkSmst = mFrameworkSmst;
699 mSmmBaseHelperReady->ServiceEntry = SmmHandlerEntry;
700
701 ///
702 /// Register SMM Base Helper services for SMM Base Thunk driver
703 ///
704 Status = gSmst->SmiHandlerRegister (SmmHandlerEntry, &gEfiSmmBaseThunkCommunicationGuid, &mDispatchHandle);
705 ASSERT_EFI_ERROR (Status);
706
707 ///
708 /// Install EFI SMM Base Helper Protocol in the UEFI handle database
709 ///
710 Status = gBS->InstallProtocolInterface (
711 &Handle,
712 &gEfiSmmBaseHelperReadyProtocolGuid,
713 EFI_NATIVE_INTERFACE,
714 mSmmBaseHelperReady
715 );
716 ASSERT_EFI_ERROR (Status);
717
718 return Status;
719 }
720