Name of user not set #1002358 has uploaded this change for review.

View Change

security/intel/stm   STM support

Initial commit for Coreboot STM supporX

Change-Id: If4adcd92c341162630ce1ec357ffcf8a135785ec
---
M src/security/Kconfig
M src/security/Makefile.inc
A src/security/intel/stm/Kconfig
A src/security/intel/stm/Makefile.inc
A src/security/intel/stm/SmmStm.c
A src/security/intel/stm/SmmStm.h
A src/security/intel/stm/StmApi.h
A src/security/intel/stm/StmPlatformResource.c
A src/security/intel/stm/StmPlatformResource.h
A src/security/intel/stm/StmPlatformSmm.c
10 files changed, 2,235 insertions(+), 0 deletions(-)

git pull ssh://review.coreboot.org:29418/coreboot refs/changes/34/33234/1
diff --git a/src/security/Kconfig b/src/security/Kconfig
index 6a334ac..e9b5225 100644
--- a/src/security/Kconfig
+++ b/src/security/Kconfig
@@ -14,3 +14,4 @@

source "src/security/vboot/Kconfig"
source "src/security/tpm/Kconfig"
+source "src/security/intel/stm/Kconfig"
diff --git a/src/security/Makefile.inc b/src/security/Makefile.inc
index a940b82..e49c172 100644
--- a/src/security/Makefile.inc
+++ b/src/security/Makefile.inc
@@ -1,2 +1,4 @@
subdirs-y += vboot
subdirs-y += tpm
+subdirs-y += intel/stm
+
diff --git a/src/security/intel/stm/Kconfig b/src/security/intel/stm/Kconfig
new file mode 100644
index 0000000..e8eea02
--- /dev/null
+++ b/src/security/intel/stm/Kconfig
@@ -0,0 +1,17 @@
+
+menu "SMI Transfer Monitor (STM)"
+
+config STM
+ bool "Enable STM"
+ default y
+ depends on (PLATFORM_USES_FSP2_0||PLATFORM_USES_FSP1_1||PLATFORM_USES_FSP1_0)
+
+if STM
+
+config MSEG_SIZE
+ hex "mseg size"
+ default 0x400000
+
+endif #STM
+
+endmenu
diff --git a/src/security/intel/stm/Makefile.inc b/src/security/intel/stm/Makefile.inc
new file mode 100644
index 0000000..24d7bac
--- /dev/null
+++ b/src/security/intel/stm/Makefile.inc
@@ -0,0 +1,16 @@
+
+# put the stm where is can be found
+
+cbfs-files-y += stm.bin
+stm.bin-file = stm.bin
+stm.bin-type = raw
+
+ramstage-y += SmmStm.c
+ramstage-y += StmPlatformSmm.c
+ramstage-y += StmPlatformResource.c
+
+smm-y += StmPlatformResource.c
+smm-y += SmmStm.c
+smm-y += StmPlatformSmm.c
+
+
diff --git a/src/security/intel/stm/SmmStm.c b/src/security/intel/stm/SmmStm.c
new file mode 100644
index 0000000..677d514
--- /dev/null
+++ b/src/security/intel/stm/SmmStm.c
@@ -0,0 +1,894 @@
+/** @file
+
+ SMM STM support
+
+ Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.
+
+ This program and the accompanying materials are licensed and made available
+ under the terms and conditions of the BSD License which accompanies this
+ distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <security/intel/stm/SmmStm.h>
+#include <cpu/x86/msr.h>
+#include <cpu/x86/cr.h>
+#include <string.h>
+#include <cpu/x86/mp.h>
+#include <console/console.h>
+
+#define TXT_EVTYPE_BASE 0x400
+#define TXT_EVTYPE_STM_HASH (TXT_EVTYPE_BASE + 14)
+
+#define RDWR_ACCS 3
+#define FULL_ACCS 7
+
+#define SIZE_4KB 0x00001000
+#define SIZE_4MB 0x00400000
+
+#define IA32_PG_P (1<<0)
+#define IA32_PG_RW (1<<1)
+#define IA32_PG_PS (1<<7)
+
+#define STM_PAGE_SHIFT 12
+#define STM_PAGE_MASK 0xFFF
+#define STM_SIZE_TO_PAGES(a) (((a) >> STM_PAGE_SHIFT) + (((a) & STM_PAGE_MASK) ? 1 : 0))
+#define STM_PAGES_TO_SIZE(a) ((a) << STM_PAGE_SHIFT)
+
+#define STM_ACCESS_DENIED 15
+#define STM_UNSUPPORTED 3
+
+#define STM_BUFFER_TOO_SMALL 1
+
+#define STM_SM_MONITOR_STATE_ENABLED 1
+
+#define RESOURCEHEAPSIZE 4096
+
+uint32_t GetVmcsSize(void);
+void StmGen4GPageTableIa32(uint32_t PageTableBase);
+void StmGen4GPageTableX64(uint32_t PageTableBase);
+bool StmCheckStmImage(void * StmImage, uint32_t StmImageSize);
+void StmLoadStmImage(void * StmImage, UINTN StmImageSize);
+
+bool HandleSingleResource(STM_RSC *Resource, STM_RSC *Record);
+void AddSingleResource(STM_RSC *Resource);
+void AddResource(STM_RSC *ResourceList, uint32_t NumEntries);
+bool ValidateResource(STM_RSC *ResourceList, uint32_t NumEntries);
+UINTN GetResourceSize(STM_RSC *ResourceList, uint32_t NumEntries);
+
+typedef struct {
+
+ uint64_t VmcsRevisionID:31;
+ uint64_t AlwaysZero:1;
+ uint64_t VmcsSize:13;
+ uint64_t Reserved1:3;
+ uint64_t VmxonAddWidth:1;
+ uint64_t StmSupported:1;
+ uint64_t VmcsMemoryType:4;
+ uint64_t InOutReporting:1;
+ uint64_t MayClearDefaults:1;
+ uint64_t Reserved2:8;
+} VMX_BASIC_MSR_BITS;
+
+typedef union {
+ VMX_BASIC_MSR_BITS bits;
+ uint64_t uint64;
+ msr_t msr;
+} VMX_BASIC_MSR;
+
+typedef struct {
+ uint64_t valid:1;
+ uint64_t reserved1:1;
+ uint64_t VmxOffBlockSmi:1;
+ uint64_t reserved2:9;
+ uint64_t MsegAddress:20;
+ uint64_t reserved3:32;
+} SMM_MONITOR_CTL_MSR_BITS;
+
+extern struct mp_state {
+ struct mp_ops ops;
+ int cpu_count;
+ uintptr_t perm_smbase;
+ size_t perm_smsize;
+ size_t smm_save_state_size;
+ int do_smm;
+} mp_state;
+
+typedef union {
+ SMM_MONITOR_CTL_MSR_BITS bits;
+ uint64_t uint64;
+ msr_t msr;
+} SMM_MONITOR_CTL_MSR;
+
+//
+// Template of STM_RSC_END structure for copying.
+//
+
+STM_RSC_END mRscEndNode = {
+ {END_OF_RESOURCES, sizeof(STM_RSC_END)},
+};
+
+uint8_t *mStmResourcesPtr = NULL;
+UINTN mStmResourceTotalSize = 0x0;
+UINTN mStmResourceSizeUsed = 0x0;
+UINTN mStmResourceSizeAvailable = 0x0;
+
+uint8_t StmResourceHeap[RESOURCEHEAPSIZE];
+
+uint32_t mStmState = 0;
+
+/**
+
+ Handle single Resource to see if it can be merged into Record.
+
+ @param Resource A pointer to resource node to be added
+ @param Record A pointer to record node to be merged
+
+ @retval true resource handled
+ @retval false resource is not handled
+
+**/
+
+bool
+HandleSingleResource(
+ STM_RSC *Resource,
+ STM_RSC *Record
+ )
+{
+ uint64_t ResourceLo;
+ uint64_t ResourceHi;
+ uint64_t RecordLo;
+ uint64_t RecordHi;
+
+ ResourceLo = 0;
+ ResourceHi = 0;
+ RecordLo = 0;
+ RecordHi = 0;
+
+ //
+ // Calling code is responsible for making sure that
+ // Resource->Header.RscType == (*Record)->Header.RscType
+ // thus we use just one of them as switch variable.
+ //
+
+ switch (Resource->Header.RscType) {
+ case MEM_RANGE:
+ case MMIO_RANGE:
+ ResourceLo = Resource->Mem.Base;
+ ResourceHi = Resource->Mem.Base + Resource->Mem.Length;
+ RecordLo = Record->Mem.Base;
+ RecordHi = Record->Mem.Base + Record->Mem.Length;
+ if (Resource->Mem.RWXAttributes != Record->Mem.RWXAttributes) {
+ if ((ResourceLo == RecordLo) && (ResourceHi == RecordHi)) {
+ Record->Mem.RWXAttributes = Resource->Mem.RWXAttributes | Record->Mem.RWXAttributes;
+ return true;
+ } else {
+ return false;
+ }
+ }
+ break;
+ case IO_RANGE:
+ case TRAPPED_IO_RANGE:
+ ResourceLo = (uint64_t) Resource->Io.Base;
+ ResourceHi = (uint64_t) Resource->Io.Base + (uint64_t) Resource->Io.Length;
+ RecordLo = (uint64_t) Record->Io.Base;
+ RecordHi = (uint64_t) Record->Io.Base + (uint64_t) Record->Io.Length;
+ break;
+ case PCI_CFG_RANGE:
+ if ((Resource->PciCfg.OriginatingBusNumber != Record->PciCfg.OriginatingBusNumber) ||
+ (Resource->PciCfg.LastNodeIndex != Record->PciCfg.LastNodeIndex)) {
+ return false;
+ }
+ if (memcmp (Resource->PciCfg.PciDevicePath, Record->PciCfg.PciDevicePath, sizeof(STM_PCI_DEVICE_PATH_NODE) * (Resource->PciCfg.LastNodeIndex + 1)) != 0) {
+ return false;
+ }
+ ResourceLo = (uint64_t) Resource->PciCfg.Base;
+ ResourceHi = (uint64_t) Resource->PciCfg.Base + (uint64_t) Resource->PciCfg.Length;
+ RecordLo = (uint64_t) Record->PciCfg.Base;
+ RecordHi = (uint64_t) Record->PciCfg.Base + (uint64_t) Record->PciCfg.Length;
+ if (Resource->PciCfg.RWAttributes != Record->PciCfg.RWAttributes) {
+ if ((ResourceLo == RecordLo) && (ResourceHi == RecordHi)) {
+ Record->PciCfg.RWAttributes = Resource->PciCfg.RWAttributes | Record->PciCfg.RWAttributes;
+ return true;
+ } else {
+ return false;
+ }
+ }
+ break;
+ case MACHINE_SPECIFIC_REG:
+ //
+ // Special case - merge MSR masks in place.
+ //
+ if (Resource->Msr.MsrIndex != Record->Msr.MsrIndex) {
+ return false;
+ }
+ Record->Msr.ReadMask |= Resource->Msr.ReadMask;
+ Record->Msr.WriteMask |= Resource->Msr.WriteMask;
+ return true;
+ default:
+ return false;
+ }
+ //
+ // If resources are disjoint
+ //
+ if ((ResourceHi < RecordLo) || (ResourceLo > RecordHi)) {
+ return false;
+ }
+
+ //
+ // If resource is consumed by record.
+ //
+ if ((ResourceLo >= RecordLo) && (ResourceHi <= RecordHi)) {
+ return true;
+ }
+ //
+ // Resources are overlapping.
+ // Resource and record are merged.
+ //
+ ResourceLo = (ResourceLo < RecordLo) ? ResourceLo : RecordLo;
+ ResourceHi = (ResourceHi > RecordHi) ? ResourceHi : RecordHi;
+
+ switch (Resource->Header.RscType) {
+ case MEM_RANGE:
+ case MMIO_RANGE:
+ Record->Mem.Base = ResourceLo;
+ Record->Mem.Length = ResourceHi - ResourceLo;
+ break;
+ case IO_RANGE:
+ case TRAPPED_IO_RANGE:
+ Record->Io.Base = (uint64_t) ResourceLo;
+ Record->Io.Length = (uint64_t) (ResourceHi - ResourceLo);
+ break;
+ case PCI_CFG_RANGE:
+ Record->PciCfg.Base = (uint64_t) ResourceLo;
+ Record->PciCfg.Length = (uint64_t) (ResourceHi - ResourceLo);
+ break;
+ default:
+ return false;
+ }
+
+ return true;
+}
+
+/**
+
+ Add resource node.
+
+ @param Resource A pointer to resource node to be added
+
+**/
+void AddSingleResource(STM_RSC *Resource)
+{
+ STM_RSC *Record;
+
+ Record = (STM_RSC *)mStmResourcesPtr;
+
+ while (true) {
+ if (Record->Header.RscType == END_OF_RESOURCES) {
+ break;
+ }
+ //
+ // Go to next record if resource and record types don't match.
+ //
+ if (Resource->Header.RscType != Record->Header.RscType) {
+ Record = (STM_RSC *)((void *)Record + Record->Header.Length);
+ continue;
+ }
+ //
+ // Record is handled inside of procedure - don't adjust.
+ //
+ if (HandleSingleResource (Resource, Record)) {
+ return ;
+ }
+ Record = (STM_RSC *)((void *)Record + Record->Header.Length);
+ }
+
+ //
+ // Add resource to the end of area.
+ //
+ memcpy (
+ mStmResourcesPtr + mStmResourceSizeUsed - sizeof(mRscEndNode),
+ Resource,
+ Resource->Header.Length
+ );
+ memcpy (
+ mStmResourcesPtr + mStmResourceSizeUsed - sizeof(mRscEndNode) + Resource->Header.Length,
+ &mRscEndNode,
+ sizeof(mRscEndNode)
+ );
+ mStmResourceSizeUsed += Resource->Header.Length;
+ mStmResourceSizeAvailable = mStmResourceTotalSize - mStmResourceSizeUsed;
+
+ return ;
+}
+
+/**
+
+ Add resource list.
+
+ @param ResourceList A pointer to resource list to be added
+ @param NumEntries Optional number of entries.
+ If 0, list must be terminated by END_OF_RESOURCES.
+
+**/
+void AddResource(STM_RSC *ResourceList, uint32_t NumEntries)
+{
+ uint32_t Count;
+ UINTN Index;
+ STM_RSC *Resource;
+
+ if (NumEntries == 0) {
+ Count = 0xFFFFFFFF;
+ } else {
+ Count = NumEntries;
+ }
+
+ Resource = ResourceList;
+
+ for (Index = 0; Index < Count; Index++) {
+ if (Resource->Header.RscType == END_OF_RESOURCES) {
+ return ;
+ }
+ AddSingleResource (Resource);
+ Resource = (STM_RSC *)((void *)Resource + Resource->Header.Length);
+ }
+ return ;
+}
+
+/**
+
+ Validate resource list.
+
+ @param ResourceList A pointer to resource list to be added
+ @param NumEntries Optional number of entries.
+ If 0, list must be terminated by END_OF_RESOURCES.
+
+ @retval true resource valid
+ @retval false resource invalid
+
+**/
+bool
+ValidateResource (
+ STM_RSC *ResourceList,
+ uint32_t NumEntries
+ )
+{
+ uint32_t Count;
+ UINTN Index;
+ STM_RSC *Resource;
+ UINTN SubIndex;
+
+ //
+ // If NumEntries == 0 make it very big. Scan will be terminated by
+ // END_OF_RESOURCES.
+ //
+ if (NumEntries == 0) {
+ Count = 0xFFFFFFFF;
+ } else {
+ Count = NumEntries;
+ }
+
+ //
+ // Start from beginning of resource list.
+ //
+ Resource = ResourceList;
+
+ for (Index = 0; Index < Count; Index++) {
+ printk(BIOS_DEBUG, "ValidateResource (%llu) - RscType(%x)\n", Index, Resource->Header.RscType);
+ //
+ // Validate resource.
+ //
+ switch (Resource->Header.RscType) {
+ case END_OF_RESOURCES:
+ if (Resource->Header.Length != sizeof (STM_RSC_END)) {
+ return false;
+ }
+ //
+ // If we are passed actual number of resources to add,
+ // END_OF_RESOURCES structure between them is considered an
+ // error. If NumEntries == 0 END_OF_RESOURCES is a termination.
+ //
+ if (NumEntries != 0) {
+ return false;
+ } else {
+ //
+ // If NumEntries == 0 and list reached end - return success.
+ //
+ return true;
+ }
+ break;
+
+ case MEM_RANGE:
+ case MMIO_RANGE:
+ if (Resource->Header.Length != sizeof (STM_RSC_MEM_DESC)) {
+ return false;
+ }
+
+ if (Resource->Mem.RWXAttributes > FULL_ACCS) {
+ return false;
+ }
+ break;
+
+ case IO_RANGE:
+ case TRAPPED_IO_RANGE:
+ if (Resource->Header.Length != sizeof (STM_RSC_IO_DESC)) {
+ return false;
+ }
+
+ if ((Resource->Io.Base + Resource->Io.Length) > 0xFFFF) {
+ return false;
+ }
+ break;
+
+ case PCI_CFG_RANGE:
+ printk(BIOS_DEBUG, "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);
+ if (Resource->Header.Length != sizeof (STM_RSC_PCI_CFG_DESC) + (sizeof(STM_PCI_DEVICE_PATH_NODE) * Resource->PciCfg.LastNodeIndex)) {
+ return false;
+ }
+ for (SubIndex = 0; SubIndex <= Resource->PciCfg.LastNodeIndex; SubIndex++) {
+ if ((Resource->PciCfg.PciDevicePath[SubIndex].PciDevice > 0x1F) || (Resource->PciCfg.PciDevicePath[SubIndex].PciFunction > 7)) {
+ return false;
+ }
+ }
+ if ((Resource->PciCfg.Base + Resource->PciCfg.Length) > 0x1000) {
+ return false;
+ }
+ break;
+
+ case MACHINE_SPECIFIC_REG:
+ if (Resource->Header.Length != sizeof (STM_RSC_MSR_DESC)) {
+ return false;
+ }
+ break;
+
+ default :
+ printk(BIOS_DEBUG, "ValidateResource - Unknown RscType(%x)\n", Resource->Header.RscType);
+ return false;
+ }
+ Resource = (STM_RSC *)((void *)Resource + Resource->Header.Length);
+ }
+ return true;
+}
+
+/**
+
+ Get resource list.
+ EndResource is excluded.
+
+ @param ResourceList A pointer to resource list to be added
+ @param NumEntries Optional number of entries.
+ If 0, list must be terminated by END_OF_RESOURCES.
+
+ @retval true resource valid
+ @retval false resource invalid
+
+**/
+UINTN
+GetResourceSize (
+ STM_RSC *ResourceList,
+ uint32_t NumEntries
+ )
+{
+ uint32_t Count;
+ UINTN Index;
+ STM_RSC *Resource;
+
+ Resource = ResourceList;
+
+ //
+ // If NumEntries == 0 make it very big. Scan will be terminated by
+ // END_OF_RESOURCES.
+ //
+ if (NumEntries == 0) {
+ Count = 0xFFFFFFFF;
+ } else {
+ Count = NumEntries;
+ }
+
+ //
+ // Start from beginning of resource list.
+ //
+ Resource = ResourceList;
+
+ for (Index = 0; Index < Count; Index++) {
+ if (Resource->Header.RscType == END_OF_RESOURCES) {
+ break;
+ }
+ Resource = (STM_RSC *)((void *)Resource + Resource->Header.Length);
+ }
+ return (UINTN)((uint32_t)Resource - (uint32_t) ResourceList);
+}
+
+/**
+
+ Add resources in list to database. Allocate new memory areas as needed.
+
+ @param ResourceList A pointer to resource list to be added
+ @param NumEntries Optional number of entries.
+ If 0, list must be terminated by END_OF_RESOURCES.
+
+ @retval EFI_SUCCESS If resources are added
+ @retval EFI_INVALID_PARAMETER If nested procedure detected resource failer
+ @retval EFI_OUT_OF_RESOURCES If nested procedure returned it and we cannot allocate more areas.
+
+**/
+int
+AddPiResource (
+ STM_RSC *ResourceList,
+ uint32_t NumEntries
+ )
+{
+ //int Status;
+ UINTN ResourceSize;
+ //void * NewResource;
+ //UINTN NewResourceSize;
+
+ printk (BIOS_DEBUG, "AddPiResource - Enter\n");
+
+ if (!ValidateResource (ResourceList, NumEntries)) {
+ return -1; //EFI_INVALID_PARAMETER;
+ }
+
+ ResourceSize = GetResourceSize (ResourceList, NumEntries);
+ printk (BIOS_DEBUG, "ResourceSize - 0x%08llx\n", ResourceSize);
+ if (ResourceSize == 0) {
+ return -1;//EFI_INVALID_PARAMETER;
+ }
+
+ if (mStmResourcesPtr == NULL) {
+ //
+ // Copy EndResource for intialization
+ //
+ //mStmResourcesPtr = (uint8_t *)(UINTN)NewResource;
+ //mStmResourceTotalSize = NewResourceSize;
+
+ mStmResourcesPtr = StmResourceHeap;
+ mStmResourceTotalSize = RESOURCEHEAPSIZE;
+ memset(mStmResourcesPtr, 0, RESOURCEHEAPSIZE);
+
+ memcpy (mStmResourcesPtr, &mRscEndNode, sizeof(mRscEndNode));
+ mStmResourceSizeUsed = sizeof(mRscEndNode);
+ mStmResourceSizeAvailable = mStmResourceTotalSize - sizeof(mRscEndNode);
+
+ //
+ // Let SmmCore change resource ptr
+ //
+ //NotifyStmResourceChange (mStmResourcesPtr);
+ } else if (mStmResourceSizeAvailable < ResourceSize) {
+ //
+ // Need enlarge
+ //
+ printk(BIOS_DEBUG, "ERROR - not enough soace for SMM resource list\n");
+ return -1;
+ }
+
+ //
+ // Check duplication
+ //
+ AddResource (ResourceList, NumEntries);
+
+ return 0;//EFI_SUCCESS;
+}
+
+/**
+
+ Delete resources in list to database.
+
+ @param ResourceList A pointer to resource list to be deleted
+ NULL means delete all resources.
+ @param NumEntries Optional number of entries.
+ If 0, list must be terminated by END_OF_RESOURCES.
+
+ @retval EFI_SUCCESS If resources are deleted
+ @retval EFI_INVALID_PARAMETER If nested procedure detected resource failer
+
+**/
+int32_t
+DeletePiResource (
+ STM_RSC *ResourceList,
+ uint32_t NumEntries
+ )
+{
+ if (ResourceList != NULL) {
+ // TBD
+ //ASSERT (false);
+ return -1;//EFI_UNSUPPORTED;
+ }
+ //
+ // Delete all
+ //
+ memcpy (mStmResourcesPtr, &mRscEndNode, sizeof(mRscEndNode));
+ mStmResourceSizeUsed = sizeof(mRscEndNode);
+ mStmResourceSizeAvailable = mStmResourceTotalSize - sizeof(mRscEndNode);
+ return 0;//EFI_SUCCESS;
+}
+
+/**
+
+ Get BIOS resources.
+
+ @param ResourceList A pointer to resource list to be filled
+ @param ResourceSize On input it means size of resource list input.
+ On output it means size of resource list filled,
+ or the size of resource list to be filled if size of too small.
+
+ @retval EFI_SUCCESS If resources are returned.
+ @retval EFI_BUFFER_TOO_SMALL If resource list buffer is too small to hold the whole resources.
+
+**/
+int32_t
+GetPiResource (
+ STM_RSC *ResourceList,
+ uint32_t *ResourceSize
+ )
+{
+ if (*ResourceSize < mStmResourceSizeUsed) {
+ *ResourceSize = (uint32_t)mStmResourceSizeUsed;
+ return -1;//EFI_BUFFER_TOO_SMALL;
+ }
+
+ memcpy (ResourceList, mStmResourcesPtr, mStmResourceSizeUsed);
+ *ResourceSize = (uint32_t)mStmResourceSizeUsed;
+ return 0;//EFI_SUCCESS;
+}
+
+/**
+ Get 4K page aligned VMCS size.
+ @return 4K page aligned VMCS size
+
+**/
+uint32_t
+GetVmcsSize (
+ void
+ )
+{
+ uint32_t ThisVmcsSize;
+ VMX_BASIC_MSR MsrData64;
+ int StmSupport;
+
+ MsrData64.msr = rdmsr (IA32_VMX_BASIC_MSR_INDEX);
+
+ ThisVmcsSize = MsrData64.bits.VmcsSize;
+ StmSupport = MsrData64.bits.StmSupported;
+ printk(BIOS_DEBUG, "GetVmcsSize: Size %d StmSupport %d\n", ThisVmcsSize, StmSupport);
+
+ //
+ // VMCS require 0x1000 alignment
+ //
+ ThisVmcsSize = STM_PAGES_TO_SIZE (STM_SIZE_TO_PAGES (ThisVmcsSize));
+
+ return ThisVmcsSize;
+}
+
+/**
+
+ Create 4G page table for STM.
+ 4M Non-PAE page table in IA32 version.
+
+ @param PageTableBase The page table base in MSEG
+
+**/
+void
+StmGen4GPageTableIa32 (
+ uint32_t PageTableBase
+ )
+{
+ UINTN Index;
+ uint32_t *Pte;
+ uint32_t Address;
+
+ Pte = (uint32_t*)(uint32_t)PageTableBase;
+
+ Address = 0;
+ for (Index = 0; Index < SIZE_4KB / sizeof (*Pte); Index++) {
+ *Pte = Address | IA32_PG_PS | IA32_PG_RW | IA32_PG_P;
+ Pte++;
+ Address += SIZE_4MB;
+ }
+
+ return ;
+}
+
+/**
+
+ Create 4G page table for STM.
+ 2M PAE page table in X64 version.
+
+ @param PageTableBase The page table base in MSEG
+
+**/
+void
+StmGen4GPageTableX64 (
+ uint32_t PageTableBase
+ )
+{
+ UINTN Index;
+ UINTN SubIndex;
+ uint64_t *Pde;
+ uint64_t *Pte;
+ uint64_t *Pml4;
+
+ Pml4 = (uint64_t*)(uint32_t) PageTableBase;
+ PageTableBase += SIZE_4KB;
+ *Pml4 = PageTableBase | IA32_PG_RW | IA32_PG_P;
+
+ Pde = (uint64_t*)(uint32_t)PageTableBase;
+ PageTableBase += SIZE_4KB;
+ Pte = (uint64_t *)(uint32_t)PageTableBase;
+
+ for (Index = 0; Index < 4; Index++) {
+ *Pde = PageTableBase | IA32_PG_RW | IA32_PG_P;
+ Pde++;
+ PageTableBase += SIZE_4KB;
+
+ for (SubIndex = 0; SubIndex < SIZE_4KB / sizeof (*Pte); SubIndex++) {
+ *Pte = (((Index << 9) + SubIndex) << 21) | IA32_PG_PS | IA32_PG_RW | IA32_PG_P;
+ Pte++;
+ }
+ }
+
+ return ;
+}
+
+/**
+
+ Check STM image size.
+
+ @param StmImage STM image
+ @param StmImageSize STM image size
+
+ @retval true check pass
+ @retval false check fail
+**/
+
+bool StmCheckStmImage (
+ void * StmImage,
+ uint32_t StmImageSize
+ )
+{
+ UINTN MinMsegSize;
+ STM_HEADER *StmHeader;
+
+ StmHeader = (STM_HEADER *)StmImage;
+
+ //
+ // Get Minimal required Mseg size
+ //
+ MinMsegSize = (STM_PAGES_TO_SIZE (STM_SIZE_TO_PAGES (StmHeader->SwStmHdr.StaticImageSize)) +
+ StmHeader->SwStmHdr.AdditionalDynamicMemorySize +
+ (StmHeader->SwStmHdr.PerProcDynamicMemorySize + GetVmcsSize () * 2) * mp_state.cpu_count);
+ if (MinMsegSize < StmImageSize) {
+ MinMsegSize = StmImageSize;
+ }
+
+ if (StmHeader->HwStmHdr.Cr3Offset >= StmHeader->SwStmHdr.StaticImageSize) {
+ //
+ // We will create page table, just in case that SINIT does not create it.
+ //
+ if (MinMsegSize < StmHeader->HwStmHdr.Cr3Offset + STM_PAGES_TO_SIZE(6)) {
+ MinMsegSize = StmHeader->HwStmHdr.Cr3Offset + STM_PAGES_TO_SIZE(6);
+ }
+ }
+
+ //
+ // Check if it exceeds MSEG size
+ //
+ if (MinMsegSize > CONFIG_MSEG_SIZE) {
+ return false;
+ }
+
+ return true;
+
+}
+
+
+/**
+
+ Load STM image to MSEG.
+
+ @param StmImage STM image
+ @param StmImageSize STM image size
+
+**/
+void
+StmLoadStmImage (
+ void * StmImage,
+ UINTN StmImageSize
+ )
+{
+ uint32_t MsegBase;
+ STM_HEADER *StmHeader;
+ SMM_MONITOR_CTL_MSR SmmMonitorMsr;
+
+ StmHeader = (STM_HEADER *)(uint32_t)StmImage;
+ SmmMonitorMsr.msr = rdmsr(IA32_SMM_MONITOR_CTL_MSR_INDEX);
+ MsegBase = SmmMonitorMsr.bits.MsegAddress << 12;
+
+ //ZeroMem ((void *)(uint32_t)MsegBase, (uint32_t)PcdGet32 (PcdCpuMsegSize));
+
+ memset((void *) MsegBase, 0, CONFIG_MSEG_SIZE);
+ //memcpy ((void *)(uint32_t)MsegBase, (void *)(uint32_t)StmImage, StmImageSize);
+ memcpy((void *) MsegBase, (void *) StmImage, (size_t) StmImageSize);
+
+
+ if (sizeof(UINTN) == sizeof(uint64_t)) {
+ StmGen4GPageTableX64 ((UINTN)MsegBase + StmHeader->HwStmHdr.Cr3Offset);
+ } else {
+ StmGen4GPageTableIa32 ((UINTN)MsegBase + StmHeader->HwStmHdr.Cr3Offset);
+ }
+
+ // BUGBUG: SNB can not write 0x9B twice
+// WriteCpuMsegInfo ();
+}
+
+/**
+
+ Load STM image to MSEG.
+
+ @param StmImage STM image
+ @param StmImageSize STM image size
+
+ @retval EFI_SUCCESS Load STM to MSEG successfully
+ @retval EFI_ALREADY_STARTED STM image is already loaded to MSEG
+ @retval EFI_BUFFER_TOO_SMALL MSEG is smaller than minimal requirement of STM image
+ @retval EFI_UNSUPPORTED MSEG is not enabled
+
+**/
+int LoadMonitor (
+ void * StmImage,
+ uint32_t StmImageSize
+ )
+{
+ SMM_MONITOR_CTL_MSR SmmMonCtlMsr;
+
+ SmmMonCtlMsr.msr = (msr_t) rdmsr(IA32_SMM_MONITOR_CTL_MSR_INDEX);
+
+ if (SmmMonCtlMsr.bits.MsegAddress == 0) {
+ return STM_UNSUPPORTED;
+ }
+ if (SmmMonCtlMsr.bits.valid != 0) {
+ // BUGBUG: SNB can not write 0x9B twice
+// return EFI_ALREADY_STARTED;
+ }
+
+ if (!StmCheckStmImage (StmImage, StmImageSize)) {
+ return STM_BUFFER_TOO_SMALL;
+ }
+
+#ifdef TPMSUPPORT
+ // Record STM_HASH to PCR 0, just in case it is NOT TXT launch, we still need provide the evidence.
+ TpmMeasureAndLogData(
+ 0, // PcrIndex
+ TXT_EVTYPE_STM_HASH, // EventType
+ NULL, // EventLog
+ 0, // LogLen
+ (void *)StmImage, // HashData
+ StmImageSize // HashDataLen
+ );
+#endif
+ StmLoadStmImage (StmImage, StmImageSize);
+
+ mStmState |= STM_SM_MONITOR_STATE_ENABLED;
+
+ return STM_SUCCESS;
+}
+
+/**
+ This function return BIOS STM resource.
+ Produced by SmmStm.
+ Comsumed by SmmMpService when Init.
+
+ @return BIOS STM resource
+**/
+void *
+GetStmResource(
+ void
+ )
+{
+ return mStmResourcesPtr;
+}
+
diff --git a/src/security/intel/stm/SmmStm.h b/src/security/intel/stm/SmmStm.h
new file mode 100644
index 0000000..4442a63
--- /dev/null
+++ b/src/security/intel/stm/SmmStm.h
@@ -0,0 +1,122 @@
+/** @file
+ SMM STM support
+
+ Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.
+ This program and the accompanying materials are licensed and made
+ available under the terms and conditions of the BSD License which
+ accompanies this distribution. The full text of the license may
+ be found at http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED
+
+**/
+
+#ifndef _SMM_STM_H_
+#define _SMM_STM_H_
+
+#include "StmApi.h"
+
+#define IA32_VMX_BASIC_MSR_INDEX 0x480
+#define IA32_VMX_MISC_MSR_INDEX 0x485
+#define IA32_SMM_MONITOR_CTL_MSR_INDEX 0x9B
+#define IA32_SMM_MONITOR_VALID (1<<0)
+
+/**
+
+ Load STM image to MSEG.
+
+ @param StmImage STM image
+ @param StmImageSize STM image size
+
+ @retval SUCCESS Load STM to MSEG successfully
+ @retval BUFFER_TOO_SMALL MSEG is smaller than minimal size of STM image
+
+**/
+int LoadMonitor(
+ void *StmImage,
+ uint32_t StmImageSize
+ );
+
+/**
+
+ Add resources in list to database. Allocate new memory areas as needed.
+
+ @param ResourceList A pointer to resource list to be added
+ @param NumEntries Optional number of entries.
+ If 0, list must be terminated by END_OF_RESOURCES.
+
+ @retval SUCCESS If resources are added
+ @retval INVALID_PARAMETER If nested procedure detected resource failer
+ @retval OUT_OF_RESOURCES If nested procedure returned it and we cannot allocate more areas.
+
+**/
+int AddPiResource(
+ STM_RSC *ResourceList,
+ uint32_t NumEntries
+ );
+
+/**
+
+ Delete resources in list to database.
+
+ @param ResourceList A pointer to resource list to be deleted
+ NULL means delete all resources.
+ @param NumEntries Optional number of entries.
+ If 0, list must be terminated by END_OF_RESOURCES.
+
+ @retval SUCCESS If resources are deleted
+ @retval NVALID_PARAMETER If nested procedure detected resource failer
+
+**/
+int DeletePiResource(
+ STM_RSC *ResourceList,
+ uint32_t NumEntries
+ );
+
+/**
+
+ Get BIOS resources.
+
+ @param ResourceList A pointer to resource list to be filled
+ @param ResourceSize On input it means size of resource list input.
+ On output it means size of resource list filled,
+ or the size of resource list to be filled if
+ size of too small.
+
+ @retval SUCCESS If resources are returned.
+ @retval BUFFER_TOO_SMALL If resource list buffer is too small to
+ hold the whole resources.
+
+**/
+int GetPiResource(
+ STM_RSC *ResourceList,
+ uint32_t *ResourceSize
+ );
+
+/**
+ This function notify STM resource change.
+
+ @param StmResource BIOS STM resource
+
+**/
+void
+NotifyStmResourceChange(
+ void *StmResource
+ );
+
+/**
+ This function return BIOS STM resource.
+
+ @return BIOS STM resource
+
+**/
+void *
+GetStmResource(
+ void
+ );
+
+void SetupSmmDescriptor(void *smbase, int32_t state_size, int32_t apic_id,
+ int32_t entry32_off);
+
+#endif
diff --git a/src/security/intel/stm/StmApi.h b/src/security/intel/stm/StmApi.h
new file mode 100644
index 0000000..2328b32
--- /dev/null
+++ b/src/security/intel/stm/StmApi.h
@@ -0,0 +1,753 @@
+/** @file
+ STM API definition
+
+ Copyright (c) 2015, Intel Corporation. All rights reserved.
+ This program and the accompanying materials are licensed and made available
+ under the terms and conditions of the BSD License which accompanies this
+ distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _STM_API_H_
+#define _STM_API_H_
+
+#include <stdint.h>
+
+// definition in STM spec
+
+#define STM_SPEC_VERSION_MAJOR 1
+#define STM_SPEC_VERSION_MINOR 0
+
+typedef uint64_t UINTN;
+
+#pragma pack (push, 1)
+
+#define STM_HARDWARE_FIELD_FILL_TO_2K (2048 - sizeof(uint32_t) * 8)
+typedef struct {
+ uint32_t StmHeaderRevision;
+ uint32_t MonitorFeatures;
+ uint32_t GdtrLimit;
+ uint32_t GdtrBaseOffset;
+ uint32_t CsSelector;
+ uint32_t EipOffset;
+ uint32_t EspOffset;
+ uint32_t Cr3Offset;
+ uint8_t Reserved[STM_HARDWARE_FIELD_FILL_TO_2K];
+} HARDWARE_STM_HEADER;
+
+#define STM_FEATURES_IA32E 0x1
+
+typedef struct {
+ uint32_t Intel64ModeSupported :1; // bitfield
+ uint32_t EptSupported :1; // bitfield
+ uint32_t Reserved :30; // must be 0
+} STM_FEAT;
+
+typedef struct {
+ uint8_t StmSpecVerMajor;
+ uint8_t StmSpecVerMinor;
+ uint16_t Reserved; // must be zero
+ uint32_t StaticImageSize;
+ uint32_t PerProcDynamicMemorySize;
+ uint32_t AdditionalDynamicMemorySize;
+ STM_FEAT StmFeatures;
+ uint32_t NumberOfRevIDs;
+ uint32_t StmSmmRevID[1];
+ //
+ // The total STM_HEADER should be 4K.
+ //
+} SOFTWARE_STM_HEADER;
+
+typedef struct {
+ HARDWARE_STM_HEADER HwStmHdr;
+ SOFTWARE_STM_HEADER SwStmHdr;
+} STM_HEADER;
+
+#define SHA1 1
+#define SHA256 2
+typedef struct {
+ uint64_t BiosComponentBase;
+ uint32_t ImageSize;
+ uint32_t HashAlgorithm; // SHA1 or SHA256
+ uint8_t Hash[32];
+} TXT_BIOS_COMPONENT_STATUS;
+
+#define PAGE_SIZE 4096
+typedef struct {
+ uint32_t ImageSize;
+ uint32_t Reserved;
+ uint64_t ImagePageBase[1]; //[NumberOfPages];
+} TXT_BIOS_COMPONENT_UPDATE;
+
+// If (ImageSizeInBytes % PAGE_SIZE == 0) {
+// NumberOfPages = ImageSizeInBytes / PAGE_SIZE
+// } else {
+// NumberOfPages = ImageSizeInBytes / PAGE_SIZE + 1
+// }
+
+
+typedef struct {
+ uint64_t SpeRip;
+ uint64_t SpeRsp;
+ uint16_t SpeSs;
+ uint16_t PageViolationException:1;
+ uint16_t MsrViolationException:1;
+ uint16_t RegisterViolationException:1;
+ uint16_t IoViolationException:1;
+ uint16_t PciViolationException:1;
+ uint16_t Reserved1:11;
+ uint32_t Reserved2;
+} STM_PROTECTION_EXCEPTION_HANDLER;
+
+typedef struct {
+ uint8_t ExecutionDisableOutsideSmrr:1;
+ uint8_t Intel64Mode:1;
+ uint8_t Cr4Pae : 1;
+ uint8_t Cr4Pse : 1;
+ uint8_t Reserved1 : 4;
+} STM_SMM_ENTRY_STATE;
+
+typedef struct {
+ uint8_t SmramToVmcsRestoreRequired : 1; // BIOS restore hint
+ uint8_t ReinitializeVmcsRequired : 1; // BIOS request
+ uint8_t Reserved2 : 6;
+} STM_SMM_RESUME_STATE;
+
+typedef struct {
+ uint8_t DomainType : 4; // STM input to BIOS on each SM
+ uint8_t XStatePolicy : 2; // STM input to BIOS on each SMI
+ uint8_t EptEnabled : 1;
+ uint8_t Reserved3 : 1;
+} STM_SMM_STATE;
+
+typedef struct {
+ uint64_t Signature;
+ uint16_t Size;
+ uint8_t SmmDescriptorVerMajor;
+ uint8_t SmmDescriptorVerMinor;
+ uint32_t LocalApicId;
+ STM_SMM_ENTRY_STATE SmmEntryState;
+ STM_SMM_RESUME_STATE SmmResumeState;
+ STM_SMM_STATE StmSmmState;
+ uint8_t Reserved4;
+ uint16_t SmmCs;
+ uint16_t SmmDs;
+ uint16_t SmmSs;
+ uint16_t SmmOtherSegment;
+ uint16_t SmmTr;
+ uint16_t Reserved5;
+ uint64_t SmmCr3;
+ uint64_t SmmStmSetupRip;
+ uint64_t SmmStmTeardownRip;
+ uint64_t SmmSmiHandlerRip;
+ uint64_t SmmSmiHandlerRsp;
+ uint64_t SmmGdtPtr;
+ uint32_t SmmGdtSize;
+ uint32_t RequiredStmSmmRevId;
+ STM_PROTECTION_EXCEPTION_HANDLER StmProtectionExceptionHandler;
+ uint64_t Reserved6;
+ uint64_t BiosHwResourceRequirementsPtr;
+ // extend area
+ uint64_t AcpiRsdp;
+ uint8_t PhysicalAddressBits;
+} TXT_PROCESSOR_SMM_DESCRIPTOR;
+
+#define TXT_PROCESSOR_SMM_DESCRIPTOR_SIGNATURE "TXTPSSIG"
+#define TXT_PROCESSOR_SMM_DESCRIPTOR_VERSION_MAJOR 1
+#define TXT_PROCESSOR_SMM_DESCRIPTOR_VERSION_MINOR 0
+
+#define SMM_PSD_OFFSET 0xfb00
+
+typedef enum {
+ TxtSmmPageViolation = 1,
+ TxtSmmMsrViolation,
+ TxtSmmRegisterViolation,
+ TxtSmmIoViolation,
+ TxtSmmPciViolation
+} TXT_SMM_PROTECTION_EXCEPTION_TYPE;
+
+typedef struct {
+ uint32_t Rdi;
+ uint32_t Rsi;
+ uint32_t Rbp;
+ uint32_t Rdx;
+ uint32_t Rcx;
+ uint32_t Rbx;
+ uint32_t Rax;
+ uint32_t Cr3;
+ uint32_t Cr2;
+ uint32_t Cr0;
+ uint32_t VmcsExitInstructionInfo;
+ uint32_t VmcsExitInstructionLength;
+ uint64_t VmcsExitQualification;
+ uint32_t ErrorCode; // TXT_SMM_PROTECTION_EXCEPTION_TYPE
+ uint32_t Rip;
+ uint32_t Cs;
+ uint32_t Rflags;
+ uint32_t Rsp;
+ uint32_t Ss;
+} STM_PROTECTION_EXCEPTION_STACK_FRAME_IA32;
+
+typedef struct {
+ uint64_t R15;
+ uint64_t R14;
+ uint64_t R13;
+ uint64_t R12;
+ uint64_t R11;
+ uint64_t R10;
+ uint64_t R9;
+ uint64_t R8;
+ uint64_t Rdi;
+ uint64_t Rsi;
+ uint64_t Rbp;
+ uint64_t Rdx;
+ uint64_t Rcx;
+ uint64_t Rbx;
+ uint64_t Rax;
+ uint64_t Cr8;
+ uint64_t Cr3;
+ uint64_t Cr2;
+ uint64_t Cr0;
+ uint64_t VmcsExitInstructionInfo;
+ uint64_t VmcsExitInstructionLength;
+ uint64_t VmcsExitQualification;
+ uint64_t ErrorCode; // TXT_SMM_PROTECTION_EXCEPTION_TYPE
+ uint64_t Rip;
+ uint64_t Cs;
+ uint64_t Rflags;
+ uint64_t Rsp;
+ uint64_t Ss;
+} STM_PROTECTION_EXCEPTION_STACK_FRAME_X64;
+
+typedef union {
+ STM_PROTECTION_EXCEPTION_STACK_FRAME_IA32 *Ia32StackFrame;
+ STM_PROTECTION_EXCEPTION_STACK_FRAME_X64 *X64StackFrame;
+} STM_PROTECTION_EXCEPTION_STACK_FRAME;
+
+#define STM_SMM_REV_ID 0x80010100
+
+typedef struct _STM_SMM_CPU_STATE {
+ uint8_t Reserved1[0x1d0]; // fc00h
+ uint32_t GdtBaseHiDword; // fdd0h : NO
+ uint32_t LdtBaseHiDword; // fdd4h : NO
+ uint32_t IdtBaseHiDword; // fdd8h : NO
+ uint8_t Reserved2[0x4]; // fddch
+ uint64_t IoRdi; // fde0h : NO
+ // - restricted
+ uint64_t IoEip; // fde8h : YES
+ uint64_t IoRcx; // fdf0h : NO
+ // - restricted
+ uint64_t IoRsi; // fdf8h : NO
+ // - restricted
+ uint8_t Reserved3[0x40]; // fe00h
+ uint32_t Cr4; // fe40h : NO
+ uint8_t Reserved4[0x48]; // fe44h
+ uint32_t GdtBaseLoDword; // fe8ch : NO
+ uint32_t GdtLimit; // fe90h : NO
+ // - RESTRICTED
+ uint32_t IdtBaseLoDword; // fe94h : NO
+ uint32_t IdtLimit; // fe98h : NO
+ // - RESTRICTED
+ uint32_t LdtBaseLoDword; // fe9ch : NO
+ uint32_t LdtLimit; // fea0h : NO
+ // - RESTRICTED
+ uint32_t LdtInfo; // fea4h : NO
+ // - RESTRICTED
+ uint8_t Reserved5[0x30]; // fea8h
+ uint64_t Eptp; // fed8h : NO
+ uint32_t EnabledEPT; // fee0h : NO
+ uint8_t Reserved6[0x14]; // fee4h
+ uint32_t Smbase; // fef8h : YES
+ // - NO for STM
+ uint32_t SMMRevId; // fefch : NO
+ uint16_t IORestart; // ff00h : YES
+ uint16_t AutoHALTRestart; // ff02h : YES
+ uint8_t Reserved7[0x18]; // ff04h
+ uint64_t R15; // ff1ch : YES
+ uint64_t R14; // ff24h : YES
+ uint64_t R13; // ff2ch : YES
+ uint64_t R12; // ff34h : YES
+ uint64_t R11; // ff3ch : YES
+ uint64_t R10; // ff44h : YES
+ uint64_t R9; // ff4ch : YES
+ uint64_t R8; // ff54h : YES
+ uint64_t Rax; // ff5ch : YES
+ uint64_t Rcx; // ff64h : YES
+ uint64_t Rdx; // ff6ch : YES
+ uint64_t Rbx; // ff74h : YES
+ uint64_t Rsp; // ff7ch : YES
+ uint64_t Rbp; // ff84h : YES
+ uint64_t Rsi; // ff8ch : YES
+ uint64_t Rdi; // ff94h : YES
+ uint64_t IOMemAddr; // ff9ch : NO
+ uint32_t IOMisc; // ffa4h : NO
+ uint32_t Es; // ffa8h : NO
+ uint32_t Cs; // ffach : NO
+ uint32_t Ss; // ffb0h : NO
+ uint32_t Ds; // ffb4h : NO
+ uint32_t Fs; // ffb8h : NO
+ uint32_t Gs; // ffbch : NO
+ uint32_t Ldtr; // ffc0h : NO
+ uint32_t Tr; // ffc4h : NO
+ uint64_t Dr7; // ffc8h : NO
+ uint64_t Dr6; // ffd0h : NO
+ uint64_t Rip; // ffd8h : YES
+ uint64_t Ia32Efer; // ffe0h : YES
+ // - NO for STM
+ uint64_t Rflags; // ffe8h : YES
+ uint64_t Cr3; // fff0h : NO
+ uint64_t Cr0; // fff8h : NO
+} STM_SMM_CPU_STATE;
+
+//
+// STM Mapping
+//
+
+typedef struct {
+ uint64_t PhysicalAddress;
+ uint64_t VirtualAddress;
+ uint32_t PageCount;
+ uint32_t PatCacheType;
+} STM_MAP_ADDRESS_RANGE_DESCRIPTOR;
+#define ST_UC 0x00
+#define WC 0x01
+#define WT 0x04
+#define WP 0x05
+#define WB 0x06
+#define UC 0x07
+#define FOLLOW_MTRR 0xFFFFFFFF
+
+typedef struct {
+ uint64_t VirtualAddress;
+ uint32_t Length;
+} STM_UNMAP_ADDRESS_RANGE_DESCRIPTOR;
+
+typedef struct {
+ uint64_t InterruptedGuestVirtualAddress;
+ uint32_t Length;
+ uint64_t InterruptedCr3;
+ uint64_t InterruptedEptp;
+ uint32_t MapToSmmGuest:2;
+ uint32_t InterruptedCr4Pae:1;
+ uint32_t InterruptedCr4Pse:1;
+ uint32_t InterruptedIa32eMode:1;
+ uint32_t Reserved1:27;
+ uint32_t Reserved2;
+ uint64_t PhysicalAddress;
+ uint64_t SmmGuestVirtualAddress;
+} STM_ADDRESS_LOOKUP_DESCRIPTOR;
+#define DO_NOT_MAP 0
+#define ONE_TO_ONE 1
+#define VIRTUAL_ADDRESS_SPECIFIED 3
+
+//
+// STM_RESOURCE_LIST
+//
+#define END_OF_RESOURCES 0
+#define MEM_RANGE 1
+#define IO_RANGE 2
+#define MMIO_RANGE 3
+#define MACHINE_SPECIFIC_REG 4
+#define PCI_CFG_RANGE 5
+#define TRAPPED_IO_RANGE 6
+#define ALL_RESOURCES 7
+#define REGISTER_VIOLATION 8
+#define MAX_DESC_TYPE 8
+
+typedef struct {
+ uint32_t RscType;
+ uint16_t Length;
+ uint16_t ReturnStatus:1;
+ uint16_t Reserved:14;
+ uint16_t IgnoreResource:1;
+} STM_RSC_DESC_HEADER;
+
+typedef struct {
+ STM_RSC_DESC_HEADER Hdr;
+ uint64_t ResourceListContinuation;
+} STM_RSC_END;
+
+// byte granular Memory range support
+#define STM_RSC_BGM 0x4
+
+typedef struct {
+ STM_RSC_DESC_HEADER Hdr;
+ uint64_t Base;
+ uint64_t Length;
+ uint32_t RWXAttributes:3;
+ uint32_t Reserved:29;
+ uint32_t Reserved_2;
+} STM_RSC_MEM_DESC;
+#define STM_RSC_MEM_R 0x1
+#define STM_RSC_MEM_W 0x2
+#define STM_RSC_MEM_X 0x4
+
+typedef struct {
+ STM_RSC_DESC_HEADER Hdr;
+ uint16_t Base;
+ uint16_t Length;
+ uint32_t Reserved;
+} STM_RSC_IO_DESC;
+
+// byte granular MMIO range support
+#define STM_RSC_BGI 0x2
+
+typedef struct {
+ STM_RSC_DESC_HEADER Hdr;
+ uint64_t Base;
+ uint64_t Length;
+ uint32_t RWXAttributes:3;
+ uint32_t Reserved:29;
+ uint32_t Reserved_2;
+} STM_RSC_MMIO_DESC;
+#define STM_RSC_MMIO_R 0x1
+#define STM_RSC_MMIO_W 0x2
+#define STM_RSC_MMIO_X 0x4
+
+typedef struct {
+ STM_RSC_DESC_HEADER Hdr;
+ uint32_t MsrIndex;
+ uint32_t KernelModeProcessing:1;
+ uint32_t Reserved:31;
+ uint64_t ReadMask;
+ uint64_t WriteMask;
+} STM_RSC_MSR_DESC;
+
+// bit granular MSR resource support
+#define STM_RSC_MSR 0x8
+
+typedef struct {
+ uint8_t Type; // must be 1, indicating Hardware Device Path
+ uint8_t Subtype; // must be 1, indicating PCI
+ uint16_t Length; // sizeof(STM_PCI_DEVICE_PATH_NODE) which is 6
+ uint8_t PciFunction;
+ uint8_t PciDevice;
+} STM_PCI_DEVICE_PATH_NODE;
+typedef struct {
+ STM_RSC_DESC_HEADER Hdr;
+ uint16_t RWAttributes:2;
+ uint16_t Reserved:14;
+ uint16_t Base;
+ uint16_t Length;
+ uint8_t OriginatingBusNumber;
+ uint8_t LastNodeIndex;
+ STM_PCI_DEVICE_PATH_NODE PciDevicePath[1];
+//STM_PCI_DEVICE_PATH_NODE PciDevicePath[LastNodeIndex + 1];
+} STM_RSC_PCI_CFG_DESC;
+
+#define STM_RSC_PCI_CFG_R 0x1
+#define STM_RSC_PCI_CFG_W 0x2
+
+typedef struct {
+ STM_RSC_DESC_HEADER Hdr;
+ uint16_t Base;
+ uint16_t Length;
+ uint16_t In:1;
+ uint16_t Out:1;
+ uint16_t Api:1;
+ uint16_t Reserved1:13;
+ uint16_t Reserved2;
+} STM_RSC_TRAPPED_IO_DESC;
+
+typedef struct {
+ STM_RSC_DESC_HEADER Hdr;
+} STM_RSC_ALL_RESOURCES_DESC;
+
+typedef struct {
+ STM_RSC_DESC_HEADER Hdr;
+ uint32_t RegisterType;
+ uint32_t Reserved;
+ uint64_t ReadMask;
+ uint64_t WriteMask;
+} STM_REGISTER_VIOLATION_DESC;
+
+typedef enum {
+ StmRegisterCr0,
+ StmRegisterCr2,
+ StmRegisterCr3,
+ StmRegisterCr4,
+ StmRegisterCr8,
+ StmRegisterMax,
+} STM_REGISTER_VIOLATION_TYPE;
+
+typedef union {
+ STM_RSC_DESC_HEADER Header;
+ STM_RSC_END End;
+ STM_RSC_MEM_DESC Mem;
+ STM_RSC_IO_DESC Io;
+ STM_RSC_MMIO_DESC Mmio;
+ STM_RSC_MSR_DESC Msr;
+ STM_RSC_PCI_CFG_DESC PciCfg;
+ STM_RSC_TRAPPED_IO_DESC TrappedIo;
+ STM_RSC_ALL_RESOURCES_DESC All;
+ STM_REGISTER_VIOLATION_DESC RegisterViolation;
+} STM_RSC;
+
+//
+// VMCS database
+//
+#define STM_VMCS_DATABASE_REQUEST_ADD 1
+#define STM_VMCS_DATABASE_REQUEST_REMOVE 0
+
+// Values for DomainType
+// Intepreter of DomainType
+#define DOMAIN_DISALLOWED_IO_OUT (1u << 0)
+#define DOMAIN_DISALLOWED_IO_IN (1u << 1)
+#define DOMAIN_INTEGRITY (1u << 2)
+#define DOMAIN_CONFIDENTIALITY (1u << 3)
+
+#define DOMAIN_UNPROTECTED 0x00
+#define DOMAIN_INTEGRITY_PROT_OUT_IN (DOMAIN_INTEGRITY)
+//#define DOMAIN_INTEGRITY_PROT_OUT (DOMAIN_INTEGRITY | DOMAIN_DISALLOWED_IO_IN)
+#define DOMAIN_FULLY_PROT_OUT_IN (DOMAIN_CONFIDENTIALITY | DOMAIN_INTEGRITY)
+//#define DOMAIN_FULLY_PROT_IN (DOMAIN_CONFIDENTIALITY | DOMAIN_INTEGRITY | DOMAIN_DISALLOWED_IO_OUT)
+//#define DOMAIN_FULLY_PROT_OUT (DOMAIN_CONFIDENTIALITY | DOMAIN_INTEGRITY | DOMAIN_DISALLOWED_IO_IN)
+#define DOMAIN_FULLY_PROT (DOMAIN_CONFIDENTIALITY | DOMAIN_INTEGRITY | DOMAIN_DISALLOWED_IO_IN | DOMAIN_DISALLOWED_IO_OUT)
+
+// Values for XStatePolicy
+#define XSTATE_READWRITE 0x00
+#define XSTATE_READONLY 0x01
+#define XSTATE_SCRUB 0x03
+
+typedef struct {
+ uint64_t VmcsPhysPointer; // bits 11:0 are reserved and must be 0
+ uint32_t DomainType :4;
+ uint32_t XStatePolicy :2;
+ uint32_t DegradationPolicy :4;
+ uint32_t Reserved1 :22; // Must be 0
+ uint32_t AddOrRemove;
+} STM_VMCS_DATABASE_REQUEST;
+
+//
+// Event log
+//
+#define NEW_LOG 1
+#define CONFIGURE_LOG 2
+#define START_LOG 3
+#define STOP_LOG 4
+#define CLEAR_LOG 5
+#define DELETE_LOG 6
+typedef enum {
+ EvtLogStarted,
+ EvtLogStopped,
+ EvtLogInvalidParameterDetected,
+ EvtHandledProtectionException,
+ // unhandled protection exceptions result in reset & cannot be logged
+ EvtBiosAccessToUnclaimedResource,
+ EvtMleResourceProtectionGranted,
+ EvtMleResourceProtectionDenied,
+ EvtMleResourceUnprotect,
+ EvtMleResourceUnprotectError,
+ EvtMleDomainTypeDegraded,
+ // add more here
+ EvtMleMax,
+ // Not used
+ EvtInvalid = 0xFFFFFFFF,
+} EVENT_TYPE;
+
+//#define STM_EVENT_LOG_PAGE_COUNT_MAX 62
+
+typedef struct {
+ uint32_t PageCount;
+ uint64_t Pages[1]; // number of elements is PageCount
+} STM_EVENT_LOG_MANAGEMENT_REQUEST_DATA_LOG_BUFFER;
+
+typedef union {
+ STM_EVENT_LOG_MANAGEMENT_REQUEST_DATA_LOG_BUFFER LogBuffer;
+ uint32_t EventEnableBitmap; // bitmap of EVENT_TYPE
+} STM_EVENT_LOG_MANAGEMENT_REQUEST_DATA;
+
+typedef struct {
+ uint32_t SubFunctionIndex;
+ STM_EVENT_LOG_MANAGEMENT_REQUEST_DATA Data;
+} STM_EVENT_LOG_MANAGEMENT_REQUEST;
+
+//
+// VMCALL API Numbers
+//
+
+// API number convention: BIOS facing VMCALL interfaces have bit 16 clear
+#define STM_API_MAP_ADDRESS_RANGE 0x00000001
+#define STM_API_UNMAP_ADDRESS_RANGE 0x00000002
+#define STM_API_ADDRESS_LOOKUP 0x00000003
+#define STM_API_RETURN_FROM_PROTECTION_EXCEPTION 0x00000004
+
+// API number convention: MLE facing VMCALL interfaces have bit 16 set
+//
+// The STM configuration lifecycle is as follows:
+// 1. SENTER->SINIT->MLE: MLE begins execution with SMI disabled (masked).
+// 2. MLE invokes InitializeProtectionVMCALL() to prepare STM for setup of
+// initial protection profile. This is done on a single CPU and has global
+// effect.
+// 3. MLE invokes ProtectResourceVMCALL() to define the initial protection
+// profile. The protection profile is global across all CPUs.
+// 4. MLE invokes StartStmVMCALL() to enable the STM to begin receiving SMI
+// events. This must be done on every logical CPU.
+// 5. MLE may invoke ProtectResourceVMCALL() or UnProtectResourceVMCALL()
+// during runtime as many times as necessary.
+// 6. MLE invokes StopStmVMCALL() to disable the STM. SMI is again masked
+// following StopStmVMCALL().
+//
+#define STM_API_START 0x00010001
+#define STM_API_STOP 0x00010002
+#define STM_API_PROTECT_RESOURCE 0x00010003
+#define STM_API_UNPROTECT_RESOURCE 0x00010004
+#define STM_API_GET_BIOS_RESOURCES 0x00010005
+#define STM_API_MANAGE_VMCS_DATABASE 0x00010006
+#define STM_API_INITIALIZE_PROTECTION 0x00010007
+#define STM_API_MANAGE_EVENT_LOG 0x00010008
+
+//
+// Return codes
+//
+typedef uint32_t STM_STATUS;
+
+#define STM_SUCCESS 0x00000000
+#define SMM_SUCCESS 0x00000000
+// all error codes have bit 31 set
+// STM errors have bit 16 set
+#define ERROR_STM_SECURITY_VIOLATION 0x80010001
+#define ERROR_STM_CACHE_TYPE_NOT_SUPPORTED 0x80010002
+#define ERROR_STM_PAGE_NOT_FOUND 0x80010003
+#define ERROR_STM_BAD_CR3 0x80010004
+#define ERROR_STM_PHYSICAL_OVER_4G 0x80010005
+#define ERROR_STM_VIRTUAL_SPACE_TOO_SMALL 0x80010006
+#define ERROR_STM_UNPROTECTABLE_RESOURCE 0x80010007
+#define ERROR_STM_ALREADY_STARTED 0x80010008
+#define ERROR_STM_WITHOUT_SMX_UNSUPPORTED 0x80010009
+#define ERROR_STM_STOPPED 0x8001000A
+#define ERROR_STM_BUFFER_TOO_SMALL 0x8001000B
+#define ERROR_STM_INVALID_VMCS_DATABASE 0x8001000C
+#define ERROR_STM_MALFORMED_RESOURCE_LIST 0x8001000D
+#define ERROR_STM_INVALID_PAGECOUNT 0x8001000E
+#define ERROR_STM_LOG_ALLOCATED 0x8001000F
+#define ERROR_STM_LOG_NOT_ALLOCATED 0x80010010
+#define ERROR_STM_LOG_NOT_STOPPED 0x80010011
+#define ERROR_STM_LOG_NOT_STARTED 0x80010012
+#define ERROR_STM_RESERVED_BIT_SET 0x80010013
+#define ERROR_STM_NO_EVENTS_ENABLED 0x80010014
+#define ERROR_STM_OUT_OF_RESOURCES 0x80010015
+#define ERROR_STM_FUNCTION_NOT_SUPPORTED 0x80010016
+#define ERROR_STM_UNPROTECTABLE 0x80010017
+#define ERROR_STM_UNSUPPORTED_MSR_BIT 0x80010018
+#define ERROR_STM_UNSPECIFIED 0x8001FFFF
+
+// SMM errors have bit 17 set
+#define ERROR_SMM_BAD_BUFFER 0x80020001
+#define ERROR_SMM_INVALID_RSC 0x80020004
+#define ERROR_SMM_INVALID_BUFFER_SIZE 0x80020005
+#define ERROR_SMM_BUFFER_TOO_SHORT 0x80020006
+#define ERROR_SMM_INVALID_LIST 0x80020007
+#define ERROR_SMM_OUT_OF_MEMORY 0x80020008
+#define ERROR_SMM_AFTER_INIT 0x80020009
+#define ERROR_SMM_UNSPECIFIED 0x8002FFFF
+
+// Errors that apply to both have bits 15, 16, and 17 set
+#define ERROR_INVALID_API 0x80038001
+#define ERROR_INVALID_PARAMETER 0x80038002
+
+//
+// STM TXT.ERRORCODE codes
+//
+#define STM_CRASH_PROTECTION_EXCEPTION 0xC000F001
+#define STM_CRASH_PROTECTION_EXCEPTION_FAILURE 0xC000F002
+#define STM_CRASH_DOMAIN_DEGRADATION_FAILURE 0xC000F003
+#define STM_CRASH_BIOS_PANIC 0xC000E000
+
+typedef struct {
+ uint32_t EventSerialNumber;
+ uint16_t Type;
+ uint16_t Lock :1;
+ uint16_t Valid :1;
+ uint16_t ReadByMle :1;
+ uint16_t Wrapped :1;
+ uint16_t Reserved :12;
+} LOG_ENTRY_HEADER;
+
+typedef struct {
+ uint32_t Reserved;
+} ENTRY_EVT_LOG_STARTED;
+
+typedef struct {
+ uint32_t Reserved;
+} ENTRY_EVT_LOG_STOPPED;
+
+typedef struct {
+ uint32_t VmcallApiNumber;
+} ENTRY_EVT_LOG_INVALID_PARAM;
+
+typedef struct {
+ STM_RSC Resource;
+} ENTRY_EVT_LOG_HANDLED_PROTECTION_EXCEPTION;
+
+typedef struct {
+ STM_RSC Resource;
+} ENTRY_EVT_BIOS_ACCESS_UNCLAIMED_RSC;
+
+typedef struct {
+ STM_RSC Resource;
+} ENTRY_EVT_MLE_RSC_PROT_GRANTED;
+
+typedef struct {
+ STM_RSC Resource;
+} ENTRY_EVT_MLE_RSC_PROT_DENIED;
+
+typedef struct {
+ STM_RSC Resource;
+} ENTRY_EVT_MLE_RSC_UNPROT;
+
+typedef struct {
+ STM_RSC Resource;
+} ENTRY_EVT_MLE_RSC_UNPROT_ERROR;
+
+typedef struct {
+ uint64_t VmcsPhysPointer;
+ uint8_t ExpectedDomainType;
+ uint8_t DegradedDomainType;
+} ENTRY_EVT_MLE_DOMAIN_TYPE_DEGRADED;
+
+typedef union {
+ ENTRY_EVT_LOG_STARTED Started;
+ ENTRY_EVT_LOG_STOPPED Stopped;
+ ENTRY_EVT_LOG_INVALID_PARAM InvalidParam;
+ ENTRY_EVT_LOG_HANDLED_PROTECTION_EXCEPTION HandledProtectionException;
+ ENTRY_EVT_BIOS_ACCESS_UNCLAIMED_RSC BiosUnclaimedRsc;
+ ENTRY_EVT_MLE_RSC_PROT_GRANTED MleRscProtGranted;
+ ENTRY_EVT_MLE_RSC_PROT_DENIED MleRscProtDenied;
+ ENTRY_EVT_MLE_RSC_UNPROT MleRscUnprot;
+ ENTRY_EVT_MLE_RSC_UNPROT_ERROR MleRscUnprotError;
+ ENTRY_EVT_MLE_DOMAIN_TYPE_DEGRADED MleDomainTypeDegraded;
+} LOG_ENTRY_DATA;
+
+typedef struct {
+ LOG_ENTRY_HEADER Hdr;
+ LOG_ENTRY_DATA Data;
+} STM_LOG_ENTRY;
+
+#define STM_LOG_ENTRY_SIZE 256
+
+//
+//
+//
+#define STM_CONFIG_SMI_UNBLOCKING_BY_VMX_OFF 0x1
+
+//
+// TXT debug
+//
+#define SW_SMI_STM_ADD_RUNTIME_RESOURCES_SUB_FUNC 0
+#define SW_SMI_STM_READ_BIOS_RESOURCES_SUB_FUNC 1
+#define SW_SMI_STM_REPLACE_BIOS_RESOURCES_SUB_FUNC 2
+
+typedef struct {
+ uint32_t BufferSize;
+ uint32_t Reserved;
+ //uint8_t Data[];
+} TXT_BIOS_DEBUG;
+
+#pragma pack (pop)
+
+#endif
diff --git a/src/security/intel/stm/StmPlatformResource.c b/src/security/intel/stm/StmPlatformResource.c
new file mode 100644
index 0000000..ad8a69b
--- /dev/null
+++ b/src/security/intel/stm/StmPlatformResource.c
@@ -0,0 +1,259 @@
+/** @file
+ STM platform SMM resource
+
+ Copyright (c) 2015, Intel Corporation. All rights reserved.
+ This program and the accompanying materials are licensed and made
+ available under the terms and conditions of the BSD License which
+ accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <stdint.h>
+#include <security/intel/stm/StmApi.h>
+#include <security/intel/stm/SmmStm.h>
+#include <security/intel/stm/StmPlatformResource.h>
+
+#include <southbridge/intel/common/pmutil.h>
+#include <cpu/x86/msr.h>
+
+#define RDWR_ACCS 3
+#define FULL_ACCS 7
+
+uint32_t mMaxBus;
+uint32_t mTsegBase;
+uint32_t mTsegSize;
+uint16_t mPmBase;
+
+typedef union {
+ uint64_t uint64;
+ msr_t msr;
+} msr64_t;
+
+//uint64_t PciRead64 (UINTN Address);
+void ResourceInit(void);
+void FixupPciexResource(void);
+void AddSimpleResources(void);
+void AddMsrResources(void);
+
+//
+// Fixed memory ranges
+//
+
+//
+// TSEG memory!
+//
+STM_RSC_MEM_DESC RscTsegMemory = {
+ {MEM_RANGE, sizeof (STM_RSC_MEM_DESC)},
+ 0,
+ 0,
+ FULL_ACCS
+};
+//
+// Flash part
+//
+STM_RSC_MEM_DESC RscSpiMemory = {
+ {MEM_RANGE, sizeof (STM_RSC_MEM_DESC)},
+ 0xFE000000,
+ 0x01000000,
+ FULL_ACCS
+};
+//
+// ACPI
+//
+STM_RSC_IO_DESC RscPmIo = {
+ {IO_RANGE, sizeof (STM_RSC_IO_DESC)},
+ 0,
+ 128
+};
+
+//
+// PCIE MMIO
+//
+STM_RSC_MMIO_DESC RscPcieMmio = {
+ {MMIO_RANGE, sizeof (STM_RSC_MMIO_DESC)},
+ 0,
+ 0, // Length
+ RDWR_ACCS
+};
+//
+// Local APIC
+//
+STM_RSC_MMIO_DESC RscApicMmio = {
+ {MMIO_RANGE, sizeof (STM_RSC_MMIO_DESC)},
+ 0,
+ 0x400,
+ RDWR_ACCS
+};
+//
+// Software SMI
+//
+STM_RSC_TRAPPED_IO_DESC RscSwSmiTrapIo = {
+ {TRAPPED_IO_RANGE, sizeof (STM_RSC_TRAPPED_IO_DESC)},
+ 0xB2,
+ 2
+};
+//
+// End of list
+//
+STM_RSC_END RscListEnd = {
+ {END_OF_RESOURCES, sizeof (STM_RSC_END)},
+ 0
+};
+
+//
+// Common PCI devices
+//
+//
+// LPC bridge
+//
+STM_RSC_PCI_CFG_DESC RscLpcBridgePci = {
+ {PCI_CFG_RANGE, sizeof (STM_RSC_PCI_CFG_DESC)},
+ RDWR_ACCS, 0,
+ 0,
+ 0x1000,
+ 0,
+ 0,
+ {
+ {1, 1, sizeof(STM_PCI_DEVICE_PATH_NODE), LPC_FUNCTION, LPC_DEVICE},
+ },
+};
+
+//
+// Template for MSR resources.
+//
+STM_RSC_MSR_DESC RscMsrTpl = {
+ {MACHINE_SPECIFIC_REG, sizeof (STM_RSC_MSR_DESC)},
+};
+
+//
+// MSR indices to register
+//
+typedef struct {
+ uint32_t MsrIndex;
+ uint64_t ReadMask;
+ uint64_t WriteMask;
+} MSR_TABLE_ENTRY;
+
+MSR_TABLE_ENTRY MsrTable[] = {
+ // Index Read Write // MASK64 means need access, MASK0 means no need access.
+ {SMRR_PHYSBASE_MSR, MASK64, MASK0},
+ {SMRR_PHYSMASK_MSR, MASK64, MASK0},
+};
+
+/**
+
+ BIOS resources initialization.
+
+**/
+void ResourceInit(void)
+{
+ mMaxBus = 255;
+
+ msr_t MsrRead;
+
+ mPmBase = get_pmbase();
+
+ //mTsegBase = (uint32_t)rdmsr(SMRR_PHYSBASE_MSR) & 0xFFFFF000;
+
+ MsrRead = rdmsr(SMRR_PHYSBASE_MSR);
+ mTsegBase = MsrRead.lo & 0xFFFFF000;
+
+ //mTsegSize = (uint32_t)(~((uint32_t)rdmsr(SMRR_PHYSMASK_MSR) & 0xFFFFF000) + 1);
+
+ MsrRead = rdmsr(SMRR_PHYSMASK_MSR);
+ mTsegSize = (~(MsrRead.lo & 0xFFFFF000) + 1);
+}
+
+/**
+
+ Fix up PCIE resource.
+
+**/
+void FixupPciexResource(void)
+{
+ // bug, bug, need to fix for coreboot
+ //
+ // Find max bus number and PCIEX length
+ //
+ //RscPcieMmio.Length = 0x10000000; // 256 MB
+ //RscPcieMmio.Base = PcdGet64 (PcdPciExpressBaseAddress);
+}
+
+/**
+
+ Add basic resources to BIOS resource database.
+
+**/
+void
+AddSimpleResources(void)
+{
+ int Status;
+ msr64_t ReadMsr;
+
+ //
+ // Fix-up values
+ //
+ RscTsegMemory.Base = mTsegBase;
+ RscTsegMemory.Length = mTsegSize;
+
+ RscPmIo.Base = (uint16_t) mPmBase;
+
+ //
+ // Local APIC. We assume that all thteads are programmed identically
+ // despite that it is possible to have individual APIC address for
+ // each of the threads. If this is the case this programming should
+ // be corrected.
+ //
+ //RscApicMmio.Base = AsmReadMsr64 (IA32_APIC_BASE_MSR_INDEX) & 0xFFFFFF000ull;
+
+ ReadMsr.msr = rdmsr(IA32_APIC_BASE_MSR_INDEX);
+ RscApicMmio.Base = ReadMsr.uint64 & 0xFFFFFF000ull;
+
+ //
+ // PCIEX BAR
+ //
+ FixupPciexResource ();
+
+ Status = AddPiResource((void *) &RscTsegMemory, 0);
+ //ASSERT_EFI_ERROR (Status);
+ Status = AddPiResource((void *) &RscLpcBridgePci, 1);
+ //ASSERT_EFI_ERROR (Status);
+}
+
+/**
+
+ Add MSR resources to BIOS resource database.
+
+**/
+void AddMsrResources(void)
+{
+ uint32_t Status;
+ uint32_t Index;
+
+ for (Index = 0; Index < sizeof(MsrTable)/sizeof(MsrTable[0]); Index ++) {
+
+ RscMsrTpl.MsrIndex = (uint32_t) MsrTable[Index].MsrIndex;
+ RscMsrTpl.ReadMask = (uint64_t) MsrTable[Index].ReadMask;
+ RscMsrTpl.WriteMask = (uint64_t) MsrTable[Index].WriteMask;
+
+ Status = AddPiResource ((void *) &RscMsrTpl, 1);
+ }
+}
+
+/**
+
+ Add resources to BIOS resource database.
+
+**/
+void AddResourcesCmd(void)
+{
+ ResourceInit();
+
+ AddSimpleResources();
+
+ AddMsrResources();
+}
diff --git a/src/security/intel/stm/StmPlatformResource.h b/src/security/intel/stm/StmPlatformResource.h
new file mode 100644
index 0000000..e31e74b
--- /dev/null
+++ b/src/security/intel/stm/StmPlatformResource.h
@@ -0,0 +1,43 @@
+/** @file
+ STM platform SMM resource
+
+ Copyright (c) 2015, Intel Corporation. All rights reserved.
+ This program and the accompanying materials are licensed and made available
+ under the terms and conditions of the BSD License which accompanies this
+ distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _STM_PLATFORM_RESOURCE_H_
+#define _STM_PLATFORM_RESOURCE_H_
+
+#define MASK0 0
+#define MASK64 0xFFFFFFFFFFFFFFFFull
+
+//
+// LPC
+//
+#define LPC_BUS 0
+#define LPC_DEVICE 31
+#define LPC_FUNCTION 0
+#define R_ACPI_PM_BASE 0x40
+#define ACPI_PM_BASE_MASK 0xFFF8
+
+//
+// MSRs
+//
+#define IA32_APIC_BASE_MSR_INDEX 0x1B
+#define SMRR_PHYSBASE_MSR 0x1F2
+#define SMRR_PHYSMASK_MSR 0x1F3
+
+/**
+
+ Add resources to BIOS resource database.
+
+**/
+void AddResourcesCmd(void);
+#endif
diff --git a/src/security/intel/stm/StmPlatformSmm.c b/src/security/intel/stm/StmPlatformSmm.c
new file mode 100644
index 0000000..bd9cea5
--- /dev/null
+++ b/src/security/intel/stm/StmPlatformSmm.c
@@ -0,0 +1,128 @@
+/** @file
+ STM platform SMM API
+
+ Copyright (c) 2015, Intel Corporation. All rights reserved.
+ This program and the accompanying materials are licensed and made
+ available under the terms and conditions of the BSD License which
+ accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <security/intel/stm/StmApi.h>
+#include <security/intel/stm/SmmStm.h>
+#include <cpu/x86/smm.h>
+
+#include <stddef.h>
+#include <cbfs.h>
+#include <console/console.h>
+#include <lib.h>
+#include <stdint.h>
+
+int LoadStmImage(uint32_t mseg);
+
+extern bool StmCheckStmImage(void *StmImage, uint32_t StmImageSize);
+extern void StmGen4GPageTableIa32(uint32_t PageTableBase);
+extern void StmGen4GPageTableX64(uint32_t PageTableBase);
+
+/**
+ Load STM image.
+
+ @retval EFI_SUCCESS STM is loaded to MSEG
+ @retval EFI_BUFFER_TOO_SMALL MSEG is too small
+ @retval EFI_UNSUPPORTED MSEG is not enabled
+**/
+int LoadStmImage(uint32_t mseg)
+{
+ int Status;
+ void *MsegBase;
+ uint32_t StmBufferSize;
+ uint32_t StmImageSize;
+ bool StmStatus;
+
+ STM_HEADER *StmHeader;
+
+ //
+ // Extract STM image from FV
+ //
+ MsegBase = (void *) mseg;
+ StmBufferSize = CONFIG_MSEG_SIZE;
+ StmImageSize = 0;
+
+ memset((void *) MsegBase, 0, CONFIG_MSEG_SIZE); // clear the mseg
+
+ StmImageSize = cbfs_boot_load_file("stm.bin", MsegBase, StmBufferSize, CBFS_TYPE_RAW);
+ printk(BIOS_DEBUG, "STM loaded into mseg: 0x%08x size: %u \n", (uint32_t) MsegBase, StmImageSize); /* status is number of bytes loaded */
+
+ StmStatus = StmCheckStmImage(MsegBase, StmImageSize);
+
+ StmHeader = MsegBase;
+
+ StmGen4GPageTableX64 ((uint32_t)MsegBase + StmHeader->HwStmHdr.Cr3Offset);
+
+ // Debug stuff
+
+ printk(BIOS_DEBUG, "STM Header - Revision: 0x%08x Features: 0x%08x ... Cr3Offset: 0x%08x\n",
+ StmHeader->HwStmHdr.StmHeaderRevision,
+ StmHeader->HwStmHdr.MonitorFeatures,
+ StmHeader->HwStmHdr.Cr3Offset);
+ printk(BIOS_DEBUG, "STM Header - StaticImageSize: %d Cr3Location: 0x%08x \n",
+ StmHeader->SwStmHdr.StaticImageSize,
+ ((uint32_t) MsegBase + StmHeader->HwStmHdr.Cr3Offset));
+
+ Status = 0; // always return good for now
+
+ return Status;
+}
+
+struct descriptor
+{
+ uint16_t limit;
+ uintptr_t base;
+} __attribute__((packed));
+
+
+void ReadGdtr( struct descriptor *gdtr);
+
+void ReadGdtr( struct descriptor *gdtr)
+{
+ __asm__ __volatile__ (
+ "sgdt %0"
+ : "=m" (*gdtr)
+ );
+}
+
+void SetupSmmDescriptor(void *smbase, int32_t state_size, int32_t apic_id, int32_t entry32_off)
+{
+ struct descriptor Gdtr;
+
+ TXT_PROCESSOR_SMM_DESCRIPTOR * Psd;
+
+ Psd = smbase + SMM_PSD_OFFSET - (apic_id * state_size);
+
+ printk(BIOS_DEBUG, "Setting up Smm Descriptor - Smbase: %p Psd: %p\n", smbase, Psd);
+
+ memset(Psd, 0, sizeof(TXT_PROCESSOR_SMM_DESCRIPTOR));
+
+ memcpy(&Psd->Signature, TXT_PROCESSOR_SMM_DESCRIPTOR_SIGNATURE, 8);
+ Psd->SmmDescriptorVerMajor = TXT_PROCESSOR_SMM_DESCRIPTOR_VERSION_MAJOR;
+ Psd->SmmDescriptorVerMinor = TXT_PROCESSOR_SMM_DESCRIPTOR_VERSION_MINOR;
+ Psd->SmmSmiHandlerRip = (uint64_t)((uint32_t)smbase + SMM_ENTRY_OFFSET + entry32_off);
+ Psd->LocalApicId = apic_id;
+ Psd->Size = sizeof(TXT_PROCESSOR_SMM_DESCRIPTOR);
+ Psd->AcpiRsdp = 0;
+ Psd->BiosHwResourceRequirementsPtr = (uint64_t)((uint32_t)GetStmResource());
+ Psd->SmmCs = 0x8;
+ Psd->SmmDs = 0x10;
+ Psd->SmmSs = 0x10;
+ Psd->SmmOtherSegment = 0x10;
+ Psd->SmmTr = 0x18;
+
+ ReadGdtr(&Gdtr);
+
+ Psd->SmmGdtPtr = Gdtr.base;
+ Psd->SmmGdtSize = Gdtr.limit + 1; // the stm will subtract, so need to compensate
+}

To view, visit change 33234. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: coreboot
Gerrit-Branch: master
Gerrit-Change-Id: If4adcd92c341162630ce1ec357ffcf8a135785ec
Gerrit-Change-Number: 33234
Gerrit-PatchSet: 1
Gerrit-Owner: Name of user not set #1002358
Gerrit-MessageType: newchange