1 /** @file
2 Agent Module to load other modules to deploy SMM Entry Vector for X86 CPU.
3 
4 Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution.  The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9 
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12 
13 **/
14 
15 #ifndef _CPU_PISMMCPUDXESMM_H_
16 #define _CPU_PISMMCPUDXESMM_H_
17 
18 #include <PiSmm.h>
19 
20 #include <Protocol/MpService.h>
21 #include <Protocol/SmmConfiguration.h>
22 #include <Protocol/SmmCpu.h>
23 #include <Protocol/SmmAccess2.h>
24 #include <Protocol/SmmReadyToLock.h>
25 #include <Protocol/SmmCpuService.h>
26 
27 #include <Guid/AcpiS3Context.h>
28 #include <Guid/PiSmmMemoryAttributesTable.h>
29 
30 #include <Library/BaseLib.h>
31 #include <Library/IoLib.h>
32 #include <Library/TimerLib.h>
33 #include <Library/SynchronizationLib.h>
34 #include <Library/DebugLib.h>
35 #include <Library/BaseMemoryLib.h>
36 #include <Library/PcdLib.h>
37 #include <Library/CacheMaintenanceLib.h>
38 #include <Library/MtrrLib.h>
39 #include <Library/SmmCpuPlatformHookLib.h>
40 #include <Library/SmmServicesTableLib.h>
41 #include <Library/MemoryAllocationLib.h>
42 #include <Library/UefiBootServicesTableLib.h>
43 #include <Library/UefiRuntimeServicesTableLib.h>
44 #include <Library/DebugAgentLib.h>
45 #include <Library/HobLib.h>
46 #include <Library/LocalApicLib.h>
47 #include <Library/UefiCpuLib.h>
48 #include <Library/CpuExceptionHandlerLib.h>
49 #include <Library/ReportStatusCodeLib.h>
50 #include <Library/SmmCpuFeaturesLib.h>
51 #include <Library/PeCoffGetEntryPointLib.h>
52 
53 #include <AcpiCpuData.h>
54 #include <CpuHotPlugData.h>
55 
56 #include <Register/Cpuid.h>
57 #include <Register/Msr.h>
58 
59 #include "CpuService.h"
60 #include "SmmProfile.h"
61 
62 //
63 // MSRs required for configuration of SMM Code Access Check
64 //
65 #define EFI_MSR_SMM_MCA_CAP                    0x17D
66 #define  SMM_CODE_ACCESS_CHK_BIT               BIT58
67 
68 #define  SMM_FEATURE_CONTROL_LOCK_BIT          BIT0
69 #define  SMM_CODE_CHK_EN_BIT                   BIT2
70 
71 ///
72 /// Page Table Entry
73 ///
74 #define IA32_PG_P                   BIT0
75 #define IA32_PG_RW                  BIT1
76 #define IA32_PG_U                   BIT2
77 #define IA32_PG_WT                  BIT3
78 #define IA32_PG_CD                  BIT4
79 #define IA32_PG_A                   BIT5
80 #define IA32_PG_D                   BIT6
81 #define IA32_PG_PS                  BIT7
82 #define IA32_PG_PAT_2M              BIT12
83 #define IA32_PG_PAT_4K              IA32_PG_PS
84 #define IA32_PG_PMNT                BIT62
85 #define IA32_PG_NX                  BIT63
86 
87 #define PAGE_ATTRIBUTE_BITS         (IA32_PG_D | IA32_PG_A | IA32_PG_U | IA32_PG_RW | IA32_PG_P)
88 //
89 // Bits 1, 2, 5, 6 are reserved in the IA32 PAE PDPTE
90 // X64 PAE PDPTE does not have such restriction
91 //
92 #define IA32_PAE_PDPTE_ATTRIBUTE_BITS    (IA32_PG_P)
93 
94 #define PAGE_PROGATE_BITS           (IA32_PG_NX | PAGE_ATTRIBUTE_BITS)
95 
96 #define PAGING_4K_MASK  0xFFF
97 #define PAGING_2M_MASK  0x1FFFFF
98 #define PAGING_1G_MASK  0x3FFFFFFF
99 
100 #define PAGING_PAE_INDEX_MASK  0x1FF
101 
102 #define PAGING_4K_ADDRESS_MASK_64 0x000FFFFFFFFFF000ull
103 #define PAGING_2M_ADDRESS_MASK_64 0x000FFFFFFFE00000ull
104 #define PAGING_1G_ADDRESS_MASK_64 0x000FFFFFC0000000ull
105 
106 typedef enum {
107   PageNone,
108   Page4K,
109   Page2M,
110   Page1G,
111 } PAGE_ATTRIBUTE;
112 
113 typedef struct {
114   PAGE_ATTRIBUTE   Attribute;
115   UINT64           Length;
116   UINT64           AddressMask;
117 } PAGE_ATTRIBUTE_TABLE;
118 
119 //
120 // Size of Task-State Segment defined in IA32 Manual
121 //
122 #define TSS_SIZE              104
123 #define TSS_X64_IST1_OFFSET   36
124 #define TSS_IA32_CR3_OFFSET   28
125 #define TSS_IA32_ESP_OFFSET   56
126 
127 #define CR0_WP                BIT16
128 
129 //
130 // Code select value
131 //
132 #define PROTECT_MODE_CODE_SEGMENT          0x08
133 #define LONG_MODE_CODE_SEGMENT             0x38
134 
135 //
136 // The size 0x20 must be bigger than
137 // the size of template code of SmmInit. Currently,
138 // the size of SmmInit requires the 0x16 Bytes buffer
139 // at least.
140 //
141 #define BACK_BUF_SIZE  0x20
142 
143 #define EXCEPTION_VECTOR_NUMBER     0x20
144 
145 #define INVALID_APIC_ID 0xFFFFFFFFFFFFFFFFULL
146 
147 typedef UINT32                              SMM_CPU_ARRIVAL_EXCEPTIONS;
148 #define ARRIVAL_EXCEPTION_BLOCKED           0x1
149 #define ARRIVAL_EXCEPTION_DELAYED           0x2
150 #define ARRIVAL_EXCEPTION_SMI_DISABLED      0x4
151 
152 //
153 // Private structure for the SMM CPU module that is stored in DXE Runtime memory
154 // Contains the SMM Configuration Protocols that is produced.
155 // Contains a mix of DXE and SMM contents.  All the fields must be used properly.
156 //
157 #define SMM_CPU_PRIVATE_DATA_SIGNATURE  SIGNATURE_32 ('s', 'c', 'p', 'u')
158 
159 typedef struct {
160   UINTN                           Signature;
161 
162   EFI_HANDLE                      SmmCpuHandle;
163 
164   EFI_PROCESSOR_INFORMATION       *ProcessorInfo;
165   SMM_CPU_OPERATION               *Operation;
166   UINTN                           *CpuSaveStateSize;
167   VOID                            **CpuSaveState;
168 
169   EFI_SMM_RESERVED_SMRAM_REGION   SmmReservedSmramRegion[1];
170   EFI_SMM_ENTRY_CONTEXT           SmmCoreEntryContext;
171   EFI_SMM_ENTRY_POINT             SmmCoreEntry;
172 
173   EFI_SMM_CONFIGURATION_PROTOCOL  SmmConfiguration;
174 } SMM_CPU_PRIVATE_DATA;
175 
176 extern SMM_CPU_PRIVATE_DATA  *gSmmCpuPrivate;
177 extern CPU_HOT_PLUG_DATA      mCpuHotPlugData;
178 extern UINTN                  mMaxNumberOfCpus;
179 extern UINTN                  mNumberOfCpus;
180 extern EFI_SMM_CPU_PROTOCOL   mSmmCpu;
181 
182 ///
183 /// The mode of the CPU at the time an SMI occurs
184 ///
185 extern UINT8  mSmmSaveStateRegisterLma;
186 
187 
188 //
189 // SMM CPU Protocol function prototypes.
190 //
191 
192 /**
193   Read information from the CPU save state.
194 
195   @param  This      EFI_SMM_CPU_PROTOCOL instance
196   @param  Width     The number of bytes to read from the CPU save state.
197   @param  Register  Specifies the CPU register to read form the save state.
198   @param  CpuIndex  Specifies the zero-based index of the CPU save state
199   @param  Buffer    Upon return, this holds the CPU register value read from the save state.
200 
201   @retval EFI_SUCCESS   The register was read from Save State
202   @retval EFI_NOT_FOUND The register is not defined for the Save State of Processor
203   @retval EFI_INVALID_PARAMTER   This or Buffer is NULL.
204 
205 **/
206 EFI_STATUS
207 EFIAPI
208 SmmReadSaveState (
209   IN CONST EFI_SMM_CPU_PROTOCOL         *This,
210   IN UINTN                              Width,
211   IN EFI_SMM_SAVE_STATE_REGISTER        Register,
212   IN UINTN                              CpuIndex,
213   OUT VOID                              *Buffer
214   );
215 
216 /**
217   Write data to the CPU save state.
218 
219   @param  This      EFI_SMM_CPU_PROTOCOL instance
220   @param  Width     The number of bytes to read from the CPU save state.
221   @param  Register  Specifies the CPU register to write to the save state.
222   @param  CpuIndex  Specifies the zero-based index of the CPU save state
223   @param  Buffer    Upon entry, this holds the new CPU register value.
224 
225   @retval EFI_SUCCESS   The register was written from Save State
226   @retval EFI_NOT_FOUND The register is not defined for the Save State of Processor
227   @retval EFI_INVALID_PARAMTER   ProcessorIndex or Width is not correct
228 
229 **/
230 EFI_STATUS
231 EFIAPI
232 SmmWriteSaveState (
233   IN CONST EFI_SMM_CPU_PROTOCOL         *This,
234   IN UINTN                              Width,
235   IN EFI_SMM_SAVE_STATE_REGISTER        Register,
236   IN UINTN                              CpuIndex,
237   IN CONST VOID                         *Buffer
238   );
239 
240 /**
241 Read a CPU Save State register on the target processor.
242 
243 This function abstracts the differences that whether the CPU Save State register is in the
244 IA32 CPU Save State Map or X64 CPU Save State Map.
245 
246 This function supports reading a CPU Save State register in SMBase relocation handler.
247 
248 @param[in]  CpuIndex       Specifies the zero-based index of the CPU save state.
249 @param[in]  RegisterIndex  Index into mSmmCpuWidthOffset[] look up table.
250 @param[in]  Width          The number of bytes to read from the CPU save state.
251 @param[out] Buffer         Upon return, this holds the CPU register value read from the save state.
252 
253 @retval EFI_SUCCESS           The register was read from Save State.
254 @retval EFI_NOT_FOUND         The register is not defined for the Save State of Processor.
255 @retval EFI_INVALID_PARAMTER  This or Buffer is NULL.
256 
257 **/
258 EFI_STATUS
259 EFIAPI
260 ReadSaveStateRegister (
261   IN UINTN                        CpuIndex,
262   IN EFI_SMM_SAVE_STATE_REGISTER  Register,
263   IN UINTN                        Width,
264   OUT VOID                        *Buffer
265   );
266 
267 /**
268 Write value to a CPU Save State register on the target processor.
269 
270 This function abstracts the differences that whether the CPU Save State register is in the
271 IA32 CPU Save State Map or X64 CPU Save State Map.
272 
273 This function supports writing a CPU Save State register in SMBase relocation handler.
274 
275 @param[in] CpuIndex       Specifies the zero-based index of the CPU save state.
276 @param[in] RegisterIndex  Index into mSmmCpuWidthOffset[] look up table.
277 @param[in] Width          The number of bytes to read from the CPU save state.
278 @param[in] Buffer         Upon entry, this holds the new CPU register value.
279 
280 @retval EFI_SUCCESS           The register was written to Save State.
281 @retval EFI_NOT_FOUND         The register is not defined for the Save State of Processor.
282 @retval EFI_INVALID_PARAMTER  ProcessorIndex or Width is not correct.
283 
284 **/
285 EFI_STATUS
286 EFIAPI
287 WriteSaveStateRegister (
288   IN UINTN                        CpuIndex,
289   IN EFI_SMM_SAVE_STATE_REGISTER  Register,
290   IN UINTN                        Width,
291   IN CONST VOID                   *Buffer
292   );
293 
294 //
295 //
296 //
297 typedef struct {
298   UINT32                            Offset;
299   UINT16                            Segment;
300   UINT16                            Reserved;
301 } IA32_FAR_ADDRESS;
302 
303 extern IA32_FAR_ADDRESS             gSmmJmpAddr;
304 
305 extern CONST UINT8                  gcSmmInitTemplate[];
306 extern CONST UINT16                 gcSmmInitSize;
307 extern UINT32                       gSmmCr0;
308 extern UINT32                       gSmmCr3;
309 extern UINT32                       gSmmCr4;
310 extern UINTN                        gSmmInitStack;
311 
312 /**
313   Semaphore operation for all processor relocate SMMBase.
314 **/
315 VOID
316 EFIAPI
317 SmmRelocationSemaphoreComplete (
318   VOID
319   );
320 
321 ///
322 /// The type of SMM CPU Information
323 ///
324 typedef struct {
325   SPIN_LOCK                         *Busy;
326   volatile EFI_AP_PROCEDURE         Procedure;
327   volatile VOID                     *Parameter;
328   volatile UINT32                   *Run;
329   volatile BOOLEAN                  *Present;
330 } SMM_CPU_DATA_BLOCK;
331 
332 typedef enum {
333   SmmCpuSyncModeTradition,
334   SmmCpuSyncModeRelaxedAp,
335   SmmCpuSyncModeMax
336 } SMM_CPU_SYNC_MODE;
337 
338 typedef struct {
339   //
340   // Pointer to an array. The array should be located immediately after this structure
341   // so that UC cache-ability can be set together.
342   //
343   SMM_CPU_DATA_BLOCK            *CpuData;
344   volatile UINT32               *Counter;
345   volatile UINT32               BspIndex;
346   volatile BOOLEAN              *InsideSmm;
347   volatile BOOLEAN              *AllCpusInSync;
348   volatile SMM_CPU_SYNC_MODE    EffectiveSyncMode;
349   volatile BOOLEAN              SwitchBsp;
350   volatile BOOLEAN              *CandidateBsp;
351 } SMM_DISPATCHER_MP_SYNC_DATA;
352 
353 #define MSR_SPIN_LOCK_INIT_NUM 15
354 
355 typedef struct {
356   SPIN_LOCK    *SpinLock;
357   UINT32       MsrIndex;
358 } MP_MSR_LOCK;
359 
360 #define SMM_PSD_OFFSET              0xfb00
361 
362 ///
363 /// All global semaphores' pointer
364 ///
365 typedef struct {
366   volatile UINT32      *Counter;
367   volatile BOOLEAN     *InsideSmm;
368   volatile BOOLEAN     *AllCpusInSync;
369   SPIN_LOCK            *PFLock;
370   SPIN_LOCK            *CodeAccessCheckLock;
371   SPIN_LOCK            *MemoryMappedLock;
372 } SMM_CPU_SEMAPHORE_GLOBAL;
373 
374 ///
375 /// All semaphores for each processor
376 ///
377 typedef struct {
378   SPIN_LOCK                         *Busy;
379   volatile UINT32                   *Run;
380   volatile BOOLEAN                  *Present;
381 } SMM_CPU_SEMAPHORE_CPU;
382 
383 ///
384 /// All MSRs semaphores' pointer and counter
385 ///
386 typedef struct {
387   SPIN_LOCK            *Msr;
388   UINTN                AvailableCounter;
389 } SMM_CPU_SEMAPHORE_MSR;
390 
391 ///
392 /// All semaphores' information
393 ///
394 typedef struct {
395   SMM_CPU_SEMAPHORE_GLOBAL          SemaphoreGlobal;
396   SMM_CPU_SEMAPHORE_CPU             SemaphoreCpu;
397   SMM_CPU_SEMAPHORE_MSR             SemaphoreMsr;
398 } SMM_CPU_SEMAPHORES;
399 
400 extern IA32_DESCRIPTOR                     gcSmiGdtr;
401 extern EFI_PHYSICAL_ADDRESS                mGdtBuffer;
402 extern UINTN                               mGdtBufferSize;
403 extern IA32_DESCRIPTOR                     gcSmiIdtr;
404 extern VOID                                *gcSmiIdtrPtr;
405 extern UINT64                              gPhyMask;
406 extern SMM_DISPATCHER_MP_SYNC_DATA         *mSmmMpSyncData;
407 extern UINTN                               mSmmStackArrayBase;
408 extern UINTN                               mSmmStackArrayEnd;
409 extern UINTN                               mSmmStackSize;
410 extern EFI_SMM_CPU_SERVICE_PROTOCOL        mSmmCpuService;
411 extern IA32_DESCRIPTOR                     gcSmiInitGdtr;
412 extern SMM_CPU_SEMAPHORES                  mSmmCpuSemaphores;
413 extern UINTN                               mSemaphoreSize;
414 extern SPIN_LOCK                           *mPFLock;
415 extern SPIN_LOCK                           *mConfigSmmCodeAccessCheckLock;
416 extern SPIN_LOCK                           *mMemoryMappedLock;
417 
418 /**
419   Create 4G PageTable in SMRAM.
420 
421   @param[in]      Is32BitPageTable Whether the page table is 32-bit PAE
422   @return         PageTable Address
423 
424 **/
425 UINT32
426 Gen4GPageTable (
427   IN      BOOLEAN                   Is32BitPageTable
428   );
429 
430 
431 /**
432   Initialize global data for MP synchronization.
433 
434   @param Stacks       Base address of SMI stack buffer for all processors.
435   @param StackSize    Stack size for each processor in SMM.
436 
437 **/
438 UINT32
439 InitializeMpServiceData (
440   IN VOID        *Stacks,
441   IN UINTN       StackSize
442   );
443 
444 /**
445   Initialize Timer for SMM AP Sync.
446 
447 **/
448 VOID
449 InitializeSmmTimer (
450   VOID
451   );
452 
453 /**
454   Start Timer for SMM AP Sync.
455 
456 **/
457 UINT64
458 EFIAPI
459 StartSyncTimer (
460   VOID
461   );
462 
463 /**
464   Check if the SMM AP Sync timer is timeout.
465 
466   @param Timer  The start timer from the begin.
467 
468 **/
469 BOOLEAN
470 EFIAPI
471 IsSyncTimerTimeout (
472   IN      UINT64                    Timer
473   );
474 
475 /**
476   Initialize IDT for SMM Stack Guard.
477 
478 **/
479 VOID
480 EFIAPI
481 InitializeIDTSmmStackGuard (
482   VOID
483   );
484 
485 /**
486   Initialize Gdt for all processors.
487 
488   @param[in]   Cr3          CR3 value.
489   @param[out]  GdtStepSize  The step size for GDT table.
490 
491   @return GdtBase for processor 0.
492           GdtBase for processor X is: GdtBase + (GdtStepSize * X)
493 **/
494 VOID *
495 InitGdt (
496   IN  UINTN  Cr3,
497   OUT UINTN  *GdtStepSize
498   );
499 
500 /**
501   This function sets GDT/IDT buffer to be RO and XP.
502 **/
503 VOID
504 PatchGdtIdtMap (
505   VOID
506   );
507 
508 /**
509 
510   Register the SMM Foundation entry point.
511 
512   @param          This              Pointer to EFI_SMM_CONFIGURATION_PROTOCOL instance
513   @param          SmmEntryPoint     SMM Foundation EntryPoint
514 
515   @retval         EFI_SUCCESS       Successfully to register SMM foundation entry point
516 
517 **/
518 EFI_STATUS
519 EFIAPI
520 RegisterSmmEntry (
521   IN CONST EFI_SMM_CONFIGURATION_PROTOCOL  *This,
522   IN EFI_SMM_ENTRY_POINT                   SmmEntryPoint
523   );
524 
525 /**
526   Create PageTable for SMM use.
527 
528   @return     PageTable Address
529 
530 **/
531 UINT32
532 SmmInitPageTable (
533   VOID
534   );
535 
536 /**
537   Schedule a procedure to run on the specified CPU.
538 
539   @param   Procedure        The address of the procedure to run
540   @param   CpuIndex         Target CPU number
541   @param   ProcArguments    The parameter to pass to the procedure
542 
543   @retval   EFI_INVALID_PARAMETER    CpuNumber not valid
544   @retval   EFI_INVALID_PARAMETER    CpuNumber specifying BSP
545   @retval   EFI_INVALID_PARAMETER    The AP specified by CpuNumber did not enter SMM
546   @retval   EFI_INVALID_PARAMETER    The AP specified by CpuNumber is busy
547   @retval   EFI_SUCCESS - The procedure has been successfully scheduled
548 
549 **/
550 EFI_STATUS
551 EFIAPI
552 SmmStartupThisAp (
553   IN      EFI_AP_PROCEDURE          Procedure,
554   IN      UINTN                     CpuIndex,
555   IN OUT  VOID                      *ProcArguments OPTIONAL
556   );
557 
558 /**
559   Schedule a procedure to run on the specified CPU in a blocking fashion.
560 
561   @param  Procedure                The address of the procedure to run
562   @param  CpuIndex                 Target CPU Index
563   @param  ProcArguments            The parameter to pass to the procedure
564 
565   @retval EFI_INVALID_PARAMETER    CpuNumber not valid
566   @retval EFI_INVALID_PARAMETER    CpuNumber specifying BSP
567   @retval EFI_INVALID_PARAMETER    The AP specified by CpuNumber did not enter SMM
568   @retval EFI_INVALID_PARAMETER    The AP specified by CpuNumber is busy
569   @retval EFI_SUCCESS              The procedure has been successfully scheduled
570 
571 **/
572 EFI_STATUS
573 EFIAPI
574 SmmBlockingStartupThisAp (
575   IN      EFI_AP_PROCEDURE          Procedure,
576   IN      UINTN                     CpuIndex,
577   IN OUT  VOID                      *ProcArguments OPTIONAL
578   );
579 
580 /**
581   This function sets the attributes for the memory region specified by BaseAddress and
582   Length from their current attributes to the attributes specified by Attributes.
583 
584   @param[in]  BaseAddress      The physical address that is the start address of a memory region.
585   @param[in]  Length           The size in bytes of the memory region.
586   @param[in]  Attributes       The bit mask of attributes to set for the memory region.
587 
588   @retval EFI_SUCCESS           The attributes were set for the memory region.
589   @retval EFI_ACCESS_DENIED     The attributes for the memory resource range specified by
590                                 BaseAddress and Length cannot be modified.
591   @retval EFI_INVALID_PARAMETER Length is zero.
592                                 Attributes specified an illegal combination of attributes that
593                                 cannot be set together.
594   @retval EFI_OUT_OF_RESOURCES  There are not enough system resources to modify the attributes of
595                                 the memory resource range.
596   @retval EFI_UNSUPPORTED       The processor does not support one or more bytes of the memory
597                                 resource range specified by BaseAddress and Length.
598                                 The bit mask of attributes is not support for the memory resource
599                                 range specified by BaseAddress and Length.
600 
601 **/
602 EFI_STATUS
603 EFIAPI
604 SmmSetMemoryAttributes (
605   IN  EFI_PHYSICAL_ADDRESS                       BaseAddress,
606   IN  UINT64                                     Length,
607   IN  UINT64                                     Attributes
608   );
609 
610 /**
611   This function clears the attributes for the memory region specified by BaseAddress and
612   Length from their current attributes to the attributes specified by Attributes.
613 
614   @param[in]  BaseAddress      The physical address that is the start address of a memory region.
615   @param[in]  Length           The size in bytes of the memory region.
616   @param[in]  Attributes       The bit mask of attributes to clear for the memory region.
617 
618   @retval EFI_SUCCESS           The attributes were cleared for the memory region.
619   @retval EFI_ACCESS_DENIED     The attributes for the memory resource range specified by
620                                 BaseAddress and Length cannot be modified.
621   @retval EFI_INVALID_PARAMETER Length is zero.
622                                 Attributes specified an illegal combination of attributes that
623                                 cannot be set together.
624   @retval EFI_OUT_OF_RESOURCES  There are not enough system resources to modify the attributes of
625                                 the memory resource range.
626   @retval EFI_UNSUPPORTED       The processor does not support one or more bytes of the memory
627                                 resource range specified by BaseAddress and Length.
628                                 The bit mask of attributes is not support for the memory resource
629                                 range specified by BaseAddress and Length.
630 
631 **/
632 EFI_STATUS
633 EFIAPI
634 SmmClearMemoryAttributes (
635   IN  EFI_PHYSICAL_ADDRESS                       BaseAddress,
636   IN  UINT64                                     Length,
637   IN  UINT64                                     Attributes
638   );
639 
640 /**
641   Initialize MP synchronization data.
642 
643 **/
644 VOID
645 EFIAPI
646 InitializeMpSyncData (
647   VOID
648   );
649 
650 /**
651 
652   Find out SMRAM information including SMRR base and SMRR size.
653 
654   @param          SmrrBase          SMRR base
655   @param          SmrrSize          SMRR size
656 
657 **/
658 VOID
659 FindSmramInfo (
660   OUT UINT32   *SmrrBase,
661   OUT UINT32   *SmrrSize
662   );
663 
664 /**
665   Relocate SmmBases for each processor.
666 
667   Execute on first boot and all S3 resumes
668 
669 **/
670 VOID
671 EFIAPI
672 SmmRelocateBases (
673   VOID
674   );
675 
676 /**
677   Page Fault handler for SMM use.
678 
679   @param  InterruptType    Defines the type of interrupt or exception that
680                            occurred on the processor.This parameter is processor architecture specific.
681   @param  SystemContext    A pointer to the processor context when
682                            the interrupt occurred on the processor.
683 **/
684 VOID
685 EFIAPI
686 SmiPFHandler (
687     IN EFI_EXCEPTION_TYPE   InterruptType,
688     IN EFI_SYSTEM_CONTEXT   SystemContext
689   );
690 
691 /**
692   Perform the remaining tasks.
693 
694 **/
695 VOID
696 PerformRemainingTasks (
697   VOID
698   );
699 
700 /**
701   Perform the pre tasks.
702 
703 **/
704 VOID
705 PerformPreTasks (
706   VOID
707   );
708 
709 /**
710   Initialize MSR spin lock by MSR index.
711 
712   @param  MsrIndex       MSR index value.
713 
714 **/
715 VOID
716 InitMsrSpinLockByIndex (
717   IN UINT32      MsrIndex
718   );
719 
720 /**
721   Hook return address of SMM Save State so that semaphore code
722   can be executed immediately after AP exits SMM to indicate to
723   the BSP that an AP has exited SMM after SMBASE relocation.
724 
725   @param[in] CpuIndex     The processor index.
726   @param[in] RebasedFlag  A pointer to a flag that is set to TRUE
727                           immediately after AP exits SMM.
728 
729 **/
730 VOID
731 SemaphoreHook (
732   IN UINTN             CpuIndex,
733   IN volatile BOOLEAN  *RebasedFlag
734   );
735 
736 /**
737 Configure SMM Code Access Check feature for all processors.
738 SMM Feature Control MSR will be locked after configuration.
739 **/
740 VOID
741 ConfigSmmCodeAccessCheck (
742   VOID
743   );
744 
745 /**
746   Hook the code executed immediately after an RSM instruction on the currently
747   executing CPU.  The mode of code executed immediately after RSM must be
748   detected, and the appropriate hook must be selected.  Always clear the auto
749   HALT restart flag if it is set.
750 
751   @param[in] CpuIndex                 The processor index for the currently
752                                       executing CPU.
753   @param[in] CpuState                 Pointer to SMRAM Save State Map for the
754                                       currently executing CPU.
755   @param[in] NewInstructionPointer32  Instruction pointer to use if resuming to
756                                       32-bit mode from 64-bit SMM.
757   @param[in] NewInstructionPointer    Instruction pointer to use if resuming to
758                                       same mode as SMM.
759 
760   @retval The value of the original instruction pointer before it was hooked.
761 
762 **/
763 UINT64
764 EFIAPI
765 HookReturnFromSmm (
766   IN UINTN              CpuIndex,
767   SMRAM_SAVE_STATE_MAP  *CpuState,
768   UINT64                NewInstructionPointer32,
769   UINT64                NewInstructionPointer
770   );
771 
772 /**
773   Get the size of the SMI Handler in bytes.
774 
775   @retval The size, in bytes, of the SMI Handler.
776 
777 **/
778 UINTN
779 EFIAPI
780 GetSmiHandlerSize (
781   VOID
782   );
783 
784 /**
785   Install the SMI handler for the CPU specified by CpuIndex.  This function
786   is called by the CPU that was elected as monarch during System Management
787   Mode initialization.
788 
789   @param[in] CpuIndex   The index of the CPU to install the custom SMI handler.
790                         The value must be between 0 and the NumberOfCpus field
791                         in the System Management System Table (SMST).
792   @param[in] SmBase     The SMBASE address for the CPU specified by CpuIndex.
793   @param[in] SmiStack   The stack to use when an SMI is processed by the
794                         the CPU specified by CpuIndex.
795   @param[in] StackSize  The size, in bytes, if the stack used when an SMI is
796                         processed by the CPU specified by CpuIndex.
797   @param[in] GdtBase    The base address of the GDT to use when an SMI is
798                         processed by the CPU specified by CpuIndex.
799   @param[in] GdtSize    The size, in bytes, of the GDT used when an SMI is
800                         processed by the CPU specified by CpuIndex.
801   @param[in] IdtBase    The base address of the IDT to use when an SMI is
802                         processed by the CPU specified by CpuIndex.
803   @param[in] IdtSize    The size, in bytes, of the IDT used when an SMI is
804                         processed by the CPU specified by CpuIndex.
805   @param[in] Cr3        The base address of the page tables to use when an SMI
806                         is processed by the CPU specified by CpuIndex.
807 **/
808 VOID
809 EFIAPI
810 InstallSmiHandler (
811   IN UINTN   CpuIndex,
812   IN UINT32  SmBase,
813   IN VOID    *SmiStack,
814   IN UINTN   StackSize,
815   IN UINTN   GdtBase,
816   IN UINTN   GdtSize,
817   IN UINTN   IdtBase,
818   IN UINTN   IdtSize,
819   IN UINT32  Cr3
820   );
821 
822 /**
823   Search module name by input IP address and output it.
824 
825   @param CallerIpAddress   Caller instruction pointer.
826 
827 **/
828 VOID
829 DumpModuleInfoByIp (
830   IN  UINTN              CallerIpAddress
831   );
832 
833 /**
834   This function sets memory attribute according to MemoryAttributesTable.
835 **/
836 VOID
837 SetMemMapAttributes (
838   VOID
839   );
840 
841 /**
842   This function sets UEFI memory attribute according to UEFI memory map.
843 **/
844 VOID
845 SetUefiMemMapAttributes (
846   VOID
847   );
848 
849 /**
850   Return if the Address is forbidden as SMM communication buffer.
851 
852   @param[in] Address the address to be checked
853 
854   @return TRUE  The address is forbidden as SMM communication buffer.
855   @return FALSE The address is allowed as SMM communication buffer.
856 **/
857 BOOLEAN
858 IsSmmCommBufferForbiddenAddress (
859   IN UINT64  Address
860   );
861 
862 /**
863   This function caches the UEFI memory map information.
864 **/
865 VOID
866 GetUefiMemoryMap (
867   VOID
868   );
869 
870 /**
871   This function sets memory attribute for page table.
872 **/
873 VOID
874 SetPageTableAttributes (
875   VOID
876   );
877 
878 /**
879   Return page table base.
880 
881   @return page table base.
882 **/
883 UINTN
884 GetPageTableBase (
885   VOID
886   );
887 
888 /**
889   This function sets the attributes for the memory region specified by BaseAddress and
890   Length from their current attributes to the attributes specified by Attributes.
891 
892   @param[in]   BaseAddress      The physical address that is the start address of a memory region.
893   @param[in]   Length           The size in bytes of the memory region.
894   @param[in]   Attributes       The bit mask of attributes to set for the memory region.
895   @param[out]  IsSplitted       TRUE means page table splitted. FALSE means page table not splitted.
896 
897   @retval EFI_SUCCESS           The attributes were set for the memory region.
898   @retval EFI_ACCESS_DENIED     The attributes for the memory resource range specified by
899                                 BaseAddress and Length cannot be modified.
900   @retval EFI_INVALID_PARAMETER Length is zero.
901                                 Attributes specified an illegal combination of attributes that
902                                 cannot be set together.
903   @retval EFI_OUT_OF_RESOURCES  There are not enough system resources to modify the attributes of
904                                 the memory resource range.
905   @retval EFI_UNSUPPORTED       The processor does not support one or more bytes of the memory
906                                 resource range specified by BaseAddress and Length.
907                                 The bit mask of attributes is not support for the memory resource
908                                 range specified by BaseAddress and Length.
909 
910 **/
911 EFI_STATUS
912 EFIAPI
913 SmmSetMemoryAttributesEx (
914   IN  EFI_PHYSICAL_ADDRESS                       BaseAddress,
915   IN  UINT64                                     Length,
916   IN  UINT64                                     Attributes,
917   OUT BOOLEAN                                    *IsSplitted  OPTIONAL
918   );
919 
920 /**
921   This function clears the attributes for the memory region specified by BaseAddress and
922   Length from their current attributes to the attributes specified by Attributes.
923 
924   @param[in]   BaseAddress      The physical address that is the start address of a memory region.
925   @param[in]   Length           The size in bytes of the memory region.
926   @param[in]   Attributes       The bit mask of attributes to clear for the memory region.
927   @param[out]  IsSplitted       TRUE means page table splitted. FALSE means page table not splitted.
928 
929   @retval EFI_SUCCESS           The attributes were cleared for the memory region.
930   @retval EFI_ACCESS_DENIED     The attributes for the memory resource range specified by
931                                 BaseAddress and Length cannot be modified.
932   @retval EFI_INVALID_PARAMETER Length is zero.
933                                 Attributes specified an illegal combination of attributes that
934                                 cannot be set together.
935   @retval EFI_OUT_OF_RESOURCES  There are not enough system resources to modify the attributes of
936                                 the memory resource range.
937   @retval EFI_UNSUPPORTED       The processor does not support one or more bytes of the memory
938                                 resource range specified by BaseAddress and Length.
939                                 The bit mask of attributes is not support for the memory resource
940                                 range specified by BaseAddress and Length.
941 
942 **/
943 EFI_STATUS
944 EFIAPI
945 SmmClearMemoryAttributesEx (
946   IN  EFI_PHYSICAL_ADDRESS                       BaseAddress,
947   IN  UINT64                                     Length,
948   IN  UINT64                                     Attributes,
949   OUT BOOLEAN                                    *IsSplitted  OPTIONAL
950   );
951 
952 /**
953   This API provides a way to allocate memory for page table.
954 
955   This API can be called more once to allocate memory for page tables.
956 
957   Allocates the number of 4KB pages of type EfiRuntimeServicesData and returns a pointer to the
958   allocated buffer.  The buffer returned is aligned on a 4KB boundary.  If Pages is 0, then NULL
959   is returned.  If there is not enough memory remaining to satisfy the request, then NULL is
960   returned.
961 
962   @param  Pages                 The number of 4 KB pages to allocate.
963 
964   @return A pointer to the allocated buffer or NULL if allocation fails.
965 
966 **/
967 VOID *
968 AllocatePageTableMemory (
969   IN UINTN           Pages
970   );
971 
972 /**
973   Allocate pages for code.
974 
975   @param[in]  Pages Number of pages to be allocated.
976 
977   @return Allocated memory.
978 **/
979 VOID *
980 AllocateCodePages (
981   IN UINTN           Pages
982   );
983 
984 /**
985   Allocate aligned pages for code.
986 
987   @param[in]  Pages                 Number of pages to be allocated.
988   @param[in]  Alignment             The requested alignment of the allocation.
989                                     Must be a power of two.
990                                     If Alignment is zero, then byte alignment is used.
991 
992   @return Allocated memory.
993 **/
994 VOID *
995 AllocateAlignedCodePages (
996   IN UINTN            Pages,
997   IN UINTN            Alignment
998   );
999 
1000 
1001 //
1002 // S3 related global variable and function prototype.
1003 //
1004 
1005 extern BOOLEAN                mSmmS3Flag;
1006 
1007 /**
1008   Initialize SMM S3 resume state structure used during S3 Resume.
1009 
1010   @param[in] Cr3    The base address of the page tables to use in SMM.
1011 
1012 **/
1013 VOID
1014 InitSmmS3ResumeState (
1015   IN UINT32  Cr3
1016   );
1017 
1018 /**
1019   Get ACPI CPU data.
1020 
1021 **/
1022 VOID
1023 GetAcpiCpuData (
1024   VOID
1025   );
1026 
1027 /**
1028   Restore SMM Configuration in S3 boot path.
1029 
1030 **/
1031 VOID
1032 RestoreSmmConfigurationInS3 (
1033   VOID
1034   );
1035 
1036 /**
1037   Get ACPI S3 enable flag.
1038 
1039 **/
1040 VOID
1041 GetAcpiS3EnableFlag (
1042   VOID
1043   );
1044 
1045 /**
1046   Transfer AP to safe hlt-loop after it finished restore CPU features on S3 patch.
1047 
1048   @param[in] ApHltLoopCode          The address of the safe hlt-loop function.
1049   @param[in] TopOfStack             A pointer to the new stack to use for the ApHltLoopCode.
1050   @param[in] NumberToFinishAddress  Address of Semaphore of APs finish count.
1051 
1052 **/
1053 VOID
1054 TransferApToSafeState (
1055   IN UINTN  ApHltLoopCode,
1056   IN UINTN  TopOfStack,
1057   IN UINTN  NumberToFinishAddress
1058   );
1059 
1060 #endif
1061