]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Core/PiSmmCore/PiSmmIpl.c
Clean up DEC files:
[mirror_edk2.git] / MdeModulePkg / Core / PiSmmCore / PiSmmIpl.c
index ff7eff73bfb08976b3f72fa4f139bbd0c804533b..0cfd746a07c7938e4f1b7ac4ec53591dbd36452d 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 - 2011, 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
@@ -210,8 +211,8 @@ SMM_CORE_PRIVATE_DATA  mSmmCorePrivateData = {
   FALSE,                              // SmmEntryPointRegistered\r
   FALSE,                              // InSmm\r
   NULL,                               // Smst\r
-  0,                                  // BufferSize\r
   NULL,                               // CommunicationBuffer\r
+  0,                                  // BufferSize\r
   EFI_SUCCESS                         // ReturnStatus\r
 };\r
 \r
@@ -227,6 +228,8 @@ EFI_SMM_CONTROL2_PROTOCOL  *mSmmControl2;
 EFI_SMM_ACCESS2_PROTOCOL   *mSmmAccess;\r
 EFI_SMRAM_DESCRIPTOR       *mCurrentSmramRange;\r
 BOOLEAN                    mSmmLocked = FALSE;\r
+EFI_PHYSICAL_ADDRESS       mSmramCacheBase;\r
+UINT64                     mSmramCacheSize;\r
 \r
 //\r
 // Table of Protocol notification and GUIDed Event notifications that the SMM IPL requires\r
@@ -272,6 +275,49 @@ SMM_IPL_EVENT_NOTIFICATION  mSmmIplEvents[] = {
   { FALSE, FALSE, NULL,                               NULL,                              NULL,                               NULL }\r
 };\r
 \r
+/**\r
+  Find the maximum SMRAM cache range that covers the range specified by SmramRange.\r
+  \r
+  This function searches and joins all adjacent ranges of SmramRange into a range to be cached.\r
+\r
+  @param   SmramRange       The SMRAM range to search from.\r
+  @param   SmramCacheBase   The returned cache range base.\r
+  @param   SmramCacheSize   The returned cache range size.\r
+\r
+**/\r
+VOID\r
+GetSmramCacheRange (\r
+  IN  EFI_SMRAM_DESCRIPTOR *SmramRange,\r
+  OUT EFI_PHYSICAL_ADDRESS *SmramCacheBase,\r
+  OUT UINT64               *SmramCacheSize\r
+  )\r
+{\r
+  UINTN                Index;\r
+  EFI_PHYSICAL_ADDRESS RangeCpuStart;\r
+  UINT64               RangePhysicalSize;\r
+  BOOLEAN              FoundAjacentRange;\r
+\r
+  *SmramCacheBase = SmramRange->CpuStart;\r
+  *SmramCacheSize = SmramRange->PhysicalSize;\r
+\r
+  do {\r
+    FoundAjacentRange = FALSE;\r
+    for (Index = 0; Index < gSmmCorePrivate->SmramRangeCount; Index++) {\r
+      RangeCpuStart     = gSmmCorePrivate->SmramRanges[Index].CpuStart;\r
+      RangePhysicalSize = gSmmCorePrivate->SmramRanges[Index].PhysicalSize;\r
+      if (RangeCpuStart < *SmramCacheBase && *SmramCacheBase == (RangeCpuStart + RangePhysicalSize)) {\r
+        *SmramCacheBase   = RangeCpuStart;\r
+        *SmramCacheSize  += RangePhysicalSize;\r
+        FoundAjacentRange = TRUE;\r
+      } else if ((*SmramCacheBase + *SmramCacheSize) == RangeCpuStart && RangePhysicalSize > 0) {\r
+        *SmramCacheSize  += RangePhysicalSize;\r
+        FoundAjacentRange = TRUE;\r
+      }\r
+    }\r
+  } while (FoundAjacentRange);\r
+  \r
+}\r
+\r
 /**\r
   Indicate whether the driver is currently executing in the SMM Initialization phase.\r
 \r
@@ -365,6 +411,13 @@ SmmCommunicationCommunicate (
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
+  //\r
+  // CommSize must hold HeaderGuid and MessageLength\r
+  //\r
+  if (*CommSize < OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
   //\r
   // If not already in SMM, then generate a Software SMI\r
   //\r
@@ -373,7 +426,7 @@ SmmCommunicationCommunicate (
     // Put arguments for Software SMI in gSmmCorePrivate\r
     //\r
     gSmmCorePrivate->CommunicationBuffer = CommBuffer;\r
-    gSmmCorePrivate->BufferSize          = CommSize;\r
+    gSmmCorePrivate->BufferSize          = *CommSize;\r
 \r
     //\r
     // Generate Software SMI\r
@@ -386,6 +439,7 @@ SmmCommunicationCommunicate (
     //\r
     // Return status from software SMI \r
     //\r
+    *CommSize = gSmmCorePrivate->BufferSize;\r
     return gSmmCorePrivate->ReturnStatus;\r
   }\r
 \r
@@ -400,9 +454,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
@@ -513,10 +567,11 @@ SmmIplSmmConfigurationEventNotify (
 \r
   //\r
   // Attempt to reset SMRAM cacheability to UC\r
+  // Assume CPU AP is available at this time\r
   //\r
   Status = gDS->SetMemorySpaceAttributes(\r
-                  mCurrentSmramRange->CpuStart\r
-                  mCurrentSmramRange->PhysicalSize,\r
+                  mSmramCacheBase\r
+                  mSmramCacheSize,\r
                   EFI_MEMORY_UC\r
                   );\r
   if (EFI_ERROR (Status)) {\r
@@ -630,81 +685,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
@@ -827,9 +807,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
@@ -978,8 +965,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
@@ -1057,6 +1045,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
@@ -1076,17 +1071,24 @@ SmmIplEntry (
       (VOID *)(UINTN)(mCurrentSmramRange->CpuStart + mCurrentSmramRange->PhysicalSize - 1)\r
       ));\r
 \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
-                    mCurrentSmramRange->CpuStart, \r
-                    mCurrentSmramRange->PhysicalSize,\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
@@ -1109,11 +1111,11 @@ SmmIplEntry (
                );\r
       if (!EFI_ERROR (Status) && LMFAConfigurationTable != NULL) {\r
         LMFAConfigurationTable->SmramBase = mCurrentSmramRange->CpuStart;\r
+        //\r
+        // Print the SMRAM base\r
+        //\r
+        DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED INFO: TSEG BASE is %x. \n", LMFAConfigurationTable->SmramBase));\r
       }\r
-      //\r
-      // Print the SMRAM base\r
-      //\r
-      DEBUG ((EFI_D_INFO, "LOADING MODULE FIXED INFO: TSEG BASE is %x. \n", LMFAConfigurationTable->SmramBase));\r
     }\r
     //\r
     // Load SMM Core into SMRAM and execute it from SMRAM\r
@@ -1128,14 +1130,16 @@ SmmIplEntry (
       //\r
       // Attempt to reset SMRAM cacheability to UC\r
       //\r
-      Status = gDS->SetMemorySpaceAttributes(\r
-                      mCurrentSmramRange->CpuStart, \r
-                      mCurrentSmramRange->PhysicalSize,\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