summaryrefslogtreecommitdiffstats
path: root/src/security/intel/stm/StmPlatformSmm.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/security/intel/stm/StmPlatformSmm.c')
-rw-r--r--src/security/intel/stm/StmPlatformSmm.c204
1 files changed, 204 insertions, 0 deletions
diff --git a/src/security/intel/stm/StmPlatformSmm.c b/src/security/intel/stm/StmPlatformSmm.c
new file mode 100644
index 000000000000..d7064b07f5b1
--- /dev/null
+++ b/src/security/intel/stm/StmPlatformSmm.c
@@ -0,0 +1,204 @@
+/* @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 <security/intel/stm/StmPlatformResource.h>
+#include <security/tpm/tspi.h>
+#include <cpu/x86/smm.h>
+#include <cpu/x86/msr.h>
+
+#include <stddef.h>
+#include <cbfs.h>
+#include <console/console.h>
+#include <lib.h>
+#include <stdint.h>
+#include <arch/rom_segs.h>
+
+/*
+ * Load STM image to MSEG
+ *
+ * @retval SUCCESS STM is loaded to MSEG
+ */
+int load_stm_image(uintptr_t mseg)
+{
+ int status;
+ void *mseg_base;
+ uint32_t stm_buffer_size;
+ uint32_t stm_image_size;
+ bool stm_status;
+
+ STM_HEADER *stm_header;
+
+ // Extract STM image from FV
+ mseg_base = (void *)mseg;
+ stm_buffer_size = CONFIG_MSEG_SIZE;
+ stm_image_size = 0;
+
+ memset((void *)mseg_base, 0, CONFIG_MSEG_SIZE); // clear the mseg
+
+ stm_image_size = cbfs_boot_load_file("stm.bin", mseg_base,
+ stm_buffer_size, CBFS_TYPE_RAW);
+ printk(BIOS_DEBUG, "STM:loaded into mseg: 0x%p size: %u\n", mseg_base,
+ stm_image_size);
+ /* status is number of bytes loaded */
+ stm_status = stm_check_stm_image(mseg_base, stm_image_size);
+
+ if (!stm_status) {
+ printk(BIOS_DEBUG, "STM: Error in STM image\n");
+ return -1;
+ }
+
+ stm_header = mseg_base;
+
+ stm_gen_4g_pagetable_x64((uint32_t)mseg_base
+ + stm_header->hw_stm_hdr.cr3_offset);
+
+ // Debug stuff
+ printk(BIOS_DEBUG,
+ "STM: Header-Revision %d Features 0x%08x Cr3Offset 0x%08x\n",
+ stm_header->hw_stm_hdr.stm_header_revision,
+ stm_header->hw_stm_hdr.monitor_features,
+ stm_header->hw_stm_hdr.cr3_offset);
+ printk(BIOS_DEBUG,
+ "STM: Header-StaticImageSize: %d Cr3Location: 0x%08x\n",
+ stm_header->sw_stm_hdr.static_image_size,
+ ((uint32_t)mseg_base + stm_header->hw_stm_hdr.cr3_offset));
+
+ status = 0; // always return good for now
+
+ return status;
+}
+
+struct descriptor {
+ uint16_t limit;
+ uintptr_t base;
+} __attribute__((packed));
+
+
+static void read_gdtr(struct descriptor *gdtr)
+{
+ __asm__ __volatile__("sgdt %0" : "=m"(*gdtr));
+}
+
+void setup_smm_descriptor(void *smbase, void *base_smbase, int32_t apic_id,
+ int32_t entry32_off)
+{
+ struct descriptor gdtr;
+ void *smbase_processor;
+ //msr_t smbase_msr;
+
+ TXT_PROCESSOR_SMM_DESCRIPTOR *psd;
+
+ smbase_processor = (void *) SMM_DEFAULT_BASE;//we are here
+ psd = smbase + SMM_PSD_OFFSET;
+
+ printk(BIOS_DEBUG,
+ "STM: Smm Descriptor setup: Smbase: %p Smbase_processor: %p Psd: %p\n",
+ smbase,
+ smbase_processor,
+ psd);
+
+ memset(psd, 0, sizeof(TXT_PROCESSOR_SMM_DESCRIPTOR));
+
+ memcpy(&psd->signature, TXT_PROCESSOR_SMM_DESCRIPTOR_SIGNATURE, 8);
+ psd->smm_descriptor_ver_major =
+ TXT_PROCESSOR_SMM_DESCRIPTOR_VERSION_MAJOR;
+ psd->smm_descriptor_ver_minor =
+ TXT_PROCESSOR_SMM_DESCRIPTOR_VERSION_MINOR;
+ psd->smm_smi_handler_rip =
+ (uint64_t)((uintptr_t)base_smbase + SMM_ENTRY_OFFSET +
+ entry32_off);
+ psd->local_apic_id = apic_id;
+ psd->size = sizeof(TXT_PROCESSOR_SMM_DESCRIPTOR);
+ psd->acpi_rsdp = 0;
+ psd->bios_hw_resource_requirements_ptr =
+ (uint64_t)((uintptr_t)get_stm_resource());
+ psd->smm_cs = ROM_CODE_SEG;
+ psd->smm_ds = ROM_DATA_SEG;
+ psd->smm_ss = ROM_DATA_SEG;
+ psd->smm_other_segment = ROM_DATA_SEG;
+ psd->smm_tr = SMM_TASK_STATE_SEG;
+
+
+ // At this point the coreboot smm_stub is relative to the default
+ // smbase and not the one for the smi handler in tseg. So we have
+ // to adjust the gdtr.base
+
+ read_gdtr(&gdtr);
+
+ gdtr.base -= (uintptr_t) smbase_processor;
+ gdtr.base += (uintptr_t) base_smbase;
+
+ psd->smm_gdt_ptr = gdtr.base;
+ psd->smm_gdt_size = gdtr.limit + 1; // the stm will subtract, so add
+ printk(BIOS_DEBUG, "STM: Smm Descriptor setup complete - Smbase: %p Psd: %p\n",
+ smbase, psd);
+}
+
+extern uint8_t *stm_resource_heap;
+
+#define FXSAVE_SIZE 512
+
+static int stm_load_status = 0;
+
+void stm_setup(uintptr_t mseg, int cpu, int num_cpus, uintptr_t smbase,
+ uintptr_t base_smbase, uint32_t offset32)
+{
+ msr_t InitMseg;
+ msr_t MsegChk;
+ uintptr_t addr_calc; // used to calculate the stm resource heap area
+
+ printk(BIOS_DEBUG, "STM: set up for cpu %d/%d\n", cpu, num_cpus);
+ if (cpu == 0) {
+
+ // need to create the BIOS resource list once
+ // first calculate the location in SMRAM
+ addr_calc = (mseg - (CONFIG_SMM_MODULE_STACK_SIZE * num_cpus));
+
+ if (CONFIG(SSE))
+ addr_calc -= FXSAVE_SIZE * num_cpus;
+
+ addr_calc -= CONFIG_BIOS_RESOURCE_LIST_SIZE;
+ stm_resource_heap = (uint8_t *) addr_calc;
+ printk(BIOS_DEBUG, "STM: stm_resource_heap located at %p\n",
+ stm_resource_heap);
+ //setup the the list
+ add_resources_cmd();
+
+ stm_load_status = load_stm_image(mseg);
+ }
+
+ if (stm_load_status == 0) {
+ // enable STM for this cpu
+ InitMseg.lo = mseg | IA32_SMM_MONITOR_VALID;
+ InitMseg.hi = 0;
+
+ wrmsr(IA32_SMM_MONITOR_CTL_MSR, InitMseg);
+
+ MsegChk = rdmsr(IA32_SMM_MONITOR_CTL_MSR);
+
+ printk(BIOS_DEBUG, "STM: MSEG Initialized (%d) 0x%08x 0x%08x\n",
+ cpu, MsegChk.hi, MsegChk.lo);
+
+ // setup the descriptor for this cpu
+ setup_smm_descriptor((void *)smbase, (void *) base_smbase,
+ cpu, offset32);
+ } else {
+ printk(BIOS_DEBUG,
+ "STM: Error in STM load, STM not enabled: %d\n",
+ cpu);
+ }
+}