EFI_STATUS Status;\r
BOOLEAN InterruptState;\r
IA32_DESCRIPTOR DxeIdtr;\r
+\r
+ //\r
+ // There are 32 (not 255) entries in it since only processor\r
+ // generated exceptions will be handled.\r
+ //\r
+ gcSmiIdtr.Limit = (sizeof(IA32_IDT_GATE_DESCRIPTOR) * 32) - 1;\r
+ //\r
+ // Allocate page aligned IDT, because it might be set as read only.\r
+ //\r
+ gcSmiIdtr.Base = (UINTN)AllocateCodePages (EFI_SIZE_TO_PAGES(gcSmiIdtr.Limit + 1));\r
+ ASSERT (gcSmiIdtr.Base != 0);\r
+ ZeroMem ((VOID *)gcSmiIdtr.Base, gcSmiIdtr.Limit + 1);\r
+\r
//\r
// Disable Interrupt and save DXE IDT table\r
//\r
//\r
BufferPages = EFI_SIZE_TO_PAGES (SIZE_32KB + TileSize * (mMaxNumberOfCpus - 1));\r
if ((FamilyId == 4) || (FamilyId == 5)) {\r
- Buffer = AllocateAlignedPages (BufferPages, SIZE_32KB);\r
+ Buffer = AllocateAlignedCodePages (BufferPages, SIZE_32KB);\r
} else {\r
- Buffer = AllocateAlignedPages (BufferPages, SIZE_4KB);\r
+ Buffer = AllocateAlignedCodePages (BufferPages, SIZE_4KB);\r
}\r
ASSERT (Buffer != NULL);\r
DEBUG ((EFI_D_INFO, "SMRAM SaveState Buffer (0x%08x, 0x%08x)\n", Buffer, EFI_PAGES_TO_SIZE(BufferPages)));\r
//\r
SmmCpuFeaturesSmmRelocationComplete ();\r
\r
+ DEBUG ((DEBUG_INFO, "mXdSupported - 0x%x\n", mXdSupported));\r
+\r
//\r
// SMM Time initialization\r
//\r
}\r
}\r
\r
+/**\r
+ Set code region to be read only and data region to be execute disable.\r
+**/\r
+VOID\r
+SetRegionAttributes (\r
+ VOID\r
+ )\r
+{\r
+ SetMemMapAttributes ();\r
+}\r
+\r
/**\r
This API provides a way to allocate memory for page table.\r
\r
return AllocatePages (Pages);\r
}\r
\r
+/**\r
+ Allocate pages for code.\r
+\r
+ @param[in] Pages Number of pages to be allocated.\r
+\r
+ @return Allocated memory.\r
+**/\r
+VOID *\r
+AllocateCodePages (\r
+ IN UINTN Pages\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_PHYSICAL_ADDRESS Memory;\r
+\r
+ if (Pages == 0) {\r
+ return NULL;\r
+ }\r
+\r
+ Status = gSmst->SmmAllocatePages (AllocateAnyPages, EfiRuntimeServicesCode, Pages, &Memory);\r
+ if (EFI_ERROR (Status)) {\r
+ return NULL;\r
+ }\r
+ return (VOID *) (UINTN) Memory;\r
+}\r
+\r
+/**\r
+ Allocate aligned pages for code.\r
+\r
+ @param[in] Pages Number of pages to be allocated.\r
+ @param[in] Alignment The requested alignment of the allocation.\r
+ Must be a power of two.\r
+ If Alignment is zero, then byte alignment is used.\r
+\r
+ @return Allocated memory.\r
+**/\r
+VOID *\r
+AllocateAlignedCodePages (\r
+ IN UINTN Pages,\r
+ IN UINTN Alignment\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_PHYSICAL_ADDRESS Memory;\r
+ UINTN AlignedMemory;\r
+ UINTN AlignmentMask;\r
+ UINTN UnalignedPages;\r
+ UINTN RealPages;\r
+\r
+ //\r
+ // Alignment must be a power of two or zero.\r
+ //\r
+ ASSERT ((Alignment & (Alignment - 1)) == 0);\r
+\r
+ if (Pages == 0) {\r
+ return NULL;\r
+ }\r
+ if (Alignment > EFI_PAGE_SIZE) {\r
+ //\r
+ // Calculate the total number of pages since alignment is larger than page size.\r
+ //\r
+ AlignmentMask = Alignment - 1;\r
+ RealPages = Pages + EFI_SIZE_TO_PAGES (Alignment);\r
+ //\r
+ // Make sure that Pages plus EFI_SIZE_TO_PAGES (Alignment) does not overflow.\r
+ //\r
+ ASSERT (RealPages > Pages);\r
+\r
+ Status = gSmst->SmmAllocatePages (AllocateAnyPages, EfiRuntimeServicesCode, RealPages, &Memory);\r
+ if (EFI_ERROR (Status)) {\r
+ return NULL;\r
+ }\r
+ AlignedMemory = ((UINTN) Memory + AlignmentMask) & ~AlignmentMask;\r
+ UnalignedPages = EFI_SIZE_TO_PAGES (AlignedMemory - (UINTN) Memory);\r
+ if (UnalignedPages > 0) {\r
+ //\r
+ // Free first unaligned page(s).\r
+ //\r
+ Status = gSmst->SmmFreePages (Memory, UnalignedPages);\r
+ ASSERT_EFI_ERROR (Status);\r
+ }\r
+ Memory = (EFI_PHYSICAL_ADDRESS) (AlignedMemory + EFI_PAGES_TO_SIZE (Pages));\r
+ UnalignedPages = RealPages - Pages - UnalignedPages;\r
+ if (UnalignedPages > 0) {\r
+ //\r
+ // Free last unaligned page(s).\r
+ //\r
+ Status = gSmst->SmmFreePages (Memory, UnalignedPages);\r
+ ASSERT_EFI_ERROR (Status);\r
+ }\r
+ } else {\r
+ //\r
+ // Do not over-allocate pages in this case.\r
+ //\r
+ Status = gSmst->SmmAllocatePages (AllocateAnyPages, EfiRuntimeServicesCode, Pages, &Memory);\r
+ if (EFI_ERROR (Status)) {\r
+ return NULL;\r
+ }\r
+ AlignedMemory = (UINTN) Memory;\r
+ }\r
+ return (VOID *) AlignedMemory;\r
+}\r
+\r
/**\r
Perform the remaining tasks.\r
\r
// Create a mix of 2MB and 4KB page table. Update some memory ranges absent and execute-disable.\r
//\r
InitPaging ();\r
+\r
+ //\r
+ // Mark critical region to be read-only in page table\r
+ //\r
+ SetRegionAttributes ();\r
+\r
+ //\r
+ // Set page table itself to be read-only\r
+ //\r
+ SetPageTableAttributes ();\r
+\r
//\r
// Configure SMM Code Access Check feature if available.\r
//\r