]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Core/PiSmmCore/PiSmmIpl.c
MdeModulePkg DxeCore/PiSmmCore: Add UEFI memory and SMRAM profile support.
[mirror_edk2.git] / MdeModulePkg / Core / PiSmmCore / PiSmmIpl.c
index 6b89ab3aa3210f2e3b14d6166d0a3cbcdea94d14..21c69ca6ef5bbf8a503b97f8f561abbc9c0d4177 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   SMM IPL that produces SMM related runtime protocols and load the SMM Core into SMRAM\r
 \r
-  Copyright (c) 2009 - 2010, Intel Corporation.  All rights reserved.<BR>\r
+  Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR>\r
   This program and the accompanying materials are licensed and made available \r
   under the terms and conditions of the BSD License which accompanies this \r
   distribution.  The full text of the license may be found at        \r
@@ -20,7 +20,7 @@
 #include <Protocol/SmmConfiguration.h>\r
 #include <Protocol/SmmControl2.h>\r
 #include <Protocol/DxeSmmReadyToLock.h>\r
-#include <Protocol/FirmwareVolume2.h>\r
+#include <Protocol/Cpu.h>\r
 \r
 #include <Guid/EventGroup.h>\r
 #include <Guid/EventLegacyBios.h>\r
@@ -34,6 +34,7 @@
 #include <Library/DebugLib.h>\r
 #include <Library/UefiBootServicesTableLib.h>\r
 #include <Library/DxeServicesTableLib.h>\r
+#include <Library/DxeServicesLib.h>\r
 #include <Library/UefiLib.h>\r
 #include <Library/UefiRuntimeLib.h>\r
 #include <Library/PcdLib.h>\r
