TianoCore EDK2 master
Loading...
Searching...
No Matches
SmmStm.c
Go to the documentation of this file.
1
9#include <PiMm.h>
17
18#include <Protocol/MpService.h>
19
20#include "CpuFeaturesLib.h"
21#include "SmmStm.h"
22
23#define TXT_EVTYPE_BASE 0x400
24#define TXT_EVTYPE_STM_HASH (TXT_EVTYPE_BASE + 14)
25
26#define RDWR_ACCS 3
27#define FULL_ACCS 7
28
29EFI_HANDLE mStmSmmCpuHandle = NULL;
30
31BOOLEAN mLockLoadMonitor = FALSE;
32
33//
34// Template of STM_RSC_END structure for copying.
35//
37 { END_OF_RESOURCES, sizeof (STM_RSC_END) },
38};
39
40GLOBAL_REMOVE_IF_UNREFERENCED UINT8 *mStmResourcesPtr = NULL;
41GLOBAL_REMOVE_IF_UNREFERENCED UINTN mStmResourceTotalSize = 0x0;
42GLOBAL_REMOVE_IF_UNREFERENCED UINTN mStmResourceSizeUsed = 0x0;
43GLOBAL_REMOVE_IF_UNREFERENCED UINTN mStmResourceSizeAvailable = 0x0;
44
45GLOBAL_REMOVE_IF_UNREFERENCED UINT32 mStmState = 0;
46
47//
48// System Configuration Table pointing to STM Configuration Table
49//
51EFI_SM_MONITOR_INIT_PROTOCOL mSmMonitorInitProtocol = {
57};
58
59#define CPUID1_EDX_XD_SUPPORT 0x100000
60
61//
62// External global variables associated with SMI Handler Template
63//
65extern UINT32 gStmSmbase;
66extern volatile UINT32 gStmSmiStack;
67extern UINT32 gStmSmiCr3;
68extern volatile UINT8 gcStmSmiHandlerTemplate[];
69extern CONST UINT16 gcStmSmiHandlerSize;
70extern UINT16 gcStmSmiHandlerOffset;
71extern BOOLEAN gStmXdSupported;
72
73//
74// Variables used by SMI Handler
75//
76IA32_DESCRIPTOR gStmSmiHandlerIdtr;
77
78//
79// MP Services Protocol
80//
81EFI_MP_SERVICES_PROTOCOL *mSmmCpuFeaturesLibMpService = NULL;
82
83//
84// MSEG Base and Length in SMRAM
85//
86UINTN mMsegBase = 0;
87UINTN mMsegSize = 0;
88
89BOOLEAN mStmConfigurationTableInitialized = FALSE;
90
101EFIAPI
103 IN EFI_HANDLE ImageHandle,
104 IN EFI_SYSTEM_TABLE *SystemTable
105 )
106{
107 EFI_STATUS Status;
109 EFI_HOB_GUID_TYPE *GuidHob;
110 EFI_SMRAM_DESCRIPTOR *SmramDescriptor;
111
112 //
113 // Initialize address fixup
114 //
116
117 //
118 // Perform library initialization common across all instances
119 //
121
122 //
123 // Lookup the MP Services Protocol
124 //
125 Status = gBS->LocateProtocol (
126 &gEfiMpServiceProtocolGuid,
127 NULL,
128 (VOID **)&mSmmCpuFeaturesLibMpService
129 );
130 ASSERT_EFI_ERROR (Status);
131
132 //
133 // If CPU supports VMX, then determine SMRAM range for MSEG.
134 //
136 if (RegEcx.Bits.VMX == 1) {
137 GuidHob = GetFirstGuidHob (&gMsegSmramGuid);
138 if (GuidHob != NULL) {
139 //
140 // Retrieve MSEG location from MSEG SRAM HOB
141 //
142 SmramDescriptor = (EFI_SMRAM_DESCRIPTOR *)GET_GUID_HOB_DATA (GuidHob);
143 if (SmramDescriptor->PhysicalSize > 0) {
144 mMsegBase = (UINTN)SmramDescriptor->CpuStart;
145 mMsegSize = (UINTN)SmramDescriptor->PhysicalSize;
146 }
147 } else if (PcdGet32 (PcdCpuMsegSize) > 0) {
148 //
149 // Allocate MSEG from SMRAM memory
150 //
151 mMsegBase = (UINTN)AllocatePages (EFI_SIZE_TO_PAGES (PcdGet32 (PcdCpuMsegSize)));
152 if (mMsegBase > 0) {
153 mMsegSize = ALIGN_VALUE (PcdGet32 (PcdCpuMsegSize), EFI_PAGE_SIZE);
154 } else {
155 DEBUG ((DEBUG_ERROR, "Not enough SMRAM resource to allocate MSEG size %08x\n", PcdGet32 (PcdCpuMsegSize)));
156 }
157 }
158
159 if (mMsegBase > 0) {
160 DEBUG ((DEBUG_INFO, "MsegBase: 0x%08x, MsegSize: 0x%08x\n", mMsegBase, mMsegSize));
161 }
162 }
163
164 return EFI_SUCCESS;
165}
166
172VOID
174 VOID
175 )
176{
178
179 //
180 // Set MSEG Base Address in SMM Monitor Control MSR.
181 //
182 if (mMsegBase > 0) {
183 SmmMonitorCtl.Uint64 = 0;
184 SmmMonitorCtl.Bits.MsegBase = (UINT32)mMsegBase >> 12;
185 SmmMonitorCtl.Bits.Valid = 1;
187 }
188}
189
200UINTN
201EFIAPI
203 VOID
204 )
205{
206 return gcStmSmiHandlerSize;
207}
208
234VOID
235EFIAPI
237 IN UINTN CpuIndex,
238 IN UINT32 SmBase,
239 IN VOID *SmiStack,
240 IN UINTN StackSize,
241 IN UINTN GdtBase,
242 IN UINTN GdtSize,
243 IN UINTN IdtBase,
244 IN UINTN IdtSize,
245 IN UINT32 Cr3
246 )
247{
248 EFI_STATUS Status;
250 VOID *Hob;
251 UINT32 RegEax;
252 UINT32 RegEdx;
253 EFI_PROCESSOR_INFORMATION ProcessorInfo;
254
255 CopyMem ((VOID *)((UINTN)SmBase + TXT_SMM_PSD_OFFSET), &gcStmPsd, sizeof (gcStmPsd));
256 Psd = (TXT_PROCESSOR_SMM_DESCRIPTOR *)(VOID *)((UINTN)SmBase + TXT_SMM_PSD_OFFSET);
257 Psd->SmmGdtPtr = GdtBase;
258 Psd->SmmGdtSize = (UINT32)GdtSize;
259
260 //
261 // Initialize values in template before copy
262 //
263 gStmSmiStack = (UINT32)((UINTN)SmiStack + StackSize - sizeof (UINTN));
264 gStmSmiCr3 = Cr3;
265 gStmSmbase = SmBase;
266 gStmSmiHandlerIdtr.Base = IdtBase;
267 gStmSmiHandlerIdtr.Limit = (UINT16)(IdtSize - 1);
268
269 if (gStmXdSupported) {
270 AsmCpuid (CPUID_EXTENDED_FUNCTION, &RegEax, NULL, NULL, NULL);
271 if (RegEax <= CPUID_EXTENDED_FUNCTION) {
272 //
273 // Extended CPUID functions are not supported on this processor.
274 //
275 gStmXdSupported = FALSE;
276 }
277
279 if ((RegEdx & CPUID1_EDX_XD_SUPPORT) == 0) {
280 //
281 // Execute Disable Bit feature is not supported on this processor.
282 //
283 gStmXdSupported = FALSE;
284 }
285 }
286
287 //
288 // Set the value at the top of the CPU stack to the CPU Index
289 //
290 *(UINTN *)(UINTN)gStmSmiStack = CpuIndex;
291
292 //
293 // Copy template to CPU specific SMI handler location
294 //
295 CopyMem (
296 (VOID *)((UINTN)SmBase + SMM_HANDLER_OFFSET),
297 (VOID *)gcStmSmiHandlerTemplate,
298 gcStmSmiHandlerSize
299 );
300
301 Psd->SmmSmiHandlerRip = SmBase + SMM_HANDLER_OFFSET + gcStmSmiHandlerOffset;
302 Psd->SmmSmiHandlerRsp = (UINTN)SmiStack + StackSize - sizeof (UINTN);
303 Psd->SmmCr3 = Cr3;
304
305 DEBUG ((DEBUG_INFO, "CpuSmmStmExceptionStackSize - %x\n", PcdGet32 (PcdCpuSmmStmExceptionStackSize)));
306 DEBUG ((DEBUG_INFO, "Pages - %x\n", EFI_SIZE_TO_PAGES (PcdGet32 (PcdCpuSmmStmExceptionStackSize))));
307 Psd->StmProtectionExceptionHandler.SpeRsp = (UINT64)(UINTN)AllocatePages (EFI_SIZE_TO_PAGES (PcdGet32 (PcdCpuSmmStmExceptionStackSize)));
308 Psd->StmProtectionExceptionHandler.SpeRsp += EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (PcdGet32 (PcdCpuSmmStmExceptionStackSize)));
309
310 Psd->BiosHwResourceRequirementsPtr = (UINT64)(UINTN)GetStmResource ();
311
312 //
313 // Get the APIC ID for the CPU specified by CpuIndex
314 //
315 Status = mSmmCpuFeaturesLibMpService->GetProcessorInfo (
316 mSmmCpuFeaturesLibMpService,
317 CpuIndex,
318 &ProcessorInfo
319 );
320 ASSERT_EFI_ERROR (Status);
321
322 Psd->LocalApicId = (UINT32)ProcessorInfo.ProcessorId;
323 Psd->AcpiRsdp = 0;
324
325 Hob = GetFirstHob (EFI_HOB_TYPE_CPU);
326 if (Hob != NULL) {
327 Psd->PhysicalAddressBits = ((EFI_HOB_CPU *)Hob)->SizeOfMemorySpace;
328 } else {
329 AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);
330 if (RegEax >= 0x80000008) {
331 AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL);
332 Psd->PhysicalAddressBits = (UINT8)RegEax;
333 } else {
334 Psd->PhysicalAddressBits = 36;
335 }
336 }
337
338 if (!mStmConfigurationTableInitialized) {
340 mStmConfigurationTableInitialized = TRUE;
341 }
342}
343
356EFIAPI
358 IN CONST EFI_GUID *Protocol,
359 IN VOID *Interface,
360 IN EFI_HANDLE Handle
361 )
362{
363 VOID *Rsdp;
364 UINTN Index;
366
367 DEBUG ((DEBUG_INFO, "SmmEndOfDxeEventNotify\n"));
368
369 //
370 // found ACPI table RSD_PTR from system table
371 //
372 Rsdp = NULL;
373 for (Index = 0; Index < gST->NumberOfTableEntries; Index++) {
374 if (CompareGuid (&(gST->ConfigurationTable[Index].VendorGuid), &gEfiAcpi20TableGuid)) {
375 //
376 // A match was found.
377 //
378 Rsdp = gST->ConfigurationTable[Index].VendorTable;
379 break;
380 }
381 }
382
383 if (Rsdp == NULL) {
384 for (Index = 0; Index < gST->NumberOfTableEntries; Index++) {
385 if (CompareGuid (&(gST->ConfigurationTable[Index].VendorGuid), &gEfiAcpi10TableGuid)) {
386 //
387 // A match was found.
388 //
389 Rsdp = gST->ConfigurationTable[Index].VendorTable;
390 break;
391 }
392 }
393 }
394
395 for (Index = 0; Index < gSmst->NumberOfCpus; Index++) {
396 Psd = (TXT_PROCESSOR_SMM_DESCRIPTOR *)((UINTN)gSmst->CpuSaveState[Index] - SMRAM_SAVE_STATE_MAP_OFFSET + TXT_SMM_PSD_OFFSET);
397 DEBUG ((DEBUG_INFO, "Index=%d Psd=%p Rsdp=%p\n", Index, Psd, Rsdp));
398 Psd->AcpiRsdp = (UINT64)(UINTN)Rsdp;
399 }
400
401 mLockLoadMonitor = TRUE;
402
403 return EFI_SUCCESS;
404}
405
409VOID
411 VOID
412 )
413{
414 EFI_STATUS Status;
415 VOID *Registration;
416
418 &mStmSmmCpuHandle,
419 &gEfiSmMonitorInitProtocolGuid,
421 &mSmMonitorInitProtocol
422 );
423 ASSERT_EFI_ERROR (Status);
424
425 //
426 //
427 // Register SMM End of DXE Event
428 //
429 Status = gSmst->SmmRegisterProtocolNotify (
430 &gEfiSmmEndOfDxeProtocolGuid,
432 &Registration
433 );
434 ASSERT_EFI_ERROR (Status);
435}
436
444EFI_SM_MONITOR_STATE
445EFIAPI
447 VOID
448 )
449{
450 return mStmState;
451}
452
464BOOLEAN
466 IN STM_RSC *Resource,
467 IN STM_RSC *Record
468 )
469{
470 UINT64 ResourceLo;
471 UINT64 ResourceHi;
472 UINT64 RecordLo;
473 UINT64 RecordHi;
474
475 ResourceLo = 0;
476 ResourceHi = 0;
477 RecordLo = 0;
478 RecordHi = 0;
479
480 //
481 // Calling code is responsible for making sure that
482 // Resource->Header.RscType == (*Record)->Header.RscType
483 // thus we use just one of them as switch variable.
484 //
485 switch (Resource->Header.RscType) {
486 case MEM_RANGE:
487 case MMIO_RANGE:
488 ResourceLo = Resource->Mem.Base;
489 ResourceHi = Resource->Mem.Base + Resource->Mem.Length;
490 RecordLo = Record->Mem.Base;
491 RecordHi = Record->Mem.Base + Record->Mem.Length;
492 if (Resource->Mem.RWXAttributes != Record->Mem.RWXAttributes) {
493 if ((ResourceLo == RecordLo) && (ResourceHi == RecordHi)) {
494 Record->Mem.RWXAttributes = Resource->Mem.RWXAttributes | Record->Mem.RWXAttributes;
495 return TRUE;
496 } else {
497 return FALSE;
498 }
499 }
500
501 break;
502 case IO_RANGE:
503 case TRAPPED_IO_RANGE:
504 ResourceLo = (UINT64)Resource->Io.Base;
505 ResourceHi = (UINT64)Resource->Io.Base + (UINT64)Resource->Io.Length;
506 RecordLo = (UINT64)Record->Io.Base;
507 RecordHi = (UINT64)Record->Io.Base + (UINT64)Record->Io.Length;
508 break;
509 case PCI_CFG_RANGE:
510 if ((Resource->PciCfg.OriginatingBusNumber != Record->PciCfg.OriginatingBusNumber) ||
511 (Resource->PciCfg.LastNodeIndex != Record->PciCfg.LastNodeIndex))
512 {
513 return FALSE;
514 }
515
516 if (CompareMem (Resource->PciCfg.PciDevicePath, Record->PciCfg.PciDevicePath, sizeof (STM_PCI_DEVICE_PATH_NODE) * (Resource->PciCfg.LastNodeIndex + 1)) != 0) {
517 return FALSE;
518 }
519
520 ResourceLo = (UINT64)Resource->PciCfg.Base;
521 ResourceHi = (UINT64)Resource->PciCfg.Base + (UINT64)Resource->PciCfg.Length;
522 RecordLo = (UINT64)Record->PciCfg.Base;
523 RecordHi = (UINT64)Record->PciCfg.Base + (UINT64)Record->PciCfg.Length;
524 if (Resource->PciCfg.RWAttributes != Record->PciCfg.RWAttributes) {
525 if ((ResourceLo == RecordLo) && (ResourceHi == RecordHi)) {
526 Record->PciCfg.RWAttributes = Resource->PciCfg.RWAttributes | Record->PciCfg.RWAttributes;
527 return TRUE;
528 } else {
529 return FALSE;
530 }
531 }
532
533 break;
534 case MACHINE_SPECIFIC_REG:
535 //
536 // Special case - merge MSR masks in place.
537 //
538 if (Resource->Msr.MsrIndex != Record->Msr.MsrIndex) {
539 return FALSE;
540 }
541
542 Record->Msr.ReadMask |= Resource->Msr.ReadMask;
543 Record->Msr.WriteMask |= Resource->Msr.WriteMask;
544 return TRUE;
545 default:
546 return FALSE;
547 }
548
549 //
550 // If resources are disjoint
551 //
552 if ((ResourceHi < RecordLo) || (ResourceLo > RecordHi)) {
553 return FALSE;
554 }
555
556 //
557 // If resource is consumed by record.
558 //
559 if ((ResourceLo >= RecordLo) && (ResourceHi <= RecordHi)) {
560 return TRUE;
561 }
562
563 //
564 // Resources are overlapping.
565 // Resource and record are merged.
566 //
567 ResourceLo = (ResourceLo < RecordLo) ? ResourceLo : RecordLo;
568 ResourceHi = (ResourceHi > RecordHi) ? ResourceHi : RecordHi;
569
570 switch (Resource->Header.RscType) {
571 case MEM_RANGE:
572 case MMIO_RANGE:
573 Record->Mem.Base = ResourceLo;
574 Record->Mem.Length = ResourceHi - ResourceLo;
575 break;
576 case IO_RANGE:
577 case TRAPPED_IO_RANGE:
578 Record->Io.Base = (UINT16)ResourceLo;
579 Record->Io.Length = (UINT16)(ResourceHi - ResourceLo);
580 break;
581 case PCI_CFG_RANGE:
582 Record->PciCfg.Base = (UINT16)ResourceLo;
583 Record->PciCfg.Length = (UINT16)(ResourceHi - ResourceLo);
584 break;
585 default:
586 return FALSE;
587 }
588
589 return TRUE;
590}
591
599VOID
601 IN STM_RSC *Resource
602 )
603{
604 STM_RSC *Record;
605
606 Record = (STM_RSC *)mStmResourcesPtr;
607
608 while (TRUE) {
609 if (Record->Header.RscType == END_OF_RESOURCES) {
610 break;
611 }
612
613 //
614 // Go to next record if resource and record types don't match.
615 //
616 if (Resource->Header.RscType != Record->Header.RscType) {
617 Record = (STM_RSC *)((UINTN)Record + Record->Header.Length);
618 continue;
619 }
620
621 //
622 // Record is handled inside of procedure - don't adjust.
623 //
624 if (HandleSingleResource (Resource, Record)) {
625 return;
626 }
627
628 Record = (STM_RSC *)((UINTN)Record + Record->Header.Length);
629 }
630
631 //
632 // Add resource to the end of area.
633 //
634 CopyMem (
635 mStmResourcesPtr + mStmResourceSizeUsed - sizeof (mRscEndNode),
636 Resource,
637 Resource->Header.Length
638 );
639 CopyMem (
640 mStmResourcesPtr + mStmResourceSizeUsed - sizeof (mRscEndNode) + Resource->Header.Length,
641 &mRscEndNode,
642 sizeof (mRscEndNode)
643 );
644 mStmResourceSizeUsed += Resource->Header.Length;
645 mStmResourceSizeAvailable = mStmResourceTotalSize - mStmResourceSizeUsed;
646
647 return;
648}
649
659VOID
661 IN STM_RSC *ResourceList,
662 IN UINT32 NumEntries OPTIONAL
663 )
664{
665 UINT32 Count;
666 UINTN Index;
667 STM_RSC *Resource;
668
669 if (NumEntries == 0) {
670 Count = 0xFFFFFFFF;
671 } else {
672 Count = NumEntries;
673 }
674
675 Resource = ResourceList;
676
677 for (Index = 0; Index < Count; Index++) {
678 if (Resource->Header.RscType == END_OF_RESOURCES) {
679 return;
680 }
681
682 AddSingleResource (Resource);
683 Resource = (STM_RSC *)((UINTN)Resource + Resource->Header.Length);
684 }
685
686 return;
687}
688
701BOOLEAN
703 IN STM_RSC *ResourceList,
704 IN UINT32 NumEntries OPTIONAL
705 )
706{
707 UINT32 Count;
708 UINTN Index;
709 STM_RSC *Resource;
710 UINTN SubIndex;
711
712 //
713 // If NumEntries == 0 make it very big. Scan will be terminated by
714 // END_OF_RESOURCES.
715 //
716 if (NumEntries == 0) {
717 Count = 0xFFFFFFFF;
718 } else {
719 Count = NumEntries;
720 }
721
722 //
723 // Start from beginning of resource list.
724 //
725 Resource = ResourceList;
726
727 for (Index = 0; Index < Count; Index++) {
728 DEBUG ((DEBUG_INFO, "ValidateResource (%d) - RscType(%x)\n", Index, Resource->Header.RscType));
729 //
730 // Validate resource.
731 //
732 switch (Resource->Header.RscType) {
733 case END_OF_RESOURCES:
734 if (Resource->Header.Length != sizeof (STM_RSC_END)) {
735 return FALSE;
736 }
737
738 //
739 // If we are passed actual number of resources to add,
740 // END_OF_RESOURCES structure between them is considered an
741 // error. If NumEntries == 0 END_OF_RESOURCES is a termination.
742 //
743 if (NumEntries != 0) {
744 return FALSE;
745 } else {
746 //
747 // If NumEntries == 0 and list reached end - return success.
748 //
749 return TRUE;
750 }
751
752 break;
753
754 case MEM_RANGE:
755 case MMIO_RANGE:
756 if (Resource->Header.Length != sizeof (STM_RSC_MEM_DESC)) {
757 return FALSE;
758 }
759
760 if (Resource->Mem.RWXAttributes > FULL_ACCS) {
761 return FALSE;
762 }
763
764 break;
765
766 case IO_RANGE:
767 case TRAPPED_IO_RANGE:
768 if (Resource->Header.Length != sizeof (STM_RSC_IO_DESC)) {
769 return FALSE;
770 }
771
772 if ((Resource->Io.Base + Resource->Io.Length) > 0xFFFF) {
773 return FALSE;
774 }
775
776 break;
777
778 case PCI_CFG_RANGE:
779 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));
780 if (Resource->Header.Length != sizeof (STM_RSC_PCI_CFG_DESC) + (sizeof (STM_PCI_DEVICE_PATH_NODE) * Resource->PciCfg.LastNodeIndex)) {
781 return FALSE;
782 }
783
784 for (SubIndex = 0; SubIndex <= Resource->PciCfg.LastNodeIndex; SubIndex++) {
785 if ((Resource->PciCfg.PciDevicePath[SubIndex].PciDevice > 0x1F) || (Resource->PciCfg.PciDevicePath[SubIndex].PciFunction > 7)) {
786 return FALSE;
787 }
788 }
789
790 if ((Resource->PciCfg.Base + Resource->PciCfg.Length) > 0x1000) {
791 return FALSE;
792 }
793
794 break;
795
796 case MACHINE_SPECIFIC_REG:
797 if (Resource->Header.Length != sizeof (STM_RSC_MSR_DESC)) {
798 return FALSE;
799 }
800
801 break;
802
803 default:
804 DEBUG ((DEBUG_ERROR, "ValidateResource - Unknown RscType(%x)\n", Resource->Header.RscType));
805 return FALSE;
806 }
807
808 Resource = (STM_RSC *)((UINTN)Resource + Resource->Header.Length);
809 }
810
811 return TRUE;
812}
813
827UINTN
829 IN STM_RSC *ResourceList,
830 IN UINT32 NumEntries OPTIONAL
831 )
832{
833 UINT32 Count;
834 UINTN Index;
835 STM_RSC *Resource;
836
837 Resource = ResourceList;
838
839 //
840 // If NumEntries == 0 make it very big. Scan will be terminated by
841 // END_OF_RESOURCES.
842 //
843 if (NumEntries == 0) {
844 Count = 0xFFFFFFFF;
845 } else {
846 Count = NumEntries;
847 }
848
849 //
850 // Start from beginning of resource list.
851 //
852 Resource = ResourceList;
853
854 for (Index = 0; Index < Count; Index++) {
855 if (Resource->Header.RscType == END_OF_RESOURCES) {
856 break;
857 }
858
859 Resource = (STM_RSC *)((UINTN)Resource + Resource->Header.Length);
860 }
861
862 return (UINTN)Resource - (UINTN)ResourceList;
863}
864
879EFIAPI
881 IN STM_RSC *ResourceList,
882 IN UINT32 NumEntries OPTIONAL
883 )
884{
885 EFI_STATUS Status;
886 UINTN ResourceSize;
887 EFI_PHYSICAL_ADDRESS NewResource;
888 UINTN NewResourceSize;
889
890 DEBUG ((DEBUG_INFO, "AddPiResource - Enter\n"));
891
892 if (!ValidateResource (ResourceList, NumEntries)) {
893 return EFI_INVALID_PARAMETER;
894 }
895
896 ResourceSize = GetResourceSize (ResourceList, NumEntries);
897 DEBUG ((DEBUG_INFO, "ResourceSize - 0x%08x\n", ResourceSize));
898 if (ResourceSize == 0) {
899 return EFI_INVALID_PARAMETER;
900 }
901
902 if (mStmResourcesPtr == NULL) {
903 //
904 // First time allocation
905 //
906 NewResourceSize = EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (ResourceSize + sizeof (mRscEndNode)));
907 DEBUG ((DEBUG_INFO, "Allocate - 0x%08x\n", NewResourceSize));
908 Status = gSmst->SmmAllocatePages (
911 EFI_SIZE_TO_PAGES (NewResourceSize),
912 &NewResource
913 );
914 if (EFI_ERROR (Status)) {
915 return Status;
916 }
917
918 //
919 // Copy EndResource for initialization
920 //
921 mStmResourcesPtr = (UINT8 *)(UINTN)NewResource;
922 mStmResourceTotalSize = NewResourceSize;
923 CopyMem (mStmResourcesPtr, &mRscEndNode, sizeof (mRscEndNode));
924 mStmResourceSizeUsed = sizeof (mRscEndNode);
925 mStmResourceSizeAvailable = mStmResourceTotalSize - sizeof (mRscEndNode);
926
927 //
928 // Let SmmCore change resource ptr
929 //
930 NotifyStmResourceChange (mStmResourcesPtr);
931 } else if (mStmResourceSizeAvailable < ResourceSize) {
932 //
933 // Need enlarge
934 //
935 NewResourceSize = mStmResourceTotalSize + (ResourceSize - mStmResourceSizeAvailable);
936 NewResourceSize = EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (NewResourceSize));
937 DEBUG ((DEBUG_INFO, "ReAllocate - 0x%08x\n", NewResourceSize));
938 Status = gSmst->SmmAllocatePages (
941 EFI_SIZE_TO_PAGES (NewResourceSize),
942 &NewResource
943 );
944 if (EFI_ERROR (Status)) {
945 return Status;
946 }
947
948 CopyMem ((VOID *)(UINTN)NewResource, mStmResourcesPtr, mStmResourceSizeUsed);
949 mStmResourceSizeAvailable = NewResourceSize - mStmResourceSizeUsed;
950
951 gSmst->SmmFreePages (
952 (EFI_PHYSICAL_ADDRESS)(UINTN)mStmResourcesPtr,
953 EFI_SIZE_TO_PAGES (mStmResourceTotalSize)
954 );
955
956 mStmResourceTotalSize = NewResourceSize;
957 mStmResourcesPtr = (UINT8 *)(UINTN)NewResource;
958
959 //
960 // Let SmmCore change resource ptr
961 //
962 NotifyStmResourceChange (mStmResourcesPtr);
963 }
964
965 //
966 // Check duplication
967 //
968 AddResource (ResourceList, NumEntries);
969
970 return EFI_SUCCESS;
971}
972
987EFIAPI
989 IN STM_RSC *ResourceList,
990 IN UINT32 NumEntries OPTIONAL
991 )
992{
993 if (ResourceList != NULL) {
994 // TBD
995 ASSERT (FALSE);
996 return EFI_UNSUPPORTED;
997 }
998
999 //
1000 // Delete all
1001 //
1002 CopyMem (mStmResourcesPtr, &mRscEndNode, sizeof (mRscEndNode));
1003 mStmResourceSizeUsed = sizeof (mRscEndNode);
1004 mStmResourceSizeAvailable = mStmResourceTotalSize - sizeof (mRscEndNode);
1005 return EFI_SUCCESS;
1006}
1007
1022EFIAPI
1024 OUT STM_RSC *ResourceList,
1025 IN OUT UINT32 *ResourceSize
1026 )
1027{
1028 if (*ResourceSize < mStmResourceSizeUsed) {
1029 *ResourceSize = (UINT32)mStmResourceSizeUsed;
1030 return EFI_BUFFER_TOO_SMALL;
1031 }
1032
1033 CopyMem (ResourceList, mStmResourcesPtr, mStmResourceSizeUsed);
1034 *ResourceSize = (UINT32)mStmResourceSizeUsed;
1035 return EFI_SUCCESS;
1036}
1037
1045VOID
1046EFIAPI
1048 IN VOID *Buffer
1049 )
1050{
1052
1054 SmmMonitorCtl.Bits.Valid = 1;
1056}
1057
1065UINT32
1067 VOID
1068 )
1069{
1071
1072 //
1073 // Read VMCS size and and align to 4KB
1074 //
1076 return ALIGN_VALUE (VmxBasic.Bits.VmcsSize, SIZE_4KB);
1077}
1078
1089BOOLEAN
1091 IN EFI_PHYSICAL_ADDRESS StmImage,
1092 IN UINTN StmImageSize
1093 )
1094{
1095 UINTN MinMsegSize;
1096 STM_HEADER *StmHeader;
1097 IA32_VMX_MISC_REGISTER VmxMiscMsr;
1098
1099 //
1100 // Check to see if STM image is compatible with CPU
1101 //
1102 StmHeader = (STM_HEADER *)(UINTN)StmImage;
1103 VmxMiscMsr.Uint64 = AsmReadMsr64 (MSR_IA32_VMX_MISC);
1104 if (StmHeader->HwStmHdr.MsegHeaderRevision != VmxMiscMsr.Bits.MsegRevisionIdentifier) {
1105 DEBUG ((DEBUG_ERROR, "STM Image not compatible with CPU\n"));
1106 DEBUG ((DEBUG_ERROR, " StmHeader->HwStmHdr.MsegHeaderRevision = %08x\n", StmHeader->HwStmHdr.MsegHeaderRevision));
1107 DEBUG ((DEBUG_ERROR, " VmxMiscMsr.Bits.MsegRevisionIdentifier = %08x\n", VmxMiscMsr.Bits.MsegRevisionIdentifier));
1108 return FALSE;
1109 }
1110
1111 //
1112 // Get Minimal required Mseg size
1113 //
1114 MinMsegSize = (EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (StmHeader->SwStmHdr.StaticImageSize)) +
1115 StmHeader->SwStmHdr.AdditionalDynamicMemorySize +
1116 (StmHeader->SwStmHdr.PerProcDynamicMemorySize + GetVmcsSize () * 2) * gSmst->NumberOfCpus);
1117 if (MinMsegSize < StmImageSize) {
1118 MinMsegSize = StmImageSize;
1119 }
1120
1121 if (StmHeader->HwStmHdr.Cr3Offset >= StmHeader->SwStmHdr.StaticImageSize) {
1122 //
1123 // We will create page table, just in case that SINIT does not create it.
1124 //
1125 if (MinMsegSize < StmHeader->HwStmHdr.Cr3Offset + EFI_PAGES_TO_SIZE (6)) {
1126 MinMsegSize = StmHeader->HwStmHdr.Cr3Offset + EFI_PAGES_TO_SIZE (6);
1127 }
1128 }
1129
1130 //
1131 // Check if it exceeds MSEG size
1132 //
1133 if (MinMsegSize > mMsegSize) {
1134 DEBUG ((DEBUG_ERROR, "MSEG too small. Min MSEG Size = %08x Current MSEG Size = %08x\n", MinMsegSize, mMsegSize));
1135 DEBUG ((DEBUG_ERROR, " StmHeader->SwStmHdr.StaticImageSize = %08x\n", StmHeader->SwStmHdr.StaticImageSize));
1136 DEBUG ((DEBUG_ERROR, " StmHeader->SwStmHdr.AdditionalDynamicMemorySize = %08x\n", StmHeader->SwStmHdr.AdditionalDynamicMemorySize));
1137 DEBUG ((DEBUG_ERROR, " StmHeader->SwStmHdr.PerProcDynamicMemorySize = %08x\n", StmHeader->SwStmHdr.PerProcDynamicMemorySize));
1138 DEBUG ((DEBUG_ERROR, " VMCS Size = %08x\n", GetVmcsSize ()));
1139 DEBUG ((DEBUG_ERROR, " Max CPUs = %08x\n", gSmst->NumberOfCpus));
1140 DEBUG ((DEBUG_ERROR, " StmHeader->HwStmHdr.Cr3Offset = %08x\n", StmHeader->HwStmHdr.Cr3Offset));
1141 return FALSE;
1142 }
1143
1144 return TRUE;
1145}
1146
1155VOID
1157 IN EFI_PHYSICAL_ADDRESS StmImage,
1158 IN UINTN StmImageSize
1159 )
1160{
1162 UINT32 MsegBase;
1163 STM_HEADER *StmHeader;
1164
1165 //
1166 // Get MSEG base address from MSR_IA32_SMM_MONITOR_CTL
1167 //
1169 MsegBase = SmmMonitorCtl.Bits.MsegBase << 12;
1170
1171 //
1172 // Zero all of MSEG base address
1173 //
1174 ZeroMem ((VOID *)(UINTN)MsegBase, mMsegSize);
1175
1176 //
1177 // Copy STM Image into MSEG
1178 //
1179 CopyMem ((VOID *)(UINTN)MsegBase, (VOID *)(UINTN)StmImage, StmImageSize);
1180
1181 //
1182 // STM Header is at the beginning of the STM Image
1183 //
1184 StmHeader = (STM_HEADER *)(UINTN)StmImage;
1185
1186 StmGen4GPageTable ((UINTN)MsegBase + StmHeader->HwStmHdr.Cr3Offset);
1187}
1188
1203EFIAPI
1205 IN EFI_PHYSICAL_ADDRESS StmImage,
1206 IN UINTN StmImageSize
1207 )
1208{
1210
1211 if (mLockLoadMonitor) {
1212 return EFI_ACCESS_DENIED;
1213 }
1214
1216 if (SmmMonitorCtl.Bits.MsegBase == 0) {
1217 return EFI_UNSUPPORTED;
1218 }
1219
1220 if (!StmCheckStmImage (StmImage, StmImageSize)) {
1221 return EFI_BUFFER_TOO_SMALL;
1222 }
1223
1224 // Record STM_HASH to PCR 0, just in case it is NOT TXT launch, we still need provide the evidence.
1226 0, // PcrIndex
1227 TXT_EVTYPE_STM_HASH, // EventType
1228 NULL, // EventLog
1229 0, // LogLen
1230 (VOID *)(UINTN)StmImage, // HashData
1231 StmImageSize // HashDataLen
1232 );
1233
1234 StmLoadStmImage (StmImage, StmImageSize);
1235
1236 mStmState |= EFI_SM_MONITOR_STATE_ENABLED;
1237
1238 return EFI_SUCCESS;
1239}
1240
1249VOID *
1251 VOID
1252 )
1253{
1254 return mStmResourcesPtr;
1255}
1256
1263VOID
1265 VOID *StmResource
1266 )
1267{
1268 UINTN Index;
1270
1271 for (Index = 0; Index < gSmst->NumberOfCpus; Index++) {
1272 Psd = (TXT_PROCESSOR_SMM_DESCRIPTOR *)((UINTN)gSmst->CpuSaveState[Index] - SMRAM_SAVE_STATE_MAP_OFFSET + TXT_SMM_PSD_OFFSET);
1273 Psd->BiosHwResourceRequirementsPtr = (UINT64)(UINTN)StmResource;
1274 }
1275
1276 return;
1277}
1278
1282VOID
1283EFIAPI
1285 VOID
1286 )
1287{
1288 mStmState |= EFI_SM_MONITOR_STATE_ACTIVATED;
1289}
1290
1294VOID
1295EFIAPI
1297 VOID
1298 )
1299{
1300 mStmState &= ~EFI_SM_MONITOR_STATE_ACTIVATED;
1301}
UINT64 UINTN
VOID CpuFeaturesLibInitialization(VOID)
VOID *EFIAPI GetFirstHob(IN UINT16 Type)
Definition: HobLib.c:142
VOID *EFIAPI GetFirstGuidHob(IN CONST EFI_GUID *Guid)
Definition: HobLib.c:215
INTN EFIAPI CompareMem(IN CONST VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
BOOLEAN EFIAPI CompareGuid(IN CONST GUID *Guid1, IN CONST GUID *Guid2)
Definition: MemLibGuid.c:73
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
UINT64 EFIAPI AsmReadMsr64(IN UINT32 Index)
Definition: GccInlinePriv.c:60
UINT64 EFIAPI AsmWriteMsr64(IN UINT32 Index, IN UINT64 Value)
VOID StmGen4GPageTable(IN UINTN PageTableBase)
Definition: SmmStmSupport.c:30
#define NULL
Definition: Base.h:319
#define CONST
Definition: Base.h:259
#define ALIGN_VALUE(Value, Alignment)
Definition: Base.h:948
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define GLOBAL_REMOVE_IF_UNREFERENCED
Definition: Base.h:48
#define ASSERT_EFI_ERROR(StatusParameter)
Definition: DebugLib.h:462
#define DEBUG(Expression)
Definition: DebugLib.h:434
#define SMM_HANDLER_OFFSET
#define MSR_IA32_VMX_BASIC
#define MSR_IA32_VMX_MISC
#define MSR_IA32_SMM_MONITOR_CTL
#define CPUID_VERSION_INFO
Definition: Cpuid.h:81
#define CPUID_EXTENDED_CPU_SIG
Definition: Cpuid.h:3768
#define SMRAM_SAVE_STATE_MAP_OFFSET
UINT32 EFIAPI AsmCpuid(IN UINT32 Index, OUT UINT32 *RegisterEax OPTIONAL, OUT UINT32 *RegisterEbx OPTIONAL, OUT UINT32 *RegisterEcx OPTIONAL, OUT UINT32 *RegisterEdx OPTIONAL)
Definition: CpuId.c:36
#define PcdGet32(TokenName)
Definition: PcdLib.h:362
EFI_SMM_SYSTEM_TABLE2 * gSmst
VOID *EFIAPI AllocatePages(IN UINTN Pages)
BOOLEAN ValidateResource(IN STM_RSC *ResourceList, IN UINT32 NumEntries OPTIONAL)
Definition: SmmStm.c:702
EFI_STATUS EFIAPI DeletePiResource(IN STM_RSC *ResourceList, IN UINT32 NumEntries OPTIONAL)
Definition: SmmStm.c:988
VOID StmSmmConfigurationTableInit(VOID)
Definition: SmmStm.c:410
VOID EFIAPI EnableMsegMsr(IN VOID *Buffer)
Definition: SmmStm.c:1047
VOID AddResource(IN STM_RSC *ResourceList, IN UINT32 NumEntries OPTIONAL)
Definition: SmmStm.c:660
VOID EFIAPI SmmStmTeardown(VOID)
Definition: SmmStm.c:1296
BOOLEAN StmCheckStmImage(IN EFI_PHYSICAL_ADDRESS StmImage, IN UINTN StmImageSize)
Definition: SmmStm.c:1090
VOID AddSingleResource(IN STM_RSC *Resource)
Definition: SmmStm.c:600
UINTN GetResourceSize(IN STM_RSC *ResourceList, IN UINT32 NumEntries OPTIONAL)
Definition: SmmStm.c:828
EFI_SM_MONITOR_STATE EFIAPI GetMonitorState(VOID)
Definition: SmmStm.c:446
EFI_STATUS EFIAPI SmmEndOfDxeEventNotify(IN CONST EFI_GUID *Protocol, IN VOID *Interface, IN EFI_HANDLE Handle)
Definition: SmmStm.c:357
EFI_STATUS EFIAPI GetPiResource(OUT STM_RSC *ResourceList, IN OUT UINT32 *ResourceSize)
Definition: SmmStm.c:1023
EFI_STATUS EFIAPI SmmCpuFeaturesLibStmConstructor(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
Definition: SmmStm.c:102
VOID * GetStmResource(VOID)
Definition: SmmStm.c:1250
EFI_STATUS EFIAPI AddPiResource(IN STM_RSC *ResourceList, IN UINT32 NumEntries OPTIONAL)
Definition: SmmStm.c:880
VOID 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)
Definition: SmmStm.c:236
UINT32 GetVmcsSize(VOID)
Definition: SmmStm.c:1066
BOOLEAN HandleSingleResource(IN STM_RSC *Resource, IN STM_RSC *Record)
Definition: SmmStm.c:465
VOID EFIAPI SmmStmSetup(VOID)
Definition: SmmStm.c:1284
VOID FinishSmmCpuFeaturesInitializeProcessor(VOID)
Definition: SmmStm.c:173
VOID StmLoadStmImage(IN EFI_PHYSICAL_ADDRESS StmImage, IN UINTN StmImageSize)
Definition: SmmStm.c:1156
EFI_STATUS EFIAPI LoadMonitor(IN EFI_PHYSICAL_ADDRESS StmImage, IN UINTN StmImageSize)
Definition: SmmStm.c:1204
VOID NotifyStmResourceChange(VOID *StmResource)
Definition: SmmStm.c:1264
UINTN EFIAPI SmmCpuFeaturesGetSmiHandlerSize(VOID)
Definition: SmmStm.c:202
VOID EFIAPI SmmCpuFeaturesLibStmSmiEntryFixupAddress()
#define END_OF_RESOURCES
EFI_STATUS EFIAPI TpmMeasureAndLogData(IN UINT32 PcrIndex, IN UINT32 EventType, IN VOID *EventLog, IN UINT32 LogLen, IN VOID *HashData, IN UINT64 HashDataLen)
UINT64 EFI_PHYSICAL_ADDRESS
Definition: UefiBaseType.h:50
#define EFI_PAGES_TO_SIZE(Pages)
Definition: UefiBaseType.h:213
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
#define EFI_SIZE_TO_PAGES(Size)
Definition: UefiBaseType.h:200
VOID * EFI_HANDLE
Definition: UefiBaseType.h:33
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_SYSTEM_TABLE * gST
EFI_BOOT_SERVICES * gBS
@ EfiRuntimeServicesData
@ EFI_NATIVE_INTERFACE
Definition: UefiSpec.h:1193
@ AllocateAnyPages
Definition: UefiSpec.h:33
EFI_INSTALL_PROTOCOL_INTERFACE SmmInstallProtocolInterface
Definition: PiSmmCis.h:185
EFI_PHYSICAL_ADDRESS CpuStart
Definition: PiMultiPhase.h:127
EFI_CONFIGURATION_TABLE * ConfigurationTable
Definition: UefiSpec.h:2092
UINTN NumberOfTableEntries
Definition: UefiSpec.h:2087
Definition: Base.h:213
UINT32 MsegHeaderRevision
struct CPUID_VERSION_INFO_ECX::@695 Bits
struct IA32_VMX_MISC_REGISTER::@664 Bits
struct MSR_IA32_SMM_MONITOR_CTL_REGISTER::@630 Bits
struct MSR_IA32_VMX_BASIC_REGISTER::@663 Bits