summaryrefslogtreecommitdiffstats
path: root/src/security/intel/stm/SmmStm.c
diff options
context:
space:
mode:
authorEugene Myers <edmyers@tycho.nsa.gov>2020-01-21 17:01:47 -0500
committerPatrick Georgi <pgeorgi@google.com>2021-02-22 07:33:43 +0000
commitbff4cb055875e59bf436de5ca4f5c5666626abaf (patch)
tree2a5c912f2a3c41154a66eb4f11c22c5b3dd7b683 /src/security/intel/stm/SmmStm.c
parent2085d6f46ad54d7148de38ddd0d183911c2732cc (diff)
downloadcoreboot-bff4cb055875e59bf436de5ca4f5c5666626abaf.tar.gz
coreboot-bff4cb055875e59bf436de5ca4f5c5666626abaf.tar.bz2
coreboot-bff4cb055875e59bf436de5ca4f5c5666626abaf.zip
security/intel/stm: Add STM support
This update is a combination of all four of the patches so that the commit can be done without breaking parts of coreboot. This possible breakage is because of the cross-dependencies between the original separate patches would cause failure because of data structure changes. security/intel/stm This directory contains the functions that check and move the STM to the MSEG, create its page tables, and create the BIOS resource list. The STM page tables is a six page region located in the MSEG and are pointed to by the CR3 Offset field in the MSEG header. The initial page tables will identity map all memory between 0-4G. The STM starts in IA32e mode, which requires page tables to exist at startup. The BIOS resource list defines the resources that the SMI Handler is allowed to access. This includes the SMM memory area where the SMI handler resides and other resources such as I/O devices. The STM uses the BIOS resource list to restrict the SMI handler's accesses. The BIOS resource list is currently located in the same area as the SMI handler. This location is shown in the comment section before smm_load_module in smm_module_loader.c Note: The files within security/intel/stm come directly from their Tianocore counterparts. Unnecessary code has been removed and the remaining code has been converted to meet coreboot coding requirements. For more information see: SMI Transfer Monitor (STM) User Guide, Intel Corp., August 2015, Rev 1.0, can be found at firmware.intel.com include/cpu/x86: Addtions to include/cpu/x86 for STM support. cpu/x86: STM Set up - The STM needs to be loaded into the MSEG during BIOS initialization and the SMM Monitor Control MSR be set to indicate that an STM is in the system. cpu/x86/smm: SMI module loader modifications needed to set up the SMM descriptors used by the STM during its initialization Original-Change-Id: If4adcd92c341162630ce1ec357ffcf8a135785ec Original-Signed-off-by: Eugene D. Myers <edmyers@tycho.nsa.gov> Original-Reviewed-on: https://review.coreboot.org/c/coreboot/+/33234 Original-Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Original-Reviewed-by: Patrick Georgi <pgeorgi@google.com> Original-Reviewed-by: ron minnich <rminnich@gmail.com> (cherry picked from commit ae438be57856e994774ec0e2521d49f1ad09bd6f) Signed-off-by: Marc Jones <marcjones@sysproconsulting.com> Change-Id: Ic0131fcada9f43c9817c8a0a942d0419c7023130 Reviewed-on: https://review.coreboot.org/c/coreboot/+/50308 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
Diffstat (limited to 'src/security/intel/stm/SmmStm.c')
-rw-r--r--src/security/intel/stm/SmmStm.c691
1 files changed, 691 insertions, 0 deletions
diff --git a/src/security/intel/stm/SmmStm.c b/src/security/intel/stm/SmmStm.c
new file mode 100644
index 000000000000..f23be70217ef
--- /dev/null
+++ b/src/security/intel/stm/SmmStm.c
@@ -0,0 +1,691 @@
+/* @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 <console/console.h>
+#include <cpu/x86/cr.h>
+#include <cpu/x86/mp.h>
+#include <cpu/x86/msr.h>
+#include <cpu/x86/cache.h>
+#include <security/intel/stm/SmmStm.h>
+#include <string.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 PTP_SIZE SIZE_4KB
+
+#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
+
+typedef struct {
+
+ uint64_t vmcs_revision_id : 31;
+ uint64_t always_zero : 1;
+ uint64_t vmcs_size : 13;
+ uint64_t reserved1 : 3;
+ uint64_t vmxon_add_width : 1;
+ uint64_t stm_supported : 1;
+ uint64_t vmcs_memory_type : 4;
+ uint64_t in_out_reporting : 1;
+ uint64_t may_clear_defaults : 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 vmx_off_blockSmi : 1;
+ uint64_t reserved2 : 9;
+ uint64_t mseg_address : 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 m_rsc_end_node = {
+ {END_OF_RESOURCES, sizeof(STM_RSC_END)},
+};
+
+uint8_t *m_stm_resources_ptr = NULL;
+uint32_t m_stm_resource_total_size = 0x0;
+uint32_t m_stm_resource_size_used = 0x0;
+uint32_t m_stm_resource_size_available = 0x0;
+
+uint8_t *stm_resource_heap = NULL;
+
+uint32_t m_stm_state = 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
+ */
+
+static bool handle_single_resource(STM_RSC *resource, STM_RSC *record)
+{
+ uint64_t resource_lo = 0;
+ uint64_t resource_hi = 0;
+ uint64_t record_lo = 0;
+ uint64_t record_hi = 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.rsc_type) {
+ case MEM_RANGE:
+ case MMIO_RANGE:
+ resource_lo = resource->mem.base;
+ resource_hi = resource->mem.base + resource->mem.length;
+ record_lo = record->mem.base;
+ record_hi = record->mem.base + record->mem.length;
+ if (resource->mem.rwx_attributes
+ != record->mem.rwx_attributes) {
+ if ((resource_lo == record_lo)
+ && (resource_hi == record_hi)) {
+ record->mem.rwx_attributes =
+ resource->mem.rwx_attributes
+ | record->mem.rwx_attributes;
+ return true;
+ } else {
+ return false;
+ }
+ }
+ break;
+ case IO_RANGE:
+ case TRAPPED_IO_RANGE:
+ resource_lo = (uint64_t)resource->io.base;
+ resource_hi = (uint64_t)resource->io.base
+ + (uint64_t)resource->io.length;
+ record_lo = (uint64_t)record->io.base;
+ record_hi =
+ (uint64_t)record->io.base + (uint64_t)record->io.length;
+ break;
+ case PCI_CFG_RANGE:
+ if ((resource->pci_cfg.originating_bus_number
+ != record->pci_cfg.originating_bus_number)
+ || (resource->pci_cfg.last_node_index
+ != record->pci_cfg.last_node_index))
+ return false;
+
+ if (memcmp(resource->pci_cfg.pci_device_path,
+ record->pci_cfg.pci_device_path,
+ sizeof(STM_PCI_DEVICE_PATH_NODE)
+ * (resource->pci_cfg.last_node_index + 1))
+ != 0) {
+ return false;
+ }
+ resource_lo = (uint64_t)resource->pci_cfg.base;
+ resource_hi = (uint64_t)resource->pci_cfg.base
+ + (uint64_t)resource->pci_cfg.length;
+ record_lo = (uint64_t)record->pci_cfg.base;
+ record_hi = (uint64_t)record->pci_cfg.base
+ + (uint64_t)record->pci_cfg.length;
+ if (resource->pci_cfg.rw_attributes
+ != record->pci_cfg.rw_attributes) {
+ if ((resource_lo == record_lo)
+ && (resource_hi == record_hi)) {
+ record->pci_cfg.rw_attributes =
+ resource->pci_cfg.rw_attributes
+ | record->pci_cfg.rw_attributes;
+ return true;
+ } else {
+ return false;
+ }
+ }
+ break;
+ case MACHINE_SPECIFIC_REG:
+
+ // Special case - merge MSR masks in place.
+ if (resource->msr.msr_index != record->msr.msr_index)
+ return false;
+ record->msr.read_mask |= resource->msr.read_mask;
+ record->msr.write_mask |= resource->msr.write_mask;
+ return true;
+ default:
+ return false;
+ }
+
+ // If resources are disjoint
+ if ((resource_hi < record_lo) || (resource_lo > record_hi))
+ return false;
+
+ // If resource is consumed by record.
+ if ((resource_lo >= record_lo) && (resource_hi <= record_hi))
+ return true;
+
+ // Resources are overlapping.
+ // Resource and record are merged.
+ resource_lo = (resource_lo < record_lo) ? resource_lo : record_lo;
+ resource_hi = (resource_hi > record_hi) ? resource_hi : record_hi;
+
+ switch (resource->header.rsc_type) {
+ case MEM_RANGE:
+ case MMIO_RANGE:
+ record->mem.base = resource_lo;
+ record->mem.length = resource_hi - resource_lo;
+ break;
+ case IO_RANGE:
+ case TRAPPED_IO_RANGE:
+ record->io.base = (uint64_t)resource_lo;
+ record->io.length = (uint64_t)(resource_hi - resource_lo);
+ break;
+ case PCI_CFG_RANGE:
+ record->pci_cfg.base = (uint64_t)resource_lo;
+ record->pci_cfg.length = (uint64_t)(resource_hi - resource_lo);
+ break;
+ default:
+ return false;
+ }
+
+ return true;
+}
+
+/*
+ * Add resource node.
+ *
+ * @param Resource A pointer to resource node to be added
+ */
+static void add_single_resource(STM_RSC *resource)
+{
+ STM_RSC *record;
+
+ record = (STM_RSC *)m_stm_resources_ptr;
+
+ while (true) {
+ if (record->header.rsc_type == END_OF_RESOURCES)
+ break;
+
+ // Go to next record if resource and record types don't match.
+ if (resource->header.rsc_type != record->header.rsc_type) {
+ record = (STM_RSC *)((void *)record
+ + record->header.length);
+ continue;
+ }
+
+ // Record is handled inside of procedure - don't adjust.
+ if (handle_single_resource(resource, record))
+ return;
+ record = (STM_RSC *)((void *)record + record->header.length);
+ }
+
+ // Add resource to the end of area.
+ memcpy(m_stm_resources_ptr + m_stm_resource_size_used
+ - sizeof(m_rsc_end_node),
+ resource, resource->header.length);
+ memcpy(m_stm_resources_ptr + m_stm_resource_size_used
+ - sizeof(m_rsc_end_node) + resource->header.length,
+ &m_rsc_end_node, sizeof(m_rsc_end_node));
+ m_stm_resource_size_used += resource->header.length;
+ m_stm_resource_size_available =
+ m_stm_resource_total_size - m_stm_resource_size_used;
+}
+
+/*
+ * Add resource list.
+ *
+ * @param resource_list A pointer to resource list to be added
+ * @param num_entries Optional number of entries.
+ * If 0, list must be terminated by END_OF_RESOURCES.
+ */
+static void add_resource(STM_RSC *resource_list, uint32_t num_entries)
+{
+ uint32_t count;
+ uint32_t index;
+ STM_RSC *resource;
+
+ if (num_entries == 0)
+ count = 0xFFFFFFFF;
+ else
+ count = num_entries;
+
+ resource = resource_list;
+
+ for (index = 0; index < count; index++) {
+ if (resource->header.rsc_type == END_OF_RESOURCES)
+ return;
+ add_single_resource(resource);
+ resource =
+ (STM_RSC *)((void *)resource + resource->header.length);
+ }
+}
+
+/*
+ * Validate resource list.
+ *
+ * @param resource_list A pointer to resource list to be added
+ * @param num_entries Optional number of entries.
+ * If 0, list must be terminated by END_OF_RESOURCES.
+ *
+ * @retval true resource valid
+ * @retval false resource invalid
+ */
+static bool validate_resource(STM_RSC *resource_list, uint32_t num_entries)
+{
+ uint32_t count;
+ uint32_t index;
+ STM_RSC *resource;
+ uint32_t sub_index;
+
+ // If NumEntries == 0 make it very big. Scan will be terminated by
+ // END_OF_RESOURCES.
+ if (num_entries == 0)
+ count = 0xFFFFFFFF;
+ else
+ count = num_entries;
+
+ // Start from beginning of resource list.
+ resource = resource_list;
+
+ for (index = 0; index < count; index++) {
+ printk(BIOS_DEBUG, "STM: %s (%u) - RscType(%x) length(0x%x)\n",
+ __func__,
+ index,
+ resource->header.rsc_type,
+ resource->header.length);
+ // Validate resource.
+ switch (resource->header.rsc_type) {
+ 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 (num_entries != 0)
+ return false;
+
+ // If NumEntries == 0 and list reached end - return
+ // success.
+ return true;
+
+ case MEM_RANGE:
+ case MMIO_RANGE:
+ printk(BIOS_DEBUG,
+ "STM: %s - MEM (0x%0llx, 0x%0llx)\n",
+ __func__,
+ resource->mem.base,
+ resource->mem.length);
+
+ if (resource->header.length != sizeof(STM_RSC_MEM_DESC))
+ return false;
+
+ if (resource->mem.rwx_attributes > 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,
+ "STM: %s - PCI (0x%02x, 0x%08x, 0x%02x, 0x%02x)\n",
+ __func__,
+ resource->pci_cfg.originating_bus_number,
+ resource->pci_cfg.last_node_index,
+ resource->pci_cfg.pci_device_path[0].pci_device,
+ resource->pci_cfg.pci_device_path[0]
+ .pci_function);
+ if (resource->header.length
+ != sizeof(STM_RSC_PCI_CFG_DESC)
+ + (sizeof(STM_PCI_DEVICE_PATH_NODE)
+ * resource->pci_cfg.last_node_index))
+ return false;
+ for (sub_index = 0;
+ sub_index <= resource->pci_cfg.last_node_index;
+ sub_index++) {
+ if ((resource->pci_cfg
+ .pci_device_path[sub_index]
+ .pci_device
+ > 0x1F)
+ || (resource->pci_cfg
+ .pci_device_path[sub_index]
+ .pci_function
+ > 7))
+ return false;
+ }
+ if ((resource->pci_cfg.base + resource->pci_cfg.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, "STM: %s - Unknown RscType(%x)\n",
+ __func__, resource->header.rsc_type);
+ return false;
+ }
+ resource =
+ (STM_RSC *)((void *)resource + resource->header.length);
+ }
+ return true;
+}
+
+/*
+ * Get resource list.
+ * EndResource is excluded.
+ *
+ * @param resou rce_list A pointer to resource list to be added
+ * @param num_entries Optional number of entries.
+ * If 0, list must be terminated by END_OF_RESOURCES.
+ *
+ * @retval true resource valid
+ * @retval false resource invalid
+ */
+static uint32_t get_resource_size(STM_RSC *resource_list, uint32_t num_entries)
+{
+ uint32_t count;
+ uint32_t index;
+ STM_RSC *resource;
+
+ resource = resource_list;
+
+ // If NumEntries == 0 make it very big. Scan will be terminated by
+ // END_OF_RESOURCES.
+ if (num_entries == 0)
+ count = 0xFFFFFFFF;
+ else
+ count = num_entries;
+
+ // Start from beginning of resource list.
+ resource = resource_list;
+
+ for (index = 0; index < count; index++) {
+ if (resource->header.rsc_type == END_OF_RESOURCES)
+ break;
+ resource =
+ (STM_RSC *)((void *)resource + resource->header.length);
+ }
+ return (uint32_t)((uint32_t)resource - (uint32_t)resource_list);
+}
+
+/*
+ * Add resources in list to database. Allocate new memory areas as needed.
+ *
+ * @param resource_list A pointer to resource list to be added
+ * @param num_entries 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 failure
+ * @retval OUT_OF_RESOURCES If nested procedure returned it and we cannot
+ * allocate more areas.
+ */
+int add_pi_resource(STM_RSC *resource_list, uint32_t num_entries)
+{
+ size_t resource_size;
+
+ printk(BIOS_DEBUG, "STM: %s - Enter\n", __func__);
+
+ if (!validate_resource(resource_list, num_entries))
+ return -1; // INVALID_PARAMETER;
+
+ resource_size = get_resource_size(resource_list, num_entries);
+ printk(BIOS_DEBUG, "STM: ResourceSize - 0x%08lx\n", resource_size);
+ if (resource_size == 0)
+ return -1; // INVALID_PARAMETER;
+
+ if (m_stm_resources_ptr == NULL) {
+
+ // Copy EndResource for initialization
+ m_stm_resources_ptr = stm_resource_heap;
+ m_stm_resource_total_size = CONFIG_BIOS_RESOURCE_LIST_SIZE;
+ memset(m_stm_resources_ptr, 0, CONFIG_BIOS_RESOURCE_LIST_SIZE);
+
+ memcpy(m_stm_resources_ptr, &m_rsc_end_node,
+ sizeof(m_rsc_end_node));
+ m_stm_resource_size_used = sizeof(m_rsc_end_node);
+ m_stm_resource_size_available =
+ m_stm_resource_total_size - sizeof(m_rsc_end_node);
+ wbinvd(); // force to memory
+
+ } else {
+ if (m_stm_resource_size_available < resource_size) {
+ printk(BIOS_DEBUG,
+ "STM: ERROR - not enough space for SMM resource list\n");
+ return -1; // OUT_OF_RESOURCES
+ }
+ }
+
+ // Check duplication
+ add_resource(resource_list, num_entries);
+
+ return 0; // SUCCESS;
+}
+
+/*
+ * Delete resources in list to database.
+ *
+ * @param resource_list A pointer to resource list to be deleted
+ * NULL means delete all resources.
+ * @param num_entries Optional number of entries.
+ * If 0, list must be terminated by END_OF_RESOURCES.
+ *
+ * @retval SUCCESS If resources are deleted
+ * @retval INVALID_PARAMETER If nested procedure detected resource failure
+ */
+int32_t delete_pi_resource(STM_RSC *resource_list, uint32_t num_entries)
+{
+ if (resource_list != NULL) {
+ // ASSERT (false);
+ return -1; // UNSUPPORTED;
+ }
+
+ // Delete all
+ memcpy(m_stm_resources_ptr, &m_rsc_end_node, sizeof(m_rsc_end_node));
+ m_stm_resource_size_used = sizeof(m_rsc_end_node);
+ m_stm_resource_size_available =
+ m_stm_resource_total_size - sizeof(m_rsc_end_node);
+ return 0; // SUCCESS;
+}
+
+/*
+ * Get BIOS resources.
+ *
+ * @param resource_list A pointer to resource list to be filled
+ * @param resource_size 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 is
+ * too small.
+ *
+ * @retval SUCCESS If resources are returned.
+ * @retval BUFFER_TOO_SMALL If resource list buffer is too small to hold
+ * the whole resource list.
+ */
+int32_t get_pi_resource(STM_RSC *resource_list, uint32_t *resource_size)
+{
+ if (*resource_size < m_stm_resource_size_used) {
+ *resource_size = (uint32_t)m_stm_resource_size_used;
+ return -1; // BUFFER_TOO_SMALL;
+ }
+
+ memcpy(resource_list, m_stm_resources_ptr, m_stm_resource_size_used);
+ *resource_size = (uint32_t)m_stm_resource_size_used;
+ return 0; // SUCCESS;
+}
+
+/*
+ * Get 4K page aligned VMCS size.
+ * @return 4K page aligned VMCS size
+ */
+static uint32_t get_vmcs_size(void)
+{
+ uint32_t this_vmcs_size;
+ VMX_BASIC_MSR msr_data64;
+ int stm_support;
+
+ msr_data64.msr = rdmsr(IA32_VMX_BASIC_MSR);
+
+ this_vmcs_size = msr_data64.bits.vmcs_size;
+ stm_support = msr_data64.bits.stm_supported;
+ printk(BIOS_DEBUG, "STM: %s: Size %d StmSupport %d\n", __func__,
+ this_vmcs_size, stm_support);
+
+ // VMCS require 0x1000 alignment
+ this_vmcs_size = STM_PAGES_TO_SIZE(STM_SIZE_TO_PAGES(this_vmcs_size));
+
+ return this_vmcs_size;
+}
+
+/*
+ * Create 4G page table for STM.
+ * 2M PTEs for x86_64 or 2M PTEs for x86_32.
+ *
+ * @param pageable_base The page table base in MSEG
+ */
+void stm_gen_4g_pagetable_x64(uint32_t pagetable_base)
+{
+ uint32_t index;
+ uint32_t sub_index;
+ uint64_t *pde;
+ uint64_t *pte;
+ uint64_t *pml4;
+
+ pml4 = (uint64_t *)(uint32_t)pagetable_base;
+ pagetable_base += PTP_SIZE;
+ *pml4 = pagetable_base | IA32_PG_RW | IA32_PG_P;
+
+ pde = (uint64_t *)(uint32_t)pagetable_base;
+ pagetable_base += PTP_SIZE;
+ pte = (uint64_t *)(uint32_t)pagetable_base;
+
+ for (index = 0; index < 4; index++) {
+ *pde = pagetable_base | IA32_PG_RW | IA32_PG_P;
+ pde++;
+ pagetable_base += PTP_SIZE;
+
+ for (sub_index = 0; sub_index < SIZE_4KB / sizeof(*pte);
+ sub_index++) {
+ *pte = (((index << 9) + sub_index) << 21) | IA32_PG_PS
+ | IA32_PG_RW | IA32_PG_P;
+ pte++;
+ }
+ }
+}
+
+/*
+ * Check STM image size.
+ *
+ * @param stm_image STM image
+ * @param stm_imageSize STM image size
+ *
+ * @retval true check pass
+ * @retval false check fail
+ */
+
+bool stm_check_stm_image(void *stm_image, uint32_t stm_imagesize)
+{
+ uint32_t min_mseg_size;
+ STM_HEADER *stm_header;
+
+ stm_header = (STM_HEADER *)stm_image;
+
+ // Get Minimal required Mseg size
+ min_mseg_size = (STM_PAGES_TO_SIZE(STM_SIZE_TO_PAGES(
+ stm_header->sw_stm_hdr.static_image_size))
+ + stm_header->sw_stm_hdr.additional_dynamic_memory_size
+ + (stm_header->sw_stm_hdr.per_proc_dynamic_memory_size
+ + get_vmcs_size() * 2)
+ * mp_state.cpu_count);
+ if (min_mseg_size < stm_imagesize)
+ min_mseg_size = stm_imagesize;
+
+ if (stm_header->hw_stm_hdr.cr3_offset
+ >= stm_header->sw_stm_hdr.static_image_size) {
+
+ // We will create page table, just in case that SINIT does not
+ // create it.
+ if (min_mseg_size < stm_header->hw_stm_hdr.cr3_offset
+ + STM_PAGES_TO_SIZE(6)) {
+ min_mseg_size = stm_header->hw_stm_hdr.cr3_offset
+ + STM_PAGES_TO_SIZE(6);
+ }
+ }
+
+ // Check if it exceeds MSEG size
+ if (min_mseg_size > CONFIG_MSEG_SIZE)
+ return false;
+
+ return true;
+}
+
+/*
+ * This function return BIOS STM resource.
+ * Produced by SmmStm.
+ * Comsumed by SmmMpService when Init.
+ *
+ * @return BIOS STM resource
+ */
+void *get_stm_resource(void)
+{
+ return m_stm_resources_ptr;
+}