UefiCpuPkg: Update SmmCpuFeatureLib pass XCODE5 tool chain
[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
09119a00
MK
5 This program and the accompanying materials\r
6 are licensed and made available under the terms and conditions of the BSD License\r
7 which accompanies this distribution. The full text of the license may be found at\r
8 http://opensource.org/licenses/bsd-license.php.\r
9\r
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13**/\r
14\r
15#include <PiSmm.h>\r
16#include <Library/BaseLib.h>\r
17#include <Library/BaseMemoryLib.h>\r
18#include <Library/MemoryAllocationLib.h>\r
19#include <Library/HobLib.h>\r
20#include <Library/DebugLib.h>\r
21#include <Library/UefiBootServicesTableLib.h>\r
22#include <Library/SmmServicesTableLib.h>\r
23#include <Library/TpmMeasurementLib.h>\r
24#include <Register/Cpuid.h>\r
25#include <Register/ArchitecturalMsr.h>\r
26#include <Register/SmramSaveStateMap.h>\r
27\r
28#include <Protocol/MpService.h>\r
29\r
30#include "SmmStm.h"\r
31\r
32#define TXT_EVTYPE_BASE 0x400\r
33#define TXT_EVTYPE_STM_HASH (TXT_EVTYPE_BASE + 14)\r
34\r
35#define RDWR_ACCS 3\r
36#define FULL_ACCS 7\r
37\r
38/**\r
39 The constructor function\r
40\r
41 @param[in] ImageHandle The firmware allocated handle for the EFI image.\r
42 @param[in] SystemTable A pointer to the EFI System Table.\r
43\r
44 @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS.\r
45\r
46**/\r
47EFI_STATUS\r
48EFIAPI\r
49SmmCpuFeaturesLibConstructor (\r
50 IN EFI_HANDLE ImageHandle,\r
51 IN EFI_SYSTEM_TABLE *SystemTable\r
52 );\r
53\r
54EFI_HANDLE mStmSmmCpuHandle = NULL;\r
55\r
56BOOLEAN mLockLoadMonitor = FALSE;\r
57\r
58//\r
59// Template of STM_RSC_END structure for copying.\r
60//\r
61GLOBAL_REMOVE_IF_UNREFERENCED STM_RSC_END mRscEndNode = {\r
62 {END_OF_RESOURCES, sizeof (STM_RSC_END)},\r
63};\r
64\r
65GLOBAL_REMOVE_IF_UNREFERENCED UINT8 *mStmResourcesPtr = NULL;\r
66GLOBAL_REMOVE_IF_UNREFERENCED UINTN mStmResourceTotalSize = 0x0;\r
67GLOBAL_REMOVE_IF_UNREFERENCED UINTN mStmResourceSizeUsed = 0x0;\r
68GLOBAL_REMOVE_IF_UNREFERENCED UINTN mStmResourceSizeAvailable = 0x0;\r
69\r
70GLOBAL_REMOVE_IF_UNREFERENCED UINT32 mStmState = 0;\r
71\r
72//\r
73// System Configuration Table pointing to STM Configuration Table\r
74//\r
75GLOBAL_REMOVE_IF_UNREFERENCED\r
76EFI_SM_MONITOR_INIT_PROTOCOL mSmMonitorInitProtocol = {\r
77 LoadMonitor,\r
78 AddPiResource,\r
79 DeletePiResource,\r
80 GetPiResource,\r
81 GetMonitorState,\r
82};\r
83\r
84\r
85\r
86\r
87#define CPUID1_EDX_XD_SUPPORT 0x100000\r
88\r
89//\r
90// External global variables associated with SMI Handler Template\r
91//\r
92extern CONST TXT_PROCESSOR_SMM_DESCRIPTOR gcStmPsd;\r
93extern UINT32 gStmSmbase;\r
94extern volatile UINT32 gStmSmiStack;\r
95extern UINT32 gStmSmiCr3;\r
96extern volatile UINT8 gcStmSmiHandlerTemplate[];\r
97extern CONST UINT16 gcStmSmiHandlerSize;\r
98extern UINT16 gcStmSmiHandlerOffset;\r
99extern BOOLEAN gStmXdSupported;\r
100\r
101//\r
102// Variables used by SMI Handler\r
103//\r
104IA32_DESCRIPTOR gStmSmiHandlerIdtr;\r
105\r
106//\r
107// MP Services Protocol\r
108//\r
109EFI_MP_SERVICES_PROTOCOL *mSmmCpuFeaturesLibMpService = NULL;\r
110\r
111//\r
112// MSEG Base and Length in SMRAM\r
113//\r
114UINTN mMsegBase = 0;\r
115UINTN mMsegSize = 0;\r
116\r
117BOOLEAN mStmConfigurationTableInitialized = FALSE;\r
118\r
09119a00
MK
119/**\r
120 The constructor function\r
121\r
122 @param[in] ImageHandle The firmware allocated handle for the EFI image.\r
123 @param[in] SystemTable A pointer to the EFI System Table.\r
124\r
125 @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS.\r
126\r
127**/\r
128EFI_STATUS\r
129EFIAPI\r
130SmmCpuFeaturesLibStmConstructor (\r
131 IN EFI_HANDLE ImageHandle,\r
132 IN EFI_SYSTEM_TABLE *SystemTable\r
133 )\r
134{\r
135 EFI_STATUS Status;\r
136 CPUID_VERSION_INFO_ECX RegEcx;\r
137 EFI_HOB_GUID_TYPE *GuidHob;\r
138 EFI_SMRAM_DESCRIPTOR *SmramDescriptor;\r
139\r
1c7a65eb
LG
140 //\r
141 // Initialize address fixup\r
142 //\r
143 SmmCpuFeaturesLibStmSmiEntryFixupAddress ();\r
144\r
09119a00
MK
145 //\r
146 // Call the common constructor function\r
147 //\r
148 Status = SmmCpuFeaturesLibConstructor (ImageHandle, SystemTable);\r
149 ASSERT_EFI_ERROR (Status);\r
150\r
151 //\r
152 // Lookup the MP Services Protocol\r
153 //\r
154 Status = gBS->LocateProtocol (\r
155 &gEfiMpServiceProtocolGuid,\r
156 NULL,\r
157 (VOID **)&mSmmCpuFeaturesLibMpService\r
158 );\r
159 ASSERT_EFI_ERROR (Status);\r
160\r
161 //\r
162 // If CPU supports VMX, then determine SMRAM range for MSEG.\r
163 //\r
164 AsmCpuid (CPUID_VERSION_INFO, NULL, NULL, &RegEcx.Uint32, NULL);\r
165 if (RegEcx.Bits.VMX == 1) {\r
166 GuidHob = GetFirstGuidHob (&gMsegSmramGuid);\r
167 if (GuidHob != NULL) {\r
168 //\r
169 // Retrieve MSEG location from MSEG SRAM HOB\r
170 //\r
171 SmramDescriptor = (EFI_SMRAM_DESCRIPTOR *) GET_GUID_HOB_DATA (GuidHob);\r
172 if (SmramDescriptor->PhysicalSize > 0) {\r
173 mMsegBase = (UINTN)SmramDescriptor->CpuStart;\r
174 mMsegSize = (UINTN)SmramDescriptor->PhysicalSize;\r
175 }\r
176 } else if (PcdGet32 (PcdCpuMsegSize) > 0) {\r
177 //\r
178 // Allocate MSEG from SMRAM memory\r
179 //\r
180 mMsegBase = (UINTN)AllocatePages (EFI_SIZE_TO_PAGES (PcdGet32 (PcdCpuMsegSize)));\r
181 if (mMsegBase > 0) {\r
182 mMsegSize = ALIGN_VALUE (PcdGet32 (PcdCpuMsegSize), EFI_PAGE_SIZE);\r
183 } else {\r
184 DEBUG ((DEBUG_ERROR, "Not enough SMRAM resource to allocate MSEG size %08x\n", PcdGet32 (PcdCpuMsegSize)));\r
185 }\r
186 }\r
187 if (mMsegBase > 0) {\r
188 DEBUG ((DEBUG_INFO, "MsegBase: 0x%08x, MsegSize: 0x%08x\n", mMsegBase, mMsegSize));\r
189 }\r
190 }\r
191\r
192 return EFI_SUCCESS;\r
193}\r
194\r
195/**\r
196 Internal worker function that is called to complete CPU initialization at the\r
d0c80b8a 197 end of SmmCpuFeaturesInitializeProcessor().\r
09119a00
MK
198\r
199**/\r
200VOID\r
201FinishSmmCpuFeaturesInitializeProcessor (\r
202 VOID\r
203 )\r
204{\r
205 MSR_IA32_SMM_MONITOR_CTL_REGISTER SmmMonitorCtl;\r
206\r
207 //\r
208 // Set MSEG Base Address in SMM Monitor Control MSR.\r
209 //\r
210 if (mMsegBase > 0) {\r
211 SmmMonitorCtl.Uint64 = 0;\r
212 SmmMonitorCtl.Bits.MsegBase = (UINT32)mMsegBase >> 12;\r
213 SmmMonitorCtl.Bits.Valid = 1;\r
214 AsmWriteMsr64 (MSR_IA32_SMM_MONITOR_CTL, SmmMonitorCtl.Uint64);\r
215 }\r
216}\r
217\r
218/**\r
219 Return the size, in bytes, of a custom SMI Handler in bytes. If 0 is\r
220 returned, then a custom SMI handler is not provided by this library,\r
221 and the default SMI handler must be used.\r
222\r
223 @retval 0 Use the default SMI handler.\r
224 @retval > 0 Use the SMI handler installed by SmmCpuFeaturesInstallSmiHandler()\r
225 The caller is required to allocate enough SMRAM for each CPU to\r
226 support the size of the custom SMI handler.\r
227**/\r
228UINTN\r
229EFIAPI\r
230SmmCpuFeaturesGetSmiHandlerSize (\r
231 VOID\r
232 )\r
233{\r
234 return gcStmSmiHandlerSize;\r
235}\r
236\r
237/**\r
238 Install a custom SMI handler for the CPU specified by CpuIndex. This function\r
239 is only called if SmmCpuFeaturesGetSmiHandlerSize() returns a size is greater\r
240 than zero and is called by the CPU that was elected as monarch during System\r
241 Management Mode initialization.\r
242\r
243 @param[in] CpuIndex The index of the CPU to install the custom SMI handler.\r
244 The value must be between 0 and the NumberOfCpus field\r
245 in the System Management System Table (SMST).\r
246 @param[in] SmBase The SMBASE address for the CPU specified by CpuIndex.\r
247 @param[in] SmiStack The stack to use when an SMI is processed by the\r
248 the CPU specified by CpuIndex.\r
249 @param[in] StackSize The size, in bytes, if the stack used when an SMI is\r
250 processed by the CPU specified by CpuIndex.\r
251 @param[in] GdtBase The base address of the GDT to use when an SMI is\r
252 processed by the CPU specified by CpuIndex.\r
253 @param[in] GdtSize The size, in bytes, of the GDT used when an SMI is\r
254 processed by the CPU specified by CpuIndex.\r
255 @param[in] IdtBase The base address of the IDT to use when an SMI is\r
256 processed by the CPU specified by CpuIndex.\r
257 @param[in] IdtSize The size, in bytes, of the IDT used when an SMI is\r
258 processed by the CPU specified by CpuIndex.\r
259 @param[in] Cr3 The base address of the page tables to use when an SMI\r
260 is processed by the CPU specified by CpuIndex.\r
261**/\r
262VOID\r
263EFIAPI\r
264SmmCpuFeaturesInstallSmiHandler (\r
265 IN UINTN CpuIndex,\r
266 IN UINT32 SmBase,\r
267 IN VOID *SmiStack,\r
268 IN UINTN StackSize,\r
269 IN UINTN GdtBase,\r
270 IN UINTN GdtSize,\r
271 IN UINTN IdtBase,\r
272 IN UINTN IdtSize,\r
273 IN UINT32 Cr3\r
274 )\r
275{\r
276 EFI_STATUS Status;\r
277 TXT_PROCESSOR_SMM_DESCRIPTOR *Psd;\r
278 VOID *Hob;\r
279 UINT32 RegEax;\r
280 UINT32 RegEdx;\r
281 EFI_PROCESSOR_INFORMATION ProcessorInfo;\r
282\r
8491e302
HW
283 CopyMem ((VOID *)((UINTN)SmBase + TXT_SMM_PSD_OFFSET), &gcStmPsd, sizeof (gcStmPsd));\r
284 Psd = (TXT_PROCESSOR_SMM_DESCRIPTOR *)(VOID *)((UINTN)SmBase + TXT_SMM_PSD_OFFSET);\r
09119a00
MK
285 Psd->SmmGdtPtr = GdtBase;\r
286 Psd->SmmGdtSize = (UINT32)GdtSize;\r
287\r
288 //\r
289 // Initialize values in template before copy\r
290 //\r
291 gStmSmiStack = (UINT32)((UINTN)SmiStack + StackSize - sizeof (UINTN));\r
292 gStmSmiCr3 = Cr3;\r
293 gStmSmbase = SmBase;\r
294 gStmSmiHandlerIdtr.Base = IdtBase;\r
295 gStmSmiHandlerIdtr.Limit = (UINT16)(IdtSize - 1);\r
296\r
297 if (gStmXdSupported) {\r
298 AsmCpuid (CPUID_EXTENDED_FUNCTION, &RegEax, NULL, NULL, NULL);\r
299 if (RegEax <= CPUID_EXTENDED_FUNCTION) {\r
300 //\r
301 // Extended CPUID functions are not supported on this processor.\r
302 //\r
303 gStmXdSupported = FALSE;\r
304 }\r
305\r
306 AsmCpuid (CPUID_EXTENDED_CPU_SIG, NULL, NULL, NULL, &RegEdx);\r
307 if ((RegEdx & CPUID1_EDX_XD_SUPPORT) == 0) {\r
308 //\r
309 // Execute Disable Bit feature is not supported on this processor.\r
310 //\r
311 gStmXdSupported = FALSE;\r
312 }\r
313 }\r
314\r
315 //\r
316 // Set the value at the top of the CPU stack to the CPU Index\r
317 //\r
318 *(UINTN*)(UINTN)gStmSmiStack = CpuIndex;\r
319\r
320 //\r
321 // Copy template to CPU specific SMI handler location\r
322 //\r
323 CopyMem (\r
8491e302 324 (VOID*)((UINTN)SmBase + SMM_HANDLER_OFFSET),\r
09119a00
MK
325 (VOID*)gcStmSmiHandlerTemplate,\r
326 gcStmSmiHandlerSize\r
327 );\r
328\r
329 Psd->SmmSmiHandlerRip = SmBase + SMM_HANDLER_OFFSET + gcStmSmiHandlerOffset;\r
330 Psd->SmmSmiHandlerRsp = (UINTN)SmiStack + StackSize - sizeof(UINTN);\r
331 Psd->SmmCr3 = Cr3;\r
332\r
5d0933f9
JF
333 DEBUG((DEBUG_INFO, "CpuSmmStmExceptionStackSize - %x\n", PcdGet32(PcdCpuSmmStmExceptionStackSize)));\r
334 DEBUG((DEBUG_INFO, "Pages - %x\n", EFI_SIZE_TO_PAGES(PcdGet32(PcdCpuSmmStmExceptionStackSize))));\r
09119a00
MK
335 Psd->StmProtectionExceptionHandler.SpeRsp = (UINT64)(UINTN)AllocatePages (EFI_SIZE_TO_PAGES (PcdGet32 (PcdCpuSmmStmExceptionStackSize)));\r
336 Psd->StmProtectionExceptionHandler.SpeRsp += EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (PcdGet32 (PcdCpuSmmStmExceptionStackSize)));\r
337\r
338 Psd->BiosHwResourceRequirementsPtr = (UINT64)(UINTN)GetStmResource ();\r
339\r
340 //\r
341 // Get the APIC ID for the CPU specified by CpuIndex\r
342 //\r
343 Status = mSmmCpuFeaturesLibMpService->GetProcessorInfo (\r
344 mSmmCpuFeaturesLibMpService,\r
345 CpuIndex,\r
346 &ProcessorInfo\r
347 );\r
348 ASSERT_EFI_ERROR (Status);\r
349\r
350 Psd->LocalApicId = (UINT32)ProcessorInfo.ProcessorId;\r
351 Psd->AcpiRsdp = 0;\r
352\r
353 Hob = GetFirstHob (EFI_HOB_TYPE_CPU);\r
354 if (Hob != NULL) {\r
355 Psd->PhysicalAddressBits = ((EFI_HOB_CPU *) Hob)->SizeOfMemorySpace;\r
356 } else {\r
357 AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);\r
358 if (RegEax >= 0x80000008) {\r
359 AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL);\r
360 Psd->PhysicalAddressBits = (UINT8) RegEax;\r
361 } else {\r
362 Psd->PhysicalAddressBits = 36;\r
363 }\r
364 }\r
365\r
366 if (!mStmConfigurationTableInitialized) {\r
367 StmSmmConfigurationTableInit ();\r
368 mStmConfigurationTableInitialized = TRUE;\r
369 }\r
370}\r
371\r
372/**\r
373 SMM End Of Dxe event notification handler.\r
374\r
375 STM support need patch AcpiRsdp in TXT_PROCESSOR_SMM_DESCRIPTOR.\r
376\r
377 @param[in] Protocol Points to the protocol's unique identifier.\r
378 @param[in] Interface Points to the interface instance.\r
379 @param[in] Handle The handle on which the interface was installed.\r
380\r
381 @retval EFI_SUCCESS Notification handler runs successfully.\r
382**/\r
383EFI_STATUS\r
384EFIAPI\r
385SmmEndOfDxeEventNotify (\r
386 IN CONST EFI_GUID *Protocol,\r
387 IN VOID *Interface,\r
388 IN EFI_HANDLE Handle\r
389 )\r
390{\r
391 VOID *Rsdp;\r
392 UINTN Index;\r
393 TXT_PROCESSOR_SMM_DESCRIPTOR *Psd;\r
394\r
395 DEBUG ((DEBUG_INFO, "SmmEndOfDxeEventNotify\n"));\r
396\r
397 //\r
398 // found ACPI table RSD_PTR from system table\r
399 //\r
400 Rsdp = NULL;\r
401 for (Index = 0; Index < gST->NumberOfTableEntries; Index++) {\r
402 if (CompareGuid (&(gST->ConfigurationTable[Index].VendorGuid), &gEfiAcpi20TableGuid)) {\r
403 //\r
404 // A match was found.\r
405 //\r
406 Rsdp = gST->ConfigurationTable[Index].VendorTable;\r
407 break;\r
408 }\r
409 }\r
410 if (Rsdp == NULL) {\r
411 for (Index = 0; Index < gST->NumberOfTableEntries; Index++) {\r
412 if (CompareGuid (&(gST->ConfigurationTable[Index].VendorGuid), &gEfiAcpi10TableGuid)) {\r
413 //\r
414 // A match was found.\r
415 //\r
416 Rsdp = gST->ConfigurationTable[Index].VendorTable;\r
417 break;\r
418 }\r
419 }\r
420 }\r
421\r
422 for (Index = 0; Index < gSmst->NumberOfCpus; Index++) {\r
423 Psd = (TXT_PROCESSOR_SMM_DESCRIPTOR *)((UINTN)gSmst->CpuSaveState[Index] - SMRAM_SAVE_STATE_MAP_OFFSET + TXT_SMM_PSD_OFFSET);\r
424 DEBUG ((DEBUG_INFO, "Index=%d Psd=%p Rsdp=%p\n", Index, Psd, Rsdp));\r
425 Psd->AcpiRsdp = (UINT64)(UINTN)Rsdp;\r
426 }\r
427\r
428 mLockLoadMonitor = TRUE;\r
429\r
430 return EFI_SUCCESS;\r
431}\r
432\r
433/**\r
434 This function initializes the STM configuration table.\r
435**/\r
436VOID\r
437StmSmmConfigurationTableInit (\r
438 VOID\r
439 )\r
440{\r
441 EFI_STATUS Status;\r
442 VOID *Registration;\r
443\r
444 Status = gSmst->SmmInstallProtocolInterface (\r
445 &mStmSmmCpuHandle,\r
446 &gEfiSmMonitorInitProtocolGuid,\r
447 EFI_NATIVE_INTERFACE,\r
448 &mSmMonitorInitProtocol\r
449 );\r
450 ASSERT_EFI_ERROR (Status);\r
451\r
452 //\r
453 //\r
454 // Register SMM End of DXE Event\r
455 //\r
456 Status = gSmst->SmmRegisterProtocolNotify (\r
457 &gEfiSmmEndOfDxeProtocolGuid,\r
458 SmmEndOfDxeEventNotify,\r
459 &Registration\r
460 );\r
461 ASSERT_EFI_ERROR (Status);\r
462}\r
463\r
464/**\r
465\r
466 Get STM state.\r
467\r
468 @return STM state\r
469\r
470**/\r
471EFI_SM_MONITOR_STATE\r
472EFIAPI\r
473GetMonitorState (\r
474 VOID\r
475 )\r
476{\r
477 return mStmState;\r
478}\r
479\r
480/**\r
481\r
482 Handle single Resource to see if it can be merged into Record.\r
483\r
484 @param Resource A pointer to resource node to be added\r
485 @param Record A pointer to record node to be merged\r
486\r
487 @retval TRUE resource handled\r
488 @retval FALSE resource is not handled\r
489\r
490**/\r
491BOOLEAN\r
492HandleSingleResource (\r
493 IN STM_RSC *Resource,\r
494 IN STM_RSC *Record\r
495 )\r
496{\r
497 UINT64 ResourceLo;\r
498 UINT64 ResourceHi;\r
499 UINT64 RecordLo;\r
500 UINT64 RecordHi;\r
501\r
502 ResourceLo = 0;\r
503 ResourceHi = 0;\r
504 RecordLo = 0;\r
505 RecordHi = 0;\r
506\r
507 //\r
508 // Calling code is responsible for making sure that\r
509 // Resource->Header.RscType == (*Record)->Header.RscType\r
510 // thus we use just one of them as switch variable.\r
511 //\r
512 switch (Resource->Header.RscType) {\r
513 case MEM_RANGE:\r
514 case MMIO_RANGE:\r
515 ResourceLo = Resource->Mem.Base;\r
516 ResourceHi = Resource->Mem.Base + Resource->Mem.Length;\r
517 RecordLo = Record->Mem.Base;\r
518 RecordHi = Record->Mem.Base + Record->Mem.Length;\r
519 if (Resource->Mem.RWXAttributes != Record->Mem.RWXAttributes) {\r
520 if ((ResourceLo == RecordLo) && (ResourceHi == RecordHi)) {\r
521 Record->Mem.RWXAttributes = Resource->Mem.RWXAttributes | Record->Mem.RWXAttributes;\r
522 return TRUE;\r
523 } else {\r
524 return FALSE;\r
525 }\r
526 }\r
527 break;\r
528 case IO_RANGE:\r
529 case TRAPPED_IO_RANGE:\r
530 ResourceLo = (UINT64) Resource->Io.Base;\r
531 ResourceHi = (UINT64) Resource->Io.Base + (UINT64) Resource->Io.Length;\r
532 RecordLo = (UINT64) Record->Io.Base;\r
533 RecordHi = (UINT64) Record->Io.Base + (UINT64) Record->Io.Length;\r
534 break;\r
535 case PCI_CFG_RANGE:\r
536 if ((Resource->PciCfg.OriginatingBusNumber != Record->PciCfg.OriginatingBusNumber) ||\r
537 (Resource->PciCfg.LastNodeIndex != Record->PciCfg.LastNodeIndex)) {\r
538 return FALSE;\r
539 }\r
540 if (CompareMem (Resource->PciCfg.PciDevicePath, Record->PciCfg.PciDevicePath, sizeof(STM_PCI_DEVICE_PATH_NODE) * (Resource->PciCfg.LastNodeIndex + 1)) != 0) {\r
541 return FALSE;\r
542 }\r
543 ResourceLo = (UINT64) Resource->PciCfg.Base;\r
544 ResourceHi = (UINT64) Resource->PciCfg.Base + (UINT64) Resource->PciCfg.Length;\r
545 RecordLo = (UINT64) Record->PciCfg.Base;\r
546 RecordHi = (UINT64) Record->PciCfg.Base + (UINT64) Record->PciCfg.Length;\r
547 if (Resource->PciCfg.RWAttributes != Record->PciCfg.RWAttributes) {\r
548 if ((ResourceLo == RecordLo) && (ResourceHi == RecordHi)) {\r
549 Record->PciCfg.RWAttributes = Resource->PciCfg.RWAttributes | Record->PciCfg.RWAttributes;\r
550 return TRUE;\r
551 } else {\r
552 return FALSE;\r
553 }\r
554 }\r
555 break;\r
556 case MACHINE_SPECIFIC_REG:\r
557 //\r
558 // Special case - merge MSR masks in place.\r
559 //\r
560 if (Resource->Msr.MsrIndex != Record->Msr.MsrIndex) {\r
561 return FALSE;\r
562 }\r
563 Record->Msr.ReadMask |= Resource->Msr.ReadMask;\r
564 Record->Msr.WriteMask |= Resource->Msr.WriteMask;\r
565 return TRUE;\r
566 default:\r
567 return FALSE;\r
568 }\r
569 //\r
570 // If resources are disjoint\r
571 //\r
572 if ((ResourceHi < RecordLo) || (ResourceLo > RecordHi)) {\r
573 return FALSE;\r
574 }\r
575\r
576 //\r
577 // If resource is consumed by record.\r
578 //\r
579 if ((ResourceLo >= RecordLo) && (ResourceHi <= RecordHi)) {\r
580 return TRUE;\r
581 }\r
582 //\r
583 // Resources are overlapping.\r
584 // Resource and record are merged.\r
585 //\r
586 ResourceLo = (ResourceLo < RecordLo) ? ResourceLo : RecordLo;\r
587 ResourceHi = (ResourceHi > RecordHi) ? ResourceHi : RecordHi;\r
588\r
589 switch (Resource->Header.RscType) {\r
590 case MEM_RANGE:\r
591 case MMIO_RANGE:\r
592 Record->Mem.Base = ResourceLo;\r
593 Record->Mem.Length = ResourceHi - ResourceLo;\r
594 break;\r
595 case IO_RANGE:\r
596 case TRAPPED_IO_RANGE:\r
597 Record->Io.Base = (UINT16) ResourceLo;\r
598 Record->Io.Length = (UINT16) (ResourceHi - ResourceLo);\r
599 break;\r
600 case PCI_CFG_RANGE:\r
601 Record->PciCfg.Base = (UINT16) ResourceLo;\r
602 Record->PciCfg.Length = (UINT16) (ResourceHi - ResourceLo);\r
603 break;\r
604 default:\r
605 return FALSE;\r
606 }\r
607\r
608 return TRUE;\r
609}\r
610\r
611/**\r
612\r
613 Add resource node.\r
614\r
615 @param Resource A pointer to resource node to be added\r
616\r
617**/\r
618VOID\r
619AddSingleResource (\r
620 IN STM_RSC *Resource\r
621 )\r
622{\r
623 STM_RSC *Record;\r
624\r
625 Record = (STM_RSC *)mStmResourcesPtr;\r
626\r
627 while (TRUE) {\r
628 if (Record->Header.RscType == END_OF_RESOURCES) {\r
629 break;\r
630 }\r
631 //\r
632 // Go to next record if resource and record types don't match.\r
633 //\r
634 if (Resource->Header.RscType != Record->Header.RscType) {\r
635 Record = (STM_RSC *)((UINTN)Record + Record->Header.Length);\r
636 continue;\r
637 }\r
638 //\r
639 // Record is handled inside of procedure - don't adjust.\r
640 //\r
641 if (HandleSingleResource (Resource, Record)) {\r
642 return ;\r
643 }\r
644 Record = (STM_RSC *)((UINTN)Record + Record->Header.Length);\r
645 }\r
646\r
647 //\r
648 // Add resource to the end of area.\r
649 //\r
650 CopyMem (\r
651 mStmResourcesPtr + mStmResourceSizeUsed - sizeof(mRscEndNode),\r
652 Resource,\r
653 Resource->Header.Length\r
654 );\r
655 CopyMem (\r
656 mStmResourcesPtr + mStmResourceSizeUsed - sizeof(mRscEndNode) + Resource->Header.Length,\r
657 &mRscEndNode,\r
658 sizeof(mRscEndNode)\r
659 );\r
660 mStmResourceSizeUsed += Resource->Header.Length;\r
661 mStmResourceSizeAvailable = mStmResourceTotalSize - mStmResourceSizeUsed;\r
662\r
663 return ;\r
664}\r
665\r
666/**\r
667\r
668 Add resource list.\r
669\r
670 @param ResourceList A pointer to resource list to be added\r
671 @param NumEntries Optional number of entries.\r
672 If 0, list must be terminated by END_OF_RESOURCES.\r
673\r
674**/\r
675VOID\r
676AddResource (\r
677 IN STM_RSC *ResourceList,\r
678 IN UINT32 NumEntries OPTIONAL\r
679 )\r
680{\r
681 UINT32 Count;\r
682 UINTN Index;\r
683 STM_RSC *Resource;\r
684\r
685 if (NumEntries == 0) {\r
686 Count = 0xFFFFFFFF;\r
687 } else {\r
688 Count = NumEntries;\r
689 }\r
690\r
691 Resource = ResourceList;\r
692\r
693 for (Index = 0; Index < Count; Index++) {\r
694 if (Resource->Header.RscType == END_OF_RESOURCES) {\r
695 return ;\r
696 }\r
697 AddSingleResource (Resource);\r
698 Resource = (STM_RSC *)((UINTN)Resource + Resource->Header.Length);\r
699 }\r
700 return ;\r
701}\r
702\r
703/**\r
704\r
705 Validate resource list.\r
706\r
707 @param ResourceList A pointer to resource list to be added\r
708 @param NumEntries Optional number of entries.\r
709 If 0, list must be terminated by END_OF_RESOURCES.\r
710\r
711 @retval TRUE resource valid\r
712 @retval FALSE resource invalid\r
713\r
714**/\r
715BOOLEAN\r
716ValidateResource (\r
717 IN STM_RSC *ResourceList,\r
718 IN UINT32 NumEntries OPTIONAL\r
719 )\r
720{\r
721 UINT32 Count;\r
722 UINTN Index;\r
723 STM_RSC *Resource;\r
724 UINTN SubIndex;\r
725\r
726 //\r
727 // If NumEntries == 0 make it very big. Scan will be terminated by\r
728 // END_OF_RESOURCES.\r
729 //\r
730 if (NumEntries == 0) {\r
731 Count = 0xFFFFFFFF;\r
732 } else {\r
733 Count = NumEntries;\r
734 }\r
735\r
736 //\r
737 // Start from beginning of resource list.\r
738 //\r
739 Resource = ResourceList;\r
740\r
741 for (Index = 0; Index < Count; Index++) {\r
5d0933f9 742 DEBUG ((DEBUG_INFO, "ValidateResource (%d) - RscType(%x)\n", Index, Resource->Header.RscType));\r
09119a00
MK
743 //\r
744 // Validate resource.\r
745 //\r
746 switch (Resource->Header.RscType) {\r
747 case END_OF_RESOURCES:\r
748 if (Resource->Header.Length != sizeof (STM_RSC_END)) {\r
749 return FALSE;\r
750 }\r
751 //\r
752 // If we are passed actual number of resources to add,\r
753 // END_OF_RESOURCES structure between them is considered an\r
754 // error. If NumEntries == 0 END_OF_RESOURCES is a termination.\r
755 //\r
756 if (NumEntries != 0) {\r
757 return FALSE;\r
758 } else {\r
759 //\r
760 // If NumEntries == 0 and list reached end - return success.\r
761 //\r
762 return TRUE;\r
763 }\r
764 break;\r
765\r
766 case MEM_RANGE:\r
767 case MMIO_RANGE:\r
768 if (Resource->Header.Length != sizeof (STM_RSC_MEM_DESC)) {\r
769 return FALSE;\r
770 }\r
771\r
772 if (Resource->Mem.RWXAttributes > FULL_ACCS) {\r
773 return FALSE;\r
774 }\r
775 break;\r
776\r
777 case IO_RANGE:\r
778 case TRAPPED_IO_RANGE:\r
779 if (Resource->Header.Length != sizeof (STM_RSC_IO_DESC)) {\r
780 return FALSE;\r
781 }\r
782\r
783 if ((Resource->Io.Base + Resource->Io.Length) > 0xFFFF) {\r
784 return FALSE;\r
785 }\r
786 break;\r
787\r
788 case PCI_CFG_RANGE:\r
5d0933f9 789 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
790 if (Resource->Header.Length != sizeof (STM_RSC_PCI_CFG_DESC) + (sizeof(STM_PCI_DEVICE_PATH_NODE) * Resource->PciCfg.LastNodeIndex)) {\r
791 return FALSE;\r
792 }\r
793 for (SubIndex = 0; SubIndex <= Resource->PciCfg.LastNodeIndex; SubIndex++) {\r
794 if ((Resource->PciCfg.PciDevicePath[SubIndex].PciDevice > 0x1F) || (Resource->PciCfg.PciDevicePath[SubIndex].PciFunction > 7)) {\r
795 return FALSE;\r
796 }\r
797 }\r
798 if ((Resource->PciCfg.Base + Resource->PciCfg.Length) > 0x1000) {\r
799 return FALSE;\r
800 }\r
801 break;\r
802\r
803 case MACHINE_SPECIFIC_REG:\r
804 if (Resource->Header.Length != sizeof (STM_RSC_MSR_DESC)) {\r
805 return FALSE;\r
806 }\r
807 break;\r
808\r
809 default :\r
810 DEBUG ((DEBUG_ERROR, "ValidateResource - Unknown RscType(%x)\n", Resource->Header.RscType));\r
811 return FALSE;\r
812 }\r
813 Resource = (STM_RSC *)((UINTN)Resource + Resource->Header.Length);\r
814 }\r
815 return TRUE;\r
816}\r
817\r
818/**\r
819\r
820 Get resource list.\r
821 EndResource is excluded.\r
822\r
823 @param ResourceList A pointer to resource list to be added\r
824 @param NumEntries Optional number of entries.\r
825 If 0, list must be terminated by END_OF_RESOURCES.\r
826\r
827 @retval TRUE resource valid\r
828 @retval FALSE resource invalid\r
829\r
830**/\r
831UINTN\r
832GetResourceSize (\r
833 IN STM_RSC *ResourceList,\r
834 IN UINT32 NumEntries OPTIONAL\r
835 )\r
836{\r
837 UINT32 Count;\r
838 UINTN Index;\r
839 STM_RSC *Resource;\r
840\r
841 Resource = ResourceList;\r
842\r
843 //\r
844 // If NumEntries == 0 make it very big. Scan will be terminated by\r
845 // END_OF_RESOURCES.\r
846 //\r
847 if (NumEntries == 0) {\r
848 Count = 0xFFFFFFFF;\r
849 } else {\r
850 Count = NumEntries;\r
851 }\r
852\r
853 //\r
854 // Start from beginning of resource list.\r
855 //\r
856 Resource = ResourceList;\r
857\r
858 for (Index = 0; Index < Count; Index++) {\r
859 if (Resource->Header.RscType == END_OF_RESOURCES) {\r
860 break;\r
861 }\r
862 Resource = (STM_RSC *)((UINTN)Resource + Resource->Header.Length);\r
863 }\r
864\r
865 return (UINTN)Resource - (UINTN)ResourceList;\r
866}\r
867\r
868/**\r
869\r
870 Add resources in list to database. Allocate new memory areas as needed.\r
871\r
872 @param ResourceList A pointer to resource list to be added\r
873 @param NumEntries Optional number of entries.\r
874 If 0, list must be terminated by END_OF_RESOURCES.\r
875\r
876 @retval EFI_SUCCESS If resources are added\r
877 @retval EFI_INVALID_PARAMETER If nested procedure detected resource failer\r
878 @retval EFI_OUT_OF_RESOURCES If nested procedure returned it and we cannot allocate more areas.\r
879\r
880**/\r
881EFI_STATUS\r
882EFIAPI\r
883AddPiResource (\r
884 IN STM_RSC *ResourceList,\r
885 IN UINT32 NumEntries OPTIONAL\r
886 )\r
887{\r
888 EFI_STATUS Status;\r
889 UINTN ResourceSize;\r
890 EFI_PHYSICAL_ADDRESS NewResource;\r
891 UINTN NewResourceSize;\r
892\r
893 DEBUG ((DEBUG_INFO, "AddPiResource - Enter\n"));\r
894\r
895 if (!ValidateResource (ResourceList, NumEntries)) {\r
896 return EFI_INVALID_PARAMETER;\r
897 }\r
898\r
899 ResourceSize = GetResourceSize (ResourceList, NumEntries);\r
900 DEBUG ((DEBUG_INFO, "ResourceSize - 0x%08x\n", ResourceSize));\r
901 if (ResourceSize == 0) {\r
902 return EFI_INVALID_PARAMETER;\r
903 }\r
904\r
905 if (mStmResourcesPtr == NULL) {\r
906 //\r
907 // First time allocation\r
908 //\r
909 NewResourceSize = EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (ResourceSize + sizeof(mRscEndNode)));\r
910 DEBUG ((DEBUG_INFO, "Allocate - 0x%08x\n", NewResourceSize));\r
911 Status = gSmst->SmmAllocatePages (\r
912 AllocateAnyPages,\r
913 EfiRuntimeServicesData,\r
914 EFI_SIZE_TO_PAGES (NewResourceSize),\r
915 &NewResource\r
916 );\r
917 if (EFI_ERROR (Status)) {\r
918 return Status;\r
919 }\r
920\r
921 //\r
922 // Copy EndResource for intialization\r
923 //\r
924 mStmResourcesPtr = (UINT8 *)(UINTN)NewResource;\r
925 mStmResourceTotalSize = NewResourceSize;\r
926 CopyMem (mStmResourcesPtr, &mRscEndNode, sizeof(mRscEndNode));\r
927 mStmResourceSizeUsed = sizeof(mRscEndNode);\r
928 mStmResourceSizeAvailable = mStmResourceTotalSize - sizeof(mRscEndNode);\r
929\r
930 //\r
931 // Let SmmCore change resource ptr\r
932 //\r
933 NotifyStmResourceChange (mStmResourcesPtr);\r
934 } else if (mStmResourceSizeAvailable < ResourceSize) {\r
935 //\r
936 // Need enlarge\r
937 //\r
938 NewResourceSize = mStmResourceTotalSize + (ResourceSize - mStmResourceSizeAvailable);\r
939 NewResourceSize = EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (NewResourceSize));\r
940 DEBUG ((DEBUG_INFO, "ReAllocate - 0x%08x\n", NewResourceSize));\r
941 Status = gSmst->SmmAllocatePages (\r
942 AllocateAnyPages,\r
943 EfiRuntimeServicesData,\r
944 EFI_SIZE_TO_PAGES (NewResourceSize),\r
945 &NewResource\r
946 );\r
947 if (EFI_ERROR (Status)) {\r
948 return Status;\r
949 }\r
950 CopyMem ((VOID *)(UINTN)NewResource, mStmResourcesPtr, mStmResourceSizeUsed);\r
951 mStmResourceSizeAvailable = NewResourceSize - mStmResourceSizeUsed;\r
952\r
953 gSmst->SmmFreePages (\r
954 (EFI_PHYSICAL_ADDRESS)(UINTN)mStmResourcesPtr,\r
955 EFI_SIZE_TO_PAGES (mStmResourceTotalSize)\r
956 );\r
957\r
958 mStmResourceTotalSize = NewResourceSize;\r
959 mStmResourcesPtr = (UINT8 *)(UINTN)NewResource;\r
960\r
961 //\r
962 // Let SmmCore change resource ptr\r
963 //\r
964 NotifyStmResourceChange (mStmResourcesPtr);\r
965 }\r
966\r
967 //\r
968 // Check duplication\r
969 //\r
970 AddResource (ResourceList, NumEntries);\r
971\r
972 return EFI_SUCCESS;\r
973}\r
974\r
975/**\r
976\r
977 Delete resources in list to database.\r
978\r
979 @param ResourceList A pointer to resource list to be deleted\r
980 NULL means delete all resources.\r
981 @param NumEntries Optional number of entries.\r
982 If 0, list must be terminated by END_OF_RESOURCES.\r
983\r
984 @retval EFI_SUCCESS If resources are deleted\r
985 @retval EFI_INVALID_PARAMETER If nested procedure detected resource failer\r
986\r
987**/\r
988EFI_STATUS\r
989EFIAPI\r
990DeletePiResource (\r
991 IN STM_RSC *ResourceList,\r
992 IN UINT32 NumEntries OPTIONAL\r
993 )\r
994{\r
995 if (ResourceList != NULL) {\r
996 // TBD\r
997 ASSERT (FALSE);\r
998 return EFI_UNSUPPORTED;\r
999 }\r
1000 //\r
1001 // Delete all\r
1002 //\r
1003 CopyMem (mStmResourcesPtr, &mRscEndNode, sizeof(mRscEndNode));\r
1004 mStmResourceSizeUsed = sizeof(mRscEndNode);\r
1005 mStmResourceSizeAvailable = mStmResourceTotalSize - sizeof(mRscEndNode);\r
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
1025 OUT STM_RSC *ResourceList,\r
1026 IN OUT UINT32 *ResourceSize\r
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
1054 SmmMonitorCtl.Uint64 = AsmReadMsr64 (MSR_IA32_SMM_MONITOR_CTL);\r
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
1092 IN EFI_PHYSICAL_ADDRESS StmImage,\r
1093 IN UINTN StmImageSize\r
1094 )\r
1095{\r
1096 UINTN MinMsegSize;\r
1097 STM_HEADER *StmHeader;\r
1098 IA32_VMX_MISC_REGISTER VmxMiscMsr;\r
1099\r
1100 //\r
1101 // Check to see if STM image is compatible with CPU\r
1102 //\r
1103 StmHeader = (STM_HEADER *)(UINTN)StmImage;\r
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
1126 if (MinMsegSize < StmHeader->HwStmHdr.Cr3Offset + EFI_PAGES_TO_SIZE(6)) {\r
1127 MinMsegSize = StmHeader->HwStmHdr.Cr3Offset + EFI_PAGES_TO_SIZE(6);\r
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
1158 IN EFI_PHYSICAL_ADDRESS StmImage,\r
1159 IN UINTN StmImageSize\r
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
1170 MsegBase = SmmMonitorCtl.Bits.MsegBase << 12;\r
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
1206 IN EFI_PHYSICAL_ADDRESS StmImage,\r
1207 IN UINTN StmImageSize\r
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
1226 TpmMeasureAndLogData(\r
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
1245 Comsumed by SmmMpService when Init.\r
1246\r
1247 @return BIOS STM resource\r
1248\r
1249**/\r
1250VOID *\r
1251GetStmResource(\r
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
1266 VOID *StmResource\r
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
1273 Psd = (TXT_PROCESSOR_SMM_DESCRIPTOR *)((UINTN)gSmst->CpuSaveState[Index] - SMRAM_SAVE_STATE_MAP_OFFSET + TXT_SMM_PSD_OFFSET);\r
1274 Psd->BiosHwResourceRequirementsPtr = (UINT64)(UINTN)StmResource;\r
1275 }\r
1276 return ;\r
1277}\r
1278\r
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
1303\r