Name of user not set #1002358 has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/33234
Change subject: security/intel/stm STM support ......................................................................
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 +}