]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Core/PiSmmCore/PiSmmCore.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[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
1436aea4
MK
30 (EFI_SMM_CPU_IO2)SmmEfiNotAvailableYetArg5, // SmmMemRead\r
31 (EFI_SMM_CPU_IO2)SmmEfiNotAvailableYetArg5 // SmmMemWrite\r
e42e9404 32 },\r
33 {\r
1436aea4
MK
34 (EFI_SMM_CPU_IO2)SmmEfiNotAvailableYetArg5, // SmmIoRead\r
35 (EFI_SMM_CPU_IO2)SmmEfiNotAvailableYetArg5 // SmmIoWrite\r
e42e9404 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
1436aea4
MK
84 { SmmDriverDispatchHandler, &gEfiEventDxeDispatchGuid, NULL, TRUE },\r
85 { SmmReadyToLockHandler, &gEfiDxeSmmReadyToLockProtocolGuid, NULL, TRUE },\r
86 { SmmLegacyBootHandler, &gEfiEventLegacyBootGuid, NULL, FALSE },\r
87 { SmmExitBootServicesHandler, &gEfiEventExitBootServicesGuid, NULL, FALSE },\r
88 { SmmReadyToBootHandler, &gEfiEventReadyToBootGuid, NULL, FALSE },\r
89 { SmmEndOfDxeHandler, &gEfiEndOfDxeEventGroupGuid, NULL, TRUE },\r
90 { NULL, NULL, NULL, FALSE }\r
bb2c9ccb
ED
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
1436aea4
MK
97 { SmmS3SmmInitDoneHandler, &gEdkiiS3SmmInitDoneGuid, NULL, FALSE },\r
98 { SmmEndOfS3ResumeHandler, &gEdkiiEndOfS3ResumeGuid, NULL, FALSE },\r
99 { NULL, NULL, NULL, FALSE }\r
e42e9404 100};\r
101\r
1436aea4
MK
102UINTN mFullSmramRangeCount;\r
103EFI_SMRAM_DESCRIPTOR *mFullSmramRanges;\r
84edd20b 104\r
1436aea4 105EFI_SMM_DRIVER_ENTRY *mSmmCoreDriverEntry;\r
285a682c 106\r
1436aea4 107EFI_LOADED_IMAGE_PROTOCOL *mSmmCoreLoadedImage;\r
0b256fb1 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
1436aea4
MK
126 UINTN Arg1,\r
127 UINTN Arg2,\r
128 UINTN Arg3,\r
129 UINTN Arg4,\r
130 UINTN Arg5\r
e42e9404 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
e3917e22
MK
161 IN CONST VOID *Context OPTIONAL,\r
162 IN OUT VOID *CommBuffer OPTIONAL,\r
e42e9404 163 IN OUT UINTN *CommBufferSize OPTIONAL\r
164 )\r
165{\r
1436aea4
MK
166 EFI_STATUS Status;\r
167 EFI_HANDLE SmmHandle;\r
168 UINTN Index;\r
53ec4d7f
SZ
169\r
170 //\r
171 // Install SMM Legacy Boot protocol.\r
172 //\r
173 SmmHandle = NULL;\r
1436aea4
MK
174 Status = SmmInstallProtocolInterface (\r
175 &SmmHandle,\r
176 &gEdkiiSmmLegacyBootProtocolGuid,\r
177 EFI_NATIVE_INTERFACE,\r
178 NULL\r
179 );\r
53ec4d7f 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
e3917e22
MK
216 IN CONST VOID *Context OPTIONAL,\r
217 IN OUT VOID *CommBuffer OPTIONAL,\r
53ec4d7f
SZ
218 IN OUT UINTN *CommBufferSize OPTIONAL\r
219 )\r
220{\r
1436aea4
MK
221 EFI_STATUS Status;\r
222 EFI_HANDLE SmmHandle;\r
223 UINTN Index;\r
53ec4d7f
SZ
224\r
225 //\r
226 // Install SMM Exit Boot Services protocol.\r
227 //\r
228 SmmHandle = NULL;\r
1436aea4
MK
229 Status = SmmInstallProtocolInterface (\r
230 &SmmHandle,\r
231 &gEdkiiSmmExitBootServicesProtocolGuid,\r
232 EFI_NATIVE_INTERFACE,\r
233 NULL\r
234 );\r
53ec4d7f
SZ
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
1436aea4
MK
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
7b9b55b2
SZ
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
e3917e22
MK
300 IN CONST VOID *Context OPTIONAL,\r
301 IN OUT VOID *CommBuffer OPTIONAL,\r
53ec4d7f
SZ
302 IN OUT UINTN *CommBufferSize OPTIONAL\r
303 )\r
304{\r
1436aea4
MK
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
1436aea4
MK
312 Status = SmmInstallProtocolInterface (\r
313 &SmmHandle,\r
314 &gEdkiiSmmReadyToBootProtocolGuid,\r
315 EFI_NATIVE_INTERFACE,\r
316 NULL\r
317 );\r
53ec4d7f
SZ
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
e3917e22
MK
345 IN CONST VOID *Context OPTIONAL,\r
346 IN OUT VOID *CommBuffer OPTIONAL,\r
e42e9404 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
1436aea4
MK
368 Status = SmmInstallProtocolInterface (\r
369 &SmmHandle,\r
370 &gEfiSmmReadyToLockProtocolGuid,\r
371 EFI_NATIVE_INTERFACE,\r
372 NULL\r
373 );\r
e42e9404 374\r
375 //\r
4be497df 376 // Make sure SMM CPU I/O 2 Protocol has been installed into the handle database\r
e42e9404 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
1436aea4
MK
384 if (EFI_ERROR (Status)) {\r
385 DEBUG ((DEBUG_ERROR, "\nSMM: SmmCpuIo Arch Protocol not present!!\n"));\r
386 }\r
387\r
e42e9404 388 DEBUG_CODE_END ();\r
389\r
390 //\r
391 // Assert if the CPU I/O 2 Protocol is not installed\r
392 //\r
393 ASSERT_EFI_ERROR (Status);\r
394\r
395 //\r
396 // Display any drivers that were not dispatched because dependency expression\r
397 // evaluated to false if this is a debug build\r
398 //\r
399 DEBUG_CODE_BEGIN ();\r
1436aea4 400 SmmDisplayDiscoveredNotDispatched ();\r
e42e9404 401 DEBUG_CODE_END ();\r
402\r
403 //\r
404 // Not allowed to use gST or gBS after lock\r
405 //\r
406 gST = NULL;\r
407 gBS = NULL;\r
408\r
84edd20b
SZ
409 SmramProfileReadyToLock ();\r
410\r
e42e9404 411 return Status;\r
412}\r
413\r
46ece1ff
JY
414/**\r
415 Software SMI handler that is called when the EndOfDxe event is signalled.\r
416 This function installs the SMM EndOfDxe Protocol so SMM Drivers are informed that\r
417 platform code will invoke 3rd part code.\r
418\r
419 @param DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().\r
420 @param Context Points to an optional handler context which was specified when the handler was registered.\r
421 @param CommBuffer A pointer to a collection of data in memory that will\r
422 be conveyed from a non-SMM environment into an SMM environment.\r
423 @param CommBufferSize The size of the CommBuffer.\r
424\r
425 @return Status Code\r
426\r
427**/\r
428EFI_STATUS\r
429EFIAPI\r
430SmmEndOfDxeHandler (\r
431 IN EFI_HANDLE DispatchHandle,\r
e3917e22
MK
432 IN CONST VOID *Context OPTIONAL,\r
433 IN OUT VOID *CommBuffer OPTIONAL,\r
46ece1ff
JY
434 IN OUT UINTN *CommBufferSize OPTIONAL\r
435 )\r
436{\r
1436aea4
MK
437 EFI_STATUS Status;\r
438 EFI_HANDLE SmmHandle;\r
439 EFI_SMM_SX_DISPATCH2_PROTOCOL *SxDispatch;\r
440 EFI_SMM_SX_REGISTER_CONTEXT EntryRegisterContext;\r
441 EFI_HANDLE S3EntryHandle;\r
46ece1ff 442\r
87000d77 443 DEBUG ((DEBUG_INFO, "SmmEndOfDxeHandler\n"));\r
b36acb21 444\r
46ece1ff
JY
445 //\r
446 // Install SMM EndOfDxe protocol\r
447 //\r
448 SmmHandle = NULL;\r
1436aea4
MK
449 Status = SmmInstallProtocolInterface (\r
450 &SmmHandle,\r
451 &gEfiSmmEndOfDxeProtocolGuid,\r
452 EFI_NATIVE_INTERFACE,\r
453 NULL\r
454 );\r
b36acb21 455\r
bb2c9ccb 456 if (mAcpiS3Enable) {\r
b36acb21 457 //\r
bb2c9ccb 458 // Locate SmmSxDispatch2 protocol.\r
b36acb21 459 //\r
bb2c9ccb
ED
460 Status = SmmLocateProtocol (\r
461 &gEfiSmmSxDispatch2ProtocolGuid,\r
462 NULL,\r
463 (VOID **)&SxDispatch\r
464 );\r
465 if (!EFI_ERROR (Status) && (SxDispatch != NULL)) {\r
466 //\r
467 // Register a S3 entry callback function to\r
468 // determine if it will be during S3 resume.\r
469 //\r
470 EntryRegisterContext.Type = SxS3;\r
471 EntryRegisterContext.Phase = SxEntry;\r
1436aea4
MK
472 Status = SxDispatch->Register (\r
473 SxDispatch,\r
474 SmmS3EntryCallBack,\r
475 &EntryRegisterContext,\r
476 &S3EntryHandle\r
477 );\r
bb2c9ccb
ED
478 ASSERT_EFI_ERROR (Status);\r
479 }\r
b36acb21
SZ
480 }\r
481\r
482 return EFI_SUCCESS;\r
46ece1ff
JY
483}\r
484\r
1bae3e0e
SZ
485/**\r
486 Software SMI handler that is called when the S3SmmInitDone signal is triggered.\r
487 This function installs the SMM S3SmmInitDone Protocol so SMM Drivers are informed that\r
488 S3 SMM initialization has been done.\r
489\r
490 @param DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().\r
491 @param Context Points to an optional handler context which was specified when the handler was registered.\r
492 @param CommBuffer A pointer to a collection of data in memory that will\r
493 be conveyed from a non-SMM environment into an SMM environment.\r
494 @param CommBufferSize The size of the CommBuffer.\r
495\r
496 @return Status Code\r
497\r
498**/\r
499EFI_STATUS\r
500EFIAPI\r
501SmmS3SmmInitDoneHandler (\r
502 IN EFI_HANDLE DispatchHandle,\r
e3917e22
MK
503 IN CONST VOID *Context OPTIONAL,\r
504 IN OUT VOID *CommBuffer OPTIONAL,\r
1bae3e0e
SZ
505 IN OUT UINTN *CommBufferSize OPTIONAL\r
506 )\r
507{\r
508 EFI_STATUS Status;\r
509 EFI_HANDLE SmmHandle;\r
510\r
511 DEBUG ((DEBUG_INFO, "SmmS3SmmInitDoneHandler\n"));\r
512\r
513 if (!mDuringS3Resume) {\r
514 DEBUG ((DEBUG_ERROR, "It is not during S3 resume\n"));\r
515 return EFI_SUCCESS;\r
516 }\r
517\r
518 //\r
519 // Install SMM S3SmmInitDone protocol\r
520 //\r
521 SmmHandle = NULL;\r
1436aea4
MK
522 Status = SmmInstallProtocolInterface (\r
523 &SmmHandle,\r
524 &gEdkiiS3SmmInitDoneGuid,\r
525 EFI_NATIVE_INTERFACE,\r
526 NULL\r
527 );\r
1bae3e0e
SZ
528 ASSERT_EFI_ERROR (Status);\r
529\r
530 //\r
531 // Uninstall the protocol here because the comsumer just hook the\r
532 // installation event.\r
533 //\r
534 Status = SmmUninstallProtocolInterface (\r
1436aea4
MK
535 SmmHandle,\r
536 &gEdkiiS3SmmInitDoneGuid,\r
537 NULL\r
538 );\r
1bae3e0e
SZ
539 ASSERT_EFI_ERROR (Status);\r
540\r
541 return Status;\r
542}\r
543\r
d76c2da8 544/**\r
a85e7127 545 Software SMI handler that is called when the EndOfS3Resume signal is triggered.\r
d76c2da8
ED
546 This function installs the SMM EndOfS3Resume Protocol so SMM Drivers are informed that\r
547 S3 resume has finished.\r
548\r
549 @param DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().\r
550 @param Context Points to an optional handler context which was specified when the handler was registered.\r
551 @param CommBuffer A pointer to a collection of data in memory that will\r
552 be conveyed from a non-SMM environment into an SMM environment.\r
553 @param CommBufferSize The size of the CommBuffer.\r
554\r
555 @return Status Code\r
556\r
557**/\r
558EFI_STATUS\r
559EFIAPI\r
560SmmEndOfS3ResumeHandler (\r
561 IN EFI_HANDLE DispatchHandle,\r
e3917e22
MK
562 IN CONST VOID *Context OPTIONAL,\r
563 IN OUT VOID *CommBuffer OPTIONAL,\r
d76c2da8
ED
564 IN OUT UINTN *CommBufferSize OPTIONAL\r
565 )\r
566{\r
567 EFI_STATUS Status;\r
568 EFI_HANDLE SmmHandle;\r
569\r
7b9b55b2
SZ
570 DEBUG ((DEBUG_INFO, "SmmEndOfS3ResumeHandler\n"));\r
571\r
572 if (!mDuringS3Resume) {\r
573 DEBUG ((DEBUG_ERROR, "It is not during S3 resume\n"));\r
574 return EFI_SUCCESS;\r
575 }\r
d76c2da8
ED
576\r
577 //\r
578 // Install SMM EndOfS3Resume protocol\r
579 //\r
580 SmmHandle = NULL;\r
1436aea4
MK
581 Status = SmmInstallProtocolInterface (\r
582 &SmmHandle,\r
583 &gEdkiiEndOfS3ResumeGuid,\r
584 EFI_NATIVE_INTERFACE,\r
585 NULL\r
586 );\r
d76c2da8
ED
587 ASSERT_EFI_ERROR (Status);\r
588\r
589 //\r
4be497df 590 // Uninstall the protocol here because the consumer just hook the\r
d76c2da8
ED
591 // installation event.\r
592 //\r
593 Status = SmmUninstallProtocolInterface (\r
1436aea4
MK
594 SmmHandle,\r
595 &gEdkiiEndOfS3ResumeGuid,\r
596 NULL\r
597 );\r
d76c2da8
ED
598 ASSERT_EFI_ERROR (Status);\r
599\r
7b9b55b2 600 mDuringS3Resume = FALSE;\r
d76c2da8
ED
601 return Status;\r
602}\r
603\r
3b657538
SZ
604/**\r
605 Determine if two buffers overlap in memory.\r
606\r
607 @param[in] Buff1 Pointer to first buffer\r
608 @param[in] Size1 Size of Buff1\r
609 @param[in] Buff2 Pointer to second buffer\r
610 @param[in] Size2 Size of Buff2\r
611\r
612 @retval TRUE Buffers overlap in memory.\r
cab1f025 613 @retval TRUE Math error. Prevents potential math over and underflows.\r
3b657538
SZ
614 @retval FALSE Buffer doesn't overlap.\r
615\r
616**/\r
617BOOLEAN\r
618InternalIsBufferOverlapped (\r
1436aea4
MK
619 IN UINT8 *Buff1,\r
620 IN UINTN Size1,\r
621 IN UINT8 *Buff2,\r
622 IN UINTN Size2\r
3b657538
SZ
623 )\r
624{\r
cab1f025
MD
625 UINTN End1;\r
626 UINTN End2;\r
627 BOOLEAN IsOverUnderflow1;\r
628 BOOLEAN IsOverUnderflow2;\r
629\r
630 // Check for over or underflow\r
631 IsOverUnderflow1 = EFI_ERROR (SafeUintnAdd ((UINTN)Buff1, Size1, &End1));\r
632 IsOverUnderflow2 = EFI_ERROR (SafeUintnAdd ((UINTN)Buff2, Size2, &End2));\r
633\r
634 if (IsOverUnderflow1 || IsOverUnderflow2) {\r
635 return TRUE;\r
636 }\r
637\r
3b657538
SZ
638 //\r
639 // If buff1's end is less than the start of buff2, then it's ok.\r
640 // Also, if buff1's start is beyond buff2's end, then it's ok.\r
641 //\r
cab1f025 642 if ((End1 <= (UINTN)Buff2) || ((UINTN)Buff1 >= End2)) {\r
3b657538
SZ
643 return FALSE;\r
644 }\r
645\r
646 return TRUE;\r
647}\r
648\r
e42e9404 649/**\r
650 The main entry point to SMM Foundation.\r
651\r
652 Note: This function is only used by SMRAM invocation. It is never used by DXE invocation.\r
653\r
654 @param SmmEntryContext Processor information and functionality\r
655 needed by SMM Foundation.\r
656\r
657**/\r
658VOID\r
659EFIAPI\r
660SmmEntryPoint (\r
661 IN CONST EFI_SMM_ENTRY_CONTEXT *SmmEntryContext\r
1436aea4 662 )\r
e42e9404 663{\r
664 EFI_STATUS Status;\r
665 EFI_SMM_COMMUNICATE_HEADER *CommunicateHeader;\r
a25cb9f6 666 BOOLEAN InLegacyBoot;\r
3b657538 667 BOOLEAN IsOverlapped;\r
cab1f025 668 BOOLEAN IsOverUnderflow;\r
eaae7b33
JF
669 VOID *CommunicationBuffer;\r
670 UINTN BufferSize;\r
e42e9404 671\r
672 //\r
229fd9e7 673 // Update SMST with contents of the SmmEntryContext structure\r
e42e9404 674 //\r
229fd9e7
MK
675 gSmmCoreSmst.SmmStartupThisAp = SmmEntryContext->SmmStartupThisAp;\r
676 gSmmCoreSmst.CurrentlyExecutingCpu = SmmEntryContext->CurrentlyExecutingCpu;\r
677 gSmmCoreSmst.NumberOfCpus = SmmEntryContext->NumberOfCpus;\r
678 gSmmCoreSmst.CpuSaveStateSize = SmmEntryContext->CpuSaveStateSize;\r
679 gSmmCoreSmst.CpuSaveState = SmmEntryContext->CpuSaveState;\r
e42e9404 680\r
495797c5 681 //\r
682 // Call platform hook before Smm Dispatch\r
683 //\r
684 PlatformHookBeforeSmmDispatch ();\r
685\r
e63da9f0
JW
686 //\r
687 // Call memory management hook function\r
688 //\r
689 SmmEntryPointMemoryManagementHook ();\r
690\r
e42e9404 691 //\r
4be497df 692 // If a legacy boot has occurred, then make sure gSmmCorePrivate is not accessed\r
e42e9404 693 //\r
a25cb9f6 694 InLegacyBoot = mInLegacyBoot;\r
695 if (!InLegacyBoot) {\r
e42e9404 696 //\r
9fa90bb4 697 // Mark the InSmm flag as TRUE, it will be used by SmmBase2 protocol\r
e42e9404 698 //\r
9fa90bb4 699 gSmmCorePrivate->InSmm = TRUE;\r
e42e9404 700\r
701 //\r
d1102dba 702 // Check to see if this is a Synchronous SMI sent through the SMM Communication\r
9fa90bb4 703 // Protocol or an Asynchronous SMI\r
e42e9404 704 //\r
eaae7b33
JF
705 CommunicationBuffer = gSmmCorePrivate->CommunicationBuffer;\r
706 BufferSize = gSmmCorePrivate->BufferSize;\r
707 if (CommunicationBuffer != NULL) {\r
9fa90bb4 708 //\r
709 // Synchronous SMI for SMM Core or request from Communicate protocol\r
710 //\r
3b657538 711 IsOverlapped = InternalIsBufferOverlapped (\r
1436aea4 712 (UINT8 *)CommunicationBuffer,\r
eaae7b33 713 BufferSize,\r
1436aea4 714 (UINT8 *)gSmmCorePrivate,\r
3b657538
SZ
715 sizeof (*gSmmCorePrivate)\r
716 );\r
cab1f025
MD
717 //\r
718 // Check for over or underflows\r
719 //\r
720 IsOverUnderflow = EFI_ERROR (SafeUintnSub (BufferSize, OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data), &BufferSize));\r
721\r
722 if (!SmmIsBufferOutsideSmmValid ((UINTN)CommunicationBuffer, BufferSize) ||\r
723 IsOverlapped || IsOverUnderflow)\r
724 {\r
3720ee6d 725 //\r
3b657538
SZ
726 // If CommunicationBuffer is not in valid address scope,\r
727 // or there is overlap between gSmmCorePrivate and CommunicationBuffer,\r
cab1f025 728 // or there is over or underflow,\r
3b657538 729 // return EFI_INVALID_PARAMETER\r
3720ee6d
JF
730 //\r
731 gSmmCorePrivate->CommunicationBuffer = NULL;\r
1436aea4 732 gSmmCorePrivate->ReturnStatus = EFI_ACCESS_DENIED;\r
3720ee6d 733 } else {\r
eaae7b33 734 CommunicateHeader = (EFI_SMM_COMMUNICATE_HEADER *)CommunicationBuffer;\r
cab1f025
MD
735 // BufferSize was updated by the SafeUintnSub() call above.\r
736 Status = SmiManage (\r
737 &CommunicateHeader->HeaderGuid,\r
738 NULL,\r
739 CommunicateHeader->Data,\r
740 &BufferSize\r
741 );\r
3720ee6d
JF
742 //\r
743 // Update CommunicationBuffer, BufferSize and ReturnStatus\r
744 // Communicate service finished, reset the pointer to CommBuffer to NULL\r
745 //\r
1436aea4 746 gSmmCorePrivate->BufferSize = BufferSize + OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data);\r
3720ee6d 747 gSmmCorePrivate->CommunicationBuffer = NULL;\r
1436aea4 748 gSmmCorePrivate->ReturnStatus = (Status == EFI_SUCCESS) ? EFI_SUCCESS : EFI_NOT_FOUND;\r
3720ee6d 749 }\r
9fa90bb4 750 }\r
e42e9404 751 }\r
9fa90bb4 752\r
753 //\r
754 // Process Asynchronous SMI sources\r
755 //\r
756 SmiManage (NULL, NULL, NULL, NULL);\r
d1102dba 757\r
495797c5 758 //\r
759 // Call platform hook after Smm Dispatch\r
760 //\r
761 PlatformHookAfterSmmDispatch ();\r
e42e9404 762\r
763 //\r
4be497df 764 // If a legacy boot has occurred, then make sure gSmmCorePrivate is not accessed\r
e42e9404 765 //\r
a25cb9f6 766 if (!InLegacyBoot) {\r
9fa90bb4 767 //\r
768 // Clear the InSmm flag as we are going to leave SMM\r
769 //\r
770 gSmmCorePrivate->InSmm = FALSE;\r
771 }\r
e42e9404 772}\r
773\r
0b256fb1
JY
774/**\r
775 Install LoadedImage protocol for SMM Core.\r
776**/\r
777VOID\r
778SmmCoreInstallLoadedImage (\r
779 VOID\r
780 )\r
781{\r
1436aea4
MK
782 EFI_STATUS Status;\r
783 EFI_HANDLE Handle;\r
0b256fb1
JY
784\r
785 //\r
786 // Allocate a Loaded Image Protocol in EfiBootServicesData\r
787 //\r
1436aea4 788 Status = gBS->AllocatePool (EfiBootServicesData, sizeof (EFI_LOADED_IMAGE_PROTOCOL), (VOID **)&mSmmCoreLoadedImage);\r
0b256fb1
JY
789 ASSERT_EFI_ERROR (Status);\r
790\r
791 ZeroMem (mSmmCoreLoadedImage, sizeof (EFI_LOADED_IMAGE_PROTOCOL));\r
792 //\r
793 // Fill in the remaining fields of the Loaded Image Protocol instance.\r
794 // Note: ImageBase is an SMRAM address that can not be accessed outside of SMRAM if SMRAM window is closed.\r
795 //\r
1436aea4
MK
796 mSmmCoreLoadedImage->Revision = EFI_LOADED_IMAGE_PROTOCOL_REVISION;\r
797 mSmmCoreLoadedImage->ParentHandle = gSmmCorePrivate->SmmIplImageHandle;\r
798 mSmmCoreLoadedImage->SystemTable = gST;\r
0b256fb1
JY
799\r
800 mSmmCoreLoadedImage->ImageBase = (VOID *)(UINTN)gSmmCorePrivate->PiSmmCoreImageBase;\r
801 mSmmCoreLoadedImage->ImageSize = gSmmCorePrivate->PiSmmCoreImageSize;\r
802 mSmmCoreLoadedImage->ImageCodeType = EfiRuntimeServicesCode;\r
803 mSmmCoreLoadedImage->ImageDataType = EfiRuntimeServicesData;\r
804\r
805 //\r
806 // Create a new image handle in the UEFI handle database for the SMM Driver\r
807 //\r
808 Handle = NULL;\r
809 Status = gBS->InstallMultipleProtocolInterfaces (\r
810 &Handle,\r
1436aea4
MK
811 &gEfiLoadedImageProtocolGuid,\r
812 mSmmCoreLoadedImage,\r
0b256fb1
JY
813 NULL\r
814 );\r
815 ASSERT_EFI_ERROR (Status);\r
816\r
285a682c
JY
817 //\r
818 // Allocate a Loaded Image Protocol in SMM\r
819 //\r
1436aea4
MK
820 Status = SmmAllocatePool (EfiRuntimeServicesData, sizeof (EFI_SMM_DRIVER_ENTRY), (VOID **)&mSmmCoreDriverEntry);\r
821 ASSERT_EFI_ERROR (Status);\r
285a682c 822\r
1436aea4 823 ZeroMem (mSmmCoreDriverEntry, sizeof (EFI_SMM_DRIVER_ENTRY));\r
285a682c
JY
824 //\r
825 // Fill in the remaining fields of the Loaded Image Protocol instance.\r
826 //\r
1436aea4
MK
827 mSmmCoreDriverEntry->Signature = EFI_SMM_DRIVER_ENTRY_SIGNATURE;\r
828 mSmmCoreDriverEntry->SmmLoadedImage.Revision = EFI_LOADED_IMAGE_PROTOCOL_REVISION;\r
285a682c 829 mSmmCoreDriverEntry->SmmLoadedImage.ParentHandle = gSmmCorePrivate->SmmIplImageHandle;\r
1436aea4 830 mSmmCoreDriverEntry->SmmLoadedImage.SystemTable = gST;\r
285a682c 831\r
1436aea4
MK
832 mSmmCoreDriverEntry->SmmLoadedImage.ImageBase = (VOID *)(UINTN)gSmmCorePrivate->PiSmmCoreImageBase;\r
833 mSmmCoreDriverEntry->SmmLoadedImage.ImageSize = gSmmCorePrivate->PiSmmCoreImageSize;\r
285a682c
JY
834 mSmmCoreDriverEntry->SmmLoadedImage.ImageCodeType = EfiRuntimeServicesCode;\r
835 mSmmCoreDriverEntry->SmmLoadedImage.ImageDataType = EfiRuntimeServicesData;\r
836\r
837 mSmmCoreDriverEntry->ImageEntryPoint = gSmmCorePrivate->PiSmmCoreEntryPoint;\r
838 mSmmCoreDriverEntry->ImageBuffer = gSmmCorePrivate->PiSmmCoreImageBase;\r
1436aea4 839 mSmmCoreDriverEntry->NumberOfPage = EFI_SIZE_TO_PAGES ((UINTN)gSmmCorePrivate->PiSmmCoreImageSize);\r
285a682c
JY
840\r
841 //\r
842 // Create a new image handle in the SMM handle database for the SMM Driver\r
843 //\r
844 mSmmCoreDriverEntry->SmmImageHandle = NULL;\r
1436aea4
MK
845 Status = SmmInstallProtocolInterface (\r
846 &mSmmCoreDriverEntry->SmmImageHandle,\r
847 &gEfiLoadedImageProtocolGuid,\r
848 EFI_NATIVE_INTERFACE,\r
849 &mSmmCoreDriverEntry->SmmLoadedImage\r
850 );\r
851 ASSERT_EFI_ERROR (Status);\r
285a682c 852\r
1436aea4 853 return;\r
0b256fb1
JY
854}\r
855\r
e42e9404 856/**\r
857 The Entry Point for SMM Core\r
858\r
d1102dba 859 Install DXE Protocols and reload SMM Core into SMRAM and register SMM Core\r
e42e9404 860 EntryPoint on the SMI vector.\r
861\r
862 Note: This function is called for both DXE invocation and SMRAM invocation.\r
863\r
864 @param ImageHandle The firmware allocated handle for the EFI image.\r
865 @param SystemTable A pointer to the EFI System Table.\r
866\r
867 @retval EFI_SUCCESS The entry point is executed successfully.\r
868 @retval Other Some error occurred when executing this entry point.\r
869\r
870**/\r
871EFI_STATUS\r
872EFIAPI\r
873SmmMain (\r
874 IN EFI_HANDLE ImageHandle,\r
875 IN EFI_SYSTEM_TABLE *SystemTable\r
876 )\r
877{\r
878 EFI_STATUS Status;\r
879 UINTN Index;\r
880\r
881 //\r
882 // Get SMM Core Private context passed in from SMM IPL in ImageHandle.\r
883 //\r
884 gSmmCorePrivate = (SMM_CORE_PRIVATE_DATA *)ImageHandle;\r
885\r
886 //\r
887 // Fill in SMRAM physical address for the SMM Services Table and the SMM Entry Point.\r
888 //\r
889 gSmmCorePrivate->Smst = &gSmmCoreSmst;\r
890 gSmmCorePrivate->SmmEntryPoint = SmmEntryPoint;\r
e63da9f0 891\r
e42e9404 892 //\r
842b1242
JY
893 // No need to initialize memory service.\r
894 // It is done in constructor of PiSmmCoreMemoryAllocationLib(),\r
4be497df 895 // so that the library linked with PiSmmCore can use AllocatePool() in constructor.\r
e42e9404 896 //\r
e42e9404 897\r
84edd20b
SZ
898 SmramProfileInit ();\r
899\r
900 //\r
901 // Copy FullSmramRanges to SMRAM\r
902 //\r
c03beb76 903 mFullSmramRangeCount = gSmmCorePrivate->SmramRangeCount;\r
1436aea4 904 mFullSmramRanges = AllocatePool (mFullSmramRangeCount * sizeof (EFI_SMRAM_DESCRIPTOR));\r
84edd20b 905 ASSERT (mFullSmramRanges != NULL);\r
c03beb76 906 CopyMem (mFullSmramRanges, gSmmCorePrivate->SmramRanges, mFullSmramRangeCount * sizeof (EFI_SMRAM_DESCRIPTOR));\r
84edd20b 907\r
e42e9404 908 //\r
909 // Register all SMI Handlers required by the SMM Core\r
910 //\r
911 for (Index = 0; mSmmCoreSmiHandlers[Index].HandlerType != NULL; Index++) {\r
912 Status = SmiHandlerRegister (\r
913 mSmmCoreSmiHandlers[Index].Handler,\r
914 mSmmCoreSmiHandlers[Index].HandlerType,\r
915 &mSmmCoreSmiHandlers[Index].DispatchHandle\r
916 );\r
917 ASSERT_EFI_ERROR (Status);\r
918 }\r
84edd20b 919\r
bb2c9ccb
ED
920 mAcpiS3Enable = PcdGetBool (PcdAcpiS3Enable);\r
921 if (mAcpiS3Enable) {\r
922 //\r
923 // Register all S3 related SMI Handlers required by the SMM Core\r
924 //\r
925 for (Index = 0; mSmmCoreS3SmiHandlers[Index].HandlerType != NULL; Index++) {\r
926 Status = SmiHandlerRegister (\r
927 mSmmCoreS3SmiHandlers[Index].Handler,\r
928 mSmmCoreS3SmiHandlers[Index].HandlerType,\r
929 &mSmmCoreS3SmiHandlers[Index].DispatchHandle\r
930 );\r
931 ASSERT_EFI_ERROR (Status);\r
932 }\r
933 }\r
934\r
84edd20b 935 RegisterSmramProfileHandler ();\r
e524f680 936 SmramProfileInstallProtocol ();\r
84edd20b 937\r
0b256fb1
JY
938 SmmCoreInstallLoadedImage ();\r
939\r
285a682c
JY
940 SmmCoreInitializeMemoryAttributesTable ();\r
941\r
ca41f3f4
JY
942 SmmCoreInitializeSmiHandlerProfile ();\r
943\r
e42e9404 944 return EFI_SUCCESS;\r
945}\r