Patrick Georgi | 593124d | 2020-05-10 19:44:08 +0200 | [diff] [blame] | 1 | /* SPDX-License-Identifier: BSD-2-Clause */ |
Eugene Myers | ae438be | 2020-01-21 17:01:47 -0500 | [diff] [blame] | 2 | |
| 3 | #include <security/intel/stm/StmApi.h> |
| 4 | #include <security/intel/stm/SmmStm.h> |
| 5 | #include <security/intel/stm/StmPlatformResource.h> |
| 6 | #include <security/tpm/tspi.h> |
| 7 | #include <cpu/x86/smm.h> |
| 8 | #include <cpu/x86/msr.h> |
| 9 | |
Eugene Myers | ae438be | 2020-01-21 17:01:47 -0500 | [diff] [blame] | 10 | #include <cbfs.h> |
| 11 | #include <console/console.h> |
Angel Pons | 002e5e0 | 2020-07-20 23:10:21 +0200 | [diff] [blame] | 12 | #include <stdbool.h> |
Eugene Myers | ae438be | 2020-01-21 17:01:47 -0500 | [diff] [blame] | 13 | #include <stdint.h> |
| 14 | #include <arch/rom_segs.h> |
| 15 | |
| 16 | /* |
| 17 | * Load STM image to MSEG |
| 18 | * |
| 19 | * @retval SUCCESS STM is loaded to MSEG |
| 20 | */ |
| 21 | int load_stm_image(uintptr_t mseg) |
| 22 | { |
| 23 | int status; |
| 24 | void *mseg_base; |
| 25 | uint32_t stm_buffer_size; |
| 26 | uint32_t stm_image_size; |
| 27 | bool stm_status; |
| 28 | |
| 29 | STM_HEADER *stm_header; |
| 30 | |
| 31 | // Extract STM image from FV |
| 32 | mseg_base = (void *)mseg; |
| 33 | stm_buffer_size = CONFIG_MSEG_SIZE; |
| 34 | stm_image_size = 0; |
| 35 | |
| 36 | memset((void *)mseg_base, 0, CONFIG_MSEG_SIZE); // clear the mseg |
| 37 | |
Julius Werner | 834b3ec | 2020-03-04 16:52:08 -0800 | [diff] [blame^] | 38 | stm_image_size = cbfs_load("stm.bin", mseg_base, stm_buffer_size); |
Eugene Myers | ae438be | 2020-01-21 17:01:47 -0500 | [diff] [blame] | 39 | printk(BIOS_DEBUG, "STM:loaded into mseg: 0x%p size: %u\n", mseg_base, |
| 40 | stm_image_size); |
| 41 | /* status is number of bytes loaded */ |
| 42 | stm_status = stm_check_stm_image(mseg_base, stm_image_size); |
| 43 | |
| 44 | if (!stm_status) { |
| 45 | printk(BIOS_DEBUG, "STM: Error in STM image\n"); |
| 46 | return -1; |
| 47 | } |
| 48 | |
| 49 | stm_header = mseg_base; |
| 50 | |
| 51 | stm_gen_4g_pagetable_x64((uint32_t)mseg_base |
| 52 | + stm_header->hw_stm_hdr.cr3_offset); |
| 53 | |
| 54 | // Debug stuff |
| 55 | printk(BIOS_DEBUG, |
| 56 | "STM: Header-Revision %d Features 0x%08x Cr3Offset 0x%08x\n", |
| 57 | stm_header->hw_stm_hdr.stm_header_revision, |
| 58 | stm_header->hw_stm_hdr.monitor_features, |
| 59 | stm_header->hw_stm_hdr.cr3_offset); |
| 60 | printk(BIOS_DEBUG, |
| 61 | "STM: Header-StaticImageSize: %d Cr3Location: 0x%08x\n", |
| 62 | stm_header->sw_stm_hdr.static_image_size, |
| 63 | ((uint32_t)mseg_base + stm_header->hw_stm_hdr.cr3_offset)); |
| 64 | |
| 65 | status = 0; // always return good for now |
| 66 | |
| 67 | return status; |
| 68 | } |
| 69 | |
| 70 | struct descriptor { |
| 71 | uint16_t limit; |
| 72 | uintptr_t base; |
| 73 | } __attribute__((packed)); |
| 74 | |
Eugene Myers | ae438be | 2020-01-21 17:01:47 -0500 | [diff] [blame] | 75 | static void read_gdtr(struct descriptor *gdtr) |
| 76 | { |
| 77 | __asm__ __volatile__("sgdt %0" : "=m"(*gdtr)); |
| 78 | } |
| 79 | |
| 80 | void setup_smm_descriptor(void *smbase, void *base_smbase, int32_t apic_id, |
| 81 | int32_t entry32_off) |
| 82 | { |
| 83 | struct descriptor gdtr; |
| 84 | void *smbase_processor; |
| 85 | //msr_t smbase_msr; |
| 86 | |
| 87 | TXT_PROCESSOR_SMM_DESCRIPTOR *psd; |
| 88 | |
| 89 | smbase_processor = (void *) SMM_DEFAULT_BASE;//we are here |
| 90 | psd = smbase + SMM_PSD_OFFSET; |
| 91 | |
| 92 | printk(BIOS_DEBUG, |
| 93 | "STM: Smm Descriptor setup: Smbase: %p Smbase_processor: %p Psd: %p\n", |
| 94 | smbase, |
| 95 | smbase_processor, |
| 96 | psd); |
| 97 | |
| 98 | memset(psd, 0, sizeof(TXT_PROCESSOR_SMM_DESCRIPTOR)); |
| 99 | |
| 100 | memcpy(&psd->signature, TXT_PROCESSOR_SMM_DESCRIPTOR_SIGNATURE, 8); |
| 101 | psd->smm_descriptor_ver_major = |
| 102 | TXT_PROCESSOR_SMM_DESCRIPTOR_VERSION_MAJOR; |
| 103 | psd->smm_descriptor_ver_minor = |
| 104 | TXT_PROCESSOR_SMM_DESCRIPTOR_VERSION_MINOR; |
| 105 | psd->smm_smi_handler_rip = |
| 106 | (uint64_t)((uintptr_t)base_smbase + SMM_ENTRY_OFFSET + |
| 107 | entry32_off); |
| 108 | psd->local_apic_id = apic_id; |
| 109 | psd->size = sizeof(TXT_PROCESSOR_SMM_DESCRIPTOR); |
| 110 | psd->acpi_rsdp = 0; |
| 111 | psd->bios_hw_resource_requirements_ptr = |
| 112 | (uint64_t)((uintptr_t)get_stm_resource()); |
| 113 | psd->smm_cs = ROM_CODE_SEG; |
| 114 | psd->smm_ds = ROM_DATA_SEG; |
| 115 | psd->smm_ss = ROM_DATA_SEG; |
| 116 | psd->smm_other_segment = ROM_DATA_SEG; |
| 117 | psd->smm_tr = SMM_TASK_STATE_SEG; |
| 118 | |
Eugene Myers | ae438be | 2020-01-21 17:01:47 -0500 | [diff] [blame] | 119 | // At this point the coreboot smm_stub is relative to the default |
| 120 | // smbase and not the one for the smi handler in tseg. So we have |
| 121 | // to adjust the gdtr.base |
| 122 | |
| 123 | read_gdtr(&gdtr); |
| 124 | |
| 125 | gdtr.base -= (uintptr_t) smbase_processor; |
| 126 | gdtr.base += (uintptr_t) base_smbase; |
| 127 | |
| 128 | psd->smm_gdt_ptr = gdtr.base; |
| 129 | psd->smm_gdt_size = gdtr.limit + 1; // the stm will subtract, so add |
| 130 | printk(BIOS_DEBUG, "STM: Smm Descriptor setup complete - Smbase: %p Psd: %p\n", |
| 131 | smbase, psd); |
| 132 | } |
| 133 | |
| 134 | extern uint8_t *stm_resource_heap; |
| 135 | |
| 136 | #define FXSAVE_SIZE 512 |
| 137 | |
| 138 | static int stm_load_status = 0; |
| 139 | |
Eugene D Myers | f213f17 | 2020-04-15 19:11:52 -0400 | [diff] [blame] | 140 | void stm_setup(uintptr_t mseg, int cpu, uintptr_t smbase, |
Eugene Myers | ae438be | 2020-01-21 17:01:47 -0500 | [diff] [blame] | 141 | uintptr_t base_smbase, uint32_t offset32) |
| 142 | { |
| 143 | msr_t InitMseg; |
| 144 | msr_t MsegChk; |
Eugene Myers | 5544f62 | 2020-02-12 13:31:30 -0500 | [diff] [blame] | 145 | msr_t vmx_basic; |
| 146 | |
Eugene Myers | ae438be | 2020-01-21 17:01:47 -0500 | [diff] [blame] | 147 | uintptr_t addr_calc; // used to calculate the stm resource heap area |
| 148 | |
Eugene D Myers | f213f17 | 2020-04-15 19:11:52 -0400 | [diff] [blame] | 149 | printk(BIOS_DEBUG, "STM: set up for cpu %d\n", cpu); |
Eugene Myers | 5544f62 | 2020-02-12 13:31:30 -0500 | [diff] [blame] | 150 | |
| 151 | vmx_basic = rdmsr(IA32_VMX_BASIC_MSR); |
| 152 | |
| 153 | // Does this processor support an STM? |
| 154 | if ((vmx_basic.hi & VMX_BASIC_HI_DUAL_MONITOR) != VMX_BASIC_HI_DUAL_MONITOR) { |
| 155 | printk(BIOS_WARNING, "STM: not supported on CPU %d\n", cpu); |
| 156 | return; |
| 157 | } |
| 158 | |
Eugene Myers | ae438be | 2020-01-21 17:01:47 -0500 | [diff] [blame] | 159 | if (cpu == 0) { |
| 160 | |
| 161 | // need to create the BIOS resource list once |
| 162 | // first calculate the location in SMRAM |
Eugene D Myers | 076605b | 2020-04-15 18:28:10 -0400 | [diff] [blame] | 163 | addr_calc = mseg - CONFIG_BIOS_RESOURCE_LIST_SIZE; |
Eugene Myers | ae438be | 2020-01-21 17:01:47 -0500 | [diff] [blame] | 164 | stm_resource_heap = (uint8_t *) addr_calc; |
| 165 | printk(BIOS_DEBUG, "STM: stm_resource_heap located at %p\n", |
| 166 | stm_resource_heap); |
| 167 | //setup the the list |
| 168 | add_resources_cmd(); |
| 169 | |
| 170 | stm_load_status = load_stm_image(mseg); |
| 171 | } |
| 172 | |
| 173 | if (stm_load_status == 0) { |
| 174 | // enable STM for this cpu |
| 175 | InitMseg.lo = mseg | IA32_SMM_MONITOR_VALID; |
| 176 | InitMseg.hi = 0; |
| 177 | |
| 178 | wrmsr(IA32_SMM_MONITOR_CTL_MSR, InitMseg); |
| 179 | |
| 180 | MsegChk = rdmsr(IA32_SMM_MONITOR_CTL_MSR); |
| 181 | |
| 182 | printk(BIOS_DEBUG, "STM: MSEG Initialized (%d) 0x%08x 0x%08x\n", |
| 183 | cpu, MsegChk.hi, MsegChk.lo); |
| 184 | |
| 185 | // setup the descriptor for this cpu |
| 186 | setup_smm_descriptor((void *)smbase, (void *) base_smbase, |
| 187 | cpu, offset32); |
| 188 | } else { |
| 189 | printk(BIOS_DEBUG, |
| 190 | "STM: Error in STM load, STM not enabled: %d\n", |
| 191 | cpu); |
| 192 | } |
| 193 | } |