xref: /aosp_15_r20/external/coreboot/src/security/intel/stm/SmmStm.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: BSD-2-Clause */
2 
3 #include <console/console.h>
4 #include <cpu/x86/cr.h>
5 #include <cpu/x86/mp.h>
6 #include <cpu/x86/msr.h>
7 #include <cpu/x86/cache.h>
8 #include <security/intel/stm/SmmStm.h>
9 #include <stdbool.h>
10 #include <string.h>
11 
12 #define TXT_EVTYPE_BASE 0x400
13 #define TXT_EVTYPE_STM_HASH (TXT_EVTYPE_BASE + 14)
14 
15 #define RDWR_ACCS 3
16 #define FULL_ACCS 7
17 
18 #define SIZE_4KB 0x00001000
19 #define SIZE_4MB 0x00400000
20 
21 #define PTP_SIZE SIZE_4KB
22 
23 #define IA32_PG_P (1 << 0)
24 #define IA32_PG_RW (1 << 1)
25 #define IA32_PG_PS (1 << 7)
26 
27 #define STM_PAGE_SHIFT 12
28 #define STM_PAGE_MASK 0xFFF
29 #define STM_SIZE_TO_PAGES(a)                                                   \
30 	(((a) >> STM_PAGE_SHIFT) + (((a)&STM_PAGE_MASK) ? 1 : 0))
31 #define STM_PAGES_TO_SIZE(a) ((a) << STM_PAGE_SHIFT)
32 
33 #define STM_ACCESS_DENIED 15
34 #define STM_UNSUPPORTED 3
35 
36 #define STM_BUFFER_TOO_SMALL 1
37 
38 #define STM_SM_MONITOR_STATE_ENABLED 1
39 
40 typedef struct {
41 	uint64_t vmcs_revision_id : 31;
42 	uint64_t always_zero : 1;
43 	uint64_t vmcs_size : 13;
44 	uint64_t reserved1 : 3;
45 	uint64_t vmxon_add_width : 1;
46 	uint64_t stm_supported : 1;
47 	uint64_t vmcs_memory_type : 4;
48 	uint64_t in_out_reporting : 1;
49 	uint64_t may_clear_defaults : 1;
50 	uint64_t reserved2 : 8;
51 } VMX_BASIC_MSR_BITS;
52 
53 typedef union {
54 	VMX_BASIC_MSR_BITS bits;
55 	uint64_t uint64;
56 	msr_t msr;
57 } VMX_BASIC_MSR;
58 
59 typedef struct {
60 	uint64_t valid : 1;
61 	uint64_t reserved1 : 1;
62 	uint64_t vmx_off_blockSmi : 1;
63 	uint64_t reserved2 : 9;
64 	uint64_t mseg_address : 20;
65 	uint64_t reserved3 : 32;
66 } SMM_MONITOR_CTL_MSR_BITS;
67 
68 extern struct mp_state {
69 	struct mp_ops ops;
70 	int cpu_count;
71 	uintptr_t perm_smbase;
72 	size_t perm_smsize;
73 	size_t smm_save_state_size;
74 	bool do_smm;
75 } mp_state;
76 
77 typedef union {
78 	SMM_MONITOR_CTL_MSR_BITS bits;
79 	uint64_t uint64;
80 	msr_t msr;
81 } SMM_MONITOR_CTL_MSR;
82 
83 // Template of STM_RSC_END structure for copying.
84 
85 STM_RSC_END m_rsc_end_node = {
86 	{END_OF_RESOURCES, sizeof(STM_RSC_END)},
87 };
88 
89 uint8_t *m_stm_resources_ptr = NULL;
90 uint32_t m_stm_resource_total_size = 0x0;
91 uint32_t m_stm_resource_size_used = 0x0;
92 uint32_t m_stm_resource_size_available = 0x0;
93 
94 uint8_t *stm_resource_heap = NULL;
95 
96 uint32_t m_stm_state = 0;
97 
98 /*
99  * Handle single Resource to see if it can be merged into Record.
100  *
101  *  @param resource  A pointer to resource node to be added
102  *  @param record    A pointer to record node to be merged
103  *
104  *  @retval true  resource handled
105  *  @retval false resource is not handled
106  */
107 
handle_single_resource(STM_RSC * resource,STM_RSC * record)108 static bool handle_single_resource(STM_RSC *resource, STM_RSC *record)
109 {
110 	uint64_t resource_lo = 0;
111 	uint64_t resource_hi = 0;
112 	uint64_t record_lo = 0;
113 	uint64_t record_hi = 0;
114 
115 	// Calling code is responsible for making sure that
116 	// Resource->Header.RscType == (*Record)->Header.RscType
117 	// thus we use just one of them as switch variable.
118 
119 	switch (resource->header.rsc_type) {
120 	case MEM_RANGE:
121 	case MMIO_RANGE:
122 		resource_lo = resource->mem.base;
123 		resource_hi = resource->mem.base + resource->mem.length;
124 		record_lo = record->mem.base;
125 		record_hi = record->mem.base + record->mem.length;
126 		if (resource->mem.rwx_attributes
127 		    != record->mem.rwx_attributes) {
128 			if ((resource_lo == record_lo)
129 			    && (resource_hi == record_hi)) {
130 				record->mem.rwx_attributes =
131 					resource->mem.rwx_attributes
132 					| record->mem.rwx_attributes;
133 				return true;
134 			} else {
135 				return false;
136 			}
137 		}
138 		break;
139 	case IO_RANGE:
140 	case TRAPPED_IO_RANGE:
141 		resource_lo = (uint64_t)resource->io.base;
142 		resource_hi = (uint64_t)resource->io.base
143 			      + (uint64_t)resource->io.length;
144 		record_lo = (uint64_t)record->io.base;
145 		record_hi =
146 			(uint64_t)record->io.base + (uint64_t)record->io.length;
147 		break;
148 	case PCI_CFG_RANGE:
149 		if ((resource->pci_cfg.originating_bus_number
150 		     != record->pci_cfg.originating_bus_number)
151 		    || (resource->pci_cfg.last_node_index
152 			!= record->pci_cfg.last_node_index))
153 			return false;
154 
155 		if (memcmp(resource->pci_cfg.pci_device_path,
156 			   record->pci_cfg.pci_device_path,
157 			   sizeof(STM_PCI_DEVICE_PATH_NODE)
158 				   * (resource->pci_cfg.last_node_index + 1))
159 		    != 0) {
160 			return false;
161 		}
162 		resource_lo = (uint64_t)resource->pci_cfg.base;
163 		resource_hi = (uint64_t)resource->pci_cfg.base
164 			      + (uint64_t)resource->pci_cfg.length;
165 		record_lo = (uint64_t)record->pci_cfg.base;
166 		record_hi = (uint64_t)record->pci_cfg.base
167 			    + (uint64_t)record->pci_cfg.length;
168 		if (resource->pci_cfg.rw_attributes
169 		    != record->pci_cfg.rw_attributes) {
170 			if ((resource_lo == record_lo)
171 			    && (resource_hi == record_hi)) {
172 				record->pci_cfg.rw_attributes =
173 					resource->pci_cfg.rw_attributes
174 					| record->pci_cfg.rw_attributes;
175 				return true;
176 			} else {
177 				return false;
178 			}
179 		}
180 		break;
181 	case MACHINE_SPECIFIC_REG:
182 
183 		// Special case - merge MSR masks in place.
184 		if (resource->msr.msr_index != record->msr.msr_index)
185 			return false;
186 		record->msr.read_mask |= resource->msr.read_mask;
187 		record->msr.write_mask |= resource->msr.write_mask;
188 		return true;
189 	default:
190 		return false;
191 	}
192 
193 	// If resources are disjoint
194 	if ((resource_hi < record_lo) || (resource_lo > record_hi))
195 		return false;
196 
197 	// If resource is consumed by record.
198 	if ((resource_lo >= record_lo) && (resource_hi <= record_hi))
199 		return true;
200 
201 	// Resources are overlapping.
202 	// Resource and record are merged.
203 	resource_lo = (resource_lo < record_lo) ? resource_lo : record_lo;
204 	resource_hi = (resource_hi > record_hi) ? resource_hi : record_hi;
205 
206 	switch (resource->header.rsc_type) {
207 	case MEM_RANGE:
208 	case MMIO_RANGE:
209 		record->mem.base = resource_lo;
210 		record->mem.length = resource_hi - resource_lo;
211 		break;
212 	case IO_RANGE:
213 	case TRAPPED_IO_RANGE:
214 		record->io.base = (uint64_t)resource_lo;
215 		record->io.length = (uint64_t)(resource_hi - resource_lo);
216 		break;
217 	case PCI_CFG_RANGE:
218 		record->pci_cfg.base = (uint64_t)resource_lo;
219 		record->pci_cfg.length = (uint64_t)(resource_hi - resource_lo);
220 		break;
221 	default:
222 		return false;
223 	}
224 
225 	return true;
226 }
227 
228 /*
229  * Add resource node.
230  *
231  * @param Resource  A pointer to resource node to be added
232  */
add_single_resource(STM_RSC * resource)233 static void add_single_resource(STM_RSC *resource)
234 {
235 	STM_RSC *record;
236 
237 	record = (STM_RSC *)m_stm_resources_ptr;
238 
239 	while (true) {
240 		if (record->header.rsc_type == END_OF_RESOURCES)
241 			break;
242 
243 		// Go to next record if resource and record types don't match.
244 		if (resource->header.rsc_type != record->header.rsc_type) {
245 			record = (STM_RSC *)((void *)record
246 					     + record->header.length);
247 			continue;
248 		}
249 
250 		// Record is handled inside of procedure - don't adjust.
251 		if (handle_single_resource(resource, record))
252 			return;
253 		record = (STM_RSC *)((void *)record + record->header.length);
254 	}
255 
256 	// Add resource to the end of area.
257 	memcpy(m_stm_resources_ptr + m_stm_resource_size_used
258 		       - sizeof(m_rsc_end_node),
259 	       resource, resource->header.length);
260 	memcpy(m_stm_resources_ptr + m_stm_resource_size_used
261 		       - sizeof(m_rsc_end_node) + resource->header.length,
262 	       &m_rsc_end_node, sizeof(m_rsc_end_node));
263 	m_stm_resource_size_used += resource->header.length;
264 	m_stm_resource_size_available =
265 		m_stm_resource_total_size - m_stm_resource_size_used;
266 }
267 
268 /*
269  *  Add resource list.
270  *
271  *  @param resource_list   A pointer to resource list to be added
272  *  @param num_entries     Optional number of entries.
273  *		            If 0, list must be terminated by END_OF_RESOURCES.
274  */
add_resource(STM_RSC * resource_list,uint32_t num_entries)275 static void add_resource(STM_RSC *resource_list, uint32_t num_entries)
276 {
277 	uint32_t count;
278 	uint32_t index;
279 	STM_RSC *resource;
280 
281 	if (num_entries == 0)
282 		count = 0xFFFFFFFF;
283 	else
284 		count = num_entries;
285 
286 	resource = resource_list;
287 
288 	for (index = 0; index < count; index++) {
289 		if (resource->header.rsc_type == END_OF_RESOURCES)
290 			return;
291 		add_single_resource(resource);
292 		resource =
293 			(STM_RSC *)((void *)resource + resource->header.length);
294 	}
295 }
296 
297 /*
298  *  Validate resource list.
299  *
300  *  @param resource_list  A pointer to resource list to be added
301  *  @param num_entries    Optional number of entries.
302  *			If 0, list must be terminated by END_OF_RESOURCES.
303  *
304  *  @retval true  resource valid
305  *  @retval false resource invalid
306  */
validate_resource(STM_RSC * resource_list,uint32_t num_entries)307 static bool validate_resource(STM_RSC *resource_list, uint32_t num_entries)
308 {
309 	uint32_t count;
310 	uint32_t index;
311 	STM_RSC *resource;
312 	uint32_t sub_index;
313 
314 	// If NumEntries == 0 make it very big. Scan will be terminated by
315 	// END_OF_RESOURCES.
316 	if (num_entries == 0)
317 		count = 0xFFFFFFFF;
318 	else
319 		count = num_entries;
320 
321 	// Start from beginning of resource list.
322 	resource = resource_list;
323 
324 	for (index = 0; index < count; index++) {
325 		printk(BIOS_DEBUG, "STM: %s (%u) - RscType(%x) length(0x%x)\n",
326 			__func__,
327 			index,
328 			resource->header.rsc_type,
329 			resource->header.length);
330 		// Validate resource.
331 		switch (resource->header.rsc_type) {
332 		case END_OF_RESOURCES:
333 			if (resource->header.length != sizeof(STM_RSC_END))
334 				return false;
335 
336 			// If we are passed actual number of resources to add,
337 			// END_OF_RESOURCES structure between them is considered
338 			// an error. If NumEntries == 0 END_OF_RESOURCES is a
339 			// termination.
340 			if (num_entries != 0)
341 				return false;
342 
343 			// If NumEntries == 0 and list reached end - return
344 			// success.
345 			return true;
346 
347 		case MEM_RANGE:
348 		case MMIO_RANGE:
349 			printk(BIOS_DEBUG,
350 				"STM: %s - MEM (0x%0llx, 0x%0llx)\n",
351 				__func__,
352 				resource->mem.base,
353 				resource->mem.length);
354 
355 			if (resource->header.length != sizeof(STM_RSC_MEM_DESC))
356 				return false;
357 			break;
358 
359 		case IO_RANGE:
360 		case TRAPPED_IO_RANGE:
361 			if (resource->header.length != sizeof(STM_RSC_IO_DESC))
362 				return false;
363 
364 			if ((resource->io.base + resource->io.length) > 0xFFFF)
365 				return false;
366 			break;
367 
368 		case PCI_CFG_RANGE:
369 			printk(BIOS_DEBUG,
370 			       "STM: %s - PCI (0x%02x, 0x%08x, 0x%02x, 0x%02x)\n",
371 			       __func__,
372 			       resource->pci_cfg.originating_bus_number,
373 			       resource->pci_cfg.last_node_index,
374 			       resource->pci_cfg.pci_device_path[0].pci_device,
375 			       resource->pci_cfg.pci_device_path[0]
376 				       .pci_function);
377 			if (resource->header.length
378 			    != sizeof(STM_RSC_PCI_CFG_DESC)
379 				       + (sizeof(STM_PCI_DEVICE_PATH_NODE)
380 					  * resource->pci_cfg.last_node_index))
381 				return false;
382 			for (sub_index = 0;
383 			     sub_index <= resource->pci_cfg.last_node_index;
384 			     sub_index++) {
385 				if ((resource->pci_cfg
386 					     .pci_device_path[sub_index]
387 					     .pci_device
388 				     > 0x1F)
389 				    || (resource->pci_cfg
390 						.pci_device_path[sub_index]
391 						.pci_function
392 					> 7))
393 					return false;
394 			}
395 			if ((resource->pci_cfg.base + resource->pci_cfg.length)
396 			    > 0x1000)
397 				return false;
398 			break;
399 
400 		case MACHINE_SPECIFIC_REG:
401 			if (resource->header.length != sizeof(STM_RSC_MSR_DESC))
402 				return false;
403 			break;
404 
405 		default:
406 			printk(BIOS_DEBUG, "STM: %s - Unknown RscType(%x)\n",
407 			       __func__, resource->header.rsc_type);
408 			return false;
409 		}
410 		resource =
411 			(STM_RSC *)((void *)resource + resource->header.length);
412 	}
413 	return true;
414 }
415 
416 /*
417  * Get resource list.
418  * EndResource is excluded.
419  *
420  *  @param resou rce_list  A pointer to resource list to be added
421  *  @param num_entries    Optional number of entries.
422  *			If 0, list must be terminated by END_OF_RESOURCES.
423  *
424  *  @retval true  resource valid
425  *  @retval false resource invalid
426  */
get_resource_size(STM_RSC * resource_list,uint32_t num_entries)427 static uint32_t get_resource_size(STM_RSC *resource_list, uint32_t num_entries)
428 {
429 	uint32_t count;
430 	uint32_t index;
431 	STM_RSC *resource;
432 
433 	resource = resource_list;
434 
435 	// If NumEntries == 0 make it very big. Scan will be terminated by
436 	// END_OF_RESOURCES.
437 	if (num_entries == 0)
438 		count = 0xFFFFFFFF;
439 	else
440 		count = num_entries;
441 
442 	// Start from beginning of resource list.
443 	resource = resource_list;
444 
445 	for (index = 0; index < count; index++) {
446 		if (resource->header.rsc_type == END_OF_RESOURCES)
447 			break;
448 		resource =
449 			(STM_RSC *)((void *)resource + resource->header.length);
450 	}
451 	return (uint32_t)((uint32_t)resource - (uint32_t)resource_list);
452 }
453 
454 /*
455  * Add resources in list to database. Allocate new memory areas as needed.
456  *
457  *  @param resource_list  A pointer to resource list to be added
458  *  @param num_entries    Optional number of entries.
459  *			If 0, list must be terminated by END_OF_RESOURCES.
460  *
461  *  @retval SUCCESS       If resources are added
462  *  @retval INVALID_PARAMETER  If nested procedure detected resource failure
463  *  @retval OUT_OF_RESOURCES   If nested procedure returned it and we cannot
464  *					allocate more areas.
465  */
add_pi_resource(STM_RSC * resource_list,uint32_t num_entries)466 int add_pi_resource(STM_RSC *resource_list, uint32_t num_entries)
467 {
468 	size_t resource_size;
469 
470 	printk(BIOS_DEBUG, "STM: %s - Enter\n", __func__);
471 
472 	if (!validate_resource(resource_list, num_entries))
473 		return -1; // INVALID_PARAMETER;
474 
475 	resource_size = get_resource_size(resource_list, num_entries);
476 	printk(BIOS_DEBUG, "STM: ResourceSize - 0x%08zx\n", resource_size);
477 	if (resource_size == 0)
478 		return -1; // INVALID_PARAMETER;
479 
480 	if (!m_stm_resources_ptr) {
481 		// Copy EndResource for initialization
482 		m_stm_resources_ptr = stm_resource_heap;
483 		m_stm_resource_total_size = CONFIG_BIOS_RESOURCE_LIST_SIZE;
484 		memset(m_stm_resources_ptr, 0, CONFIG_BIOS_RESOURCE_LIST_SIZE);
485 
486 		memcpy(m_stm_resources_ptr, &m_rsc_end_node,
487 		       sizeof(m_rsc_end_node));
488 		m_stm_resource_size_used = sizeof(m_rsc_end_node);
489 		m_stm_resource_size_available =
490 			m_stm_resource_total_size - sizeof(m_rsc_end_node);
491 		wbinvd(); // force to memory
492 
493 	} else {
494 		if (m_stm_resource_size_available < resource_size) {
495 			printk(BIOS_DEBUG,
496 			"STM: ERROR - not enough space for SMM resource list\n");
497 			return -1; // OUT_OF_RESOURCES
498 		}
499 	}
500 
501 	// Check duplication
502 	add_resource(resource_list, num_entries);
503 
504 	return 0; // SUCCESS;
505 }
506 
507 /*
508  * Delete resources in list to database.
509  *
510  *  @param resource_list  A pointer to resource list to be deleted
511  *			 NULL means delete all resources.
512  *  @param num_entries    Optional number of entries.
513  *			 If 0, list must be terminated by END_OF_RESOURCES.
514  *
515  *  @retval SUCCESS            If resources are deleted
516  *  @retval INVALID_PARAMETER  If nested procedure detected resource failure
517  */
delete_pi_resource(STM_RSC * resource_list,uint32_t num_entries)518 int32_t delete_pi_resource(STM_RSC *resource_list, uint32_t num_entries)
519 {
520 	if (resource_list) {
521 		// ASSERT (false);
522 		return -1; // UNSUPPORTED;
523 	}
524 
525 	// Delete all
526 	memcpy(m_stm_resources_ptr, &m_rsc_end_node, sizeof(m_rsc_end_node));
527 	m_stm_resource_size_used = sizeof(m_rsc_end_node);
528 	m_stm_resource_size_available =
529 		m_stm_resource_total_size - sizeof(m_rsc_end_node);
530 	return 0; // SUCCESS;
531 }
532 
533 /*
534  * Get BIOS resources.
535  *
536  *  @param resource_list  A pointer to resource list to be filled
537  *  @param resource_size  On input it means size of resource list input.
538  *			  On output it means size of resource list filled,
539  *			  or the size of resource list to be filled if size is
540  *			  too small.
541  *
542  *  @retval SUCCESS            If resources are returned.
543  *  @retval BUFFER_TOO_SMALL   If resource list buffer is too small to hold
544  *				the whole resource list.
545  */
get_pi_resource(STM_RSC * resource_list,uint32_t * resource_size)546 int32_t get_pi_resource(STM_RSC *resource_list, uint32_t *resource_size)
547 {
548 	if (*resource_size < m_stm_resource_size_used) {
549 		*resource_size = (uint32_t)m_stm_resource_size_used;
550 		return -1; // BUFFER_TOO_SMALL;
551 	}
552 
553 	memcpy(resource_list, m_stm_resources_ptr, m_stm_resource_size_used);
554 	*resource_size = (uint32_t)m_stm_resource_size_used;
555 	return 0; // SUCCESS;
556 }
557 
558 /*
559  *  Get 4K page aligned VMCS size.
560  *  @return 4K page aligned VMCS size
561  */
get_vmcs_size(void)562 static uint32_t get_vmcs_size(void)
563 {
564 	uint32_t this_vmcs_size;
565 	VMX_BASIC_MSR msr_data64;
566 	int stm_support;
567 
568 	msr_data64.msr = rdmsr(IA32_VMX_BASIC_MSR);
569 
570 	this_vmcs_size = msr_data64.bits.vmcs_size;
571 	stm_support = msr_data64.bits.stm_supported;
572 	printk(BIOS_DEBUG, "STM: %s: Size %d StmSupport %d\n", __func__,
573 	       this_vmcs_size, stm_support);
574 
575 	// VMCS require 0x1000 alignment
576 	this_vmcs_size = STM_PAGES_TO_SIZE(STM_SIZE_TO_PAGES(this_vmcs_size));
577 
578 	return this_vmcs_size;
579 }
580 
581 /*
582  *  Create 4G page table for STM.
583  *  2M PTEs for x86_64 or 2M PTEs for x86_32.
584  *
585  *  @param pageable_base        The page table base in MSEG
586  */
stm_gen_4g_pagetable_x64(uint32_t pagetable_base)587 void stm_gen_4g_pagetable_x64(uint32_t pagetable_base)
588 {
589 	uint32_t index;
590 	uint32_t sub_index;
591 	uint64_t *pde;
592 	uint64_t *pte;
593 	uint64_t *pml4;
594 
595 	pml4 = (uint64_t *)(uint32_t)pagetable_base;
596 	pagetable_base += PTP_SIZE;
597 	*pml4 = pagetable_base | IA32_PG_RW | IA32_PG_P;
598 
599 	pde = (uint64_t *)(uint32_t)pagetable_base;
600 	pagetable_base += PTP_SIZE;
601 	pte = (uint64_t *)(uint32_t)pagetable_base;
602 
603 	for (index = 0; index < 4; index++) {
604 		*pde = pagetable_base | IA32_PG_RW | IA32_PG_P;
605 		pde++;
606 		pagetable_base += PTP_SIZE;
607 
608 		for (sub_index = 0; sub_index < SIZE_4KB / sizeof(*pte);
609 		     sub_index++) {
610 			*pte = (((index << 9) + sub_index) << 21) | IA32_PG_PS
611 			       | IA32_PG_RW | IA32_PG_P;
612 			pte++;
613 		}
614 	}
615 }
616 
617 /*
618  * Check STM image size.
619  *
620  *  @param stm_image      STM image
621  *  @param stm_imageSize  STM image size
622  *
623  *  @retval true  check pass
624  *  @retval false check fail
625  */
626 
stm_check_stm_image(void * stm_image,uint32_t stm_imagesize)627 bool stm_check_stm_image(void *stm_image, uint32_t stm_imagesize)
628 {
629 	uint32_t min_mseg_size;
630 	STM_HEADER *stm_header;
631 
632 	stm_header = (STM_HEADER *)stm_image;
633 
634 	// Get Minimal required Mseg size
635 	min_mseg_size = (STM_PAGES_TO_SIZE(STM_SIZE_TO_PAGES(
636 				 stm_header->sw_stm_hdr.static_image_size))
637 			 + stm_header->sw_stm_hdr.additional_dynamic_memory_size
638 			 + (stm_header->sw_stm_hdr.per_proc_dynamic_memory_size
639 			    + get_vmcs_size() * 2)
640 				   * mp_state.cpu_count);
641 	if (min_mseg_size < stm_imagesize)
642 		min_mseg_size = stm_imagesize;
643 
644 	if (stm_header->hw_stm_hdr.cr3_offset
645 	    >= stm_header->sw_stm_hdr.static_image_size) {
646 		// We will create page table, just in case that SINIT does not
647 		// create it.
648 		if (min_mseg_size < stm_header->hw_stm_hdr.cr3_offset
649 					    + STM_PAGES_TO_SIZE(6)) {
650 			min_mseg_size = stm_header->hw_stm_hdr.cr3_offset
651 					+ STM_PAGES_TO_SIZE(6);
652 		}
653 	}
654 
655 	// Check if it exceeds MSEG size
656 	if (min_mseg_size > CONFIG_MSEG_SIZE)
657 		return false;
658 
659 	return true;
660 }
661 
662 /*
663  *  This function return BIOS STM resource.
664  *  Produced by SmmStm.
665  *  Consumed by SmmMpService when Init.
666  *
667  *  @return BIOS STM resource
668  */
get_stm_resource(void)669 void *get_stm_resource(void)
670 {
671 	return m_stm_resources_ptr;
672 }
673