1 /* SPDX-License-Identifier: BSD-2-Clause */
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>
11 #include <console/console.h>
14 #include <arch/rom_segs.h>
17 * Load STM image to MSEG
19 * @retval SUCCESS STM is loaded to MSEG
21 int load_stm_image(uintptr_t mseg
)
25 uint32_t stm_buffer_size
;
26 uint32_t stm_image_size
;
29 STM_HEADER
*stm_header
;
31 // Extract STM image from FV
32 mseg_base
= (void *)mseg
;
33 stm_buffer_size
= CONFIG_MSEG_SIZE
;
36 memset((void *)mseg_base
, 0, CONFIG_MSEG_SIZE
); // clear the mseg
38 stm_image_size
= cbfs_load("stm.bin", mseg_base
, stm_buffer_size
);
39 printk(BIOS_DEBUG
, "STM:loaded into mseg: 0x%p size: %u\n", mseg_base
,
41 /* status is number of bytes loaded */
42 stm_status
= stm_check_stm_image(mseg_base
, stm_image_size
);
45 printk(BIOS_DEBUG
, "STM: Error in STM image\n");
49 stm_header
= mseg_base
;
51 stm_gen_4g_pagetable_x64((uint32_t)mseg_base
52 + stm_header
->hw_stm_hdr
.cr3_offset
);
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
);
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
));
65 status
= 0; // always return good for now
75 static void read_gdtr(struct descriptor
*gdtr
)
77 __asm__
__volatile__("sgdt %0" : "=m"(*gdtr
));
80 void setup_smm_descriptor(void *smbase
, int32_t apic_id
, int32_t entry32_off
)
82 struct descriptor gdtr
;
83 void *smbase_processor
;
86 TXT_PROCESSOR_SMM_DESCRIPTOR
*psd
;
88 smbase_processor
= (void *)SMM_DEFAULT_BASE
;//we are here
89 psd
= smbase
+ SMM_PSD_OFFSET
;
92 "STM: Smm Descriptor setup: Smbase: %p Smbase_processor: %p Psd: %p\n",
97 memset(psd
, 0, sizeof(TXT_PROCESSOR_SMM_DESCRIPTOR
));
99 memcpy(&psd
->signature
, TXT_PROCESSOR_SMM_DESCRIPTOR_SIGNATURE
, 8);
100 psd
->smm_descriptor_ver_major
=
101 TXT_PROCESSOR_SMM_DESCRIPTOR_VERSION_MAJOR
;
102 psd
->smm_descriptor_ver_minor
=
103 TXT_PROCESSOR_SMM_DESCRIPTOR_VERSION_MINOR
;
104 psd
->smm_smi_handler_rip
=
105 (uint64_t)((uintptr_t)smbase
+ SMM_ENTRY_OFFSET
+
107 psd
->local_apic_id
= apic_id
;
108 psd
->size
= sizeof(TXT_PROCESSOR_SMM_DESCRIPTOR
);
110 psd
->bios_hw_resource_requirements_ptr
=
111 (uint64_t)((uintptr_t)get_stm_resource());
112 psd
->smm_cs
= ROM_CODE_SEG
;
113 psd
->smm_ds
= ROM_DATA_SEG
;
114 psd
->smm_ss
= ROM_DATA_SEG
;
115 psd
->smm_other_segment
= ROM_DATA_SEG
;
116 psd
->smm_tr
= SMM_TASK_STATE_SEG
;
118 // At this point the coreboot smm_stub is relative to the default
119 // smbase and not the one for the smi handler in tseg. So we have
120 // to adjust the gdtr.base
124 gdtr
.base
-= (uintptr_t)smbase_processor
;
125 gdtr
.base
+= (uintptr_t)smbase
;
127 psd
->smm_gdt_ptr
= gdtr
.base
;
128 psd
->smm_gdt_size
= gdtr
.limit
+ 1; // the stm will subtract, so add
129 printk(BIOS_DEBUG
, "STM: Smm Descriptor setup complete - Smbase: %p Psd: %p\n",
133 extern uint8_t *stm_resource_heap
;
135 #define FXSAVE_SIZE 512
137 static int stm_load_status
= 0;
139 void stm_setup(uintptr_t mseg
, int cpu
, uintptr_t smbase
,
140 uintptr_t base_smbase
, uint32_t offset32
)
146 uintptr_t addr_calc
; // used to calculate the stm resource heap area
148 printk(BIOS_DEBUG
, "STM: set up for cpu %d\n", cpu
);
150 vmx_basic
= rdmsr(IA32_VMX_BASIC_MSR
);
152 // Does this processor support an STM?
153 if ((vmx_basic
.hi
& VMX_BASIC_HI_DUAL_MONITOR
) != VMX_BASIC_HI_DUAL_MONITOR
) {
154 printk(BIOS_WARNING
, "STM: not supported on CPU %d\n", cpu
);
158 // This code moved here because paralled SMM set can cause
159 // some processor to receive a bad value
160 // calculate the location in SMRAM
161 addr_calc
= mseg
- CONFIG_BIOS_RESOURCE_LIST_SIZE
;
162 stm_resource_heap
= (uint8_t *)addr_calc
;
165 // need to create the BIOS resource list once
166 printk(BIOS_DEBUG
, "STM: stm_resource_heap located at %p\n",
171 stm_load_status
= load_stm_image(mseg
);
174 if (stm_load_status
== 0) {
175 // enable STM for this cpu
176 InitMseg
.lo
= mseg
| IA32_SMM_MONITOR_VALID
;
179 wrmsr(IA32_SMM_MONITOR_CTL_MSR
, InitMseg
);
181 MsegChk
= rdmsr(IA32_SMM_MONITOR_CTL_MSR
);
183 printk(BIOS_DEBUG
, "STM: MSEG Initialized (%d) 0x%08x 0x%08x\n",
184 cpu
, MsegChk
.hi
, MsegChk
.lo
);
186 // setup the descriptor for this cpu
187 setup_smm_descriptor((void *)smbase
, cpu
, offset32
);
191 "STM: Error in STM load, STM not enabled: %d\n",