]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Core/PiSmmCore/PiSmmCore.c
MdeModulePkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / MdeModulePkg / Core / PiSmmCore / PiSmmCore.c
CommitLineData
e42e9404 1/** @file\r
2 SMM Core Main Entry Point\r
3\r
bb2c9ccb 4 Copyright (c) 2009 - 2019, Intel Corporation. All rights reserved.<BR>\r
9d510e61 5 SPDX-License-Identifier: BSD-2-Clause-Patent\r
e42e9404 6\r
7**/\r
8\r
9#include "PiSmmCore.h"\r
10\r
11//\r
12// Physical pointer to private structure shared between SMM IPL and the SMM Core\r
13//\r
14SMM_CORE_PRIVATE_DATA *gSmmCorePrivate;\r
15\r
16//\r
17// SMM Core global variable for SMM System Table. Only accessed as a physical structure in SMRAM.\r
18//\r
19EFI_SMM_SYSTEM_TABLE2 gSmmCoreSmst = {\r
20 {\r
21 SMM_SMST_SIGNATURE,\r
22 EFI_SMM_SYSTEM_TABLE2_REVISION,\r
23 sizeof (gSmmCoreSmst.Hdr)\r
24 },\r
25 NULL, // SmmFirmwareVendor\r
26 0, // SmmFirmwareRevision\r
27 SmmInstallConfigurationTable,\r
28 {\r
29 {\r
30 (EFI_SMM_CPU_IO2) SmmEfiNotAvailableYetArg5, // SmmMemRead\r
31 (EFI_SMM_CPU_IO2) SmmEfiNotAvailableYetArg5 // SmmMemWrite\r
32 },\r
33 {\r
34 (EFI_SMM_CPU_IO2) SmmEfiNotAvailableYetArg5, // SmmIoRead\r
35 (EFI_SMM_CPU_IO2) SmmEfiNotAvailableYetArg5 // SmmIoWrite\r
36 }\r
37 },\r
38 SmmAllocatePool,\r
39 SmmFreePool,\r
40 SmmAllocatePages,\r
41 SmmFreePages,\r
42 NULL, // SmmStartupThisAp\r
43 0, // CurrentlyExecutingCpu\r
44 0, // NumberOfCpus\r
45 NULL, // CpuSaveStateSize\r
46 NULL, // CpuSaveState\r
47 0, // NumberOfTableEntries\r
48 NULL, // SmmConfigurationTable\r
49 SmmInstallProtocolInterface,\r
50 SmmUninstallProtocolInterface,\r
51 SmmHandleProtocol,\r
52 SmmRegisterProtocolNotify,\r
53 SmmLocateHandle,\r
54 SmmLocateProtocol,\r
55 SmiManage,\r
56 SmiHandlerRegister,\r
57 SmiHandlerUnRegister\r
58};\r
59\r
60//\r
61// Flag to determine if the platform has performed a legacy boot.\r
d1102dba 62// If this flag is TRUE, then the runtime code and runtime data associated with the\r
53ec4d7f 63// SMM IPL are converted to free memory, so the SMM Core must guarantee that is\r
e42e9404 64// does not touch of the code/data associated with the SMM IPL if this flag is TRUE.\r
65//\r
66BOOLEAN mInLegacyBoot = FALSE;\r
67\r
7b9b55b2
SZ
68//\r
69// Flag to determine if it is during S3 resume.\r
70// It will be set in S3 entry callback and cleared at EndOfS3Resume.\r
71//\r
72BOOLEAN mDuringS3Resume = FALSE;\r
73\r
bb2c9ccb
ED
74//\r
75// Flag to determine if platform enabled S3.\r
76// Get the value from PcdAcpiS3Enable.\r
77//\r
78BOOLEAN mAcpiS3Enable = FALSE;\r
79\r
e42e9404 80//\r
81// Table of SMI Handlers that are registered by the SMM Core when it is initialized\r
82//\r
83SMM_CORE_SMI_HANDLERS mSmmCoreSmiHandlers[] = {\r
d76c2da8 84 { SmmDriverDispatchHandler, &gEfiEventDxeDispatchGuid, NULL, TRUE },\r
d1102dba 85 { SmmReadyToLockHandler, &gEfiDxeSmmReadyToLockProtocolGuid, NULL, TRUE },\r
d76c2da8
ED
86 { SmmLegacyBootHandler, &gEfiEventLegacyBootGuid, NULL, FALSE },\r
87 { SmmExitBootServicesHandler, &gEfiEventExitBootServicesGuid, NULL, FALSE },\r
88 { SmmReadyToBootHandler, &gEfiEventReadyToBootGuid, NULL, FALSE },\r
89 { SmmEndOfDxeHandler, &gEfiEndOfDxeEventGroupGuid, NULL, TRUE },\r
bb2c9ccb
ED
90 { NULL, NULL, NULL, FALSE }\r
91};\r
92\r
93//\r
94// Table of SMI Handlers that are registered by the SMM Core when it is initialized\r
95//\r
96SMM_CORE_SMI_HANDLERS mSmmCoreS3SmiHandlers[] = {\r
1bae3e0e 97 { SmmS3SmmInitDoneHandler, &gEdkiiS3SmmInitDoneGuid, NULL, FALSE },\r
a85e7127 98 { SmmEndOfS3ResumeHandler, &gEdkiiEndOfS3ResumeGuid, NULL, FALSE },\r
d76c2da8 99 { NULL, NULL, NULL, FALSE }\r
e42e9404 100};\r
101\r
84edd20b
SZ
102UINTN mFullSmramRangeCount;\r
103EFI_SMRAM_DESCRIPTOR *mFullSmramRanges;\r
104\r
285a682c
JY
105EFI_SMM_DRIVER_ENTRY *mSmmCoreDriverEntry;\r
106\r
0b256fb1
JY
107EFI_LOADED_IMAGE_PROTOCOL *mSmmCoreLoadedImage;\r
108\r
e42e9404 109/**\r
110 Place holder function until all the SMM System Table Service are available.\r
111\r
112 Note: This function is only used by SMRAM invocation. It is never used by DXE invocation.\r
113\r
114 @param Arg1 Undefined\r
115 @param Arg2 Undefined\r
116 @param Arg3 Undefined\r
117 @param Arg4 Undefined\r
118 @param Arg5 Undefined\r
119\r
120 @return EFI_NOT_AVAILABLE_YET\r
121\r
122**/\r
123EFI_STATUS\r
124EFIAPI\r
125SmmEfiNotAvailableYetArg5 (\r
126 UINTN Arg1,\r
127 UINTN Arg2,\r
128 UINTN Arg3,\r
129 UINTN Arg4,\r
130 UINTN Arg5\r
131 )\r
132{\r
133 //\r
134 // This function should never be executed. If it does, then the architectural protocols\r
135 // have not been designed correctly.\r
136 //\r
137 return EFI_NOT_AVAILABLE_YET;\r
138}\r
139\r
140/**\r
141 Software SMI handler that is called when a Legacy Boot event is signalled. The SMM\r
d1102dba 142 Core uses this signal to know that a Legacy Boot has been performed and that\r
e42e9404 143 gSmmCorePrivate that is shared between the UEFI and SMM execution environments can\r
144 not be accessed from SMM anymore since that structure is considered free memory by\r
53ec4d7f
SZ
145 a legacy OS. Then the SMM Core also install SMM Legacy Boot protocol to notify SMM\r
146 driver that system enter legacy boot.\r
e42e9404 147\r
148 @param DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().\r
149 @param Context Points to an optional handler context which was specified when the handler was registered.\r
150 @param CommBuffer A pointer to a collection of data in memory that will\r
151 be conveyed from a non-SMM environment into an SMM environment.\r
152 @param CommBufferSize The size of the CommBuffer.\r
153\r
154 @return Status Code\r
155\r
156**/\r
157EFI_STATUS\r
158EFIAPI\r
159SmmLegacyBootHandler (\r
160 IN EFI_HANDLE DispatchHandle,\r
161 IN CONST VOID *Context, OPTIONAL\r
162 IN OUT VOID *CommBuffer, OPTIONAL\r
163 IN OUT UINTN *CommBufferSize OPTIONAL\r
164 )\r
165{\r
53ec4d7f
SZ
166 EFI_STATUS Status;\r
167 EFI_HANDLE SmmHandle;\r
c6ded48c 168 UINTN Index;\r
53ec4d7f
SZ
169\r
170 //\r
171 // Install SMM Legacy Boot protocol.\r
172 //\r
173 SmmHandle = NULL;\r
174 Status = SmmInstallProtocolInterface (\r
175 &SmmHandle,\r
176 &gEdkiiSmmLegacyBootProtocolGuid,\r
177 EFI_NATIVE_INTERFACE,\r
178 NULL\r
179 );\r
180\r
e42e9404 181 mInLegacyBoot = TRUE;\r
53ec4d7f
SZ
182\r
183 SmiHandlerUnRegister (DispatchHandle);\r
184\r
c6ded48c
SZ
185 //\r
186 // It is legacy boot, unregister ExitBootService SMI handler.\r
187 //\r
188 for (Index = 0; mSmmCoreSmiHandlers[Index].HandlerType != NULL; Index++) {\r
189 if (CompareGuid (mSmmCoreSmiHandlers[Index].HandlerType, &gEfiEventExitBootServicesGuid)) {\r
190 SmiHandlerUnRegister (mSmmCoreSmiHandlers[Index].DispatchHandle);\r
191 break;\r
192 }\r
193 }\r
194\r
53ec4d7f
SZ
195 return Status;\r
196}\r
197\r
198/**\r
199 Software SMI handler that is called when an Exit Boot Services event is signalled.\r
200 Then the SMM Core also install SMM Exit Boot Services protocol to notify SMM driver\r
201 that system enter exit boot services.\r
202\r
203 @param DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().\r
204 @param Context Points to an optional handler context which was specified when the handler was registered.\r
205 @param CommBuffer A pointer to a collection of data in memory that will\r
206 be conveyed from a non-SMM environment into an SMM environment.\r
207 @param CommBufferSize The size of the CommBuffer.\r
208\r
209 @return Status Code\r
210\r
211**/\r
212EFI_STATUS\r
213EFIAPI\r
214SmmExitBootServicesHandler (\r
215 IN EFI_HANDLE DispatchHandle,\r
216 IN CONST VOID *Context, OPTIONAL\r
217 IN OUT VOID *CommBuffer, OPTIONAL\r
218 IN OUT UINTN *CommBufferSize OPTIONAL\r
219 )\r
220{\r
221 EFI_STATUS Status;\r
222 EFI_HANDLE SmmHandle;\r
c6ded48c 223 UINTN Index;\r
53ec4d7f
SZ
224\r
225 //\r
226 // Install SMM Exit Boot Services protocol.\r
227 //\r
228 SmmHandle = NULL;\r
229 Status = SmmInstallProtocolInterface (\r
230 &SmmHandle,\r
231 &gEdkiiSmmExitBootServicesProtocolGuid,\r
232 EFI_NATIVE_INTERFACE,\r
233 NULL\r
234 );\r
235\r
236 SmiHandlerUnRegister (DispatchHandle);\r
237\r
c6ded48c
SZ
238 //\r
239 // It is UEFI boot, unregister LegacyBoot SMI handler.\r
240 //\r
241 for (Index = 0; mSmmCoreSmiHandlers[Index].HandlerType != NULL; Index++) {\r
242 if (CompareGuid (mSmmCoreSmiHandlers[Index].HandlerType, &gEfiEventLegacyBootGuid)) {\r
243 SmiHandlerUnRegister (mSmmCoreSmiHandlers[Index].DispatchHandle);\r
244 break;\r
245 }\r
246 }\r
247\r
53ec4d7f
SZ
248 return Status;\r
249}\r
250\r
7b9b55b2
SZ
251/**\r
252 Main entry point for an SMM handler dispatch or communicate-based callback.\r
253\r
254 @param[in] DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().\r
255 @param[in] Context Points to an optional handler context which was specified when the\r
256 handler was registered.\r
257 @param[in,out] CommBuffer A pointer to a collection of data in memory that will\r
258 be conveyed from a non-SMM environment into an SMM environment.\r
259 @param[in,out] CommBufferSize The size of the CommBuffer.\r
260\r
261 @retval EFI_SUCCESS The interrupt was handled and quiesced. No other handlers\r
262 should still be called.\r
263 @retval EFI_WARN_INTERRUPT_SOURCE_QUIESCED The interrupt has been quiesced but other handlers should\r
264 still be called.\r
265 @retval EFI_WARN_INTERRUPT_SOURCE_PENDING The interrupt is still pending and other handlers should still\r
266 be called.\r
267 @retval EFI_INTERRUPT_PENDING The interrupt could not be quiesced.\r
268**/\r
269EFI_STATUS\r
270EFIAPI\r
271SmmS3EntryCallBack (\r
272 IN EFI_HANDLE DispatchHandle,\r
273 IN CONST VOID *Context OPTIONAL,\r
274 IN OUT VOID *CommBuffer OPTIONAL,\r
275 IN OUT UINTN *CommBufferSize OPTIONAL\r
276 )\r
277{\r
278 mDuringS3Resume = TRUE;\r
279 return EFI_SUCCESS;\r
280}\r
281\r
53ec4d7f
SZ
282/**\r
283 Software SMI handler that is called when an Ready To Boot event is signalled.\r
284 Then the SMM Core also install SMM Ready To Boot protocol to notify SMM driver\r
285 that system enter ready to boot.\r
286\r
287 @param DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().\r
288 @param Context Points to an optional handler context which was specified when the handler was registered.\r
289 @param CommBuffer A pointer to a collection of data in memory that will\r
290 be conveyed from a non-SMM environment into an SMM environment.\r
291 @param CommBufferSize The size of the CommBuffer.\r
292\r
293 @return Status Code\r
294\r
295**/\r
296EFI_STATUS\r
297EFIAPI\r
298SmmReadyToBootHandler (\r
299 IN EFI_HANDLE DispatchHandle,\r
300 IN CONST VOID *Context, OPTIONAL\r
301 IN OUT VOID *CommBuffer, OPTIONAL\r
302 IN OUT UINTN *CommBufferSize OPTIONAL\r
303 )\r
304{\r
7b9b55b2
SZ
305 EFI_STATUS Status;\r
306 EFI_HANDLE SmmHandle;\r
53ec4d7f
SZ
307\r
308 //\r
309 // Install SMM Ready To Boot protocol.\r
310 //\r
311 SmmHandle = NULL;\r
312 Status = SmmInstallProtocolInterface (\r
313 &SmmHandle,\r
314 &gEdkiiSmmReadyToBootProtocolGuid,\r
315 EFI_NATIVE_INTERFACE,\r
316 NULL\r
317 );\r
318\r
319 SmiHandlerUnRegister (DispatchHandle);\r
320\r
b36acb21 321 return Status;\r
e42e9404 322}\r
323\r
324/**\r
325 Software SMI handler that is called when the DxeSmmReadyToLock protocol is added\r
d1102dba
LG
326 or if gEfiEventReadyToBootGuid is signalled. This function unregisters the\r
327 Software SMIs that are nor required after SMRAM is locked and installs the\r
328 SMM Ready To Lock Protocol so SMM Drivers are informed that SMRAM is about\r
2048c585 329 to be locked. It also verifies the SMM CPU I/O 2 Protocol has been installed\r
e42e9404 330 and NULLs gBS and gST because they can not longer be used after SMRAM is locked.\r
331\r
332 @param DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().\r
333 @param Context Points to an optional handler context which was specified when the handler was registered.\r
334 @param CommBuffer A pointer to a collection of data in memory that will\r
335 be conveyed from a non-SMM environment into an SMM environment.\r
336 @param CommBufferSize The size of the CommBuffer.\r
337\r
338 @return Status Code\r
339\r
340**/\r
341EFI_STATUS\r
342EFIAPI\r
343SmmReadyToLockHandler (\r
344 IN EFI_HANDLE DispatchHandle,\r
345 IN CONST VOID *Context, OPTIONAL\r
346 IN OUT VOID *CommBuffer, OPTIONAL\r
347 IN OUT UINTN *CommBufferSize OPTIONAL\r
348 )\r
349{\r
350 EFI_STATUS Status;\r
351 UINTN Index;\r
352 EFI_HANDLE SmmHandle;\r
353 VOID *Interface;\r
354\r
355 //\r
356 // Unregister SMI Handlers that are no required after the SMM driver dispatch is stopped\r
357 //\r
358 for (Index = 0; mSmmCoreSmiHandlers[Index].HandlerType != NULL; Index++) {\r
359 if (mSmmCoreSmiHandlers[Index].UnRegister) {\r
360 SmiHandlerUnRegister (mSmmCoreSmiHandlers[Index].DispatchHandle);\r
361 }\r
362 }\r
363\r
364 //\r
365 // Install SMM Ready to lock protocol\r
366 //\r
367 SmmHandle = NULL;\r
368 Status = SmmInstallProtocolInterface (\r
369 &SmmHandle,\r
370 &gEfiSmmReadyToLockProtocolGuid,\r
371 EFI_NATIVE_INTERFACE,\r
372 NULL\r
373 );\r
374\r
375 //\r
376 // Make sure SMM CPU I/O 2 Procol has been installed into the handle database\r
377 //\r
378 Status = SmmLocateProtocol (&gEfiSmmCpuIo2ProtocolGuid, NULL, &Interface);\r
379\r
380 //\r
381 // Print a message on a debug build if the SMM CPU I/O 2 Protocol is not installed\r
382 //\r
383 DEBUG_CODE_BEGIN ();\r
384 if (EFI_ERROR (Status)) {\r
385 DEBUG ((DEBUG_ERROR, "\nSMM: SmmCpuIo Arch Protocol not present!!\n"));\r
386 }\r
387 DEBUG_CODE_END ();\r
388\r
389 //\r
390 // Assert if the CPU I/O 2 Protocol is not installed\r
391 //\r
392 ASSERT_EFI_ERROR (Status);\r
393\r
394 //\r
395 // Display any drivers that were not dispatched because dependency expression\r
396 // evaluated to false if this is a debug build\r
397 //\r
398 DEBUG_CODE_BEGIN ();\r
399 SmmDisplayDiscoveredNotDispatched ();\r
400 DEBUG_CODE_END ();\r
401\r
402 //\r
403 // Not allowed to use gST or gBS after lock\r
404 //\r
405 gST = NULL;\r
406 gBS = NULL;\r
407\r
84edd20b
SZ
408 SmramProfileReadyToLock ();\r
409\r
e42e9404 410 return Status;\r
411}\r
412\r
46ece1ff
JY
413/**\r
414 Software SMI handler that is called when the EndOfDxe event is signalled.\r
415 This function installs the SMM EndOfDxe Protocol so SMM Drivers are informed that\r
416 platform code will invoke 3rd part code.\r
417\r
418 @param DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().\r
419 @param Context Points to an optional handler context which was specified when the handler was registered.\r
420 @param CommBuffer A pointer to a collection of data in memory that will\r
421 be conveyed from a non-SMM environment into an SMM environment.\r
422 @param CommBufferSize The size of the CommBuffer.\r
423\r
424 @return Status Code\r
425\r
426**/\r
427EFI_STATUS\r
428EFIAPI\r
429SmmEndOfDxeHandler (\r
430 IN EFI_HANDLE DispatchHandle,\r
431 IN CONST VOID *Context, OPTIONAL\r
432 IN OUT VOID *CommBuffer, OPTIONAL\r
433 IN OUT UINTN *CommBufferSize OPTIONAL\r
434 )\r
435{\r
b36acb21
SZ
436 EFI_STATUS Status;\r
437 EFI_HANDLE SmmHandle;\r
438 EFI_SMM_SX_DISPATCH2_PROTOCOL *SxDispatch;\r
439 EFI_SMM_SX_REGISTER_CONTEXT EntryRegisterContext;\r
440 EFI_HANDLE S3EntryHandle;\r
46ece1ff
JY
441\r
442 DEBUG ((EFI_D_INFO, "SmmEndOfDxeHandler\n"));\r
b36acb21 443\r
46ece1ff
JY
444 //\r
445 // Install SMM EndOfDxe protocol\r
446 //\r
447 SmmHandle = NULL;\r
448 Status = SmmInstallProtocolInterface (\r
449 &SmmHandle,\r
450 &gEfiSmmEndOfDxeProtocolGuid,\r
451 EFI_NATIVE_INTERFACE,\r
452 NULL\r
453 );\r
b36acb21 454\r
bb2c9ccb 455 if (mAcpiS3Enable) {\r
b36acb21 456 //\r
bb2c9ccb 457 // Locate SmmSxDispatch2 protocol.\r
b36acb21 458 //\r
bb2c9ccb
ED
459 Status = SmmLocateProtocol (\r
460 &gEfiSmmSxDispatch2ProtocolGuid,\r
461 NULL,\r
462 (VOID **)&SxDispatch\r
463 );\r
464 if (!EFI_ERROR (Status) && (SxDispatch != NULL)) {\r
465 //\r
466 // Register a S3 entry callback function to\r
467 // determine if it will be during S3 resume.\r
468 //\r
469 EntryRegisterContext.Type = SxS3;\r
470 EntryRegisterContext.Phase = SxEntry;\r
471 Status = SxDispatch->Register (\r
472 SxDispatch,\r
473 SmmS3EntryCallBack,\r
474 &EntryRegisterContext,\r
475 &S3EntryHandle\r
476 );\r
477 ASSERT_EFI_ERROR (Status);\r
478 }\r
b36acb21
SZ
479 }\r
480\r
481 return EFI_SUCCESS;\r
46ece1ff
JY
482}\r
483\r
1bae3e0e
SZ
484/**\r
485 Software SMI handler that is called when the S3SmmInitDone signal is triggered.\r
486 This function installs the SMM S3SmmInitDone Protocol so SMM Drivers are informed that\r
487 S3 SMM initialization has been done.\r
488\r
489 @param DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().\r
490 @param Context Points to an optional handler context which was specified when the handler was registered.\r
491 @param CommBuffer A pointer to a collection of data in memory that will\r
492 be conveyed from a non-SMM environment into an SMM environment.\r
493 @param CommBufferSize The size of the CommBuffer.\r
494\r
495 @return Status Code\r
496\r
497**/\r
498EFI_STATUS\r
499EFIAPI\r
500SmmS3SmmInitDoneHandler (\r
501 IN EFI_HANDLE DispatchHandle,\r
502 IN CONST VOID *Context, OPTIONAL\r
503 IN OUT VOID *CommBuffer, OPTIONAL\r
504 IN OUT UINTN *CommBufferSize OPTIONAL\r
505 )\r
506{\r
507 EFI_STATUS Status;\r
508 EFI_HANDLE SmmHandle;\r
509\r
510 DEBUG ((DEBUG_INFO, "SmmS3SmmInitDoneHandler\n"));\r
511\r
512 if (!mDuringS3Resume) {\r
513 DEBUG ((DEBUG_ERROR, "It is not during S3 resume\n"));\r
514 return EFI_SUCCESS;\r
515 }\r
516\r
517 //\r
518 // Install SMM S3SmmInitDone protocol\r
519 //\r
520 SmmHandle = NULL;\r
521 Status = SmmInstallProtocolInterface (\r
522 &SmmHandle,\r
523 &gEdkiiS3SmmInitDoneGuid,\r
524 EFI_NATIVE_INTERFACE,\r
525 NULL\r
526 );\r
527 ASSERT_EFI_ERROR (Status);\r
528\r
529 //\r
530 // Uninstall the protocol here because the comsumer just hook the\r
531 // installation event.\r
532 //\r
533 Status = SmmUninstallProtocolInterface (\r
534 SmmHandle,\r
535 &gEdkiiS3SmmInitDoneGuid,\r
536 NULL\r
537 );\r
538 ASSERT_EFI_ERROR (Status);\r
539\r
540 return Status;\r
541}\r
542\r
d76c2da8 543/**\r
a85e7127 544 Software SMI handler that is called when the EndOfS3Resume signal is triggered.\r
d76c2da8
ED
545 This function installs the SMM EndOfS3Resume Protocol so SMM Drivers are informed that\r
546 S3 resume has finished.\r
547\r
548 @param DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().\r
549 @param Context Points to an optional handler context which was specified when the handler was registered.\r
550 @param CommBuffer A pointer to a collection of data in memory that will\r
551 be conveyed from a non-SMM environment into an SMM environment.\r
552 @param CommBufferSize The size of the CommBuffer.\r
553\r
554 @return Status Code\r
555\r
556**/\r
557EFI_STATUS\r
558EFIAPI\r
559SmmEndOfS3ResumeHandler (\r
560 IN EFI_HANDLE DispatchHandle,\r
561 IN CONST VOID *Context, OPTIONAL\r
562 IN OUT VOID *CommBuffer, OPTIONAL\r
563 IN OUT UINTN *CommBufferSize OPTIONAL\r
564 )\r
565{\r
566 EFI_STATUS Status;\r
567 EFI_HANDLE SmmHandle;\r
568\r
7b9b55b2
SZ
569 DEBUG ((DEBUG_INFO, "SmmEndOfS3ResumeHandler\n"));\r
570\r
571 if (!mDuringS3Resume) {\r
572 DEBUG ((DEBUG_ERROR, "It is not during S3 resume\n"));\r
573 return EFI_SUCCESS;\r
574 }\r
d76c2da8
ED
575\r
576 //\r
577 // Install SMM EndOfS3Resume protocol\r
578 //\r
579 SmmHandle = NULL;\r
580 Status = SmmInstallProtocolInterface (\r
581 &SmmHandle,\r
a85e7127 582 &gEdkiiEndOfS3ResumeGuid,\r
d76c2da8
ED
583 EFI_NATIVE_INTERFACE,\r
584 NULL\r
585 );\r
586 ASSERT_EFI_ERROR (Status);\r
587\r
588 //\r
a85e7127 589 // Uninstall the protocol here because the comsumer just hook the\r
d76c2da8
ED
590 // installation event.\r
591 //\r
592 Status = SmmUninstallProtocolInterface (\r
593 SmmHandle,\r
a85e7127 594 &gEdkiiEndOfS3ResumeGuid,\r
d76c2da8
ED
595 NULL\r
596 );\r
597 ASSERT_EFI_ERROR (Status);\r
598\r
7b9b55b2 599 mDuringS3Resume = FALSE;\r
d76c2da8
ED
600 return Status;\r
601}\r
602\r
3b657538
SZ
603/**\r
604 Determine if two buffers overlap in memory.\r
605\r
606 @param[in] Buff1 Pointer to first buffer\r
607 @param[in] Size1 Size of Buff1\r
608 @param[in] Buff2 Pointer to second buffer\r
609 @param[in] Size2 Size of Buff2\r
610\r
611 @retval TRUE Buffers overlap in memory.\r
612 @retval FALSE Buffer doesn't overlap.\r
613\r
614**/\r
615BOOLEAN\r
616InternalIsBufferOverlapped (\r
617 IN UINT8 *Buff1,\r
618 IN UINTN Size1,\r
619 IN UINT8 *Buff2,\r
620 IN UINTN Size2\r
621 )\r
622{\r
623 //\r
624 // If buff1's end is less than the start of buff2, then it's ok.\r
625 // Also, if buff1's start is beyond buff2's end, then it's ok.\r
626 //\r
627 if (((Buff1 + Size1) <= Buff2) || (Buff1 >= (Buff2 + Size2))) {\r
628 return FALSE;\r
629 }\r
630\r
631 return TRUE;\r
632}\r
633\r
e42e9404 634/**\r
635 The main entry point to SMM Foundation.\r
636\r
637 Note: This function is only used by SMRAM invocation. It is never used by DXE invocation.\r
638\r
639 @param SmmEntryContext Processor information and functionality\r
640 needed by SMM Foundation.\r
641\r
642**/\r
643VOID\r
644EFIAPI\r
645SmmEntryPoint (\r
646 IN CONST EFI_SMM_ENTRY_CONTEXT *SmmEntryContext\r
647)\r
648{\r
649 EFI_STATUS Status;\r
650 EFI_SMM_COMMUNICATE_HEADER *CommunicateHeader;\r
a25cb9f6 651 BOOLEAN InLegacyBoot;\r
3b657538 652 BOOLEAN IsOverlapped;\r
eaae7b33
JF
653 VOID *CommunicationBuffer;\r
654 UINTN BufferSize;\r
e42e9404 655\r
656 //\r
229fd9e7 657 // Update SMST with contents of the SmmEntryContext structure\r
e42e9404 658 //\r
229fd9e7
MK
659 gSmmCoreSmst.SmmStartupThisAp = SmmEntryContext->SmmStartupThisAp;\r
660 gSmmCoreSmst.CurrentlyExecutingCpu = SmmEntryContext->CurrentlyExecutingCpu;\r
661 gSmmCoreSmst.NumberOfCpus = SmmEntryContext->NumberOfCpus;\r
662 gSmmCoreSmst.CpuSaveStateSize = SmmEntryContext->CpuSaveStateSize;\r
663 gSmmCoreSmst.CpuSaveState = SmmEntryContext->CpuSaveState;\r
e42e9404 664\r
495797c5 665 //\r
666 // Call platform hook before Smm Dispatch\r
667 //\r
668 PlatformHookBeforeSmmDispatch ();\r
669\r
e63da9f0
JW
670 //\r
671 // Call memory management hook function\r
672 //\r
673 SmmEntryPointMemoryManagementHook ();\r
674\r
e42e9404 675 //\r
676 // If a legacy boot has occured, then make sure gSmmCorePrivate is not accessed\r
677 //\r
a25cb9f6 678 InLegacyBoot = mInLegacyBoot;\r
679 if (!InLegacyBoot) {\r
e42e9404 680 //\r
9fa90bb4 681 // Mark the InSmm flag as TRUE, it will be used by SmmBase2 protocol\r
e42e9404 682 //\r
9fa90bb4 683 gSmmCorePrivate->InSmm = TRUE;\r
e42e9404 684\r
685 //\r
d1102dba 686 // Check to see if this is a Synchronous SMI sent through the SMM Communication\r
9fa90bb4 687 // Protocol or an Asynchronous SMI\r
e42e9404 688 //\r
eaae7b33
JF
689 CommunicationBuffer = gSmmCorePrivate->CommunicationBuffer;\r
690 BufferSize = gSmmCorePrivate->BufferSize;\r
691 if (CommunicationBuffer != NULL) {\r
9fa90bb4 692 //\r
693 // Synchronous SMI for SMM Core or request from Communicate protocol\r
694 //\r
3b657538 695 IsOverlapped = InternalIsBufferOverlapped (\r
eaae7b33
JF
696 (UINT8 *) CommunicationBuffer,\r
697 BufferSize,\r
3b657538
SZ
698 (UINT8 *) gSmmCorePrivate,\r
699 sizeof (*gSmmCorePrivate)\r
700 );\r
eaae7b33 701 if (!SmmIsBufferOutsideSmmValid ((UINTN)CommunicationBuffer, BufferSize) || IsOverlapped) {\r
3720ee6d 702 //\r
3b657538
SZ
703 // If CommunicationBuffer is not in valid address scope,\r
704 // or there is overlap between gSmmCorePrivate and CommunicationBuffer,\r
705 // return EFI_INVALID_PARAMETER\r
3720ee6d
JF
706 //\r
707 gSmmCorePrivate->CommunicationBuffer = NULL;\r
d1632f69 708 gSmmCorePrivate->ReturnStatus = EFI_ACCESS_DENIED;\r
3720ee6d 709 } else {\r
eaae7b33
JF
710 CommunicateHeader = (EFI_SMM_COMMUNICATE_HEADER *)CommunicationBuffer;\r
711 BufferSize -= OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data);\r
3720ee6d 712 Status = SmiManage (\r
d1102dba
LG
713 &CommunicateHeader->HeaderGuid,\r
714 NULL,\r
715 CommunicateHeader->Data,\r
eaae7b33 716 &BufferSize\r
3720ee6d
JF
717 );\r
718 //\r
719 // Update CommunicationBuffer, BufferSize and ReturnStatus\r
720 // Communicate service finished, reset the pointer to CommBuffer to NULL\r
721 //\r
eaae7b33 722 gSmmCorePrivate->BufferSize = BufferSize + OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data);\r
3720ee6d
JF
723 gSmmCorePrivate->CommunicationBuffer = NULL;\r
724 gSmmCorePrivate->ReturnStatus = (Status == EFI_SUCCESS) ? EFI_SUCCESS : EFI_NOT_FOUND;\r
725 }\r
9fa90bb4 726 }\r
e42e9404 727 }\r
9fa90bb4 728\r
729 //\r
730 // Process Asynchronous SMI sources\r
731 //\r
732 SmiManage (NULL, NULL, NULL, NULL);\r
d1102dba 733\r
495797c5 734 //\r
735 // Call platform hook after Smm Dispatch\r
736 //\r
737 PlatformHookAfterSmmDispatch ();\r
e42e9404 738\r
739 //\r
9fa90bb4 740 // If a legacy boot has occured, then make sure gSmmCorePrivate is not accessed\r
e42e9404 741 //\r
a25cb9f6 742 if (!InLegacyBoot) {\r
9fa90bb4 743 //\r
744 // Clear the InSmm flag as we are going to leave SMM\r
745 //\r
746 gSmmCorePrivate->InSmm = FALSE;\r
747 }\r
e42e9404 748}\r
749\r
0b256fb1
JY
750/**\r
751 Install LoadedImage protocol for SMM Core.\r
752**/\r
753VOID\r
754SmmCoreInstallLoadedImage (\r
755 VOID\r
756 )\r
757{\r
758 EFI_STATUS Status;\r
759 EFI_HANDLE Handle;\r
760\r
761 //\r
762 // Allocate a Loaded Image Protocol in EfiBootServicesData\r
763 //\r
764 Status = gBS->AllocatePool (EfiBootServicesData, sizeof(EFI_LOADED_IMAGE_PROTOCOL), (VOID **)&mSmmCoreLoadedImage);\r
765 ASSERT_EFI_ERROR (Status);\r
766\r
767 ZeroMem (mSmmCoreLoadedImage, sizeof (EFI_LOADED_IMAGE_PROTOCOL));\r
768 //\r
769 // Fill in the remaining fields of the Loaded Image Protocol instance.\r
770 // Note: ImageBase is an SMRAM address that can not be accessed outside of SMRAM if SMRAM window is closed.\r
771 //\r
772 mSmmCoreLoadedImage->Revision = EFI_LOADED_IMAGE_PROTOCOL_REVISION;\r
773 mSmmCoreLoadedImage->ParentHandle = gSmmCorePrivate->SmmIplImageHandle;\r
774 mSmmCoreLoadedImage->SystemTable = gST;\r
775\r
776 mSmmCoreLoadedImage->ImageBase = (VOID *)(UINTN)gSmmCorePrivate->PiSmmCoreImageBase;\r
777 mSmmCoreLoadedImage->ImageSize = gSmmCorePrivate->PiSmmCoreImageSize;\r
778 mSmmCoreLoadedImage->ImageCodeType = EfiRuntimeServicesCode;\r
779 mSmmCoreLoadedImage->ImageDataType = EfiRuntimeServicesData;\r
780\r
781 //\r
782 // Create a new image handle in the UEFI handle database for the SMM Driver\r
783 //\r
784 Handle = NULL;\r
785 Status = gBS->InstallMultipleProtocolInterfaces (\r
786 &Handle,\r
787 &gEfiLoadedImageProtocolGuid, mSmmCoreLoadedImage,\r
788 NULL\r
789 );\r
790 ASSERT_EFI_ERROR (Status);\r
791\r
285a682c
JY
792 //\r
793 // Allocate a Loaded Image Protocol in SMM\r
794 //\r
795 Status = SmmAllocatePool (EfiRuntimeServicesData, sizeof(EFI_SMM_DRIVER_ENTRY), (VOID **)&mSmmCoreDriverEntry);\r
796 ASSERT_EFI_ERROR(Status);\r
797\r
798 ZeroMem (mSmmCoreDriverEntry, sizeof(EFI_SMM_DRIVER_ENTRY));\r
799 //\r
800 // Fill in the remaining fields of the Loaded Image Protocol instance.\r
801 //\r
802 mSmmCoreDriverEntry->Signature = EFI_SMM_DRIVER_ENTRY_SIGNATURE;\r
803 mSmmCoreDriverEntry->SmmLoadedImage.Revision = EFI_LOADED_IMAGE_PROTOCOL_REVISION;\r
804 mSmmCoreDriverEntry->SmmLoadedImage.ParentHandle = gSmmCorePrivate->SmmIplImageHandle;\r
805 mSmmCoreDriverEntry->SmmLoadedImage.SystemTable = gST;\r
806\r
807 mSmmCoreDriverEntry->SmmLoadedImage.ImageBase = (VOID *)(UINTN)gSmmCorePrivate->PiSmmCoreImageBase;\r
808 mSmmCoreDriverEntry->SmmLoadedImage.ImageSize = gSmmCorePrivate->PiSmmCoreImageSize;\r
809 mSmmCoreDriverEntry->SmmLoadedImage.ImageCodeType = EfiRuntimeServicesCode;\r
810 mSmmCoreDriverEntry->SmmLoadedImage.ImageDataType = EfiRuntimeServicesData;\r
811\r
812 mSmmCoreDriverEntry->ImageEntryPoint = gSmmCorePrivate->PiSmmCoreEntryPoint;\r
813 mSmmCoreDriverEntry->ImageBuffer = gSmmCorePrivate->PiSmmCoreImageBase;\r
814 mSmmCoreDriverEntry->NumberOfPage = EFI_SIZE_TO_PAGES((UINTN)gSmmCorePrivate->PiSmmCoreImageSize);\r
815\r
816 //\r
817 // Create a new image handle in the SMM handle database for the SMM Driver\r
818 //\r
819 mSmmCoreDriverEntry->SmmImageHandle = NULL;\r
820 Status = SmmInstallProtocolInterface (\r
821 &mSmmCoreDriverEntry->SmmImageHandle,\r
822 &gEfiLoadedImageProtocolGuid,\r
823 EFI_NATIVE_INTERFACE,\r
824 &mSmmCoreDriverEntry->SmmLoadedImage\r
825 );\r
826 ASSERT_EFI_ERROR(Status);\r
827\r
0b256fb1
JY
828 return ;\r
829}\r
830\r
e42e9404 831/**\r
832 The Entry Point for SMM Core\r
833\r
d1102dba 834 Install DXE Protocols and reload SMM Core into SMRAM and register SMM Core\r
e42e9404 835 EntryPoint on the SMI vector.\r
836\r
837 Note: This function is called for both DXE invocation and SMRAM invocation.\r
838\r
839 @param ImageHandle The firmware allocated handle for the EFI image.\r
840 @param SystemTable A pointer to the EFI System Table.\r
841\r
842 @retval EFI_SUCCESS The entry point is executed successfully.\r
843 @retval Other Some error occurred when executing this entry point.\r
844\r
845**/\r
846EFI_STATUS\r
847EFIAPI\r
848SmmMain (\r
849 IN EFI_HANDLE ImageHandle,\r
850 IN EFI_SYSTEM_TABLE *SystemTable\r
851 )\r
852{\r
853 EFI_STATUS Status;\r
854 UINTN Index;\r
855\r
856 //\r
857 // Get SMM Core Private context passed in from SMM IPL in ImageHandle.\r
858 //\r
859 gSmmCorePrivate = (SMM_CORE_PRIVATE_DATA *)ImageHandle;\r
860\r
861 //\r
862 // Fill in SMRAM physical address for the SMM Services Table and the SMM Entry Point.\r
863 //\r
864 gSmmCorePrivate->Smst = &gSmmCoreSmst;\r
865 gSmmCorePrivate->SmmEntryPoint = SmmEntryPoint;\r
e63da9f0 866\r
e42e9404 867 //\r
842b1242
JY
868 // No need to initialize memory service.\r
869 // It is done in constructor of PiSmmCoreMemoryAllocationLib(),\r
870 // so that the library linked with PiSmmCore can use AllocatePool() in constuctor.\r
e42e9404 871 //\r
e42e9404 872\r
84edd20b
SZ
873 SmramProfileInit ();\r
874\r
875 //\r
876 // Copy FullSmramRanges to SMRAM\r
877 //\r
c03beb76 878 mFullSmramRangeCount = gSmmCorePrivate->SmramRangeCount;\r
84edd20b
SZ
879 mFullSmramRanges = AllocatePool (mFullSmramRangeCount * sizeof (EFI_SMRAM_DESCRIPTOR));\r
880 ASSERT (mFullSmramRanges != NULL);\r
c03beb76 881 CopyMem (mFullSmramRanges, gSmmCorePrivate->SmramRanges, mFullSmramRangeCount * sizeof (EFI_SMRAM_DESCRIPTOR));\r
84edd20b 882\r
e42e9404 883 //\r
884 // Register all SMI Handlers required by the SMM Core\r
885 //\r
886 for (Index = 0; mSmmCoreSmiHandlers[Index].HandlerType != NULL; Index++) {\r
887 Status = SmiHandlerRegister (\r
888 mSmmCoreSmiHandlers[Index].Handler,\r
889 mSmmCoreSmiHandlers[Index].HandlerType,\r
890 &mSmmCoreSmiHandlers[Index].DispatchHandle\r
891 );\r
892 ASSERT_EFI_ERROR (Status);\r
893 }\r
84edd20b 894\r
bb2c9ccb
ED
895 mAcpiS3Enable = PcdGetBool (PcdAcpiS3Enable);\r
896 if (mAcpiS3Enable) {\r
897 //\r
898 // Register all S3 related SMI Handlers required by the SMM Core\r
899 //\r
900 for (Index = 0; mSmmCoreS3SmiHandlers[Index].HandlerType != NULL; Index++) {\r
901 Status = SmiHandlerRegister (\r
902 mSmmCoreS3SmiHandlers[Index].Handler,\r
903 mSmmCoreS3SmiHandlers[Index].HandlerType,\r
904 &mSmmCoreS3SmiHandlers[Index].DispatchHandle\r
905 );\r
906 ASSERT_EFI_ERROR (Status);\r
907 }\r
908 }\r
909\r
84edd20b 910 RegisterSmramProfileHandler ();\r
e524f680 911 SmramProfileInstallProtocol ();\r
84edd20b 912\r
0b256fb1
JY
913 SmmCoreInstallLoadedImage ();\r
914\r
285a682c
JY
915 SmmCoreInitializeMemoryAttributesTable ();\r
916\r
ca41f3f4
JY
917 SmmCoreInitializeSmiHandlerProfile ();\r
918\r
e42e9404 919 return EFI_SUCCESS;\r
920}\r