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