]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Core/PiSmmCore/Dispatcher.c
Update PEI/DXE/SMM dispatchers to include DEBUG ((DEBUG_DISPATCH, )) macros to log...
[mirror_edk2.git] / MdeModulePkg / Core / PiSmmCore / Dispatcher.c
index 9e1a77890079e9f4907d17d4bee60080f17c2fe7..d83224e322aa33dd05394852f8bcd6df23a49087 100644 (file)
@@ -28,7 +28,7 @@
   Depex - Dependency Expresion.\r
   SOR   - Schedule On Request - Don't schedule if this bit is set.\r
 \r
-  Copyright (c) 2009 - 2010, Intel Corporation.  All rights reserved.<BR>\r
+  Copyright (c) 2009 - 2010, 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
@@ -122,6 +122,176 @@ FV_FILEPATH_DEVICE_PATH  mFvDevicePath;
 //\r
 EFI_SECURITY_ARCH_PROTOCOL  *mSecurity = NULL;\r
 \r
+//\r
+// The global variable is defined for Loading modules at fixed address feature to track the SMM code\r
+// memory range usage. It is a bit mapped array in which every bit indicates the correspoding \r
+// memory page available or not. \r
+//\r
+GLOBAL_REMOVE_IF_UNREFERENCED    UINT64                *mSmmCodeMemoryRangeUsageBitMap=NULL;\r
+\r
+/**\r
+  To check memory usage bit map array to figure out if the memory range in which the image will be loaded is available or not. If \r
+  memory range is avaliable, the function will mark the correponding bits to 1 which indicates the memory range is used.\r
+  The function is only invoked when load modules at fixed address feature is enabled. \r
+  \r
+  @param  ImageBase                The base addres the image will be loaded at.\r
+  @param  ImageSize                The size of the image\r
+  \r
+  @retval EFI_SUCCESS              The memory range the image will be loaded in is available\r
+  @retval EFI_NOT_FOUND            The memory range the image will be loaded in is not available\r
+**/\r
+EFI_STATUS\r
+CheckAndMarkFixLoadingMemoryUsageBitMap (\r
+  IN  EFI_PHYSICAL_ADDRESS          ImageBase,\r
+  IN  UINTN                         ImageSize\r
+  )\r
+{\r
+   UINT32                             SmmCodePageNumber;\r
+   UINT64                             SmmCodeSize; \r
+   EFI_PHYSICAL_ADDRESS               SmmCodeBase;\r
+   UINTN                              BaseOffsetPageNumber;\r
+   UINTN                              TopOffsetPageNumber;\r
+   UINTN                              Index;\r
+   //\r
+   // Build tool will calculate the smm code size and then patch the PcdLoadFixAddressSmmCodePageNumber\r
+   //\r
+   SmmCodePageNumber = PcdGet32(PcdLoadFixAddressSmmCodePageNumber);\r
+   SmmCodeSize = EFI_PAGES_TO_SIZE (SmmCodePageNumber);\r
+   SmmCodeBase = gLoadModuleAtFixAddressSmramBase;\r
+   \r
+   //\r
+   // If the memory usage bit map is not initialized,  do it. Every bit in the array \r
+   // indicate the status of the corresponding memory page, available or not\r
+   // \r
+   if (mSmmCodeMemoryRangeUsageBitMap == NULL) {\r
+     mSmmCodeMemoryRangeUsageBitMap = AllocateZeroPool(((SmmCodePageNumber / 64) + 1)*sizeof(UINT64));\r
+   }\r
+   //\r
+   // If the Dxe code memory range is not allocated or the bit map array allocation failed, return EFI_NOT_FOUND\r
+   //\r
+   if (mSmmCodeMemoryRangeUsageBitMap == NULL) {\r
+     return EFI_NOT_FOUND;\r
+   }\r
+   //\r
+   // see if the memory range for loading the image is in the SMM code range.\r
+   //\r
+   if (SmmCodeBase + SmmCodeSize <  ImageBase + ImageSize || SmmCodeBase >  ImageBase) {\r
+     return EFI_NOT_FOUND;   \r
+   }   \r
+   //\r
+   // Test if the memory is avalaible or not.\r
+   // \r
+   BaseOffsetPageNumber = (UINTN)EFI_SIZE_TO_PAGES((UINT32)(ImageBase - SmmCodeBase));\r
+   TopOffsetPageNumber  = (UINTN)EFI_SIZE_TO_PAGES((UINT32)(ImageBase + ImageSize - SmmCodeBase));\r
+   for (Index = BaseOffsetPageNumber; Index < TopOffsetPageNumber; Index ++) {\r
+     if ((mSmmCodeMemoryRangeUsageBitMap[Index / 64] & LShiftU64(1, (Index % 64))) != 0) {\r
+       //\r
+       // This page is already used.\r
+       //\r
+       return EFI_NOT_FOUND;  \r
+     }\r
+   }\r
+   \r
+   //\r
+   // Being here means the memory range is available.  So mark the bits for the memory range\r
+   // \r
+   for (Index = BaseOffsetPageNumber; Index < TopOffsetPageNumber; Index ++) {\r
+     mSmmCodeMemoryRangeUsageBitMap[Index / 64] |= LShiftU64(1, (Index % 64));\r
+   }\r
+   return  EFI_SUCCESS;   \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
+  \r
+  @param  ImageContext              Pointer to the image context structure that describes the PE/COFF\r
+                                    image that needs to be examined by this function.\r
+  @retval EFI_SUCCESS               An fixed loading address is assigned to this image by build tools .\r
+  @retval EFI_NOT_FOUND             The image has no assigned fixed loadding address.\r
+\r
+**/\r
+EFI_STATUS\r
+GetPeCoffImageFixLoadingAssignedAddress(\r
+  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *ImageContext\r
+  )\r
+{\r
+        UINTN                              SectionHeaderOffset;\r
+        EFI_STATUS                         Status;\r
+        EFI_IMAGE_SECTION_HEADER           SectionHeader;\r
+        EFI_IMAGE_OPTIONAL_HEADER_UNION    *ImgHdr;\r
+        EFI_PHYSICAL_ADDRESS               FixLoaddingAddress;\r
+        UINT16                             Index;\r
+        UINTN                              Size; \r
+        UINT16                             NumberOfSections;\r
+        UINT64                             ValueInSectionHeader;\r
+        \r
+        FixLoaddingAddress = 0;\r
+        Status = EFI_NOT_FOUND;\r
+       \r
+        //\r
+   // Get PeHeader pointer\r
+   //\r
+   ImgHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)((CHAR8* )ImageContext->Handle + ImageContext->PeCoffHeaderOffset);\r
+        SectionHeaderOffset = (UINTN)(\r
+                                 ImageContext->PeCoffHeaderOffset +\r
+                                 sizeof (UINT32) +\r
+                                 sizeof (EFI_IMAGE_FILE_HEADER) +\r
+                                 ImgHdr->Pe32.FileHeader.SizeOfOptionalHeader\r
+                                 );\r
+   NumberOfSections = ImgHdr->Pe32.FileHeader.NumberOfSections;\r
+     \r
+   //\r
+   // Get base address from the first section header that doesn't point to code section.\r
+   //\r
+   for (Index = 0; Index < NumberOfSections; Index++) {\r
+     //\r
+     // Read section header from file\r
+     //\r
+     Size = sizeof (EFI_IMAGE_SECTION_HEADER);\r
+     Status = ImageContext->ImageRead (\r
+                              ImageContext->Handle,\r
+                              SectionHeaderOffset,\r
+                              &Size,\r
+                              &SectionHeader\r
+                              );\r
+     if (EFI_ERROR (Status)) {\r
+       return Status;\r
+     }\r
+     \r
+     Status = EFI_NOT_FOUND;\r
+     \r
+     if ((SectionHeader.Characteristics & EFI_IMAGE_SCN_CNT_CODE) == 0) {\r
+       //\r
+       // Build tool will save the address in PointerToRelocations & PointerToLineNumbers fields in the first section header \r
+       // that doesn't point to code section in image header.So there is an assumption that when the feature is enabled,\r
+       // if a module with a loading address assigned by tools, the PointerToRelocations & PointerToLineNumbers fields\r
+       // should not be Zero, or else, these 2 fileds should be set to Zero\r
+       //\r
+       ValueInSectionHeader = ReadUnaligned64((UINT64*)&SectionHeader.PointerToRelocations);\r
+       if (ValueInSectionHeader != 0) {\r
+         //\r
+         // Found first section header that doesn't point to code section in which uild tool saves the\r
+         // offset to SMRAM base as image base in PointerToRelocations & PointerToLineNumbers fields\r
+         //      \r
+         FixLoaddingAddress = (EFI_PHYSICAL_ADDRESS)(gLoadModuleAtFixAddressSmramBase + (INT64)ValueInSectionHeader);\r
+         //\r
+         // Check if the memory range is avaliable.\r
+         //\r
+         Status = CheckAndMarkFixLoadingMemoryUsageBitMap (FixLoaddingAddress, (UINTN)(ImageContext->ImageSize + ImageContext->SectionAlignment));\r
+         if (!EFI_ERROR(Status)) {\r
+           //\r
+           // The assigned address is valid. Return the specified loadding address\r
+           //\r
+           ImageContext->ImageAddress = FixLoaddingAddress;\r
+         }\r
+       }\r
+       break;     \r
+     }\r
+     SectionHeaderOffset += sizeof (EFI_IMAGE_SECTION_HEADER);     \r
+   }\r
+   DEBUG ((EFI_D_INFO|EFI_D_LOAD, "LOADING MODULE FIXED INFO: Loading module at fixed address %x, Status = %r\n", FixLoaddingAddress, Status));\r
+   return Status;\r
+}\r
 /**\r
   Loads an EFI image into SMRAM.\r
 \r
@@ -258,24 +428,63 @@ SmmLoadImage (
     }\r
     return Status;\r
   }\r
-\r
-  PageCount = (UINTN)EFI_SIZE_TO_PAGES(ImageContext.ImageSize + ImageContext.SectionAlignment);\r
-  DstBuffer = (UINTN)(-1);\r
-  \r
-  Status = SmmAllocatePages (\r
-             AllocateMaxAddress,\r
-             EfiRuntimeServicesCode,\r
-             PageCount,\r
-             &DstBuffer\r
-             );\r
-  if (EFI_ERROR (Status)) {\r
-    if (Buffer != NULL) {\r
-      Status = gBS->FreePool (Buffer);\r
+  //\r
+  // if Loading module at Fixed Address feature is enabled, then  cut out a memory range started from TESG BASE\r
+  // to hold the Smm driver code\r
+  //\r
+  if (PcdGet64(PcdLoadModuleAtFixAddressEnable) != 0) {\r
+    //\r
+    // Get the fixed loading address assigned by Build tool\r
+    //\r
+    Status = GetPeCoffImageFixLoadingAssignedAddress (&ImageContext);\r
+    if (!EFI_ERROR (Status)) {\r
+      //\r
+      // Since the memory range to load Smm core alreay been cut out, so no need to allocate and free this range\r
+      // following statements is to bypass SmmFreePages\r
+      //\r
+      PageCount = 0;\r
+      DstBuffer = (UINTN)gLoadModuleAtFixAddressSmramBase;   \r
+    } else {\r
+       DEBUG ((EFI_D_INFO|EFI_D_LOAD, "LOADING MODULE FIXED ERROR: Failed to load module at fixed address. \n"));\r
+       //\r
+       // allocate the memory to load the SMM driver\r
+       //\r
+       PageCount = (UINTN)EFI_SIZE_TO_PAGES(ImageContext.ImageSize + ImageContext.SectionAlignment);\r
+       DstBuffer = (UINTN)(-1);\r
+     \r
+       Status = SmmAllocatePages (\r
+                   AllocateMaxAddress,\r
+                   EfiRuntimeServicesCode,\r
+                   PageCount,\r
+                   &DstBuffer\r
+                   );\r
+       if (EFI_ERROR (Status)) {\r
+         if (Buffer != NULL) {\r
+           Status = gBS->FreePool (Buffer);\r
+         } \r
+         return Status;\r
+       }     \r
+      ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)DstBuffer;\r
     }\r
-    return Status;\r
+  } else {\r
+     PageCount = (UINTN)EFI_SIZE_TO_PAGES(ImageContext.ImageSize + ImageContext.SectionAlignment);\r
+     DstBuffer = (UINTN)(-1);\r
+     \r
+     Status = SmmAllocatePages (\r
+                  AllocateMaxAddress,\r
+                  EfiRuntimeServicesCode,\r
+                  PageCount,\r
+                  &DstBuffer\r
+                  );\r
+     if (EFI_ERROR (Status)) {\r
+       if (Buffer != NULL) {\r
+         Status = gBS->FreePool (Buffer);\r
+       }\r
+       return Status;\r
+     }\r
+     \r
+     ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)DstBuffer;\r
   }\r
-\r
-  ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)DstBuffer;\r
   //\r
   // Align buffer on section boundry\r
   //\r
@@ -573,9 +782,14 @@ SmmSchedule (
       DriverEntry->Unrequested  = FALSE;\r
       DriverEntry->Dependent    = TRUE;\r
 \r
+      DEBUG ((DEBUG_DISPATCH, "Schedule FFS(%g) - EFI_SUCCESS\n", DriverName));\r
+\r
       return EFI_SUCCESS;\r
     }\r
   }\r
+  \r
+  DEBUG ((DEBUG_DISPATCH, "Schedule FFS(%g) - EFI_NOT_FOUND\n", DriverName));\r
+  \r
   return EFI_NOT_FOUND;\r
 }\r
 \r
@@ -716,6 +930,12 @@ SmmDispatcher (
           SmmInsertOnScheduledQueueWhileProcessingBeforeAndAfter (DriverEntry);\r
           ReadyToRun = TRUE;\r
         }\r
+      } else {\r
+        if (DriverEntry->Unrequested) {\r
+          DEBUG ((DEBUG_DISPATCH, "Evaluate SMM DEPEX for FFS(%g)\n", &DriverEntry->FileName));\r
+          DEBUG ((DEBUG_DISPATCH, "  SOR                                             = Not Requested\n"));\r
+          DEBUG ((DEBUG_DISPATCH, "  RESULT = FALSE\n"));\r
+        }\r
       }\r
     }\r
   } while (ReadyToRun);\r
@@ -765,12 +985,17 @@ SmmInsertOnScheduledQueueWhileProcessingBeforeAndAfter (
   //\r
   for (Link = mDiscoveredList.ForwardLink; Link != &mDiscoveredList; Link = Link->ForwardLink) {\r
     DriverEntry = CR(Link, EFI_SMM_DRIVER_ENTRY, Link, EFI_SMM_DRIVER_ENTRY_SIGNATURE);\r
-    if (DriverEntry->Before && DriverEntry->Dependent) {\r
+    if (DriverEntry->Before && DriverEntry->Dependent && DriverEntry != InsertedDriverEntry) {\r
+      DEBUG ((DEBUG_DISPATCH, "Evaluate SMM DEPEX for FFS(%g)\n", &DriverEntry->FileName));\r
+      DEBUG ((DEBUG_DISPATCH, "  BEFORE FFS(%g) = ", &DriverEntry->BeforeAfterGuid));\r
       if (CompareGuid (&InsertedDriverEntry->FileName, &DriverEntry->BeforeAfterGuid)) {\r
         //\r
         // Recursively process BEFORE\r
         //\r
+        DEBUG ((DEBUG_DISPATCH, "TRUE\n  END\n  RESULT = TRUE\n"));\r
         SmmInsertOnScheduledQueueWhileProcessingBeforeAndAfter (DriverEntry);\r
+      } else {\r
+        DEBUG ((DEBUG_DISPATCH, "FALSE\n  END\n  RESULT = FALSE\n"));\r
       }\r
     }\r
   }\r
@@ -789,12 +1014,17 @@ SmmInsertOnScheduledQueueWhileProcessingBeforeAndAfter (
   //\r
   for (Link = mDiscoveredList.ForwardLink; Link != &mDiscoveredList; Link = Link->ForwardLink) {\r
     DriverEntry = CR(Link, EFI_SMM_DRIVER_ENTRY, Link, EFI_SMM_DRIVER_ENTRY_SIGNATURE);\r
-    if (DriverEntry->After && DriverEntry->Dependent) {\r
+    if (DriverEntry->After && DriverEntry->Dependent && DriverEntry != InsertedDriverEntry) {\r
+      DEBUG ((DEBUG_DISPATCH, "Evaluate SMM DEPEX for FFS(%g)\n", &DriverEntry->FileName));\r
+      DEBUG ((DEBUG_DISPATCH, "  AFTER FFS(%g) = ", &DriverEntry->BeforeAfterGuid));\r
       if (CompareGuid (&InsertedDriverEntry->FileName, &DriverEntry->BeforeAfterGuid)) {\r
         //\r
         // Recursively process AFTER\r
         //\r
+        DEBUG ((DEBUG_DISPATCH, "TRUE\n  END\n  RESULT = TRUE\n"));\r
         SmmInsertOnScheduledQueueWhileProcessingBeforeAndAfter (DriverEntry);\r
+      } else {\r
+        DEBUG ((DEBUG_DISPATCH, "FALSE\n  END\n  RESULT = FALSE\n"));\r
       }\r
     }\r
   }\r
@@ -1131,6 +1361,8 @@ SmmDriverDispatchHandler (
           DriverEntry->Dependent = FALSE;\r
           DriverEntry->Scheduled = TRUE;\r
           InsertTailList (&mScheduledQueue, &DriverEntry->ScheduledLink);\r
+          DEBUG ((DEBUG_DISPATCH, "Evaluate SMM DEPEX for FFS(%g)\n", &DriverEntry->FileName));\r
+          DEBUG ((DEBUG_DISPATCH, "  RESULT = TRUE (Apriori)\n"));\r
           break;\r
         }\r
       }\r