]> git.proxmox.com Git - mirror_edk2.git/blame - UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmStm.c
UefiCpuPkg/SmmCpuFeaturesLib: Clean up header file inclusion in SmmStm.c
[mirror_edk2.git] / UefiCpuPkg / Library / SmmCpuFeaturesLib / SmmStm.c
CommitLineData
09119a00
MK
1/** @file\r
2 SMM STM support functions\r
3\r
1c7a65eb 4 Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>\r
0acd8697 5 SPDX-License-Identifier: BSD-2-Clause-Patent\r
09119a00
MK
6\r
7**/\r
8\r
edd46cd4 9#include <PiMm.h>\r
09119a00 10#include <Library/BaseMemoryLib.h>\r
09119a00 11#include <Library/HobLib.h>\r
09119a00
MK
12#include <Library/UefiBootServicesTableLib.h>\r
13#include <Library/SmmServicesTableLib.h>\r
14#include <Library/TpmMeasurementLib.h>\r
01acb06c
RN
15#include <Register/Intel/Cpuid.h>\r
16#include <Register/Intel/ArchitecturalMsr.h>\r
17#include <Register/Intel/SmramSaveStateMap.h>\r
09119a00
MK
18\r
19#include <Protocol/MpService.h>\r
20\r
3e062ea4 21#include "CpuFeaturesLib.h"\r
09119a00
MK
22#include "SmmStm.h"\r
23\r
053e878b
MK
24#define TXT_EVTYPE_BASE 0x400\r
25#define TXT_EVTYPE_STM_HASH (TXT_EVTYPE_BASE + 14)\r
09119a00 26\r
053e878b
MK
27#define RDWR_ACCS 3\r
28#define FULL_ACCS 7\r
09119a00 29\r
09119a00
MK
30EFI_HANDLE mStmSmmCpuHandle = NULL;\r
31\r
053e878b 32BOOLEAN mLockLoadMonitor = FALSE;\r
09119a00
MK
33\r
34//\r
35// Template of STM_RSC_END structure for copying.\r
36//\r
053e878b
MK
37GLOBAL_REMOVE_IF_UNREFERENCED STM_RSC_END mRscEndNode = {\r
38 { END_OF_RESOURCES, sizeof (STM_RSC_END) },\r
09119a00
MK
39};\r
40\r
41GLOBAL_REMOVE_IF_UNREFERENCED UINT8 *mStmResourcesPtr = NULL;\r
42GLOBAL_REMOVE_IF_UNREFERENCED UINTN mStmResourceTotalSize = 0x0;\r
43GLOBAL_REMOVE_IF_UNREFERENCED UINTN mStmResourceSizeUsed = 0x0;\r
44GLOBAL_REMOVE_IF_UNREFERENCED UINTN mStmResourceSizeAvailable = 0x0;\r
45\r
46GLOBAL_REMOVE_IF_UNREFERENCED UINT32 mStmState = 0;\r
47\r
48//\r
49// System Configuration Table pointing to STM Configuration Table\r
50//\r
51GLOBAL_REMOVE_IF_UNREFERENCED\r
053e878b 52EFI_SM_MONITOR_INIT_PROTOCOL mSmMonitorInitProtocol = {\r
09119a00
MK
53 LoadMonitor,\r
54 AddPiResource,\r
55 DeletePiResource,\r
56 GetPiResource,\r
57 GetMonitorState,\r
58};\r
59\r
053e878b 60#define CPUID1_EDX_XD_SUPPORT 0x100000\r
09119a00
MK
61\r
62//\r
63// External global variables associated with SMI Handler Template\r
64//\r
65extern CONST TXT_PROCESSOR_SMM_DESCRIPTOR gcStmPsd;\r
66extern UINT32 gStmSmbase;\r
67extern volatile UINT32 gStmSmiStack;\r
68extern UINT32 gStmSmiCr3;\r
69extern volatile UINT8 gcStmSmiHandlerTemplate[];\r
70extern CONST UINT16 gcStmSmiHandlerSize;\r
71extern UINT16 gcStmSmiHandlerOffset;\r
72extern BOOLEAN gStmXdSupported;\r
73\r
74//\r
75// Variables used by SMI Handler\r
76//\r
77IA32_DESCRIPTOR gStmSmiHandlerIdtr;\r
78\r
79//\r
80// MP Services Protocol\r
81//\r
82EFI_MP_SERVICES_PROTOCOL *mSmmCpuFeaturesLibMpService = NULL;\r
83\r
84//\r
85// MSEG Base and Length in SMRAM\r
86//\r
87UINTN mMsegBase = 0;\r
88UINTN mMsegSize = 0;\r
89\r
90BOOLEAN mStmConfigurationTableInitialized = FALSE;\r
91\r
09119a00 92/**\r
2002e950 93 The constructor function for the Traditional MM library instance with STM.\r
09119a00
MK
94\r
95 @param[in] ImageHandle The firmware allocated handle for the EFI image.\r
96 @param[in] SystemTable A pointer to the EFI System Table.\r
97\r
98 @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS.\r
99\r
100**/\r
101EFI_STATUS\r
102EFIAPI\r
103SmmCpuFeaturesLibStmConstructor (\r
104 IN EFI_HANDLE ImageHandle,\r
105 IN EFI_SYSTEM_TABLE *SystemTable\r
106 )\r
107{\r
108 EFI_STATUS Status;\r
109 CPUID_VERSION_INFO_ECX RegEcx;\r
110 EFI_HOB_GUID_TYPE *GuidHob;\r
111 EFI_SMRAM_DESCRIPTOR *SmramDescriptor;\r
112\r
1c7a65eb
LG
113 //\r
114 // Initialize address fixup\r
115 //\r
116 SmmCpuFeaturesLibStmSmiEntryFixupAddress ();\r
117\r
09119a00 118 //\r
2002e950 119 // Perform library initialization common across all instances\r
09119a00 120 //\r
2002e950 121 CpuFeaturesLibInitialization ();\r
09119a00
MK
122\r
123 //\r
124 // Lookup the MP Services Protocol\r
125 //\r
126 Status = gBS->LocateProtocol (\r
127 &gEfiMpServiceProtocolGuid,\r
128 NULL,\r
129 (VOID **)&mSmmCpuFeaturesLibMpService\r
130 );\r
131 ASSERT_EFI_ERROR (Status);\r
132\r
133 //\r
134 // If CPU supports VMX, then determine SMRAM range for MSEG.\r
135 //\r
136 AsmCpuid (CPUID_VERSION_INFO, NULL, NULL, &RegEcx.Uint32, NULL);\r
137 if (RegEcx.Bits.VMX == 1) {\r
138 GuidHob = GetFirstGuidHob (&gMsegSmramGuid);\r
139 if (GuidHob != NULL) {\r
140 //\r
141 // Retrieve MSEG location from MSEG SRAM HOB\r
142 //\r
053e878b 143 SmramDescriptor = (EFI_SMRAM_DESCRIPTOR *)GET_GUID_HOB_DATA (GuidHob);\r
09119a00 144 if (SmramDescriptor->PhysicalSize > 0) {\r
053e878b
MK
145 mMsegBase = (UINTN)SmramDescriptor->CpuStart;\r
146 mMsegSize = (UINTN)SmramDescriptor->PhysicalSize;\r
09119a00
MK
147 }\r
148 } else if (PcdGet32 (PcdCpuMsegSize) > 0) {\r
149 //\r
150 // Allocate MSEG from SMRAM memory\r
151 //\r
152 mMsegBase = (UINTN)AllocatePages (EFI_SIZE_TO_PAGES (PcdGet32 (PcdCpuMsegSize)));\r
153 if (mMsegBase > 0) {\r
154 mMsegSize = ALIGN_VALUE (PcdGet32 (PcdCpuMsegSize), EFI_PAGE_SIZE);\r
155 } else {\r
156 DEBUG ((DEBUG_ERROR, "Not enough SMRAM resource to allocate MSEG size %08x\n", PcdGet32 (PcdCpuMsegSize)));\r
157 }\r
158 }\r
053e878b 159\r
09119a00
MK
160 if (mMsegBase > 0) {\r
161 DEBUG ((DEBUG_INFO, "MsegBase: 0x%08x, MsegSize: 0x%08x\n", mMsegBase, mMsegSize));\r
162 }\r
163 }\r
164\r
165 return EFI_SUCCESS;\r
166}\r
167\r
168/**\r
169 Internal worker function that is called to complete CPU initialization at the\r
d0c80b8a 170 end of SmmCpuFeaturesInitializeProcessor().\r
09119a00
MK
171\r
172**/\r
173VOID\r
174FinishSmmCpuFeaturesInitializeProcessor (\r
175 VOID\r
176 )\r
177{\r
178 MSR_IA32_SMM_MONITOR_CTL_REGISTER SmmMonitorCtl;\r
179\r
180 //\r
181 // Set MSEG Base Address in SMM Monitor Control MSR.\r
182 //\r
183 if (mMsegBase > 0) {\r
184 SmmMonitorCtl.Uint64 = 0;\r
185 SmmMonitorCtl.Bits.MsegBase = (UINT32)mMsegBase >> 12;\r
186 SmmMonitorCtl.Bits.Valid = 1;\r
187 AsmWriteMsr64 (MSR_IA32_SMM_MONITOR_CTL, SmmMonitorCtl.Uint64);\r
188 }\r
189}\r
190\r
191/**\r
192 Return the size, in bytes, of a custom SMI Handler in bytes. If 0 is\r
193 returned, then a custom SMI handler is not provided by this library,\r
194 and the default SMI handler must be used.\r
195\r
196 @retval 0 Use the default SMI handler.\r
197 @retval > 0 Use the SMI handler installed by SmmCpuFeaturesInstallSmiHandler()\r
198 The caller is required to allocate enough SMRAM for each CPU to\r
199 support the size of the custom SMI handler.\r
200**/\r
201UINTN\r
202EFIAPI\r
203SmmCpuFeaturesGetSmiHandlerSize (\r
204 VOID\r
205 )\r
206{\r
207 return gcStmSmiHandlerSize;\r
208}\r
209\r
210/**\r
211 Install a custom SMI handler for the CPU specified by CpuIndex. This function\r
212 is only called if SmmCpuFeaturesGetSmiHandlerSize() returns a size is greater\r
213 than zero and is called by the CPU that was elected as monarch during System\r
214 Management Mode initialization.\r
215\r
216 @param[in] CpuIndex The index of the CPU to install the custom SMI handler.\r
217 The value must be between 0 and the NumberOfCpus field\r
218 in the System Management System Table (SMST).\r
219 @param[in] SmBase The SMBASE address for the CPU specified by CpuIndex.\r
220 @param[in] SmiStack The stack to use when an SMI is processed by the\r
221 the CPU specified by CpuIndex.\r
222 @param[in] StackSize The size, in bytes, if the stack used when an SMI is\r
223 processed by the CPU specified by CpuIndex.\r
224 @param[in] GdtBase The base address of the GDT to use when an SMI is\r
225 processed by the CPU specified by CpuIndex.\r
226 @param[in] GdtSize The size, in bytes, of the GDT used when an SMI is\r
227 processed by the CPU specified by CpuIndex.\r
228 @param[in] IdtBase The base address of the IDT to use when an SMI is\r
229 processed by the CPU specified by CpuIndex.\r
230 @param[in] IdtSize The size, in bytes, of the IDT used when an SMI is\r
231 processed by the CPU specified by CpuIndex.\r
232 @param[in] Cr3 The base address of the page tables to use when an SMI\r
233 is processed by the CPU specified by CpuIndex.\r
234**/\r
235VOID\r
236EFIAPI\r
237SmmCpuFeaturesInstallSmiHandler (\r
238 IN UINTN CpuIndex,\r
239 IN UINT32 SmBase,\r
240 IN VOID *SmiStack,\r
241 IN UINTN StackSize,\r
242 IN UINTN GdtBase,\r
243 IN UINTN GdtSize,\r
244 IN UINTN IdtBase,\r
245 IN UINTN IdtSize,\r
246 IN UINT32 Cr3\r
247 )\r
248{\r
053e878b
MK
249 EFI_STATUS Status;\r
250 TXT_PROCESSOR_SMM_DESCRIPTOR *Psd;\r
251 VOID *Hob;\r
252 UINT32 RegEax;\r
253 UINT32 RegEdx;\r
254 EFI_PROCESSOR_INFORMATION ProcessorInfo;\r
09119a00 255\r
8491e302 256 CopyMem ((VOID *)((UINTN)SmBase + TXT_SMM_PSD_OFFSET), &gcStmPsd, sizeof (gcStmPsd));\r
053e878b
MK
257 Psd = (TXT_PROCESSOR_SMM_DESCRIPTOR *)(VOID *)((UINTN)SmBase + TXT_SMM_PSD_OFFSET);\r
258 Psd->SmmGdtPtr = GdtBase;\r
09119a00
MK
259 Psd->SmmGdtSize = (UINT32)GdtSize;\r
260\r
261 //\r
262 // Initialize values in template before copy\r
263 //\r
264 gStmSmiStack = (UINT32)((UINTN)SmiStack + StackSize - sizeof (UINTN));\r
265 gStmSmiCr3 = Cr3;\r
266 gStmSmbase = SmBase;\r
267 gStmSmiHandlerIdtr.Base = IdtBase;\r
268 gStmSmiHandlerIdtr.Limit = (UINT16)(IdtSize - 1);\r
269\r
270 if (gStmXdSupported) {\r
271 AsmCpuid (CPUID_EXTENDED_FUNCTION, &RegEax, NULL, NULL, NULL);\r
272 if (RegEax <= CPUID_EXTENDED_FUNCTION) {\r
273 //\r
274 // Extended CPUID functions are not supported on this processor.\r
275 //\r
276 gStmXdSupported = FALSE;\r
277 }\r
278\r
279 AsmCpuid (CPUID_EXTENDED_CPU_SIG, NULL, NULL, NULL, &RegEdx);\r
280 if ((RegEdx & CPUID1_EDX_XD_SUPPORT) == 0) {\r
281 //\r
282 // Execute Disable Bit feature is not supported on this processor.\r
283 //\r
284 gStmXdSupported = FALSE;\r
285 }\r
286 }\r
287\r
288 //\r
289 // Set the value at the top of the CPU stack to the CPU Index\r
290 //\r
053e878b 291 *(UINTN *)(UINTN)gStmSmiStack = CpuIndex;\r
09119a00
MK
292\r
293 //\r
294 // Copy template to CPU specific SMI handler location\r
295 //\r
296 CopyMem (\r
053e878b
MK
297 (VOID *)((UINTN)SmBase + SMM_HANDLER_OFFSET),\r
298 (VOID *)gcStmSmiHandlerTemplate,\r
09119a00
MK
299 gcStmSmiHandlerSize\r
300 );\r
301\r
302 Psd->SmmSmiHandlerRip = SmBase + SMM_HANDLER_OFFSET + gcStmSmiHandlerOffset;\r
053e878b 303 Psd->SmmSmiHandlerRsp = (UINTN)SmiStack + StackSize - sizeof (UINTN);\r
09119a00
MK
304 Psd->SmmCr3 = Cr3;\r
305\r
053e878b
MK
306 DEBUG ((DEBUG_INFO, "CpuSmmStmExceptionStackSize - %x\n", PcdGet32 (PcdCpuSmmStmExceptionStackSize)));\r
307 DEBUG ((DEBUG_INFO, "Pages - %x\n", EFI_SIZE_TO_PAGES (PcdGet32 (PcdCpuSmmStmExceptionStackSize))));\r
308 Psd->StmProtectionExceptionHandler.SpeRsp = (UINT64)(UINTN)AllocatePages (EFI_SIZE_TO_PAGES (PcdGet32 (PcdCpuSmmStmExceptionStackSize)));\r
09119a00
MK
309 Psd->StmProtectionExceptionHandler.SpeRsp += EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (PcdGet32 (PcdCpuSmmStmExceptionStackSize)));\r
310\r
053e878b 311 Psd->BiosHwResourceRequirementsPtr = (UINT64)(UINTN)GetStmResource ();\r
09119a00
MK
312\r
313 //\r
314 // Get the APIC ID for the CPU specified by CpuIndex\r
315 //\r
316 Status = mSmmCpuFeaturesLibMpService->GetProcessorInfo (\r
053e878b
MK
317 mSmmCpuFeaturesLibMpService,\r
318 CpuIndex,\r
319 &ProcessorInfo\r
320 );\r
09119a00
MK
321 ASSERT_EFI_ERROR (Status);\r
322\r
323 Psd->LocalApicId = (UINT32)ProcessorInfo.ProcessorId;\r
053e878b 324 Psd->AcpiRsdp = 0;\r
09119a00
MK
325\r
326 Hob = GetFirstHob (EFI_HOB_TYPE_CPU);\r
327 if (Hob != NULL) {\r
053e878b 328 Psd->PhysicalAddressBits = ((EFI_HOB_CPU *)Hob)->SizeOfMemorySpace;\r
09119a00
MK
329 } else {\r
330 AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);\r
331 if (RegEax >= 0x80000008) {\r
332 AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL);\r
053e878b 333 Psd->PhysicalAddressBits = (UINT8)RegEax;\r
09119a00
MK
334 } else {\r
335 Psd->PhysicalAddressBits = 36;\r
336 }\r
337 }\r
338\r
339 if (!mStmConfigurationTableInitialized) {\r
340 StmSmmConfigurationTableInit ();\r
341 mStmConfigurationTableInitialized = TRUE;\r
342 }\r
343}\r
344\r
345/**\r
346 SMM End Of Dxe event notification handler.\r
347\r
348 STM support need patch AcpiRsdp in TXT_PROCESSOR_SMM_DESCRIPTOR.\r
349\r
350 @param[in] Protocol Points to the protocol's unique identifier.\r
351 @param[in] Interface Points to the interface instance.\r
352 @param[in] Handle The handle on which the interface was installed.\r
353\r
354 @retval EFI_SUCCESS Notification handler runs successfully.\r
355**/\r
356EFI_STATUS\r
357EFIAPI\r
358SmmEndOfDxeEventNotify (\r
359 IN CONST EFI_GUID *Protocol,\r
360 IN VOID *Interface,\r
361 IN EFI_HANDLE Handle\r
362 )\r
363{\r
364 VOID *Rsdp;\r
365 UINTN Index;\r
366 TXT_PROCESSOR_SMM_DESCRIPTOR *Psd;\r
367\r
368 DEBUG ((DEBUG_INFO, "SmmEndOfDxeEventNotify\n"));\r
369\r
370 //\r
371 // found ACPI table RSD_PTR from system table\r
372 //\r
373 Rsdp = NULL;\r
374 for (Index = 0; Index < gST->NumberOfTableEntries; Index++) {\r
375 if (CompareGuid (&(gST->ConfigurationTable[Index].VendorGuid), &gEfiAcpi20TableGuid)) {\r
376 //\r
377 // A match was found.\r
378 //\r
379 Rsdp = gST->ConfigurationTable[Index].VendorTable;\r
380 break;\r
381 }\r
382 }\r
053e878b 383\r
09119a00
MK
384 if (Rsdp == NULL) {\r
385 for (Index = 0; Index < gST->NumberOfTableEntries; Index++) {\r
386 if (CompareGuid (&(gST->ConfigurationTable[Index].VendorGuid), &gEfiAcpi10TableGuid)) {\r
387 //\r
388 // A match was found.\r
389 //\r
390 Rsdp = gST->ConfigurationTable[Index].VendorTable;\r
391 break;\r
392 }\r
393 }\r
394 }\r
395\r
396 for (Index = 0; Index < gSmst->NumberOfCpus; Index++) {\r
397 Psd = (TXT_PROCESSOR_SMM_DESCRIPTOR *)((UINTN)gSmst->CpuSaveState[Index] - SMRAM_SAVE_STATE_MAP_OFFSET + TXT_SMM_PSD_OFFSET);\r
398 DEBUG ((DEBUG_INFO, "Index=%d Psd=%p Rsdp=%p\n", Index, Psd, Rsdp));\r
399 Psd->AcpiRsdp = (UINT64)(UINTN)Rsdp;\r
400 }\r
401\r
402 mLockLoadMonitor = TRUE;\r
403\r
404 return EFI_SUCCESS;\r
405}\r
406\r
407/**\r
408 This function initializes the STM configuration table.\r
409**/\r
410VOID\r
411StmSmmConfigurationTableInit (\r
412 VOID\r
413 )\r
414{\r
053e878b
MK
415 EFI_STATUS Status;\r
416 VOID *Registration;\r
09119a00
MK
417\r
418 Status = gSmst->SmmInstallProtocolInterface (\r
419 &mStmSmmCpuHandle,\r
420 &gEfiSmMonitorInitProtocolGuid,\r
421 EFI_NATIVE_INTERFACE,\r
422 &mSmMonitorInitProtocol\r
423 );\r
424 ASSERT_EFI_ERROR (Status);\r
425\r
426 //\r
427 //\r
428 // Register SMM End of DXE Event\r
429 //\r
430 Status = gSmst->SmmRegisterProtocolNotify (\r
431 &gEfiSmmEndOfDxeProtocolGuid,\r
432 SmmEndOfDxeEventNotify,\r
433 &Registration\r
434 );\r
435 ASSERT_EFI_ERROR (Status);\r
436}\r
437\r
438/**\r
439\r
440 Get STM state.\r
441\r
442 @return STM state\r
443\r
444**/\r
445EFI_SM_MONITOR_STATE\r
446EFIAPI\r
447GetMonitorState (\r
448 VOID\r
449 )\r
450{\r
451 return mStmState;\r
452}\r
453\r
454/**\r
455\r
456 Handle single Resource to see if it can be merged into Record.\r
457\r
458 @param Resource A pointer to resource node to be added\r
459 @param Record A pointer to record node to be merged\r
460\r
461 @retval TRUE resource handled\r
462 @retval FALSE resource is not handled\r
463\r
464**/\r
465BOOLEAN\r
466HandleSingleResource (\r
053e878b
MK
467 IN STM_RSC *Resource,\r
468 IN STM_RSC *Record\r
09119a00
MK
469 )\r
470{\r
053e878b
MK
471 UINT64 ResourceLo;\r
472 UINT64 ResourceHi;\r
473 UINT64 RecordLo;\r
474 UINT64 RecordHi;\r
09119a00
MK
475\r
476 ResourceLo = 0;\r
477 ResourceHi = 0;\r
053e878b
MK
478 RecordLo = 0;\r
479 RecordHi = 0;\r
09119a00
MK
480\r
481 //\r
482 // Calling code is responsible for making sure that\r
483 // Resource->Header.RscType == (*Record)->Header.RscType\r
484 // thus we use just one of them as switch variable.\r
485 //\r
486 switch (Resource->Header.RscType) {\r
053e878b
MK
487 case MEM_RANGE:\r
488 case MMIO_RANGE:\r
489 ResourceLo = Resource->Mem.Base;\r
490 ResourceHi = Resource->Mem.Base + Resource->Mem.Length;\r
491 RecordLo = Record->Mem.Base;\r
492 RecordHi = Record->Mem.Base + Record->Mem.Length;\r
493 if (Resource->Mem.RWXAttributes != Record->Mem.RWXAttributes) {\r
494 if ((ResourceLo == RecordLo) && (ResourceHi == RecordHi)) {\r
495 Record->Mem.RWXAttributes = Resource->Mem.RWXAttributes | Record->Mem.RWXAttributes;\r
496 return TRUE;\r
497 } else {\r
498 return FALSE;\r
499 }\r
500 }\r
501\r
502 break;\r
503 case IO_RANGE:\r
504 case TRAPPED_IO_RANGE:\r
505 ResourceLo = (UINT64)Resource->Io.Base;\r
506 ResourceHi = (UINT64)Resource->Io.Base + (UINT64)Resource->Io.Length;\r
507 RecordLo = (UINT64)Record->Io.Base;\r
508 RecordHi = (UINT64)Record->Io.Base + (UINT64)Record->Io.Length;\r
509 break;\r
510 case PCI_CFG_RANGE:\r
511 if ((Resource->PciCfg.OriginatingBusNumber != Record->PciCfg.OriginatingBusNumber) ||\r
512 (Resource->PciCfg.LastNodeIndex != Record->PciCfg.LastNodeIndex))\r
513 {\r
09119a00
MK
514 return FALSE;\r
515 }\r
053e878b
MK
516\r
517 if (CompareMem (Resource->PciCfg.PciDevicePath, Record->PciCfg.PciDevicePath, sizeof (STM_PCI_DEVICE_PATH_NODE) * (Resource->PciCfg.LastNodeIndex + 1)) != 0) {\r
09119a00
MK
518 return FALSE;\r
519 }\r
053e878b
MK
520\r
521 ResourceLo = (UINT64)Resource->PciCfg.Base;\r
522 ResourceHi = (UINT64)Resource->PciCfg.Base + (UINT64)Resource->PciCfg.Length;\r
523 RecordLo = (UINT64)Record->PciCfg.Base;\r
524 RecordHi = (UINT64)Record->PciCfg.Base + (UINT64)Record->PciCfg.Length;\r
525 if (Resource->PciCfg.RWAttributes != Record->PciCfg.RWAttributes) {\r
526 if ((ResourceLo == RecordLo) && (ResourceHi == RecordHi)) {\r
527 Record->PciCfg.RWAttributes = Resource->PciCfg.RWAttributes | Record->PciCfg.RWAttributes;\r
528 return TRUE;\r
529 } else {\r
530 return FALSE;\r
531 }\r
532 }\r
533\r
534 break;\r
535 case MACHINE_SPECIFIC_REG:\r
536 //\r
537 // Special case - merge MSR masks in place.\r
538 //\r
539 if (Resource->Msr.MsrIndex != Record->Msr.MsrIndex) {\r
540 return FALSE;\r
541 }\r
542\r
543 Record->Msr.ReadMask |= Resource->Msr.ReadMask;\r
544 Record->Msr.WriteMask |= Resource->Msr.WriteMask;\r
545 return TRUE;\r
546 default:\r
09119a00 547 return FALSE;\r
09119a00 548 }\r
053e878b 549\r
09119a00
MK
550 //\r
551 // If resources are disjoint\r
552 //\r
553 if ((ResourceHi < RecordLo) || (ResourceLo > RecordHi)) {\r
554 return FALSE;\r
555 }\r
556\r
557 //\r
558 // If resource is consumed by record.\r
559 //\r
560 if ((ResourceLo >= RecordLo) && (ResourceHi <= RecordHi)) {\r
561 return TRUE;\r
562 }\r
053e878b 563\r
09119a00
MK
564 //\r
565 // Resources are overlapping.\r
566 // Resource and record are merged.\r
567 //\r
568 ResourceLo = (ResourceLo < RecordLo) ? ResourceLo : RecordLo;\r
569 ResourceHi = (ResourceHi > RecordHi) ? ResourceHi : RecordHi;\r
570\r
571 switch (Resource->Header.RscType) {\r
053e878b
MK
572 case MEM_RANGE:\r
573 case MMIO_RANGE:\r
574 Record->Mem.Base = ResourceLo;\r
575 Record->Mem.Length = ResourceHi - ResourceLo;\r
576 break;\r
577 case IO_RANGE:\r
578 case TRAPPED_IO_RANGE:\r
579 Record->Io.Base = (UINT16)ResourceLo;\r
580 Record->Io.Length = (UINT16)(ResourceHi - ResourceLo);\r
581 break;\r
582 case PCI_CFG_RANGE:\r
583 Record->PciCfg.Base = (UINT16)ResourceLo;\r
584 Record->PciCfg.Length = (UINT16)(ResourceHi - ResourceLo);\r
585 break;\r
586 default:\r
587 return FALSE;\r
09119a00
MK
588 }\r
589\r
590 return TRUE;\r
591}\r
592\r
593/**\r
594\r
595 Add resource node.\r
596\r
597 @param Resource A pointer to resource node to be added\r
598\r
599**/\r
600VOID\r
601AddSingleResource (\r
053e878b 602 IN STM_RSC *Resource\r
09119a00
MK
603 )\r
604{\r
053e878b 605 STM_RSC *Record;\r
09119a00
MK
606\r
607 Record = (STM_RSC *)mStmResourcesPtr;\r
608\r
609 while (TRUE) {\r
610 if (Record->Header.RscType == END_OF_RESOURCES) {\r
611 break;\r
612 }\r
053e878b 613\r
09119a00
MK
614 //\r
615 // Go to next record if resource and record types don't match.\r
616 //\r
617 if (Resource->Header.RscType != Record->Header.RscType) {\r
618 Record = (STM_RSC *)((UINTN)Record + Record->Header.Length);\r
619 continue;\r
620 }\r
053e878b 621\r
09119a00
MK
622 //\r
623 // Record is handled inside of procedure - don't adjust.\r
624 //\r
625 if (HandleSingleResource (Resource, Record)) {\r
053e878b 626 return;\r
09119a00 627 }\r
053e878b 628\r
09119a00
MK
629 Record = (STM_RSC *)((UINTN)Record + Record->Header.Length);\r
630 }\r
631\r
632 //\r
633 // Add resource to the end of area.\r
634 //\r
635 CopyMem (\r
053e878b 636 mStmResourcesPtr + mStmResourceSizeUsed - sizeof (mRscEndNode),\r
09119a00
MK
637 Resource,\r
638 Resource->Header.Length\r
639 );\r
640 CopyMem (\r
053e878b 641 mStmResourcesPtr + mStmResourceSizeUsed - sizeof (mRscEndNode) + Resource->Header.Length,\r
09119a00 642 &mRscEndNode,\r
053e878b 643 sizeof (mRscEndNode)\r
09119a00 644 );\r
053e878b 645 mStmResourceSizeUsed += Resource->Header.Length;\r
09119a00
MK
646 mStmResourceSizeAvailable = mStmResourceTotalSize - mStmResourceSizeUsed;\r
647\r
053e878b 648 return;\r
09119a00
MK
649}\r
650\r
651/**\r
652\r
653 Add resource list.\r
654\r
655 @param ResourceList A pointer to resource list to be added\r
656 @param NumEntries Optional number of entries.\r
657 If 0, list must be terminated by END_OF_RESOURCES.\r
658\r
659**/\r
660VOID\r
661AddResource (\r
053e878b
MK
662 IN STM_RSC *ResourceList,\r
663 IN UINT32 NumEntries OPTIONAL\r
09119a00
MK
664 )\r
665{\r
053e878b
MK
666 UINT32 Count;\r
667 UINTN Index;\r
668 STM_RSC *Resource;\r
09119a00
MK
669\r
670 if (NumEntries == 0) {\r
671 Count = 0xFFFFFFFF;\r
672 } else {\r
673 Count = NumEntries;\r
674 }\r
675\r
676 Resource = ResourceList;\r
677\r
678 for (Index = 0; Index < Count; Index++) {\r
679 if (Resource->Header.RscType == END_OF_RESOURCES) {\r
053e878b 680 return;\r
09119a00 681 }\r
053e878b 682\r
09119a00
MK
683 AddSingleResource (Resource);\r
684 Resource = (STM_RSC *)((UINTN)Resource + Resource->Header.Length);\r
685 }\r
053e878b
MK
686\r
687 return;\r
09119a00
MK
688}\r
689\r
690/**\r
691\r
692 Validate resource list.\r
693\r
694 @param ResourceList A pointer to resource list to be added\r
695 @param NumEntries Optional number of entries.\r
696 If 0, list must be terminated by END_OF_RESOURCES.\r
697\r
698 @retval TRUE resource valid\r
699 @retval FALSE resource invalid\r
700\r
701**/\r
702BOOLEAN\r
703ValidateResource (\r
053e878b
MK
704 IN STM_RSC *ResourceList,\r
705 IN UINT32 NumEntries OPTIONAL\r
09119a00
MK
706 )\r
707{\r
053e878b
MK
708 UINT32 Count;\r
709 UINTN Index;\r
710 STM_RSC *Resource;\r
711 UINTN SubIndex;\r
09119a00
MK
712\r
713 //\r
714 // If NumEntries == 0 make it very big. Scan will be terminated by\r
715 // END_OF_RESOURCES.\r
716 //\r
717 if (NumEntries == 0) {\r
718 Count = 0xFFFFFFFF;\r
719 } else {\r
720 Count = NumEntries;\r
721 }\r
722\r
723 //\r
724 // Start from beginning of resource list.\r
725 //\r
726 Resource = ResourceList;\r
727\r
728 for (Index = 0; Index < Count; Index++) {\r
5d0933f9 729 DEBUG ((DEBUG_INFO, "ValidateResource (%d) - RscType(%x)\n", Index, Resource->Header.RscType));\r
09119a00
MK
730 //\r
731 // Validate resource.\r
732 //\r
733 switch (Resource->Header.RscType) {\r
734 case END_OF_RESOURCES:\r
735 if (Resource->Header.Length != sizeof (STM_RSC_END)) {\r
053e878b 736 return FALSE;\r
09119a00 737 }\r
053e878b 738\r
09119a00
MK
739 //\r
740 // If we are passed actual number of resources to add,\r
741 // END_OF_RESOURCES structure between them is considered an\r
742 // error. If NumEntries == 0 END_OF_RESOURCES is a termination.\r
743 //\r
744 if (NumEntries != 0) {\r
053e878b 745 return FALSE;\r
09119a00
MK
746 } else {\r
747 //\r
748 // If NumEntries == 0 and list reached end - return success.\r
749 //\r
750 return TRUE;\r
751 }\r
053e878b 752\r
09119a00
MK
753 break;\r
754\r
755 case MEM_RANGE:\r
756 case MMIO_RANGE:\r
757 if (Resource->Header.Length != sizeof (STM_RSC_MEM_DESC)) {\r
758 return FALSE;\r
759 }\r
760\r
761 if (Resource->Mem.RWXAttributes > FULL_ACCS) {\r
762 return FALSE;\r
763 }\r
053e878b 764\r
09119a00
MK
765 break;\r
766\r
767 case IO_RANGE:\r
768 case TRAPPED_IO_RANGE:\r
769 if (Resource->Header.Length != sizeof (STM_RSC_IO_DESC)) {\r
770 return FALSE;\r
771 }\r
772\r
773 if ((Resource->Io.Base + Resource->Io.Length) > 0xFFFF) {\r
774 return FALSE;\r
775 }\r
053e878b 776\r
09119a00
MK
777 break;\r
778\r
779 case PCI_CFG_RANGE:\r
5d0933f9 780 DEBUG ((DEBUG_INFO, "ValidateResource - PCI (0x%02x, 0x%08x, 0x%02x, 0x%02x)\n", Resource->PciCfg.OriginatingBusNumber, Resource->PciCfg.LastNodeIndex, Resource->PciCfg.PciDevicePath[0].PciDevice, Resource->PciCfg.PciDevicePath[0].PciFunction));\r
053e878b 781 if (Resource->Header.Length != sizeof (STM_RSC_PCI_CFG_DESC) + (sizeof (STM_PCI_DEVICE_PATH_NODE) * Resource->PciCfg.LastNodeIndex)) {\r
09119a00
MK
782 return FALSE;\r
783 }\r
053e878b 784\r
09119a00
MK
785 for (SubIndex = 0; SubIndex <= Resource->PciCfg.LastNodeIndex; SubIndex++) {\r
786 if ((Resource->PciCfg.PciDevicePath[SubIndex].PciDevice > 0x1F) || (Resource->PciCfg.PciDevicePath[SubIndex].PciFunction > 7)) {\r
787 return FALSE;\r
788 }\r
789 }\r
053e878b 790\r
09119a00
MK
791 if ((Resource->PciCfg.Base + Resource->PciCfg.Length) > 0x1000) {\r
792 return FALSE;\r
793 }\r
053e878b 794\r
09119a00
MK
795 break;\r
796\r
797 case MACHINE_SPECIFIC_REG:\r
798 if (Resource->Header.Length != sizeof (STM_RSC_MSR_DESC)) {\r
799 return FALSE;\r
800 }\r
053e878b 801\r
09119a00
MK
802 break;\r
803\r
053e878b 804 default:\r
09119a00
MK
805 DEBUG ((DEBUG_ERROR, "ValidateResource - Unknown RscType(%x)\n", Resource->Header.RscType));\r
806 return FALSE;\r
807 }\r
053e878b 808\r
09119a00
MK
809 Resource = (STM_RSC *)((UINTN)Resource + Resource->Header.Length);\r
810 }\r
053e878b 811\r
09119a00
MK
812 return TRUE;\r
813}\r
814\r
815/**\r
816\r
817 Get resource list.\r
818 EndResource is excluded.\r
819\r
820 @param ResourceList A pointer to resource list to be added\r
821 @param NumEntries Optional number of entries.\r
822 If 0, list must be terminated by END_OF_RESOURCES.\r
823\r
824 @retval TRUE resource valid\r
825 @retval FALSE resource invalid\r
826\r
827**/\r
828UINTN\r
829GetResourceSize (\r
053e878b
MK
830 IN STM_RSC *ResourceList,\r
831 IN UINT32 NumEntries OPTIONAL\r
09119a00
MK
832 )\r
833{\r
053e878b
MK
834 UINT32 Count;\r
835 UINTN Index;\r
836 STM_RSC *Resource;\r
09119a00
MK
837\r
838 Resource = ResourceList;\r
839\r
840 //\r
841 // If NumEntries == 0 make it very big. Scan will be terminated by\r
842 // END_OF_RESOURCES.\r
843 //\r
844 if (NumEntries == 0) {\r
845 Count = 0xFFFFFFFF;\r
846 } else {\r
847 Count = NumEntries;\r
848 }\r
849\r
850 //\r
851 // Start from beginning of resource list.\r
852 //\r
853 Resource = ResourceList;\r
854\r
855 for (Index = 0; Index < Count; Index++) {\r
856 if (Resource->Header.RscType == END_OF_RESOURCES) {\r
857 break;\r
858 }\r
053e878b 859\r
09119a00
MK
860 Resource = (STM_RSC *)((UINTN)Resource + Resource->Header.Length);\r
861 }\r
862\r
863 return (UINTN)Resource - (UINTN)ResourceList;\r
864}\r
865\r
866/**\r
867\r
868 Add resources in list to database. Allocate new memory areas as needed.\r
869\r
870 @param ResourceList A pointer to resource list to be added\r
871 @param NumEntries Optional number of entries.\r
872 If 0, list must be terminated by END_OF_RESOURCES.\r
873\r
874 @retval EFI_SUCCESS If resources are added\r
875 @retval EFI_INVALID_PARAMETER If nested procedure detected resource failer\r
876 @retval EFI_OUT_OF_RESOURCES If nested procedure returned it and we cannot allocate more areas.\r
877\r
878**/\r
879EFI_STATUS\r
880EFIAPI\r
881AddPiResource (\r
053e878b
MK
882 IN STM_RSC *ResourceList,\r
883 IN UINT32 NumEntries OPTIONAL\r
09119a00
MK
884 )\r
885{\r
886 EFI_STATUS Status;\r
887 UINTN ResourceSize;\r
888 EFI_PHYSICAL_ADDRESS NewResource;\r
889 UINTN NewResourceSize;\r
890\r
891 DEBUG ((DEBUG_INFO, "AddPiResource - Enter\n"));\r
892\r
893 if (!ValidateResource (ResourceList, NumEntries)) {\r
894 return EFI_INVALID_PARAMETER;\r
895 }\r
896\r
897 ResourceSize = GetResourceSize (ResourceList, NumEntries);\r
898 DEBUG ((DEBUG_INFO, "ResourceSize - 0x%08x\n", ResourceSize));\r
899 if (ResourceSize == 0) {\r
900 return EFI_INVALID_PARAMETER;\r
901 }\r
902\r
903 if (mStmResourcesPtr == NULL) {\r
904 //\r
905 // First time allocation\r
906 //\r
053e878b 907 NewResourceSize = EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (ResourceSize + sizeof (mRscEndNode)));\r
09119a00
MK
908 DEBUG ((DEBUG_INFO, "Allocate - 0x%08x\n", NewResourceSize));\r
909 Status = gSmst->SmmAllocatePages (\r
910 AllocateAnyPages,\r
911 EfiRuntimeServicesData,\r
912 EFI_SIZE_TO_PAGES (NewResourceSize),\r
913 &NewResource\r
914 );\r
915 if (EFI_ERROR (Status)) {\r
916 return Status;\r
917 }\r
918\r
919 //\r
418aded9 920 // Copy EndResource for initialization\r
09119a00 921 //\r
053e878b 922 mStmResourcesPtr = (UINT8 *)(UINTN)NewResource;\r
09119a00 923 mStmResourceTotalSize = NewResourceSize;\r
053e878b
MK
924 CopyMem (mStmResourcesPtr, &mRscEndNode, sizeof (mRscEndNode));\r
925 mStmResourceSizeUsed = sizeof (mRscEndNode);\r
926 mStmResourceSizeAvailable = mStmResourceTotalSize - sizeof (mRscEndNode);\r
09119a00
MK
927\r
928 //\r
929 // Let SmmCore change resource ptr\r
930 //\r
931 NotifyStmResourceChange (mStmResourcesPtr);\r
932 } else if (mStmResourceSizeAvailable < ResourceSize) {\r
933 //\r
934 // Need enlarge\r
935 //\r
936 NewResourceSize = mStmResourceTotalSize + (ResourceSize - mStmResourceSizeAvailable);\r
937 NewResourceSize = EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (NewResourceSize));\r
938 DEBUG ((DEBUG_INFO, "ReAllocate - 0x%08x\n", NewResourceSize));\r
939 Status = gSmst->SmmAllocatePages (\r
940 AllocateAnyPages,\r
941 EfiRuntimeServicesData,\r
942 EFI_SIZE_TO_PAGES (NewResourceSize),\r
943 &NewResource\r
944 );\r
945 if (EFI_ERROR (Status)) {\r
946 return Status;\r
947 }\r
053e878b 948\r
09119a00
MK
949 CopyMem ((VOID *)(UINTN)NewResource, mStmResourcesPtr, mStmResourceSizeUsed);\r
950 mStmResourceSizeAvailable = NewResourceSize - mStmResourceSizeUsed;\r
951\r
952 gSmst->SmmFreePages (\r
953 (EFI_PHYSICAL_ADDRESS)(UINTN)mStmResourcesPtr,\r
954 EFI_SIZE_TO_PAGES (mStmResourceTotalSize)\r
955 );\r
956\r
957 mStmResourceTotalSize = NewResourceSize;\r
053e878b 958 mStmResourcesPtr = (UINT8 *)(UINTN)NewResource;\r
09119a00
MK
959\r
960 //\r
961 // Let SmmCore change resource ptr\r
962 //\r
963 NotifyStmResourceChange (mStmResourcesPtr);\r
964 }\r
965\r
966 //\r
967 // Check duplication\r
968 //\r
969 AddResource (ResourceList, NumEntries);\r
970\r
971 return EFI_SUCCESS;\r
972}\r
973\r
974/**\r
975\r
976 Delete resources in list to database.\r
977\r
978 @param ResourceList A pointer to resource list to be deleted\r
979 NULL means delete all resources.\r
980 @param NumEntries Optional number of entries.\r
981 If 0, list must be terminated by END_OF_RESOURCES.\r
982\r
983 @retval EFI_SUCCESS If resources are deleted\r
984 @retval EFI_INVALID_PARAMETER If nested procedure detected resource failer\r
985\r
986**/\r
987EFI_STATUS\r
988EFIAPI\r
989DeletePiResource (\r
053e878b
MK
990 IN STM_RSC *ResourceList,\r
991 IN UINT32 NumEntries OPTIONAL\r
09119a00
MK
992 )\r
993{\r
994 if (ResourceList != NULL) {\r
995 // TBD\r
996 ASSERT (FALSE);\r
997 return EFI_UNSUPPORTED;\r
998 }\r
053e878b 999\r
09119a00
MK
1000 //\r
1001 // Delete all\r
1002 //\r
053e878b
MK
1003 CopyMem (mStmResourcesPtr, &mRscEndNode, sizeof (mRscEndNode));\r
1004 mStmResourceSizeUsed = sizeof (mRscEndNode);\r
1005 mStmResourceSizeAvailable = mStmResourceTotalSize - sizeof (mRscEndNode);\r
09119a00
MK
1006 return EFI_SUCCESS;\r
1007}\r
1008\r
1009/**\r
1010\r
1011 Get BIOS resources.\r
1012\r
1013 @param ResourceList A pointer to resource list to be filled\r
1014 @param ResourceSize On input it means size of resource list input.\r
1015 On output it means size of resource list filled,\r
1016 or the size of resource list to be filled if size of too small.\r
1017\r
1018 @retval EFI_SUCCESS If resources are returned.\r
1019 @retval EFI_BUFFER_TOO_SMALL If resource list buffer is too small to hold the whole resources.\r
1020\r
1021**/\r
1022EFI_STATUS\r
1023EFIAPI\r
1024GetPiResource (\r
053e878b
MK
1025 OUT STM_RSC *ResourceList,\r
1026 IN OUT UINT32 *ResourceSize\r
09119a00
MK
1027 )\r
1028{\r
1029 if (*ResourceSize < mStmResourceSizeUsed) {\r
1030 *ResourceSize = (UINT32)mStmResourceSizeUsed;\r
1031 return EFI_BUFFER_TOO_SMALL;\r
1032 }\r
1033\r
1034 CopyMem (ResourceList, mStmResourcesPtr, mStmResourceSizeUsed);\r
1035 *ResourceSize = (UINT32)mStmResourceSizeUsed;\r
1036 return EFI_SUCCESS;\r
1037}\r
1038\r
1039/**\r
1040\r
1041 Set valid bit for MSEG MSR.\r
1042\r
1043 @param Buffer Ap function buffer. (not used)\r
1044\r
1045**/\r
1046VOID\r
1047EFIAPI\r
1048EnableMsegMsr (\r
1049 IN VOID *Buffer\r
1050 )\r
1051{\r
1052 MSR_IA32_SMM_MONITOR_CTL_REGISTER SmmMonitorCtl;\r
1053\r
053e878b 1054 SmmMonitorCtl.Uint64 = AsmReadMsr64 (MSR_IA32_SMM_MONITOR_CTL);\r
09119a00
MK
1055 SmmMonitorCtl.Bits.Valid = 1;\r
1056 AsmWriteMsr64 (MSR_IA32_SMM_MONITOR_CTL, SmmMonitorCtl.Uint64);\r
1057}\r
1058\r
1059/**\r
1060\r
1061 Get 4K page aligned VMCS size.\r
1062\r
1063 @return 4K page aligned VMCS size\r
1064\r
1065**/\r
1066UINT32\r
1067GetVmcsSize (\r
1068 VOID\r
1069 )\r
1070{\r
1071 MSR_IA32_VMX_BASIC_REGISTER VmxBasic;\r
1072\r
1073 //\r
1074 // Read VMCS size and and align to 4KB\r
1075 //\r
1076 VmxBasic.Uint64 = AsmReadMsr64 (MSR_IA32_VMX_BASIC);\r
1077 return ALIGN_VALUE (VmxBasic.Bits.VmcsSize, SIZE_4KB);\r
1078}\r
1079\r
1080/**\r
1081\r
1082 Check STM image size.\r
1083\r
1084 @param StmImage STM image\r
1085 @param StmImageSize STM image size\r
1086\r
1087 @retval TRUE check pass\r
1088 @retval FALSE check fail\r
1089**/\r
1090BOOLEAN\r
1091StmCheckStmImage (\r
053e878b
MK
1092 IN EFI_PHYSICAL_ADDRESS StmImage,\r
1093 IN UINTN StmImageSize\r
09119a00
MK
1094 )\r
1095{\r
053e878b
MK
1096 UINTN MinMsegSize;\r
1097 STM_HEADER *StmHeader;\r
1098 IA32_VMX_MISC_REGISTER VmxMiscMsr;\r
09119a00
MK
1099\r
1100 //\r
1101 // Check to see if STM image is compatible with CPU\r
1102 //\r
053e878b 1103 StmHeader = (STM_HEADER *)(UINTN)StmImage;\r
09119a00
MK
1104 VmxMiscMsr.Uint64 = AsmReadMsr64 (MSR_IA32_VMX_MISC);\r
1105 if (StmHeader->HwStmHdr.MsegHeaderRevision != VmxMiscMsr.Bits.MsegRevisionIdentifier) {\r
1106 DEBUG ((DEBUG_ERROR, "STM Image not compatible with CPU\n"));\r
1107 DEBUG ((DEBUG_ERROR, " StmHeader->HwStmHdr.MsegHeaderRevision = %08x\n", StmHeader->HwStmHdr.MsegHeaderRevision));\r
1108 DEBUG ((DEBUG_ERROR, " VmxMiscMsr.Bits.MsegRevisionIdentifier = %08x\n", VmxMiscMsr.Bits.MsegRevisionIdentifier));\r
1109 return FALSE;\r
1110 }\r
1111\r
1112 //\r
1113 // Get Minimal required Mseg size\r
1114 //\r
1115 MinMsegSize = (EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (StmHeader->SwStmHdr.StaticImageSize)) +\r
1116 StmHeader->SwStmHdr.AdditionalDynamicMemorySize +\r
1117 (StmHeader->SwStmHdr.PerProcDynamicMemorySize + GetVmcsSize () * 2) * gSmst->NumberOfCpus);\r
1118 if (MinMsegSize < StmImageSize) {\r
1119 MinMsegSize = StmImageSize;\r
1120 }\r
1121\r
1122 if (StmHeader->HwStmHdr.Cr3Offset >= StmHeader->SwStmHdr.StaticImageSize) {\r
1123 //\r
1124 // We will create page table, just in case that SINIT does not create it.\r
1125 //\r
053e878b
MK
1126 if (MinMsegSize < StmHeader->HwStmHdr.Cr3Offset + EFI_PAGES_TO_SIZE (6)) {\r
1127 MinMsegSize = StmHeader->HwStmHdr.Cr3Offset + EFI_PAGES_TO_SIZE (6);\r
09119a00
MK
1128 }\r
1129 }\r
1130\r
1131 //\r
1132 // Check if it exceeds MSEG size\r
1133 //\r
1134 if (MinMsegSize > mMsegSize) {\r
1135 DEBUG ((DEBUG_ERROR, "MSEG too small. Min MSEG Size = %08x Current MSEG Size = %08x\n", MinMsegSize, mMsegSize));\r
1136 DEBUG ((DEBUG_ERROR, " StmHeader->SwStmHdr.StaticImageSize = %08x\n", StmHeader->SwStmHdr.StaticImageSize));\r
1137 DEBUG ((DEBUG_ERROR, " StmHeader->SwStmHdr.AdditionalDynamicMemorySize = %08x\n", StmHeader->SwStmHdr.AdditionalDynamicMemorySize));\r
1138 DEBUG ((DEBUG_ERROR, " StmHeader->SwStmHdr.PerProcDynamicMemorySize = %08x\n", StmHeader->SwStmHdr.PerProcDynamicMemorySize));\r
1139 DEBUG ((DEBUG_ERROR, " VMCS Size = %08x\n", GetVmcsSize ()));\r
1140 DEBUG ((DEBUG_ERROR, " Max CPUs = %08x\n", gSmst->NumberOfCpus));\r
1141 DEBUG ((DEBUG_ERROR, " StmHeader->HwStmHdr.Cr3Offset = %08x\n", StmHeader->HwStmHdr.Cr3Offset));\r
1142 return FALSE;\r
1143 }\r
1144\r
1145 return TRUE;\r
1146}\r
1147\r
1148/**\r
1149\r
1150 Load STM image to MSEG.\r
1151\r
1152 @param StmImage STM image\r
1153 @param StmImageSize STM image size\r
1154\r
1155**/\r
1156VOID\r
1157StmLoadStmImage (\r
053e878b
MK
1158 IN EFI_PHYSICAL_ADDRESS StmImage,\r
1159 IN UINTN StmImageSize\r
09119a00
MK
1160 )\r
1161{\r
1162 MSR_IA32_SMM_MONITOR_CTL_REGISTER SmmMonitorCtl;\r
1163 UINT32 MsegBase;\r
1164 STM_HEADER *StmHeader;\r
1165\r
1166 //\r
1167 // Get MSEG base address from MSR_IA32_SMM_MONITOR_CTL\r
1168 //\r
1169 SmmMonitorCtl.Uint64 = AsmReadMsr64 (MSR_IA32_SMM_MONITOR_CTL);\r
053e878b 1170 MsegBase = SmmMonitorCtl.Bits.MsegBase << 12;\r
09119a00
MK
1171\r
1172 //\r
1173 // Zero all of MSEG base address\r
1174 //\r
1175 ZeroMem ((VOID *)(UINTN)MsegBase, mMsegSize);\r
1176\r
1177 //\r
1178 // Copy STM Image into MSEG\r
1179 //\r
1180 CopyMem ((VOID *)(UINTN)MsegBase, (VOID *)(UINTN)StmImage, StmImageSize);\r
1181\r
1182 //\r
1183 // STM Header is at the beginning of the STM Image\r
1184 //\r
1185 StmHeader = (STM_HEADER *)(UINTN)StmImage;\r
1186\r
1187 StmGen4GPageTable ((UINTN)MsegBase + StmHeader->HwStmHdr.Cr3Offset);\r
1188}\r
1189\r
1190/**\r
1191\r
1192 Load STM image to MSEG.\r
1193\r
1194 @param StmImage STM image\r
1195 @param StmImageSize STM image size\r
1196\r
1197 @retval EFI_SUCCESS Load STM to MSEG successfully\r
1198 @retval EFI_ALREADY_STARTED STM image is already loaded to MSEG\r
1199 @retval EFI_BUFFER_TOO_SMALL MSEG is smaller than minimal requirement of STM image\r
1200 @retval EFI_UNSUPPORTED MSEG is not enabled\r
1201\r
1202**/\r
1203EFI_STATUS\r
1204EFIAPI\r
1205LoadMonitor (\r
053e878b
MK
1206 IN EFI_PHYSICAL_ADDRESS StmImage,\r
1207 IN UINTN StmImageSize\r
09119a00
MK
1208 )\r
1209{\r
1210 MSR_IA32_SMM_MONITOR_CTL_REGISTER SmmMonitorCtl;\r
1211\r
1212 if (mLockLoadMonitor) {\r
1213 return EFI_ACCESS_DENIED;\r
1214 }\r
1215\r
1216 SmmMonitorCtl.Uint64 = AsmReadMsr64 (MSR_IA32_SMM_MONITOR_CTL);\r
1217 if (SmmMonitorCtl.Bits.MsegBase == 0) {\r
1218 return EFI_UNSUPPORTED;\r
1219 }\r
1220\r
1221 if (!StmCheckStmImage (StmImage, StmImageSize)) {\r
1222 return EFI_BUFFER_TOO_SMALL;\r
1223 }\r
1224\r
1225 // Record STM_HASH to PCR 0, just in case it is NOT TXT launch, we still need provide the evidence.\r
053e878b 1226 TpmMeasureAndLogData (\r
09119a00
MK
1227 0, // PcrIndex\r
1228 TXT_EVTYPE_STM_HASH, // EventType\r
1229 NULL, // EventLog\r
1230 0, // LogLen\r
1231 (VOID *)(UINTN)StmImage, // HashData\r
1232 StmImageSize // HashDataLen\r
1233 );\r
1234\r
1235 StmLoadStmImage (StmImage, StmImageSize);\r
1236\r
1237 mStmState |= EFI_SM_MONITOR_STATE_ENABLED;\r
1238\r
1239 return EFI_SUCCESS;\r
1240}\r
1241\r
1242/**\r
1243 This function return BIOS STM resource.\r
1244 Produced by SmmStm.\r
418aded9 1245 Consumed by SmmMpService when Init.\r
09119a00
MK
1246\r
1247 @return BIOS STM resource\r
1248\r
1249**/\r
1250VOID *\r
053e878b 1251GetStmResource (\r
09119a00
MK
1252 VOID\r
1253 )\r
1254{\r
1255 return mStmResourcesPtr;\r
1256}\r
1257\r
1258/**\r
1259 This function notify STM resource change.\r
1260\r
1261 @param StmResource BIOS STM resource\r
1262\r
1263**/\r
1264VOID\r
1265NotifyStmResourceChange (\r
053e878b 1266 VOID *StmResource\r
09119a00
MK
1267 )\r
1268{\r
1269 UINTN Index;\r
1270 TXT_PROCESSOR_SMM_DESCRIPTOR *Psd;\r
1271\r
1272 for (Index = 0; Index < gSmst->NumberOfCpus; Index++) {\r
053e878b 1273 Psd = (TXT_PROCESSOR_SMM_DESCRIPTOR *)((UINTN)gSmst->CpuSaveState[Index] - SMRAM_SAVE_STATE_MAP_OFFSET + TXT_SMM_PSD_OFFSET);\r
09119a00
MK
1274 Psd->BiosHwResourceRequirementsPtr = (UINT64)(UINTN)StmResource;\r
1275 }\r
09119a00 1276\r
053e878b
MK
1277 return;\r
1278}\r
09119a00
MK
1279\r
1280/**\r
1281 This is STM setup BIOS callback.\r
1282**/\r
1283VOID\r
1284EFIAPI\r
1285SmmStmSetup (\r
1286 VOID\r
1287 )\r
1288{\r
1289 mStmState |= EFI_SM_MONITOR_STATE_ACTIVATED;\r
1290}\r
1291\r
1292/**\r
1293 This is STM teardown BIOS callback.\r
1294**/\r
1295VOID\r
1296EFIAPI\r
1297SmmStmTeardown (\r
1298 VOID\r
1299 )\r
1300{\r
1301 mStmState &= ~EFI_SM_MONITOR_STATE_ACTIVATED;\r
1302}\r