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