1 /** @file
2   SMM STM support functions
3 
4   Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
5   SPDX-License-Identifier: BSD-2-Clause-Patent
6 
7 **/
8 
9 #include <PiSmm.h>
10 #include <Library/BaseLib.h>
11 #include <Library/BaseMemoryLib.h>
12 #include <Library/MemoryAllocationLib.h>
13 #include <Library/HobLib.h>
14 #include <Library/DebugLib.h>
15 #include <Library/UefiBootServicesTableLib.h>
16 #include <Library/SmmServicesTableLib.h>
17 #include <Library/TpmMeasurementLib.h>
18 #include <Register/Intel/Cpuid.h>
19 #include <Register/Intel/ArchitecturalMsr.h>
20 #include <Register/Intel/SmramSaveStateMap.h>
21 
22 #include <Protocol/MpService.h>
23 
24 #include "SmmStm.h"
25 
26 #define TXT_EVTYPE_BASE                  0x400
27 #define TXT_EVTYPE_STM_HASH              (TXT_EVTYPE_BASE + 14)
28 
29 #define RDWR_ACCS             3
30 #define FULL_ACCS             7
31 
32 /**
33   The constructor function
34 
35   @param[in]  ImageHandle  The firmware allocated handle for the EFI image.
36   @param[in]  SystemTable  A pointer to the EFI System Table.
37 
38   @retval EFI_SUCCESS      The constructor always returns EFI_SUCCESS.
39 
40 **/
41 EFI_STATUS
42 EFIAPI
43 SmmCpuFeaturesLibConstructor (
44   IN EFI_HANDLE        ImageHandle,
45   IN EFI_SYSTEM_TABLE  *SystemTable
46   );
47 
48 EFI_HANDLE  mStmSmmCpuHandle = NULL;
49 
50 BOOLEAN mLockLoadMonitor = FALSE;
51 
52 //
53 // Template of STM_RSC_END structure for copying.
54 //
55 GLOBAL_REMOVE_IF_UNREFERENCED STM_RSC_END mRscEndNode = {
56   {END_OF_RESOURCES, sizeof (STM_RSC_END)},
57 };
58 
59 GLOBAL_REMOVE_IF_UNREFERENCED UINT8  *mStmResourcesPtr         = NULL;
60 GLOBAL_REMOVE_IF_UNREFERENCED UINTN  mStmResourceTotalSize     = 0x0;
61 GLOBAL_REMOVE_IF_UNREFERENCED UINTN  mStmResourceSizeUsed      = 0x0;
62 GLOBAL_REMOVE_IF_UNREFERENCED UINTN  mStmResourceSizeAvailable = 0x0;
63 
64 GLOBAL_REMOVE_IF_UNREFERENCED UINT32  mStmState = 0;
65 
66 //
67 // System Configuration Table pointing to STM Configuration Table
68 //
69 GLOBAL_REMOVE_IF_UNREFERENCED
70 EFI_SM_MONITOR_INIT_PROTOCOL mSmMonitorInitProtocol = {
71   LoadMonitor,
72   AddPiResource,
73   DeletePiResource,
74   GetPiResource,
75   GetMonitorState,
76 };
77 
78 
79 
80 
81 #define   CPUID1_EDX_XD_SUPPORT      0x100000
82 
83 //
84 // External global variables associated with SMI Handler Template
85 //
86 extern CONST TXT_PROCESSOR_SMM_DESCRIPTOR  gcStmPsd;
87 extern UINT32                              gStmSmbase;
88 extern volatile UINT32                     gStmSmiStack;
89 extern UINT32                              gStmSmiCr3;
90 extern volatile UINT8                      gcStmSmiHandlerTemplate[];
91 extern CONST UINT16                        gcStmSmiHandlerSize;
92 extern UINT16                              gcStmSmiHandlerOffset;
93 extern BOOLEAN                             gStmXdSupported;
94 
95 //
96 // Variables used by SMI Handler
97 //
98 IA32_DESCRIPTOR  gStmSmiHandlerIdtr;
99 
100 //
101 // MP Services Protocol
102 //
103 EFI_MP_SERVICES_PROTOCOL  *mSmmCpuFeaturesLibMpService = NULL;
104 
105 //
106 // MSEG Base and Length in SMRAM
107 //
108 UINTN  mMsegBase = 0;
109 UINTN  mMsegSize = 0;
110 
111 BOOLEAN  mStmConfigurationTableInitialized = FALSE;
112 
113 /**
114   The constructor function
115 
116   @param[in]  ImageHandle  The firmware allocated handle for the EFI image.
117   @param[in]  SystemTable  A pointer to the EFI System Table.
118 
119   @retval EFI_SUCCESS      The constructor always returns EFI_SUCCESS.
120 
121 **/
122 EFI_STATUS
123 EFIAPI
SmmCpuFeaturesLibStmConstructor(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)124 SmmCpuFeaturesLibStmConstructor (
125   IN EFI_HANDLE        ImageHandle,
126   IN EFI_SYSTEM_TABLE  *SystemTable
127   )
128 {
129   EFI_STATUS              Status;
130   CPUID_VERSION_INFO_ECX  RegEcx;
131   EFI_HOB_GUID_TYPE       *GuidHob;
132   EFI_SMRAM_DESCRIPTOR    *SmramDescriptor;
133 
134   //
135   // Initialize address fixup
136   //
137   SmmCpuFeaturesLibStmSmiEntryFixupAddress ();
138 
139   //
140   // Call the common constructor function
141   //
142   Status = SmmCpuFeaturesLibConstructor (ImageHandle, SystemTable);
143   ASSERT_EFI_ERROR (Status);
144 
145   //
146   // Lookup the MP Services Protocol
147   //
148   Status = gBS->LocateProtocol (
149                   &gEfiMpServiceProtocolGuid,
150                   NULL,
151                   (VOID **)&mSmmCpuFeaturesLibMpService
152                   );
153   ASSERT_EFI_ERROR (Status);
154 
155   //
156   // If CPU supports VMX, then determine SMRAM range for MSEG.
157   //
158   AsmCpuid (CPUID_VERSION_INFO, NULL, NULL, &RegEcx.Uint32, NULL);
159   if (RegEcx.Bits.VMX == 1) {
160     GuidHob = GetFirstGuidHob (&gMsegSmramGuid);
161     if (GuidHob != NULL) {
162       //
163       // Retrieve MSEG location from MSEG SRAM HOB
164       //
165       SmramDescriptor = (EFI_SMRAM_DESCRIPTOR *) GET_GUID_HOB_DATA (GuidHob);
166       if (SmramDescriptor->PhysicalSize > 0) {
167         mMsegBase       = (UINTN)SmramDescriptor->CpuStart;
168         mMsegSize       = (UINTN)SmramDescriptor->PhysicalSize;
169       }
170     } else if (PcdGet32 (PcdCpuMsegSize) > 0) {
171       //
172       // Allocate MSEG from SMRAM memory
173       //
174       mMsegBase = (UINTN)AllocatePages (EFI_SIZE_TO_PAGES (PcdGet32 (PcdCpuMsegSize)));
175       if (mMsegBase > 0) {
176         mMsegSize = ALIGN_VALUE (PcdGet32 (PcdCpuMsegSize), EFI_PAGE_SIZE);
177       } else {
178         DEBUG ((DEBUG_ERROR, "Not enough SMRAM resource to allocate MSEG size %08x\n", PcdGet32 (PcdCpuMsegSize)));
179       }
180     }
181     if (mMsegBase > 0) {
182       DEBUG ((DEBUG_INFO, "MsegBase: 0x%08x, MsegSize: 0x%08x\n", mMsegBase, mMsegSize));
183     }
184   }
185 
186   return EFI_SUCCESS;
187 }
188 
189 /**
190   Internal worker function that is called to complete CPU initialization at the
191   end of SmmCpuFeaturesInitializeProcessor().
192 
193 **/
194 VOID
FinishSmmCpuFeaturesInitializeProcessor(VOID)195 FinishSmmCpuFeaturesInitializeProcessor (
196   VOID
197   )
198 {
199   MSR_IA32_SMM_MONITOR_CTL_REGISTER  SmmMonitorCtl;
200 
201   //
202   // Set MSEG Base Address in SMM Monitor Control MSR.
203   //
204   if (mMsegBase > 0) {
205     SmmMonitorCtl.Uint64        = 0;
206     SmmMonitorCtl.Bits.MsegBase = (UINT32)mMsegBase >> 12;
207     SmmMonitorCtl.Bits.Valid    = 1;
208     AsmWriteMsr64 (MSR_IA32_SMM_MONITOR_CTL, SmmMonitorCtl.Uint64);
209   }
210 }
211 
212 /**
213   Return the size, in bytes, of a custom SMI Handler in bytes.  If 0 is
214   returned, then a custom SMI handler is not provided by this library,
215   and the default SMI handler must be used.
216 
217   @retval 0    Use the default SMI handler.
218   @retval > 0  Use the SMI handler installed by SmmCpuFeaturesInstallSmiHandler()
219                The caller is required to allocate enough SMRAM for each CPU to
220                support the size of the custom SMI handler.
221 **/
222 UINTN
223 EFIAPI
SmmCpuFeaturesGetSmiHandlerSize(VOID)224 SmmCpuFeaturesGetSmiHandlerSize (
225   VOID
226   )
227 {
228   return gcStmSmiHandlerSize;
229 }
230 
231 /**
232   Install a custom SMI handler for the CPU specified by CpuIndex.  This function
233   is only called if SmmCpuFeaturesGetSmiHandlerSize() returns a size is greater
234   than zero and is called by the CPU that was elected as monarch during System
235   Management Mode initialization.
236 
237   @param[in] CpuIndex   The index of the CPU to install the custom SMI handler.
238                         The value must be between 0 and the NumberOfCpus field
239                         in the System Management System Table (SMST).
240   @param[in] SmBase     The SMBASE address for the CPU specified by CpuIndex.
241   @param[in] SmiStack   The stack to use when an SMI is processed by the
242                         the CPU specified by CpuIndex.
243   @param[in] StackSize  The size, in bytes, if the stack used when an SMI is
244                         processed by the CPU specified by CpuIndex.
245   @param[in] GdtBase    The base address of the GDT to use when an SMI is
246                         processed by the CPU specified by CpuIndex.
247   @param[in] GdtSize    The size, in bytes, of the GDT used when an SMI is
248                         processed by the CPU specified by CpuIndex.
249   @param[in] IdtBase    The base address of the IDT to use when an SMI is
250                         processed by the CPU specified by CpuIndex.
251   @param[in] IdtSize    The size, in bytes, of the IDT used when an SMI is
252                         processed by the CPU specified by CpuIndex.
253   @param[in] Cr3        The base address of the page tables to use when an SMI
254                         is processed by the CPU specified by CpuIndex.
255 **/
256 VOID
257 EFIAPI
SmmCpuFeaturesInstallSmiHandler(IN UINTN CpuIndex,IN UINT32 SmBase,IN VOID * SmiStack,IN UINTN StackSize,IN UINTN GdtBase,IN UINTN GdtSize,IN UINTN IdtBase,IN UINTN IdtSize,IN UINT32 Cr3)258 SmmCpuFeaturesInstallSmiHandler (
259   IN UINTN   CpuIndex,
260   IN UINT32  SmBase,
261   IN VOID    *SmiStack,
262   IN UINTN   StackSize,
263   IN UINTN   GdtBase,
264   IN UINTN   GdtSize,
265   IN UINTN   IdtBase,
266   IN UINTN   IdtSize,
267   IN UINT32  Cr3
268   )
269 {
270   EFI_STATUS                     Status;
271   TXT_PROCESSOR_SMM_DESCRIPTOR   *Psd;
272   VOID                           *Hob;
273   UINT32                         RegEax;
274   UINT32                         RegEdx;
275   EFI_PROCESSOR_INFORMATION      ProcessorInfo;
276 
277   CopyMem ((VOID *)((UINTN)SmBase + TXT_SMM_PSD_OFFSET), &gcStmPsd, sizeof (gcStmPsd));
278   Psd = (TXT_PROCESSOR_SMM_DESCRIPTOR *)(VOID *)((UINTN)SmBase + TXT_SMM_PSD_OFFSET);
279   Psd->SmmGdtPtr = GdtBase;
280   Psd->SmmGdtSize = (UINT32)GdtSize;
281 
282   //
283   // Initialize values in template before copy
284   //
285   gStmSmiStack             = (UINT32)((UINTN)SmiStack + StackSize - sizeof (UINTN));
286   gStmSmiCr3               = Cr3;
287   gStmSmbase               = SmBase;
288   gStmSmiHandlerIdtr.Base  = IdtBase;
289   gStmSmiHandlerIdtr.Limit = (UINT16)(IdtSize - 1);
290 
291   if (gStmXdSupported) {
292     AsmCpuid (CPUID_EXTENDED_FUNCTION, &RegEax, NULL, NULL, NULL);
293     if (RegEax <= CPUID_EXTENDED_FUNCTION) {
294       //
295       // Extended CPUID functions are not supported on this processor.
296       //
297       gStmXdSupported = FALSE;
298     }
299 
300     AsmCpuid (CPUID_EXTENDED_CPU_SIG, NULL, NULL, NULL, &RegEdx);
301     if ((RegEdx & CPUID1_EDX_XD_SUPPORT) == 0) {
302       //
303       // Execute Disable Bit feature is not supported on this processor.
304       //
305       gStmXdSupported = FALSE;
306     }
307   }
308 
309   //
310   // Set the value at the top of the CPU stack to the CPU Index
311   //
312   *(UINTN*)(UINTN)gStmSmiStack = CpuIndex;
313 
314   //
315   // Copy template to CPU specific SMI handler location
316   //
317   CopyMem (
318     (VOID*)((UINTN)SmBase + SMM_HANDLER_OFFSET),
319     (VOID*)gcStmSmiHandlerTemplate,
320     gcStmSmiHandlerSize
321     );
322 
323   Psd->SmmSmiHandlerRip = SmBase + SMM_HANDLER_OFFSET + gcStmSmiHandlerOffset;
324   Psd->SmmSmiHandlerRsp = (UINTN)SmiStack + StackSize - sizeof(UINTN);
325   Psd->SmmCr3           = Cr3;
326 
327   DEBUG((DEBUG_INFO, "CpuSmmStmExceptionStackSize - %x\n", PcdGet32(PcdCpuSmmStmExceptionStackSize)));
328   DEBUG((DEBUG_INFO, "Pages - %x\n", EFI_SIZE_TO_PAGES(PcdGet32(PcdCpuSmmStmExceptionStackSize))));
329   Psd->StmProtectionExceptionHandler.SpeRsp = (UINT64)(UINTN)AllocatePages (EFI_SIZE_TO_PAGES (PcdGet32 (PcdCpuSmmStmExceptionStackSize)));
330   Psd->StmProtectionExceptionHandler.SpeRsp += EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (PcdGet32 (PcdCpuSmmStmExceptionStackSize)));
331 
332   Psd->BiosHwResourceRequirementsPtr        = (UINT64)(UINTN)GetStmResource ();
333 
334   //
335   // Get the APIC ID for the CPU specified by CpuIndex
336   //
337   Status = mSmmCpuFeaturesLibMpService->GetProcessorInfo (
338              mSmmCpuFeaturesLibMpService,
339              CpuIndex,
340              &ProcessorInfo
341              );
342   ASSERT_EFI_ERROR (Status);
343 
344   Psd->LocalApicId = (UINT32)ProcessorInfo.ProcessorId;
345   Psd->AcpiRsdp = 0;
346 
347   Hob = GetFirstHob (EFI_HOB_TYPE_CPU);
348   if (Hob != NULL) {
349     Psd->PhysicalAddressBits = ((EFI_HOB_CPU *) Hob)->SizeOfMemorySpace;
350   } else {
351     AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);
352     if (RegEax >= 0x80000008) {
353       AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL);
354       Psd->PhysicalAddressBits = (UINT8) RegEax;
355     } else {
356       Psd->PhysicalAddressBits = 36;
357     }
358   }
359 
360   if (!mStmConfigurationTableInitialized) {
361     StmSmmConfigurationTableInit ();
362     mStmConfigurationTableInitialized = TRUE;
363   }
364 }
365 
366 /**
367   SMM End Of Dxe event notification handler.
368 
369   STM support need patch AcpiRsdp in TXT_PROCESSOR_SMM_DESCRIPTOR.
370 
371   @param[in] Protocol   Points to the protocol's unique identifier.
372   @param[in] Interface  Points to the interface instance.
373   @param[in] Handle     The handle on which the interface was installed.
374 
375   @retval EFI_SUCCESS   Notification handler runs successfully.
376 **/
377 EFI_STATUS
378 EFIAPI
SmmEndOfDxeEventNotify(IN CONST EFI_GUID * Protocol,IN VOID * Interface,IN EFI_HANDLE Handle)379 SmmEndOfDxeEventNotify (
380   IN CONST EFI_GUID  *Protocol,
381   IN VOID            *Interface,
382   IN EFI_HANDLE      Handle
383   )
384 {
385   VOID                          *Rsdp;
386   UINTN                         Index;
387   TXT_PROCESSOR_SMM_DESCRIPTOR  *Psd;
388 
389   DEBUG ((DEBUG_INFO, "SmmEndOfDxeEventNotify\n"));
390 
391   //
392   // found ACPI table RSD_PTR from system table
393   //
394   Rsdp = NULL;
395   for (Index = 0; Index < gST->NumberOfTableEntries; Index++) {
396     if (CompareGuid (&(gST->ConfigurationTable[Index].VendorGuid), &gEfiAcpi20TableGuid)) {
397       //
398       // A match was found.
399       //
400       Rsdp = gST->ConfigurationTable[Index].VendorTable;
401       break;
402     }
403   }
404   if (Rsdp == NULL) {
405     for (Index = 0; Index < gST->NumberOfTableEntries; Index++) {
406       if (CompareGuid (&(gST->ConfigurationTable[Index].VendorGuid), &gEfiAcpi10TableGuid)) {
407         //
408         // A match was found.
409         //
410         Rsdp = gST->ConfigurationTable[Index].VendorTable;
411         break;
412       }
413     }
414   }
415 
416   for (Index = 0; Index < gSmst->NumberOfCpus; Index++) {
417     Psd = (TXT_PROCESSOR_SMM_DESCRIPTOR *)((UINTN)gSmst->CpuSaveState[Index] - SMRAM_SAVE_STATE_MAP_OFFSET + TXT_SMM_PSD_OFFSET);
418     DEBUG ((DEBUG_INFO, "Index=%d  Psd=%p  Rsdp=%p\n", Index, Psd, Rsdp));
419     Psd->AcpiRsdp = (UINT64)(UINTN)Rsdp;
420   }
421 
422   mLockLoadMonitor = TRUE;
423 
424   return EFI_SUCCESS;
425 }
426 
427 /**
428   This function initializes the STM configuration table.
429 **/
430 VOID
StmSmmConfigurationTableInit(VOID)431 StmSmmConfigurationTableInit (
432   VOID
433   )
434 {
435   EFI_STATUS    Status;
436     VOID        *Registration;
437 
438   Status = gSmst->SmmInstallProtocolInterface (
439                     &mStmSmmCpuHandle,
440                     &gEfiSmMonitorInitProtocolGuid,
441                     EFI_NATIVE_INTERFACE,
442                     &mSmMonitorInitProtocol
443                     );
444   ASSERT_EFI_ERROR (Status);
445 
446   //
447   //
448   // Register SMM End of DXE Event
449   //
450   Status = gSmst->SmmRegisterProtocolNotify (
451                     &gEfiSmmEndOfDxeProtocolGuid,
452                     SmmEndOfDxeEventNotify,
453                     &Registration
454                     );
455   ASSERT_EFI_ERROR (Status);
456 }
457 
458 /**
459 
460   Get STM state.
461 
462   @return STM state
463 
464 **/
465 EFI_SM_MONITOR_STATE
466 EFIAPI
GetMonitorState(VOID)467 GetMonitorState (
468   VOID
469   )
470 {
471   return mStmState;
472 }
473 
474 /**
475 
476   Handle single Resource to see if it can be merged into Record.
477 
478   @param Resource  A pointer to resource node to be added
479   @param Record    A pointer to record node to be merged
480 
481   @retval TRUE  resource handled
482   @retval FALSE resource is not handled
483 
484 **/
485 BOOLEAN
HandleSingleResource(IN STM_RSC * Resource,IN STM_RSC * Record)486 HandleSingleResource (
487   IN  STM_RSC      *Resource,
488   IN  STM_RSC      *Record
489   )
490 {
491   UINT64      ResourceLo;
492   UINT64      ResourceHi;
493   UINT64      RecordLo;
494   UINT64      RecordHi;
495 
496   ResourceLo = 0;
497   ResourceHi = 0;
498   RecordLo = 0;
499   RecordHi = 0;
500 
501   //
502   // Calling code is responsible for making sure that
503   // Resource->Header.RscType == (*Record)->Header.RscType
504   // thus we use just one of them as switch variable.
505   //
506   switch (Resource->Header.RscType) {
507   case MEM_RANGE:
508   case MMIO_RANGE:
509     ResourceLo = Resource->Mem.Base;
510     ResourceHi = Resource->Mem.Base + Resource->Mem.Length;
511     RecordLo = Record->Mem.Base;
512     RecordHi = Record->Mem.Base + Record->Mem.Length;
513     if (Resource->Mem.RWXAttributes != Record->Mem.RWXAttributes) {
514       if ((ResourceLo == RecordLo) && (ResourceHi == RecordHi)) {
515         Record->Mem.RWXAttributes = Resource->Mem.RWXAttributes | Record->Mem.RWXAttributes;
516         return TRUE;
517       } else {
518         return FALSE;
519       }
520     }
521     break;
522   case IO_RANGE:
523   case TRAPPED_IO_RANGE:
524     ResourceLo = (UINT64) Resource->Io.Base;
525     ResourceHi = (UINT64) Resource->Io.Base + (UINT64) Resource->Io.Length;
526     RecordLo = (UINT64) Record->Io.Base;
527     RecordHi = (UINT64) Record->Io.Base + (UINT64) Record->Io.Length;
528     break;
529   case PCI_CFG_RANGE:
530     if ((Resource->PciCfg.OriginatingBusNumber != Record->PciCfg.OriginatingBusNumber) ||
531         (Resource->PciCfg.LastNodeIndex != Record->PciCfg.LastNodeIndex)) {
532       return FALSE;
533     }
534     if (CompareMem (Resource->PciCfg.PciDevicePath, Record->PciCfg.PciDevicePath, sizeof(STM_PCI_DEVICE_PATH_NODE) * (Resource->PciCfg.LastNodeIndex + 1)) != 0) {
535       return FALSE;
536     }
537     ResourceLo = (UINT64) Resource->PciCfg.Base;
538     ResourceHi = (UINT64) Resource->PciCfg.Base + (UINT64) Resource->PciCfg.Length;
539     RecordLo = (UINT64) Record->PciCfg.Base;
540     RecordHi = (UINT64) Record->PciCfg.Base + (UINT64) Record->PciCfg.Length;
541     if (Resource->PciCfg.RWAttributes != Record->PciCfg.RWAttributes) {
542       if ((ResourceLo == RecordLo) && (ResourceHi == RecordHi)) {
543         Record->PciCfg.RWAttributes = Resource->PciCfg.RWAttributes | Record->PciCfg.RWAttributes;
544         return TRUE;
545       } else {
546         return FALSE;
547       }
548     }
549     break;
550   case MACHINE_SPECIFIC_REG:
551     //
552     // Special case - merge MSR masks in place.
553     //
554     if (Resource->Msr.MsrIndex != Record->Msr.MsrIndex) {
555       return FALSE;
556     }
557     Record->Msr.ReadMask |= Resource->Msr.ReadMask;
558     Record->Msr.WriteMask |= Resource->Msr.WriteMask;
559     return TRUE;
560   default:
561     return FALSE;
562   }
563   //
564   // If resources are disjoint
565   //
566   if ((ResourceHi < RecordLo) || (ResourceLo > RecordHi)) {
567     return FALSE;
568   }
569 
570   //
571   // If resource is consumed by record.
572   //
573   if ((ResourceLo >= RecordLo) && (ResourceHi <= RecordHi)) {
574     return TRUE;
575   }
576   //
577   // Resources are overlapping.
578   // Resource and record are merged.
579   //
580   ResourceLo = (ResourceLo < RecordLo) ? ResourceLo : RecordLo;
581   ResourceHi = (ResourceHi > RecordHi) ? ResourceHi : RecordHi;
582 
583   switch (Resource->Header.RscType) {
584   case MEM_RANGE:
585   case MMIO_RANGE:
586     Record->Mem.Base = ResourceLo;
587     Record->Mem.Length = ResourceHi - ResourceLo;
588     break;
589   case IO_RANGE:
590   case TRAPPED_IO_RANGE:
591     Record->Io.Base = (UINT16) ResourceLo;
592     Record->Io.Length = (UINT16) (ResourceHi - ResourceLo);
593     break;
594   case PCI_CFG_RANGE:
595     Record->PciCfg.Base = (UINT16) ResourceLo;
596     Record->PciCfg.Length = (UINT16) (ResourceHi - ResourceLo);
597     break;
598   default:
599     return FALSE;
600   }
601 
602   return TRUE;
603 }
604 
605 /**
606 
607   Add resource node.
608 
609   @param Resource  A pointer to resource node to be added
610 
611 **/
612 VOID
AddSingleResource(IN STM_RSC * Resource)613 AddSingleResource (
614   IN  STM_RSC    *Resource
615   )
616 {
617   STM_RSC    *Record;
618 
619   Record = (STM_RSC *)mStmResourcesPtr;
620 
621   while (TRUE) {
622     if (Record->Header.RscType == END_OF_RESOURCES) {
623       break;
624     }
625     //
626     // Go to next record if resource and record types don't match.
627     //
628     if (Resource->Header.RscType != Record->Header.RscType) {
629       Record = (STM_RSC *)((UINTN)Record + Record->Header.Length);
630       continue;
631     }
632     //
633     // Record is handled inside of procedure - don't adjust.
634     //
635     if (HandleSingleResource (Resource, Record)) {
636       return ;
637     }
638     Record = (STM_RSC *)((UINTN)Record + Record->Header.Length);
639   }
640 
641   //
642   // Add resource to the end of area.
643   //
644   CopyMem (
645     mStmResourcesPtr + mStmResourceSizeUsed - sizeof(mRscEndNode),
646     Resource,
647     Resource->Header.Length
648     );
649   CopyMem (
650     mStmResourcesPtr + mStmResourceSizeUsed - sizeof(mRscEndNode) + Resource->Header.Length,
651     &mRscEndNode,
652     sizeof(mRscEndNode)
653     );
654   mStmResourceSizeUsed += Resource->Header.Length;
655   mStmResourceSizeAvailable = mStmResourceTotalSize - mStmResourceSizeUsed;
656 
657   return ;
658 }
659 
660 /**
661 
662   Add resource list.
663 
664   @param ResourceList  A pointer to resource list to be added
665   @param NumEntries    Optional number of entries.
666                        If 0, list must be terminated by END_OF_RESOURCES.
667 
668 **/
669 VOID
AddResource(IN STM_RSC * ResourceList,IN UINT32 NumEntries OPTIONAL)670 AddResource (
671   IN  STM_RSC    *ResourceList,
672   IN  UINT32      NumEntries OPTIONAL
673   )
674 {
675   UINT32      Count;
676   UINTN       Index;
677   STM_RSC    *Resource;
678 
679   if (NumEntries == 0) {
680     Count = 0xFFFFFFFF;
681   } else {
682     Count = NumEntries;
683   }
684 
685   Resource = ResourceList;
686 
687   for (Index = 0; Index < Count; Index++) {
688     if (Resource->Header.RscType == END_OF_RESOURCES) {
689       return ;
690     }
691     AddSingleResource (Resource);
692     Resource = (STM_RSC *)((UINTN)Resource + Resource->Header.Length);
693   }
694   return ;
695 }
696 
697 /**
698 
699   Validate resource list.
700 
701   @param ResourceList  A pointer to resource list to be added
702   @param NumEntries    Optional number of entries.
703                        If 0, list must be terminated by END_OF_RESOURCES.
704 
705   @retval TRUE  resource valid
706   @retval FALSE resource invalid
707 
708 **/
709 BOOLEAN
ValidateResource(IN STM_RSC * ResourceList,IN UINT32 NumEntries OPTIONAL)710 ValidateResource (
711   IN  STM_RSC    *ResourceList,
712   IN  UINT32      NumEntries OPTIONAL
713   )
714 {
715   UINT32      Count;
716   UINTN       Index;
717   STM_RSC    *Resource;
718   UINTN       SubIndex;
719 
720   //
721   // If NumEntries == 0 make it very big. Scan will be terminated by
722   // END_OF_RESOURCES.
723   //
724   if (NumEntries == 0) {
725     Count = 0xFFFFFFFF;
726   } else {
727     Count = NumEntries;
728   }
729 
730   //
731   // Start from beginning of resource list.
732   //
733   Resource = ResourceList;
734 
735   for (Index = 0; Index < Count; Index++) {
736     DEBUG ((DEBUG_INFO, "ValidateResource (%d) - RscType(%x)\n", Index, Resource->Header.RscType));
737     //
738     // Validate resource.
739     //
740     switch (Resource->Header.RscType) {
741       case END_OF_RESOURCES:
742         if (Resource->Header.Length != sizeof (STM_RSC_END)) {
743           return  FALSE;
744         }
745         //
746         // If we are passed actual number of resources to add,
747         // END_OF_RESOURCES structure between them is considered an
748         // error. If NumEntries == 0 END_OF_RESOURCES is a termination.
749         //
750         if (NumEntries != 0) {
751           return  FALSE;
752         } else {
753           //
754           // If NumEntries == 0 and list reached end - return success.
755           //
756           return TRUE;
757         }
758         break;
759 
760       case MEM_RANGE:
761       case MMIO_RANGE:
762         if (Resource->Header.Length != sizeof (STM_RSC_MEM_DESC)) {
763           return FALSE;
764         }
765 
766         if (Resource->Mem.RWXAttributes > FULL_ACCS) {
767           return FALSE;
768         }
769         break;
770 
771       case IO_RANGE:
772       case TRAPPED_IO_RANGE:
773         if (Resource->Header.Length != sizeof (STM_RSC_IO_DESC)) {
774           return FALSE;
775         }
776 
777         if ((Resource->Io.Base + Resource->Io.Length) > 0xFFFF) {
778           return FALSE;
779         }
780         break;
781 
782       case PCI_CFG_RANGE:
783         DEBUG ((DEBUG_INFO, "ValidateResource - PCI (0x%02x, 0x%08x, 0x%02x, 0x%02x)\n", Resource->PciCfg.OriginatingBusNumber, Resource->PciCfg.LastNodeIndex, Resource->PciCfg.PciDevicePath[0].PciDevice, Resource->PciCfg.PciDevicePath[0].PciFunction));
784         if (Resource->Header.Length != sizeof (STM_RSC_PCI_CFG_DESC) + (sizeof(STM_PCI_DEVICE_PATH_NODE) * Resource->PciCfg.LastNodeIndex)) {
785           return FALSE;
786         }
787         for (SubIndex = 0; SubIndex <= Resource->PciCfg.LastNodeIndex; SubIndex++) {
788           if ((Resource->PciCfg.PciDevicePath[SubIndex].PciDevice > 0x1F) || (Resource->PciCfg.PciDevicePath[SubIndex].PciFunction > 7)) {
789             return FALSE;
790           }
791         }
792         if ((Resource->PciCfg.Base + Resource->PciCfg.Length) > 0x1000) {
793           return FALSE;
794         }
795         break;
796 
797       case MACHINE_SPECIFIC_REG:
798         if (Resource->Header.Length != sizeof (STM_RSC_MSR_DESC)) {
799           return FALSE;
800         }
801         break;
802 
803       default :
804         DEBUG ((DEBUG_ERROR, "ValidateResource - Unknown RscType(%x)\n", Resource->Header.RscType));
805         return FALSE;
806     }
807     Resource = (STM_RSC *)((UINTN)Resource + Resource->Header.Length);
808   }
809   return TRUE;
810 }
811 
812 /**
813 
814   Get resource list.
815   EndResource is excluded.
816 
817   @param ResourceList  A pointer to resource list to be added
818   @param NumEntries    Optional number of entries.
819                        If 0, list must be terminated by END_OF_RESOURCES.
820 
821   @retval TRUE  resource valid
822   @retval FALSE resource invalid
823 
824 **/
825 UINTN
GetResourceSize(IN STM_RSC * ResourceList,IN UINT32 NumEntries OPTIONAL)826 GetResourceSize (
827   IN  STM_RSC    *ResourceList,
828   IN  UINT32      NumEntries OPTIONAL
829   )
830 {
831   UINT32      Count;
832   UINTN       Index;
833   STM_RSC    *Resource;
834 
835   Resource = ResourceList;
836 
837   //
838   // If NumEntries == 0 make it very big. Scan will be terminated by
839   // END_OF_RESOURCES.
840   //
841   if (NumEntries == 0) {
842     Count = 0xFFFFFFFF;
843   } else {
844     Count = NumEntries;
845   }
846 
847   //
848   // Start from beginning of resource list.
849   //
850   Resource = ResourceList;
851 
852   for (Index = 0; Index < Count; Index++) {
853     if (Resource->Header.RscType == END_OF_RESOURCES) {
854       break;
855     }
856     Resource = (STM_RSC *)((UINTN)Resource + Resource->Header.Length);
857   }
858 
859   return (UINTN)Resource - (UINTN)ResourceList;
860 }
861 
862 /**
863 
864   Add resources in list to database. Allocate new memory areas as needed.
865 
866   @param ResourceList  A pointer to resource list to be added
867   @param NumEntries    Optional number of entries.
868                        If 0, list must be terminated by END_OF_RESOURCES.
869 
870   @retval EFI_SUCCESS            If resources are added
871   @retval EFI_INVALID_PARAMETER  If nested procedure detected resource failer
872   @retval EFI_OUT_OF_RESOURCES   If nested procedure returned it and we cannot allocate more areas.
873 
874 **/
875 EFI_STATUS
876 EFIAPI
AddPiResource(IN STM_RSC * ResourceList,IN UINT32 NumEntries OPTIONAL)877 AddPiResource (
878   IN  STM_RSC    *ResourceList,
879   IN  UINT32      NumEntries OPTIONAL
880   )
881 {
882   EFI_STATUS            Status;
883   UINTN                 ResourceSize;
884   EFI_PHYSICAL_ADDRESS  NewResource;
885   UINTN                 NewResourceSize;
886 
887   DEBUG ((DEBUG_INFO, "AddPiResource - Enter\n"));
888 
889   if (!ValidateResource (ResourceList, NumEntries)) {
890     return EFI_INVALID_PARAMETER;
891   }
892 
893   ResourceSize = GetResourceSize (ResourceList, NumEntries);
894   DEBUG ((DEBUG_INFO, "ResourceSize - 0x%08x\n", ResourceSize));
895   if (ResourceSize == 0) {
896     return EFI_INVALID_PARAMETER;
897   }
898 
899   if (mStmResourcesPtr == NULL) {
900     //
901     // First time allocation
902     //
903     NewResourceSize = EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (ResourceSize + sizeof(mRscEndNode)));
904     DEBUG ((DEBUG_INFO, "Allocate - 0x%08x\n", NewResourceSize));
905     Status = gSmst->SmmAllocatePages (
906                       AllocateAnyPages,
907                       EfiRuntimeServicesData,
908                       EFI_SIZE_TO_PAGES (NewResourceSize),
909                       &NewResource
910                       );
911     if (EFI_ERROR (Status)) {
912       return Status;
913     }
914 
915     //
916     // Copy EndResource for intialization
917     //
918     mStmResourcesPtr = (UINT8 *)(UINTN)NewResource;
919     mStmResourceTotalSize = NewResourceSize;
920     CopyMem (mStmResourcesPtr, &mRscEndNode, sizeof(mRscEndNode));
921     mStmResourceSizeUsed      = sizeof(mRscEndNode);
922     mStmResourceSizeAvailable = mStmResourceTotalSize - sizeof(mRscEndNode);
923 
924     //
925     // Let SmmCore change resource ptr
926     //
927     NotifyStmResourceChange (mStmResourcesPtr);
928   } else if (mStmResourceSizeAvailable < ResourceSize) {
929     //
930     // Need enlarge
931     //
932     NewResourceSize = mStmResourceTotalSize + (ResourceSize - mStmResourceSizeAvailable);
933     NewResourceSize = EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (NewResourceSize));
934     DEBUG ((DEBUG_INFO, "ReAllocate - 0x%08x\n", NewResourceSize));
935     Status = gSmst->SmmAllocatePages (
936                       AllocateAnyPages,
937                       EfiRuntimeServicesData,
938                       EFI_SIZE_TO_PAGES (NewResourceSize),
939                       &NewResource
940                       );
941     if (EFI_ERROR (Status)) {
942       return Status;
943     }
944     CopyMem ((VOID *)(UINTN)NewResource, mStmResourcesPtr, mStmResourceSizeUsed);
945     mStmResourceSizeAvailable = NewResourceSize - mStmResourceSizeUsed;
946 
947     gSmst->SmmFreePages (
948              (EFI_PHYSICAL_ADDRESS)(UINTN)mStmResourcesPtr,
949              EFI_SIZE_TO_PAGES (mStmResourceTotalSize)
950              );
951 
952     mStmResourceTotalSize = NewResourceSize;
953     mStmResourcesPtr = (UINT8 *)(UINTN)NewResource;
954 
955     //
956     // Let SmmCore change resource ptr
957     //
958     NotifyStmResourceChange (mStmResourcesPtr);
959   }
960 
961   //
962   // Check duplication
963   //
964   AddResource (ResourceList, NumEntries);
965 
966   return EFI_SUCCESS;
967 }
968 
969 /**
970 
971   Delete resources in list to database.
972 
973   @param ResourceList  A pointer to resource list to be deleted
974                        NULL means delete all resources.
975   @param NumEntries    Optional number of entries.
976                        If 0, list must be terminated by END_OF_RESOURCES.
977 
978   @retval EFI_SUCCESS            If resources are deleted
979   @retval EFI_INVALID_PARAMETER  If nested procedure detected resource failer
980 
981 **/
982 EFI_STATUS
983 EFIAPI
DeletePiResource(IN STM_RSC * ResourceList,IN UINT32 NumEntries OPTIONAL)984 DeletePiResource (
985   IN  STM_RSC    *ResourceList,
986   IN  UINT32      NumEntries OPTIONAL
987   )
988 {
989   if (ResourceList != NULL) {
990     // TBD
991     ASSERT (FALSE);
992     return EFI_UNSUPPORTED;
993   }
994   //
995   // Delete all
996   //
997   CopyMem (mStmResourcesPtr, &mRscEndNode, sizeof(mRscEndNode));
998   mStmResourceSizeUsed      = sizeof(mRscEndNode);
999   mStmResourceSizeAvailable = mStmResourceTotalSize - sizeof(mRscEndNode);
1000   return EFI_SUCCESS;
1001 }
1002 
1003 /**
1004 
1005   Get BIOS resources.
1006 
1007   @param ResourceList  A pointer to resource list to be filled
1008   @param ResourceSize  On input it means size of resource list input.
1009                        On output it means size of resource list filled,
1010                        or the size of resource list to be filled if size of too small.
1011 
1012   @retval EFI_SUCCESS            If resources are returned.
1013   @retval EFI_BUFFER_TOO_SMALL   If resource list buffer is too small to hold the whole resources.
1014 
1015 **/
1016 EFI_STATUS
1017 EFIAPI
GetPiResource(OUT STM_RSC * ResourceList,IN OUT UINT32 * ResourceSize)1018 GetPiResource (
1019   OUT    STM_RSC *ResourceList,
1020   IN OUT UINT32  *ResourceSize
1021   )
1022 {
1023   if (*ResourceSize < mStmResourceSizeUsed) {
1024     *ResourceSize = (UINT32)mStmResourceSizeUsed;
1025     return EFI_BUFFER_TOO_SMALL;
1026   }
1027 
1028   CopyMem (ResourceList, mStmResourcesPtr, mStmResourceSizeUsed);
1029   *ResourceSize = (UINT32)mStmResourceSizeUsed;
1030   return EFI_SUCCESS;
1031 }
1032 
1033 /**
1034 
1035   Set valid bit for MSEG MSR.
1036 
1037   @param Buffer Ap function buffer. (not used)
1038 
1039 **/
1040 VOID
1041 EFIAPI
EnableMsegMsr(IN VOID * Buffer)1042 EnableMsegMsr (
1043   IN VOID  *Buffer
1044   )
1045 {
1046   MSR_IA32_SMM_MONITOR_CTL_REGISTER  SmmMonitorCtl;
1047 
1048   SmmMonitorCtl.Uint64 = AsmReadMsr64 (MSR_IA32_SMM_MONITOR_CTL);
1049   SmmMonitorCtl.Bits.Valid = 1;
1050   AsmWriteMsr64 (MSR_IA32_SMM_MONITOR_CTL, SmmMonitorCtl.Uint64);
1051 }
1052 
1053 /**
1054 
1055   Get 4K page aligned VMCS size.
1056 
1057   @return 4K page aligned VMCS size
1058 
1059 **/
1060 UINT32
GetVmcsSize(VOID)1061 GetVmcsSize (
1062   VOID
1063   )
1064 {
1065   MSR_IA32_VMX_BASIC_REGISTER  VmxBasic;
1066 
1067   //
1068   // Read VMCS size and and align to 4KB
1069   //
1070   VmxBasic.Uint64 = AsmReadMsr64 (MSR_IA32_VMX_BASIC);
1071   return ALIGN_VALUE (VmxBasic.Bits.VmcsSize, SIZE_4KB);
1072 }
1073 
1074 /**
1075 
1076   Check STM image size.
1077 
1078   @param StmImage      STM image
1079   @param StmImageSize  STM image size
1080 
1081   @retval TRUE  check pass
1082   @retval FALSE check fail
1083 **/
1084 BOOLEAN
StmCheckStmImage(IN EFI_PHYSICAL_ADDRESS StmImage,IN UINTN StmImageSize)1085 StmCheckStmImage (
1086   IN EFI_PHYSICAL_ADDRESS StmImage,
1087   IN UINTN                StmImageSize
1088   )
1089 {
1090   UINTN                     MinMsegSize;
1091   STM_HEADER                *StmHeader;
1092   IA32_VMX_MISC_REGISTER    VmxMiscMsr;
1093 
1094   //
1095   // Check to see if STM image is compatible with CPU
1096   //
1097   StmHeader = (STM_HEADER *)(UINTN)StmImage;
1098   VmxMiscMsr.Uint64 = AsmReadMsr64 (MSR_IA32_VMX_MISC);
1099   if (StmHeader->HwStmHdr.MsegHeaderRevision != VmxMiscMsr.Bits.MsegRevisionIdentifier) {
1100     DEBUG ((DEBUG_ERROR, "STM Image not compatible with CPU\n"));
1101     DEBUG ((DEBUG_ERROR, "  StmHeader->HwStmHdr.MsegHeaderRevision = %08x\n", StmHeader->HwStmHdr.MsegHeaderRevision));
1102     DEBUG ((DEBUG_ERROR, "  VmxMiscMsr.Bits.MsegRevisionIdentifier = %08x\n", VmxMiscMsr.Bits.MsegRevisionIdentifier));
1103     return FALSE;
1104   }
1105 
1106   //
1107   // Get Minimal required Mseg size
1108   //
1109   MinMsegSize = (EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (StmHeader->SwStmHdr.StaticImageSize)) +
1110                  StmHeader->SwStmHdr.AdditionalDynamicMemorySize +
1111                  (StmHeader->SwStmHdr.PerProcDynamicMemorySize + GetVmcsSize () * 2) * gSmst->NumberOfCpus);
1112   if (MinMsegSize < StmImageSize) {
1113     MinMsegSize = StmImageSize;
1114   }
1115 
1116   if (StmHeader->HwStmHdr.Cr3Offset >= StmHeader->SwStmHdr.StaticImageSize) {
1117     //
1118     // We will create page table, just in case that SINIT does not create it.
1119     //
1120     if (MinMsegSize < StmHeader->HwStmHdr.Cr3Offset + EFI_PAGES_TO_SIZE(6)) {
1121       MinMsegSize = StmHeader->HwStmHdr.Cr3Offset + EFI_PAGES_TO_SIZE(6);
1122     }
1123   }
1124 
1125   //
1126   // Check if it exceeds MSEG size
1127   //
1128   if (MinMsegSize > mMsegSize) {
1129     DEBUG ((DEBUG_ERROR, "MSEG too small.  Min MSEG Size = %08x  Current MSEG Size = %08x\n", MinMsegSize, mMsegSize));
1130     DEBUG ((DEBUG_ERROR, "  StmHeader->SwStmHdr.StaticImageSize             = %08x\n", StmHeader->SwStmHdr.StaticImageSize));
1131     DEBUG ((DEBUG_ERROR, "  StmHeader->SwStmHdr.AdditionalDynamicMemorySize = %08x\n", StmHeader->SwStmHdr.AdditionalDynamicMemorySize));
1132     DEBUG ((DEBUG_ERROR, "  StmHeader->SwStmHdr.PerProcDynamicMemorySize    = %08x\n", StmHeader->SwStmHdr.PerProcDynamicMemorySize));
1133     DEBUG ((DEBUG_ERROR, "  VMCS Size                                       = %08x\n", GetVmcsSize ()));
1134     DEBUG ((DEBUG_ERROR, "  Max CPUs                                        = %08x\n", gSmst->NumberOfCpus));
1135     DEBUG ((DEBUG_ERROR, "  StmHeader->HwStmHdr.Cr3Offset                   = %08x\n", StmHeader->HwStmHdr.Cr3Offset));
1136     return FALSE;
1137   }
1138 
1139   return TRUE;
1140 }
1141 
1142 /**
1143 
1144   Load STM image to MSEG.
1145 
1146   @param StmImage      STM image
1147   @param StmImageSize  STM image size
1148 
1149 **/
1150 VOID
StmLoadStmImage(IN EFI_PHYSICAL_ADDRESS StmImage,IN UINTN StmImageSize)1151 StmLoadStmImage (
1152   IN EFI_PHYSICAL_ADDRESS StmImage,
1153   IN UINTN                StmImageSize
1154   )
1155 {
1156   MSR_IA32_SMM_MONITOR_CTL_REGISTER  SmmMonitorCtl;
1157   UINT32                             MsegBase;
1158   STM_HEADER                         *StmHeader;
1159 
1160   //
1161   // Get MSEG base address from MSR_IA32_SMM_MONITOR_CTL
1162   //
1163   SmmMonitorCtl.Uint64 = AsmReadMsr64 (MSR_IA32_SMM_MONITOR_CTL);
1164   MsegBase = SmmMonitorCtl.Bits.MsegBase << 12;
1165 
1166   //
1167   // Zero all of MSEG base address
1168   //
1169   ZeroMem ((VOID *)(UINTN)MsegBase, mMsegSize);
1170 
1171   //
1172   // Copy STM Image into MSEG
1173   //
1174   CopyMem ((VOID *)(UINTN)MsegBase, (VOID *)(UINTN)StmImage, StmImageSize);
1175 
1176   //
1177   // STM Header is at the beginning of the STM Image
1178   //
1179   StmHeader = (STM_HEADER *)(UINTN)StmImage;
1180 
1181   StmGen4GPageTable ((UINTN)MsegBase + StmHeader->HwStmHdr.Cr3Offset);
1182 }
1183 
1184 /**
1185 
1186   Load STM image to MSEG.
1187 
1188   @param StmImage      STM image
1189   @param StmImageSize  STM image size
1190 
1191   @retval EFI_SUCCESS            Load STM to MSEG successfully
1192   @retval EFI_ALREADY_STARTED    STM image is already loaded to MSEG
1193   @retval EFI_BUFFER_TOO_SMALL   MSEG is smaller than minimal requirement of STM image
1194   @retval EFI_UNSUPPORTED        MSEG is not enabled
1195 
1196 **/
1197 EFI_STATUS
1198 EFIAPI
LoadMonitor(IN EFI_PHYSICAL_ADDRESS StmImage,IN UINTN StmImageSize)1199 LoadMonitor (
1200   IN EFI_PHYSICAL_ADDRESS StmImage,
1201   IN UINTN                StmImageSize
1202   )
1203 {
1204   MSR_IA32_SMM_MONITOR_CTL_REGISTER  SmmMonitorCtl;
1205 
1206   if (mLockLoadMonitor) {
1207     return EFI_ACCESS_DENIED;
1208   }
1209 
1210   SmmMonitorCtl.Uint64 = AsmReadMsr64 (MSR_IA32_SMM_MONITOR_CTL);
1211   if (SmmMonitorCtl.Bits.MsegBase == 0) {
1212     return EFI_UNSUPPORTED;
1213   }
1214 
1215   if (!StmCheckStmImage (StmImage, StmImageSize)) {
1216     return EFI_BUFFER_TOO_SMALL;
1217   }
1218 
1219   // Record STM_HASH to PCR 0, just in case it is NOT TXT launch, we still need provide the evidence.
1220   TpmMeasureAndLogData(
1221     0,                        // PcrIndex
1222     TXT_EVTYPE_STM_HASH,      // EventType
1223     NULL,                     // EventLog
1224     0,                        // LogLen
1225     (VOID *)(UINTN)StmImage,  // HashData
1226     StmImageSize              // HashDataLen
1227     );
1228 
1229   StmLoadStmImage (StmImage, StmImageSize);
1230 
1231   mStmState |= EFI_SM_MONITOR_STATE_ENABLED;
1232 
1233   return EFI_SUCCESS;
1234 }
1235 
1236 /**
1237   This function return BIOS STM resource.
1238   Produced by SmmStm.
1239   Comsumed by SmmMpService when Init.
1240 
1241   @return BIOS STM resource
1242 
1243 **/
1244 VOID *
GetStmResource(VOID)1245 GetStmResource(
1246   VOID
1247   )
1248 {
1249   return mStmResourcesPtr;
1250 }
1251 
1252 /**
1253   This function notify STM resource change.
1254 
1255   @param StmResource BIOS STM resource
1256 
1257 **/
1258 VOID
NotifyStmResourceChange(VOID * StmResource)1259 NotifyStmResourceChange (
1260   VOID *StmResource
1261   )
1262 {
1263   UINTN                         Index;
1264   TXT_PROCESSOR_SMM_DESCRIPTOR  *Psd;
1265 
1266   for (Index = 0; Index < gSmst->NumberOfCpus; Index++) {
1267     Psd = (TXT_PROCESSOR_SMM_DESCRIPTOR *)((UINTN)gSmst->CpuSaveState[Index] - SMRAM_SAVE_STATE_MAP_OFFSET + TXT_SMM_PSD_OFFSET);
1268     Psd->BiosHwResourceRequirementsPtr = (UINT64)(UINTN)StmResource;
1269   }
1270   return ;
1271 }
1272 
1273 
1274 /**
1275   This is STM setup BIOS callback.
1276 **/
1277 VOID
1278 EFIAPI
SmmStmSetup(VOID)1279 SmmStmSetup (
1280   VOID
1281   )
1282 {
1283   mStmState |= EFI_SM_MONITOR_STATE_ACTIVATED;
1284 }
1285 
1286 /**
1287   This is STM teardown BIOS callback.
1288 **/
1289 VOID
1290 EFIAPI
SmmStmTeardown(VOID)1291 SmmStmTeardown (
1292   VOID
1293   )
1294 {
1295   mStmState &= ~EFI_SM_MONITOR_STATE_ACTIVATED;
1296 }
1297 
1298