@@ -139,6 +140,20 @@ SmmIplReadyToLockEventNotify (
   @param  Event                 The Event that is being processed, not used.\r
   @param  Context               Event Context, not used.\r
 \r
+**/\r
+VOID\r
+EFIAPI\r
+SmmIplDxeDispatchEventNotify (\r
+  IN EFI_EVENT  Event,\r
+  IN VOID       *Context\r
+  );\r
+\r
+/**\r
+  Event notification that is fired when a GUIDed Event Group is signaled.\r
+\r
+  @param  Event                 The Event that is being processed, not used.\r
+  @param  Context               Event Context, not used.\r
+\r
 **/\r
 VOID\r
 EFIAPI\r
@@ -174,6 +189,7 @@ typedef struct {
   EFI_GUID          *Guid;\r
   EFI_EVENT_NOTIFY  NotifyFunction;\r
   VOID              *NotifyContext;\r
+  EFI_TPL           NotifyTpl;\r
   EFI_EVENT         Event;\r
 } SMM_IPL_EVENT_NOTIFICATION;\r
 \r
@@ -239,39 +255,45 @@ SMM_IPL_EVENT_NOTIFICATION  mSmmIplEvents[] = {
   // the associated event is immediately signalled, so the notification function will be executed and the \r
   // SMM Configuration Protocol will be found if it is already in the handle database.\r
   //\r
-  { TRUE,  FALSE, &gEfiSmmConfigurationProtocolGuid,  SmmIplSmmConfigurationEventNotify, &gEfiSmmConfigurationProtocolGuid,  NULL },\r
+  { TRUE,  FALSE, &gEfiSmmConfigurationProtocolGuid,  SmmIplSmmConfigurationEventNotify, &gEfiSmmConfigurationProtocolGuid,  TPL_NOTIFY,   NULL },\r
   //\r
   // Declare protocl notification on DxeSmmReadyToLock protocols.  When this notification is etablished, \r
   // the associated event is immediately signalled, so the notification function will be executed and the \r
   // DXE SMM Ready To Lock Protocol will be found if it is already in the handle database.\r
   //\r
-  { TRUE,  TRUE,  &gEfiDxeSmmReadyToLockProtocolGuid, SmmIplReadyToLockEventNotify,      &gEfiDxeSmmReadyToLockProtocolGuid, NULL },\r
+  { TRUE,  TRUE,  &gEfiDxeSmmReadyToLockProtocolGuid, SmmIplReadyToLockEventNotify,      &gEfiDxeSmmReadyToLockProtocolGuid, TPL_CALLBACK, NULL },\r
+  //\r
+  // Declare event notification on EndOfDxe event.  When this notification is etablished, \r
+  // the associated event is immediately signalled, so the notification function will be executed and the \r
+  // SMM End Of Dxe Protocol will be found if it is already in the handle database.\r
+  //\r
+  { FALSE, FALSE,  &gEfiEndOfDxeEventGroupGuid,        SmmIplGuidedEventNotify,           &gEfiEndOfDxeEventGroupGuid,        TPL_CALLBACK, NULL },\r
   //\r
   // Declare event notification on the DXE Dispatch Event Group.  This event is signaled by the DXE Core\r
   // each time the DXE Core dispatcher has completed its work.  When this event is signalled, the SMM Core\r
   // if notified, so the SMM Core can dispatch SMM drivers.\r
   //\r
-  { FALSE, TRUE,  &gEfiEventDxeDispatchGuid,          SmmIplGuidedEventNotify,           &gEfiEventDxeDispatchGuid,          NULL },\r
+  { FALSE, TRUE,  &gEfiEventDxeDispatchGuid,          SmmIplDxeDispatchEventNotify,      &gEfiEventDxeDispatchGuid,          TPL_CALLBACK, NULL },\r
   //\r
   // Declare event notification on Ready To Boot Event Group.  This is an extra event notification that is\r
   // used to make sure SMRAM is locked before any boot options are processed.\r
   //\r
-  { FALSE, TRUE,  &gEfiEventReadyToBootGuid,          SmmIplReadyToLockEventNotify,      &gEfiEventReadyToBootGuid,          NULL },\r
+  { FALSE, TRUE,  &gEfiEventReadyToBootGuid,          SmmIplReadyToLockEventNotify,      &gEfiEventReadyToBootGuid,          TPL_CALLBACK, NULL },\r
   //\r
   // Declare event notification on Legacy Boot Event Group.  This is used to inform the SMM Core that the platform \r
   // is performing a legacy boot operation, and that the UEFI environment is no longer available and the SMM Core \r
   // must guarantee that it does not access any UEFI related structures outside of SMRAM.\r
   //\r
-  { FALSE, FALSE, &gEfiEventLegacyBootGuid,           SmmIplGuidedEventNotify,           &gEfiEventLegacyBootGuid,           NULL },\r
+  { FALSE, FALSE, &gEfiEventLegacyBootGuid,           SmmIplGuidedEventNotify,           &gEfiEventLegacyBootGuid,           TPL_CALLBACK, NULL },\r
   //\r
   // Declare event notification on SetVirtualAddressMap() Event Group.  This is used to convert gSmmCorePrivate \r
   // and mSmmControl2 from physical addresses to virtual addresses.\r
   //\r
-  { FALSE, FALSE, &gEfiEventVirtualAddressChangeGuid, SmmIplSetVirtualAddressNotify,     NULL,                               NULL },\r
+  { FALSE, FALSE, &gEfiEventVirtualAddressChangeGuid, SmmIplSetVirtualAddressNotify,     NULL,                               TPL_CALLBACK, NULL },\r
   //\r
   // Terminate the table of event notifications\r
   //\r
-  { FALSE, FALSE, NULL,                               NULL,                              NULL,                               NULL }\r
+  { FALSE, FALSE, NULL,                               NULL,                              NULL,                               TPL_CALLBACK, NULL }\r
 };\r
 \r
 /**\r
@@ -453,9 +475,9 @@ SmmCommunicationCommunicate (
   }\r
 \r
   //\r
-  // Don't allow call SmiManage() directly when SMRAM is closed or locked.\r
+  // If we are not in SMM, don't allow call SmiManage() directly when SMRAM is closed or locked.\r
   //\r
-  if (!mSmmAccess->OpenState || mSmmAccess->LockState) {\r
+  if ((!gSmmCorePrivate->InSmm) && (!mSmmAccess->OpenState || mSmmAccess->LockState)) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
  \r
@@ -488,11 +510,11 @@ SmmCommunicationCommunicate (
   //\r
   gSmmCorePrivate->InSmm = OldInSmm;\r
 \r
-  return (Status == EFI_WARN_INTERRUPT_SOURCE_QUIESCED) ? EFI_SUCCESS : EFI_NOT_FOUND;\r
+  return (Status == EFI_SUCCESS) ? EFI_SUCCESS : EFI_NOT_FOUND;\r
 }\r
 \r
 /**\r
-  Event notification that is fired when DxeDispatch Event Group is signaled.\r
+  Event notification that is fired when GUIDed Event Group is signaled.\r
 \r
   @param  Event                 The Event that is being processed, not used.\r
   @param  Context               Event Context, not used.\r
@@ -522,6 +544,76 @@ SmmIplGuidedEventNotify (
   SmmCommunicationCommunicate (&mSmmCommunication, &CommunicateHeader, &Size);\r
 }\r
 \r
+/**\r
+  Event notification that is fired when DxeDispatch Event Group is signaled.\r
+\r
+  @param  Event                 The Event that is being processed, not used.\r
+  @param  Context               Event Context, not used.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+SmmIplDxeDispatchEventNotify (\r
+  IN EFI_EVENT  Event,\r
+  IN VOID       *Context\r
+  )\r
+{\r
+  EFI_SMM_COMMUNICATE_HEADER  CommunicateHeader;\r
+  UINTN                       Size;\r
+  EFI_STATUS                  Status;\r
+\r
+  //\r
+  // Keep calling the SMM Core Dispatcher until there is no request to restart it.\r
+  //\r
+  while (TRUE) {\r
+    //\r
+    // Use Guid to initialize EFI_SMM_COMMUNICATE_HEADER structure\r
+    // Clear the buffer passed into the Software SMI.  This buffer will return\r
+    // the status of the SMM Core Dispatcher.\r
+    //\r
+    CopyGuid (&CommunicateHeader.HeaderGuid, (EFI_GUID *)Context);\r
+    CommunicateHeader.MessageLength = 1;\r
+    CommunicateHeader.Data[0] = 0;\r
+\r
+    //\r
+    // Generate the Software SMI and return the result\r
+    //\r
+    Size = sizeof (CommunicateHeader);\r
+    SmmCommunicationCommunicate (&mSmmCommunication, &CommunicateHeader, &Size);\r
+    \r
+    //\r
+    // Return if there is no request to restart the SMM Core Dispatcher\r
+    //\r
+    if (CommunicateHeader.Data[0] != COMM_BUFFER_SMM_DISPATCH_RESTART) {\r
+      return;\r
+    }\r
+      \r
+    //\r
+    // Attempt to reset SMRAM cacheability to UC\r
+    // Assume CPU AP is available at this time\r
+    //\r
+    Status = gDS->SetMemorySpaceAttributes(\r
+                    mSmramCacheBase, \r
+                    mSmramCacheSize,\r
+                    EFI_MEMORY_UC\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      DEBUG ((DEBUG_WARN, "SMM IPL failed to reset SMRAM window to EFI_MEMORY_UC\n"));\r
+    }  \r
+\r
+    //\r
+    // Close all SMRAM ranges to protect SMRAM\r
+    //\r
+    Status = mSmmAccess->Close (mSmmAccess);\r
+    ASSERT_EFI_ERROR (Status);\r
+\r
+    //\r
+    // Print debug message that the SMRAM window is now closed.\r
+    //\r
+    DEBUG ((DEBUG_INFO, "SMM IPL closed SMRAM window\n"));\r
+  }\r
+}\r
+\r
 /**\r
   Event notification that is fired every time a gEfiSmmConfigurationProtocol installs.\r
 \r
@@ -554,7 +646,7 @@ SmmIplSmmConfigurationEventNotify (
   ASSERT_EFI_ERROR (Status);\r
 \r
   //\r
-  // Set flag to indicate that the SM< Entry Point has been registered which \r
+  // Set flag to indicate that the SMM Entry Point has been registered which \r
   // means that SMIs are now fully operational.\r
   //\r
   gSmmCorePrivate->SmmEntryPointRegistered = TRUE;\r
@@ -563,29 +655,6 @@ SmmIplSmmConfigurationEventNotify (
   // Print debug message showing SMM Core entry point address.\r
   //\r
   DEBUG ((DEBUG_INFO, "SMM IPL registered SMM Entry Point address %p\n", (VOID *)(UINTN)gSmmCorePrivate->SmmEntryPoint));\r
-\r
-  //\r
-  // Attempt to reset SMRAM cacheability to UC\r
-  //\r
-  Status = gDS->SetMemorySpaceAttributes(\r
-                  mSmramCacheBase, \r
-                  mSmramCacheSize,\r
-                  EFI_MEMORY_UC\r
-                  );\r
-  if (EFI_ERROR (Status)) {\r
-    DEBUG ((DEBUG_WARN, "SMM IPL failed to reset SMRAM window to EFI_MEMORY_UC\n"));\r
-  }  \r
-\r
-  //\r
-  // Close all SMRAM ranges to protect SMRAM\r
-  //\r
-  Status = mSmmAccess->Close (mSmmAccess);\r
-  ASSERT_EFI_ERROR (Status);\r
-\r
-  //\r
-  // Print debug message that the SMRAM window is now closed.\r
-  //\r
-  DEBUG ((DEBUG_INFO, "SMM IPL closed SMRAM window\n"));\r
 }\r
 \r
 /**\r
@@ -635,7 +704,7 @@ SmmIplReadyToLockEventNotify (
   // Lock the SMRAM (Note: Locking SMRAM may not be supported on all platforms)\r
   //\r
   mSmmAccess->Lock (mSmmAccess);\r
-\r
+  \r
   //\r
   // Close protocol and event notification events that do not apply after the \r
   // DXE SMM Ready To Lock Protocol has been installed or the Ready To Boot \r
@@ -683,81 +752,6 @@ SmmIplSetVirtualAddressNotify (
   EfiConvertPointer (0x0, (VOID **)&mSmmControl2);\r
 }\r
 \r
-/**\r
-  Searches all Firmware Volumes for the first file matching FileType and SectionType and returns the section data.\r
-\r
-  @param   FileType                FileType to search for within any of the firmware volumes in the platform.\r
-  @param   SectionType             SectionType to search for within any of the matching FileTypes in the firmware volumes in the platform.\r
-  @param   SourceSize              Return the size of the returned section data..\r
-\r
-  @retval  != NULL                 Pointer to the allocated buffer containing the section data.\r
-  @retval  NULL                    Section data was not found.\r
-\r
-**/\r
-VOID *\r
-GetSectionInAnyFv (\r
-  IN  EFI_FV_FILETYPE   FileType,\r
-  IN  EFI_SECTION_TYPE  SectionType,\r
-  OUT UINTN             *SourceSize\r
-  )\r
-{\r
-  EFI_STATUS                    Status;\r
-  UINTN                         HandleCount;\r
-  EFI_HANDLE                    *HandleBuffer;\r
-  UINTN                         Index;\r
-  EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv;\r
-  UINTN                         Key;\r
-  EFI_GUID                      NameGuid;\r
-  EFI_FV_FILE_ATTRIBUTES        Attributes;\r
-  VOID                          *SourceBuffer;\r
-  UINT32                        AuthenticationStatus;\r
-\r
-  HandleBuffer = NULL;\r
-  Status = gBS->LocateHandleBuffer (\r
-                  ByProtocol,\r
-                  &gEfiFirmwareVolume2ProtocolGuid,\r
-                  NULL,\r
-                  &HandleCount,\r
-                  &HandleBuffer\r
-                  );\r
-  if (EFI_ERROR (Status)) {\r
-    return NULL;\r
-  }\r
-\r
-  for (Index = 0; Index < HandleCount; Index++) {\r
-    Status = gBS->HandleProtocol (\r
-                    HandleBuffer[Index],\r
-                    &gEfiFirmwareVolume2ProtocolGuid,\r
-                    (VOID **)&Fv\r
-                    );\r
-    if (EFI_ERROR (Status)) {\r
-      continue;\r
-    }\r
-\r
-    //\r
-    // Use Firmware Volume 2 Protocol to search for a file of type FileType\r
-    //\r
-    Key = 0;   \r
-    Status = Fv->GetNextFile (Fv, &Key, &FileType, &NameGuid, &Attributes, SourceSize);\r
-    if (EFI_ERROR (Status)) {\r
-      continue;\r
-    }\r
-\r
-    //\r
-    // Use Firmware Volume 2 Protocol to read a section of type SectionType\r
-    //\r
-    SourceBuffer = NULL;\r
-    Status = Fv->ReadSection (Fv, &NameGuid, SectionType, 0, &SourceBuffer, SourceSize, &AuthenticationStatus);\r
-    if (!EFI_ERROR (Status)) {\r
-      FreePool (HandleBuffer);\r
-      return SourceBuffer;\r
-    }\r
-  }  \r
-\r
-  FreePool(HandleBuffer);\r
-  \r
-  return NULL;\r
-}\r
 /**\r
   Get the fixed loadding address from image header assigned by build tool. This function only be called\r
   when Loading module at Fixed address feature enabled.\r
@@ -880,9 +874,16 @@ ExecuteSmmCoreFromSmram (
   //\r
   // Search all Firmware Volumes for a PE/COFF image in a file of type SMM_CORE\r
   //  \r
-  SourceBuffer = GetSectionInAnyFv (EFI_FV_FILETYPE_SMM_CORE, EFI_SECTION_PE32, &SourceSize);\r
-  if (SourceBuffer == NULL) {\r
-    return EFI_NOT_FOUND;\r
+  Status = GetSectionFromAnyFvByFileType (\r
+             EFI_FV_FILETYPE_SMM_CORE, \r
+             0,\r
+             EFI_SECTION_PE32, \r
+             0,\r
+             &SourceBuffer, \r
+             &SourceSize\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
   }\r
   \r
   //\r
@@ -918,7 +919,7 @@ ExecuteSmmCoreFromSmram (
       // Allocate memory for the image being loaded from the EFI_SRAM_DESCRIPTOR \r
       // specified by SmramRange\r
       //\r
-      PageCount = (UINTN)EFI_SIZE_TO_PAGES(ImageContext.ImageSize + ImageContext.SectionAlignment);\r
+      PageCount = (UINTN)EFI_SIZE_TO_PAGES((UINTN)ImageContext.ImageSize + ImageContext.SectionAlignment);\r
 \r
       ASSERT ((SmramRange->PhysicalSize & EFI_PAGE_MASK) == 0);\r
       ASSERT (SmramRange->PhysicalSize > EFI_PAGES_TO_SIZE (PageCount));\r
@@ -936,7 +937,7 @@ ExecuteSmmCoreFromSmram (
     // Allocate memory for the image being loaded from the EFI_SRAM_DESCRIPTOR \r
     // specified by SmramRange\r
     //\r
-    PageCount = (UINTN)EFI_SIZE_TO_PAGES(ImageContext.ImageSize + ImageContext.SectionAlignment);\r
+    PageCount = (UINTN)EFI_SIZE_TO_PAGES((UINTN)ImageContext.ImageSize + ImageContext.SectionAlignment);\r
 \r
     ASSERT ((SmramRange->PhysicalSize & EFI_PAGE_MASK) == 0);\r
     ASSERT (SmramRange->PhysicalSize > EFI_PAGES_TO_SIZE (PageCount));\r
@@ -951,7 +952,7 @@ ExecuteSmmCoreFromSmram (
   }\r
   \r
   ImageContext.ImageAddress += ImageContext.SectionAlignment - 1;\r
-  ImageContext.ImageAddress &= ~(ImageContext.SectionAlignment - 1);\r
+  ImageContext.ImageAddress &= ~((EFI_PHYSICAL_ADDRESS)(ImageContext.SectionAlignment - 1));\r
 \r
   //\r
   // Print debug message showing SMM Core load address.\r
@@ -978,6 +979,13 @@ ExecuteSmmCoreFromSmram (
       //\r
       DEBUG ((DEBUG_INFO, "SMM IPL calling SMM Core at SMRAM address %p\n", (VOID *)(UINTN)ImageContext.EntryPoint));\r
 \r
+      gSmmCorePrivate->PiSmmCoreImageBase = ImageContext.ImageAddress;\r
+      gSmmCorePrivate->PiSmmCoreImageSize = ImageContext.ImageSize;\r
+      DEBUG ((DEBUG_INFO, "PiSmmCoreImageBase - 0x%016lx\n", gSmmCorePrivate->PiSmmCoreImageBase));\r
+      DEBUG ((DEBUG_INFO, "PiSmmCoreImageSize - 0x%016lx\n", gSmmCorePrivate->PiSmmCoreImageSize));\r
+\r
+      gSmmCorePrivate->PiSmmCoreEntryPoint = ImageContext.EntryPoint;\r
+\r
       //\r
       // Execute image\r
       //\r
@@ -1031,8 +1039,9 @@ SmmIplEntry (
   EFI_SMM_RESERVED_SMRAM_REGION   *SmramResRegion;\r
   UINT64                          MaxSize;\r
   VOID                            *Registration;\r
-  UINT64                           SmmCodeSize;\r
+  UINT64                          SmmCodeSize;\r
   EFI_LOAD_FIXED_ADDRESS_CONFIGURATION_TABLE    *LMFAConfigurationTable;\r
+  EFI_CPU_ARCH_PROTOCOL           *CpuArch;\r
 \r
   //\r
   // Fill in the image handle of the SMM IPL so the SMM Core can use this as the \r
@@ -1074,6 +1083,14 @@ SmmIplEntry (
 \r
   gSmmCorePrivate->SmramRangeCount = Size / sizeof (EFI_SMRAM_DESCRIPTOR);\r
 \r
+  //\r
+  // Save a full copy\r
+  //\r
+  gSmmCorePrivate->FullSmramRangeCount = gSmmCorePrivate->SmramRangeCount;\r
+  gSmmCorePrivate->FullSmramRanges = (EFI_SMRAM_DESCRIPTOR *) AllocatePool (Size);\r
+  ASSERT (gSmmCorePrivate->FullSmramRanges != NULL);\r
+  CopyMem (gSmmCorePrivate->FullSmramRanges, gSmmCorePrivate->SmramRanges, Size);\r
+\r
   //\r
   // Open all SMRAM ranges\r
   //\r
@@ -1110,6 +1127,13 @@ SmmIplEntry (
   //\r
   mCurrentSmramRange = NULL;\r
   for (Index = 0, MaxSize = SIZE_256KB - EFI_PAGE_SIZE; Index < gSmmCorePrivate->SmramRangeCount; Index++) {\r
+    //\r
+    // Skip any SMRAM region that is already allocated, needs testing, or needs ECC initialization\r
+    //\r
+    if ((gSmmCorePrivate->SmramRanges[Index].RegionState & (EFI_ALLOCATED | EFI_NEEDS_TESTING | EFI_NEEDS_ECC_INITIALIZATION)) != 0) {\r
+      continue;\r
+    }\r
+\r
     if (gSmmCorePrivate->SmramRanges[Index].CpuStart >= BASE_1MB) {\r
       if ((gSmmCorePrivate->SmramRanges[Index].CpuStart + gSmmCorePrivate->SmramRanges[Index].PhysicalSize) <= BASE_4GB) {\r
         if (gSmmCorePrivate->SmramRanges[Index].PhysicalSize >= MaxSize) {\r
@@ -1131,16 +1155,22 @@ SmmIplEntry (
 \r
     GetSmramCacheRange (mCurrentSmramRange, &mSmramCacheBase, &mSmramCacheSize);\r
     //\r
-    // Attempt to set SMRAM cacheability to WB\r
+    // If CPU AP is present, attempt to set SMRAM cacheability to WB\r
+    // Note that it is expected that cacheability of SMRAM has been set to WB if CPU AP\r
+    // is not available here.\r
     //\r
-    Status = gDS->SetMemorySpaceAttributes(\r
-                    mSmramCacheBase, \r
-                    mSmramCacheSize,\r
-                    EFI_MEMORY_WB\r
-                    );\r
-    if (EFI_ERROR (Status)) {\r
-      DEBUG ((DEBUG_WARN, "SMM IPL failed to set SMRAM window to EFI_MEMORY_WB\n"));\r
-    }  \r
+    CpuArch = NULL;\r
+    Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **)&CpuArch);\r
+    if (!EFI_ERROR (Status)) {\r
+      Status = gDS->SetMemorySpaceAttributes(\r
+                      mSmramCacheBase, \r
+                      mSmramCacheSize,\r
+                      EFI_MEMORY_WB\r
+                      );\r
+      if (EFI_ERROR (Status)) {\r
+        DEBUG ((DEBUG_WARN, "SMM IPL failed to set SMRAM window to EFI_MEMORY_WB\n"));\r
+      }  \r
+    }\r
     //\r
     // if Loading module at Fixed Address feature is enabled, save the SMRAM base to Load\r
     // Modules At Fixed Address Configuration Table.\r
@@ -1182,14 +1212,16 @@ SmmIplEntry (
       //\r
       // Attempt to reset SMRAM cacheability to UC\r
       //\r
-      Status = gDS->SetMemorySpaceAttributes(\r
-                      mSmramCacheBase, \r
-                      mSmramCacheSize,\r
-                      EFI_MEMORY_UC\r
-                      );\r
-      if (EFI_ERROR (Status)) {\r
-        DEBUG ((DEBUG_WARN, "SMM IPL failed to reset SMRAM window to EFI_MEMORY_UC\n"));\r
-      }  \r
+      if (CpuArch != NULL) {\r
+        Status = gDS->SetMemorySpaceAttributes(\r
+                        mSmramCacheBase, \r
+                        mSmramCacheSize,\r
+                        EFI_MEMORY_UC\r
+                        );\r
+        if (EFI_ERROR (Status)) {\r
+          DEBUG ((DEBUG_WARN, "SMM IPL failed to reset SMRAM window to EFI_MEMORY_UC\n"));\r
+        }  \r
+      }\r
     }\r
   } else {\r
     //\r
@@ -1240,7 +1272,7 @@ SmmIplEntry (
     if (mSmmIplEvents[Index].Protocol) {\r
       mSmmIplEvents[Index].Event = EfiCreateProtocolNotifyEvent (\r
                                      mSmmIplEvents[Index].Guid,\r
-                                    TPL_CALLBACK,\r
+                                     mSmmIplEvents[Index].NotifyTpl,\r
                                      mSmmIplEvents[Index].NotifyFunction,\r
                                      mSmmIplEvents[Index].NotifyContext,\r
                                     &Registration\r
@@ -1248,7 +1280,7 @@ SmmIplEntry (
     } else {\r
       Status = gBS->CreateEventEx (\r
                       EVT_NOTIFY_SIGNAL,\r
-                      TPL_CALLBACK,\r
+                      mSmmIplEvents[Index].NotifyTpl,\r
                       mSmmIplEvents[Index].NotifyFunction,\r
                       mSmmIplEvents[Index].NotifyContext,\r
                       mSmmIplEvents[Index].Guid,\r