]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Core/PiSmmCore/Dispatcher.c
MdeModulePkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / MdeModulePkg / Core / PiSmmCore / Dispatcher.c
index 78c29ffe2255670927cd4251dbce074d317ff4be..1c88c8fb17c57ea2177dac2a565fc4cb867095e9 100644 (file)
 \r
   Depex - Dependency Expresion.\r
 \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
-  http://opensource.org/licenses/bsd-license.php                                            \r
-\r
-  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
-  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
+  Copyright (c) 2014, Hewlett-Packard Development Company, L.P.\r
+  Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>\r
+  SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 \r
@@ -102,7 +97,8 @@ BOOLEAN  gRequestDispatch = FALSE;
 //\r
 EFI_FV_FILETYPE mSmmFileTypes[] = {\r
   EFI_FV_FILETYPE_SMM,\r
-  EFI_FV_FILETYPE_COMBINED_SMM_DXE\r
+  EFI_FV_FILETYPE_COMBINED_SMM_DXE,\r
+  EFI_FV_FILETYPE_SMM_CORE,\r
   //\r
   // Note: DXE core will process the FV image file, so skip it in SMM core\r
   // EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE\r
@@ -120,22 +116,23 @@ FV_FILEPATH_DEVICE_PATH  mFvDevicePath;
 // DXE Architecture Protocols\r
 //\r
 EFI_SECURITY_ARCH_PROTOCOL  *mSecurity = NULL;\r
+EFI_SECURITY2_ARCH_PROTOCOL *mSecurity2 = 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
+// memory range usage. It is a bit mapped array in which every bit indicates the corresponding\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
+  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 available, the function will mark the corresponding 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 address the image will be loaded at.\r
   @param  ImageSize                The size of the image\r
-  \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
@@ -146,7 +143,7 @@ CheckAndMarkFixLoadingMemoryUsageBitMap (
   )\r
 {\r
    UINT32                             SmmCodePageNumber;\r
-   UINT64                             SmmCodeSize; \r
+   UINT64                             SmmCodeSize;\r
    EFI_PHYSICAL_ADDRESS               SmmCodeBase;\r
    UINTN                              BaseOffsetPageNumber;\r
    UINTN                              TopOffsetPageNumber;\r
@@ -157,11 +154,11 @@ CheckAndMarkFixLoadingMemoryUsageBitMap (
    SmmCodePageNumber = PcdGet32(PcdLoadFixAddressSmmCodePageNumber);\r
    SmmCodeSize = EFI_PAGES_TO_SIZE (SmmCodePageNumber);\r
    SmmCodeBase = gLoadModuleAtFixAddressSmramBase;\r
-   \r
+\r
    //\r
-   // If the memory usage bit map is not initialized,  do it. Every bit in the array \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
+   //\r
    if (mSmmCodeMemoryRangeUsageBitMap == NULL) {\r
      mSmmCodeMemoryRangeUsageBitMap = AllocateZeroPool(((SmmCodePageNumber / 64) + 1)*sizeof(UINT64));\r
    }\r
@@ -175,38 +172,38 @@ CheckAndMarkFixLoadingMemoryUsageBitMap (
    // 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
+     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
+   //\r
+   BaseOffsetPageNumber = EFI_SIZE_TO_PAGES((UINT32)(ImageBase - SmmCodeBase));\r
+   TopOffsetPageNumber  = 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
+       return EFI_NOT_FOUND;\r
      }\r
    }\r
-   \r
+\r
    //\r
    // Being here means the memory range is available.  So mark the bits for the memory range\r
-   // \r
+   //\r
    for (Index = BaseOffsetPageNumber; Index < TopOffsetPageNumber; Index ++) {\r
      mSmmCodeMemoryRangeUsageBitMap[Index / 64] |= LShiftU64(1, (Index % 64));\r
    }\r
-   return  EFI_SUCCESS;   \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
+  Get the fixed loading address from image header assigned by build tool. This function only be called\r
   when Loading module at Fixed address feature enabled.\r
-  \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
+  @retval EFI_NOT_FOUND             The image has no assigned fixed loading address.\r
 \r
 **/\r
 EFI_STATUS\r
@@ -214,82 +211,80 @@ GetPeCoffImageFixLoadingAssignedAddress(
   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
+  UINTN                              SectionHeaderOffset;\r
+  EFI_STATUS                         Status;\r
+  EFI_IMAGE_SECTION_HEADER           SectionHeader;\r
+  EFI_IMAGE_OPTIONAL_HEADER_UNION    *ImgHdr;\r
+  EFI_PHYSICAL_ADDRESS               FixLoadingAddress;\r
+  UINT16                             Index;\r
+  UINTN                              Size;\r
+  UINT16                             NumberOfSections;\r
+  UINT64                             ValueInSectionHeader;\r
+\r
+  FixLoadingAddress = 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 = ImageContext->PeCoffHeaderOffset +\r
+                        sizeof (UINT32) +\r
+                        sizeof (EFI_IMAGE_FILE_HEADER) +\r
+                        ImgHdr->Pe32.FileHeader.SizeOfOptionalHeader;\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
+    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 fields 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 build tool saves the\r
+        // offset to SMRAM base as image base in PointerToRelocations & PointerToLineNumbers fields\r
+        //\r
+        FixLoadingAddress = (EFI_PHYSICAL_ADDRESS)(gLoadModuleAtFixAddressSmramBase + (INT64)ValueInSectionHeader);\r
+        //\r
+        // Check if the memory range is available.\r
+        //\r
+        Status = CheckAndMarkFixLoadingMemoryUsageBitMap (FixLoadingAddress, (UINTN)(ImageContext->ImageSize + ImageContext->SectionAlignment));\r
+        if (!EFI_ERROR(Status)) {\r
+          //\r
+          // The assigned address is valid. Return the specified loading address\r
+          //\r
+          ImageContext->ImageAddress = FixLoadingAddress;\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", FixLoadingAddress, Status));\r
+  return Status;\r
 }\r
 /**\r
   Loads an EFI image into SMRAM.\r
@@ -320,7 +315,9 @@ SmmLoadImage (
   EFI_DEVICE_PATH_PROTOCOL       *HandleFilePath;\r
   EFI_FIRMWARE_VOLUME2_PROTOCOL  *Fv;\r
   PE_COFF_LOADER_IMAGE_CONTEXT   ImageContext;\r
-   \r
+\r
+  PERF_LOAD_IMAGE_BEGIN (DriverEntry->ImageHandle);\r
+\r
   Buffer               = NULL;\r
   Size                 = 0;\r
   Fv                   = DriverEntry->Fv;\r
@@ -343,27 +340,19 @@ SmmLoadImage (
   }\r
 \r
   //\r
-  // If the Security Architectural Protocol has not been located yet, then attempt to locate it\r
+  // If the Security2 and Security Architectural Protocol has not been located yet, then attempt to locate it\r
   //\r
+  if (mSecurity2 == NULL) {\r
+    gBS->LocateProtocol (&gEfiSecurity2ArchProtocolGuid, NULL, (VOID**)&mSecurity2);\r
+  }\r
   if (mSecurity == NULL) {\r
     gBS->LocateProtocol (&gEfiSecurityArchProtocolGuid, NULL, (VOID**)&mSecurity);\r
   }\r
-\r
   //\r
-  // Verify the Authentication Status through the Security Architectural Protocol\r
+  // When Security2 is installed, Security Architectural Protocol must be published.\r
   //\r
-  if ((mSecurity != NULL) && (OriginalFilePath != NULL)) {\r
-    SecurityStatus = mSecurity->FileAuthenticationState (\r
-                                  mSecurity,\r
-                                  AuthenticationStatus,\r
-                                  OriginalFilePath\r
-                                  );\r
-    if (EFI_ERROR (SecurityStatus) && SecurityStatus != EFI_SECURITY_VIOLATION) {\r
-      Status = SecurityStatus;\r
-      return Status;\r
-    }\r
-  }\r
-  \r
+  ASSERT (mSecurity2 == NULL || mSecurity != NULL);\r
+\r
   //\r
   // Pull out just the file portion of the DevicePath for the LoadedImage FilePath\r
   //\r
@@ -403,14 +392,45 @@ SmmLoadImage (
                   &AuthenticationStatus\r
                   );\r
   }\r
-  \r
+\r
   if (EFI_ERROR (Status)) {\r
     if (Buffer != NULL) {\r
-      Status = gBS->FreePool (Buffer);\r
+      gBS->FreePool (Buffer);\r
     }\r
     return Status;\r
   }\r
 \r
+  //\r
+  // Verify File Authentication through the Security2 Architectural Protocol\r
+  //\r
+  if (mSecurity2 != NULL) {\r
+    SecurityStatus = mSecurity2->FileAuthentication (\r
+                                  mSecurity2,\r
+                                  OriginalFilePath,\r
+                                  Buffer,\r
+                                  Size,\r
+                                  FALSE\r
+                                  );\r
+  }\r
+\r
+  //\r
+  // Verify the Authentication Status through the Security Architectural Protocol\r
+  // Only on images that have been read using Firmware Volume protocol.\r
+  // All SMM images are from FV protocol.\r
+  //\r
+  if (!EFI_ERROR (SecurityStatus) && (mSecurity != NULL)) {\r
+    SecurityStatus = mSecurity->FileAuthenticationState (\r
+                                  mSecurity,\r
+                                  AuthenticationStatus,\r
+                                  OriginalFilePath\r
+                                  );\r
+  }\r
+\r
+  if (EFI_ERROR (SecurityStatus) && SecurityStatus != EFI_SECURITY_VIOLATION) {\r
+    Status = SecurityStatus;\r
+    return Status;\r
+  }\r
+\r
   //\r
   // Initialize ImageContext\r
   //\r
@@ -423,7 +443,7 @@ SmmLoadImage (
   Status = PeCoffLoaderGetImageInfo (&ImageContext);\r
   if (EFI_ERROR (Status)) {\r
     if (Buffer != NULL) {\r
-      Status = gBS->FreePool (Buffer);\r
+      gBS->FreePool (Buffer);\r
     }\r
     return Status;\r
   }\r
@@ -442,15 +462,15 @@ SmmLoadImage (
       // following statements is to bypass SmmFreePages\r
       //\r
       PageCount = 0;\r
-      DstBuffer = (UINTN)gLoadModuleAtFixAddressSmramBase;   \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
+       PageCount = (UINTN)EFI_SIZE_TO_PAGES((UINTN)ImageContext.ImageSize + ImageContext.SectionAlignment);\r
        DstBuffer = (UINTN)(-1);\r
-     \r
+\r
        Status = SmmAllocatePages (\r
                    AllocateMaxAddress,\r
                    EfiRuntimeServicesCode,\r
@@ -459,16 +479,16 @@ SmmLoadImage (
                    );\r
        if (EFI_ERROR (Status)) {\r
          if (Buffer != NULL) {\r
-           Status = gBS->FreePool (Buffer);\r
-         } \r
+           gBS->FreePool (Buffer);\r
+         }\r
          return Status;\r
-       }     \r
+       }\r
       ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)DstBuffer;\r
     }\r
   } else {\r
-     PageCount = (UINTN)EFI_SIZE_TO_PAGES(ImageContext.ImageSize + ImageContext.SectionAlignment);\r
+     PageCount = (UINTN)EFI_SIZE_TO_PAGES((UINTN)ImageContext.ImageSize + ImageContext.SectionAlignment);\r
      DstBuffer = (UINTN)(-1);\r
-     \r
+\r
      Status = SmmAllocatePages (\r
                   AllocateMaxAddress,\r
                   EfiRuntimeServicesCode,\r
@@ -477,18 +497,18 @@ SmmLoadImage (
                   );\r
      if (EFI_ERROR (Status)) {\r
        if (Buffer != NULL) {\r
-         Status = gBS->FreePool (Buffer);\r
+         gBS->FreePool (Buffer);\r
        }\r
        return Status;\r
      }\r
-     \r
+\r
      ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)DstBuffer;\r
   }\r
   //\r
-  // Align buffer on section boundry\r
+  // Align buffer on section boundary\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
   // Load the image to our new buffer\r
@@ -496,7 +516,7 @@ SmmLoadImage (
   Status = PeCoffLoaderLoadImage (&ImageContext);\r
   if (EFI_ERROR (Status)) {\r
     if (Buffer != NULL) {\r
-      Status = gBS->FreePool (Buffer);\r
+      gBS->FreePool (Buffer);\r
     }\r
     SmmFreePages (DstBuffer, PageCount);\r
     return Status;\r
@@ -508,7 +528,7 @@ SmmLoadImage (
   Status = PeCoffLoaderRelocateImage (&ImageContext);\r
   if (EFI_ERROR (Status)) {\r
     if (Buffer != NULL) {\r
-      Status = gBS->FreePool (Buffer);\r
+      gBS->FreePool (Buffer);\r
     }\r
     SmmFreePages (DstBuffer, PageCount);\r
     return Status;\r
@@ -523,7 +543,7 @@ SmmLoadImage (
   // Save Image EntryPoint in DriverEntry\r
   //\r
   DriverEntry->ImageEntryPoint  = ImageContext.EntryPoint;\r
-  DriverEntry->ImageBuffer      = DstBuffer; \r
+  DriverEntry->ImageBuffer      = DstBuffer;\r
   DriverEntry->NumberOfPage     = PageCount;\r
 \r
   //\r
@@ -532,12 +552,13 @@ SmmLoadImage (
   Status = gBS->AllocatePool (EfiBootServicesData, sizeof (EFI_LOADED_IMAGE_PROTOCOL), (VOID **)&DriverEntry->LoadedImage);\r
   if (EFI_ERROR (Status)) {\r
     if (Buffer != NULL) {\r
-      Status = gBS->FreePool (Buffer);\r
+      gBS->FreePool (Buffer);\r
     }\r
     SmmFreePages (DstBuffer, PageCount);\r
     return Status;\r
   }\r
 \r
+  ZeroMem (DriverEntry->LoadedImage, sizeof (EFI_LOADED_IMAGE_PROTOCOL));\r
   //\r
   // Fill in the remaining fields of the Loaded Image Protocol instance.\r
   // Note: ImageBase is an SMRAM address that can not be accessed outside of SMRAM if SMRAM window is closed.\r
@@ -547,24 +568,48 @@ SmmLoadImage (
   DriverEntry->LoadedImage->SystemTable   = gST;\r
   DriverEntry->LoadedImage->DeviceHandle  = DeviceHandle;\r
 \r
+  DriverEntry->SmmLoadedImage.Revision     = EFI_LOADED_IMAGE_PROTOCOL_REVISION;\r
+  DriverEntry->SmmLoadedImage.ParentHandle = gSmmCorePrivate->SmmIplImageHandle;\r
+  DriverEntry->SmmLoadedImage.SystemTable  = gST;\r
+  DriverEntry->SmmLoadedImage.DeviceHandle = DeviceHandle;\r
+\r
   //\r
   // Make an EfiBootServicesData buffer copy of FilePath\r
   //\r
   Status = gBS->AllocatePool (EfiBootServicesData, GetDevicePathSize (FilePath), (VOID **)&DriverEntry->LoadedImage->FilePath);\r
   if (EFI_ERROR (Status)) {\r
     if (Buffer != NULL) {\r
-      Status = gBS->FreePool (Buffer);\r
+      gBS->FreePool (Buffer);\r
     }\r
     SmmFreePages (DstBuffer, PageCount);\r
     return Status;\r
   }\r
   CopyMem (DriverEntry->LoadedImage->FilePath, FilePath, GetDevicePathSize (FilePath));\r
 \r
-  DriverEntry->LoadedImage->ImageBase     = (VOID *)(UINTN)DriverEntry->ImageBuffer;\r
+  DriverEntry->LoadedImage->ImageBase     = (VOID *)(UINTN) ImageContext.ImageAddress;\r
   DriverEntry->LoadedImage->ImageSize     = ImageContext.ImageSize;\r
   DriverEntry->LoadedImage->ImageCodeType = EfiRuntimeServicesCode;\r
   DriverEntry->LoadedImage->ImageDataType = EfiRuntimeServicesData;\r
 \r
+  //\r
+  // Make a buffer copy of FilePath\r
+  //\r
+  Status = SmmAllocatePool (EfiRuntimeServicesData, GetDevicePathSize(FilePath), (VOID **)&DriverEntry->SmmLoadedImage.FilePath);\r
+  if (EFI_ERROR (Status)) {\r
+    if (Buffer != NULL) {\r
+      gBS->FreePool (Buffer);\r
+    }\r
+    gBS->FreePool (DriverEntry->LoadedImage->FilePath);\r
+    SmmFreePages (DstBuffer, PageCount);\r
+    return Status;\r
+  }\r
+  CopyMem (DriverEntry->SmmLoadedImage.FilePath, FilePath, GetDevicePathSize(FilePath));\r
+\r
+  DriverEntry->SmmLoadedImage.ImageBase = (VOID *)(UINTN) ImageContext.ImageAddress;\r
+  DriverEntry->SmmLoadedImage.ImageSize = ImageContext.ImageSize;\r
+  DriverEntry->SmmLoadedImage.ImageCodeType = EfiRuntimeServicesCode;\r
+  DriverEntry->SmmLoadedImage.ImageDataType = EfiRuntimeServicesData;\r
+\r
   //\r
   // Create a new image handle in the UEFI handle database for the SMM Driver\r
   //\r
@@ -575,6 +620,19 @@ SmmLoadImage (
                   NULL\r
                   );\r
 \r
+  //\r
+  // Create a new image handle in the SMM handle database for the SMM Driver\r
+  //\r
+  DriverEntry->SmmImageHandle = NULL;\r
+  Status = SmmInstallProtocolInterface (\r
+             &DriverEntry->SmmImageHandle,\r
+             &gEfiLoadedImageProtocolGuid,\r
+             EFI_NATIVE_INTERFACE,\r
+             &DriverEntry->SmmLoadedImage\r
+             );\r
+\r
+  PERF_LOAD_IMAGE_END (DriverEntry->ImageHandle);\r
+\r
   //\r
   // Print the load address and the PDB file name if it is available\r
   //\r
@@ -634,17 +692,20 @@ SmmLoadImage (
   //\r
   // Free buffer allocated by Fv->ReadSection.\r
   //\r
-  // The UEFI Boot Services FreePool() function must be used because Fv->ReadSection \r
+  // The UEFI Boot Services FreePool() function must be used because Fv->ReadSection\r
   // used the UEFI Boot Services AllocatePool() function\r
   //\r
   Status = gBS->FreePool(Buffer);\r
-  return Status;  \r
+  if (!EFI_ERROR (Status) && EFI_ERROR (SecurityStatus)) {\r
+    Status = SecurityStatus;\r
+  }\r
+  return Status;\r
 }\r
 \r
 /**\r
   Preprocess dependency expression and update DriverEntry to reflect the\r
   state of  Before and After dependencies. If DriverEntry->Before\r
-  or DriverEntry->After is set it will never be cleared. \r
+  or DriverEntry->After is set it will never be cleared.\r
 \r
   @param  DriverEntry           DriverEntry element to update .\r
 \r
@@ -743,13 +804,15 @@ SmmGetDepexSectionAndPreProccess (
   drivers to run. Drain the mScheduledQueue and load and start a PE\r
   image for each driver. Search the mDiscoveredList to see if any driver can\r
   be placed on the mScheduledQueue. If no drivers are placed on the\r
-  mScheduledQueue exit the function. On exit it is assumed the Bds()\r
-  will be called, and when the Bds() exits the Dispatcher will be called\r
-  again.\r
-\r
+  mScheduledQueue exit the function.\r
+\r
+  @retval EFI_SUCCESS           All of the SMM Drivers that could be dispatched\r
+                                have been run and the SMM Entry Point has been\r
+                                registered.\r
+  @retval EFI_NOT_READY         The SMM Driver that registered the SMM Entry Point\r
+                                was just dispatched.\r
+  @retval EFI_NOT_FOUND         There are no SMM Drivers available to be dispatched.\r
   @retval EFI_ALREADY_STARTED   The SMM Dispatcher is already running\r
-  @retval EFI_NOT_FOUND         No SMM Drivers were dispatched\r
-  @retval EFI_SUCCESS           One or more SMM Drivers were dispatched\r
 \r
 **/\r
 EFI_STATUS\r
@@ -758,10 +821,10 @@ SmmDispatcher (
   )\r
 {\r
   EFI_STATUS            Status;\r
-  EFI_STATUS            ReturnStatus;\r
   LIST_ENTRY            *Link;\r
   EFI_SMM_DRIVER_ENTRY  *DriverEntry;\r
   BOOLEAN               ReadyToRun;\r
+  BOOLEAN               PreviousSmmEntryPointRegistered;\r
 \r
   if (!gRequestDispatch) {\r
     return EFI_NOT_FOUND;\r
@@ -776,7 +839,6 @@ SmmDispatcher (
 \r
   gDispatcherRunning = TRUE;\r
 \r
-  ReturnStatus = EFI_NOT_FOUND;\r
   do {\r
     //\r
     // Drain the Scheduled Queue\r
@@ -827,12 +889,45 @@ SmmDispatcher (
         sizeof (DriverEntry->ImageHandle)\r
         );\r
 \r
+      //\r
+      // Cache state of SmmEntryPointRegistered before calling entry point\r
+      //\r
+      PreviousSmmEntryPointRegistered = gSmmCorePrivate->SmmEntryPointRegistered;\r
+\r
       //\r
       // For each SMM driver, pass NULL as ImageHandle\r
       //\r
+      RegisterSmramProfileImage (DriverEntry, TRUE);\r
+      PERF_START_IMAGE_BEGIN (DriverEntry->ImageHandle);\r
       Status = ((EFI_IMAGE_ENTRY_POINT)(UINTN)DriverEntry->ImageEntryPoint)(DriverEntry->ImageHandle, gST);\r
+      PERF_START_IMAGE_END (DriverEntry->ImageHandle);\r
       if (EFI_ERROR(Status)){\r
+        UnregisterSmramProfileImage (DriverEntry, TRUE);\r
         SmmFreePages(DriverEntry->ImageBuffer, DriverEntry->NumberOfPage);\r
+        //\r
+        // Uninstall LoadedImage\r
+        //\r
+        Status = gBS->UninstallProtocolInterface (\r
+                        DriverEntry->ImageHandle,\r
+                        &gEfiLoadedImageProtocolGuid,\r
+                        DriverEntry->LoadedImage\r
+                        );\r
+        if (!EFI_ERROR (Status)) {\r
+          if (DriverEntry->LoadedImage->FilePath != NULL) {\r
+            gBS->FreePool (DriverEntry->LoadedImage->FilePath);\r
+          }\r
+          gBS->FreePool (DriverEntry->LoadedImage);\r
+        }\r
+        Status = SmmUninstallProtocolInterface (\r
+                   DriverEntry->SmmImageHandle,\r
+                   &gEfiLoadedImageProtocolGuid,\r
+                   &DriverEntry->SmmLoadedImage\r
+                   );\r
+        if (!EFI_ERROR(Status)) {\r
+          if (DriverEntry->SmmLoadedImage.FilePath != NULL) {\r
+            SmmFreePool (DriverEntry->SmmLoadedImage.FilePath);\r
+          }\r
+        }\r
       }\r
 \r
       REPORT_STATUS_CODE_WITH_EXTENDED_DATA (\r
@@ -842,7 +937,19 @@ SmmDispatcher (
         sizeof (DriverEntry->ImageHandle)\r
         );\r
 \r
-      ReturnStatus = EFI_SUCCESS;\r
+      if (!PreviousSmmEntryPointRegistered && gSmmCorePrivate->SmmEntryPointRegistered) {\r
+        //\r
+        // Return immediately if the SMM Entry Point was registered by the SMM\r
+        // Driver that was just dispatched.  The SMM IPL will reinvoke the SMM\r
+        // Core Dispatcher.  This is required so SMM Mode may be enabled as soon\r
+        // as all the dependent SMM Drivers for SMM Mode have been dispatched.\r
+        // Once the SMM Entry Point has been registered, then SMM Mode will be\r
+        // used.\r
+        //\r
+        gRequestDispatch = TRUE;\r
+        gDispatcherRunning = FALSE;\r
+        return EFI_NOT_READY;\r
+      }\r
     }\r
 \r
     //\r
@@ -886,7 +993,7 @@ SmmDispatcher (
 \r
   gDispatcherRunning = FALSE;\r
 \r
-  return ReturnStatus;\r
+  return EFI_SUCCESS;\r
 }\r
 \r
 /**\r
@@ -1144,7 +1251,6 @@ SmmDriverDispatchHandler (
   UINTN                         HandleCount;\r
   EFI_HANDLE                    *HandleBuffer;\r
   EFI_STATUS                    GetNextFileStatus;\r
-  EFI_STATUS                    SecurityStatus;\r
   EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv;\r
   EFI_DEVICE_PATH_PROTOCOL      *FvDevicePath;\r
   EFI_HANDLE                    FvHandle;\r
@@ -1156,7 +1262,9 @@ SmmDriverDispatchHandler (
   EFI_SMM_DRIVER_ENTRY          *DriverEntry;\r
   EFI_GUID                      *AprioriFile;\r
   UINTN                         AprioriEntryCount;\r
-  UINTN                         Index;\r
+  UINTN                         HandleIndex;\r
+  UINTN                         SmmTypeIndex;\r
+  UINTN                         AprioriIndex;\r
   LIST_ENTRY                    *Link;\r
   UINT32                        AuthenticationStatus;\r
   UINTN                         SizeOfBuffer;\r
@@ -1173,8 +1281,8 @@ SmmDriverDispatchHandler (
     return EFI_NOT_FOUND;\r
   }\r
 \r
-  for (Index = 0; Index < HandleCount; Index++) {\r
-    FvHandle = HandleBuffer[Index];\r
+  for (HandleIndex = 0; HandleIndex < HandleCount; HandleIndex++) {\r
+    FvHandle = HandleBuffer[HandleIndex];\r
 \r
     if (FvHasBeenProcessed (FvHandle)) {\r
       //\r
@@ -1205,42 +1313,18 @@ SmmDriverDispatchHandler (
       continue;\r
     }\r
 \r
-    //\r
-    // If the Security Architectural Protocol has not been located yet, then attempt to locate it\r
-    //\r
-    if (mSecurity == NULL) {\r
-      gBS->LocateProtocol (&gEfiSecurityArchProtocolGuid, NULL, (VOID**)&mSecurity);\r
-    }\r
-\r
-    //\r
-    // Evaluate the authentication status of the Firmware Volume through\r
-    // Security Architectural Protocol\r
-    //\r
-    if (mSecurity != NULL) {\r
-      SecurityStatus = mSecurity->FileAuthenticationState (\r
-                                    mSecurity,\r
-                                    0,\r
-                                    FvDevicePath\r
-                                    );\r
-      if (SecurityStatus != EFI_SUCCESS) {\r
-        //\r
-        // Security check failed. The firmware volume should not be used for any purpose.\r
-        //\r
-        continue;\r
-      }\r
-    }\r
-\r
     //\r
     // Discover Drivers in FV and add them to the Discovered Driver List.\r
     // Process EFI_FV_FILETYPE_SMM type and then EFI_FV_FILETYPE_COMBINED_SMM_DXE\r
+    //  EFI_FV_FILETYPE_SMM_CORE is processed to produce a Loaded Image protocol for the core\r
     //\r
-    for (Index = 0; Index < sizeof (mSmmFileTypes)/sizeof (EFI_FV_FILETYPE); Index++) {\r
+    for (SmmTypeIndex = 0; SmmTypeIndex < sizeof (mSmmFileTypes)/sizeof (EFI_FV_FILETYPE); SmmTypeIndex++) {\r
       //\r
       // Initialize the search key\r
       //\r
       Key = 0;\r
       do {\r
-        Type = mSmmFileTypes[Index];\r
+        Type = mSmmFileTypes[SmmTypeIndex];\r
         GetNextFileStatus = Fv->GetNextFile (\r
                                   Fv,\r
                                   &Key,\r
@@ -1250,7 +1334,55 @@ SmmDriverDispatchHandler (
                                   &Size\r
                                   );\r
         if (!EFI_ERROR (GetNextFileStatus)) {\r
-          SmmAddToDriverList (Fv, FvHandle, &NameGuid);\r
+          if (Type == EFI_FV_FILETYPE_SMM_CORE) {\r
+            //\r
+            // If this is the SMM core fill in it's DevicePath & DeviceHandle\r
+            //\r
+            if (mSmmCoreLoadedImage->FilePath == NULL) {\r
+              //\r
+              // Maybe one special FV contains only one SMM_CORE module, so its device path must\r
+              // be initialized completely.\r
+              //\r
+              EfiInitializeFwVolDevicepathNode (&mFvDevicePath.File, &NameGuid);\r
+              SetDevicePathEndNode (&mFvDevicePath.End);\r
+\r
+              //\r
+              // Make an EfiBootServicesData buffer copy of FilePath\r
+              //\r
+              Status = gBS->AllocatePool (\r
+                              EfiBootServicesData,\r
+                              GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *)&mFvDevicePath),\r
+                              (VOID **)&mSmmCoreLoadedImage->FilePath\r
+                              );\r
+              ASSERT_EFI_ERROR (Status);\r
+              CopyMem (mSmmCoreLoadedImage->FilePath, &mFvDevicePath, GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *)&mFvDevicePath));\r
+\r
+              mSmmCoreLoadedImage->DeviceHandle = FvHandle;\r
+            }\r
+            if (mSmmCoreDriverEntry->SmmLoadedImage.FilePath == NULL) {\r
+              //\r
+              // Maybe one special FV contains only one SMM_CORE module, so its device path must\r
+              // be initialized completely.\r
+              //\r
+              EfiInitializeFwVolDevicepathNode (&mFvDevicePath.File, &NameGuid);\r
+              SetDevicePathEndNode (&mFvDevicePath.End);\r
+\r
+              //\r
+              // Make a buffer copy FilePath\r
+              //\r
+              Status = SmmAllocatePool (\r
+                         EfiRuntimeServicesData,\r
+                         GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *)&mFvDevicePath),\r
+                         (VOID **)&mSmmCoreDriverEntry->SmmLoadedImage.FilePath\r
+                         );\r
+              ASSERT_EFI_ERROR (Status);\r
+              CopyMem (mSmmCoreDriverEntry->SmmLoadedImage.FilePath, &mFvDevicePath, GetDevicePathSize((EFI_DEVICE_PATH_PROTOCOL *)&mFvDevicePath));\r
+\r
+              mSmmCoreDriverEntry->SmmLoadedImage.DeviceHandle = FvHandle;\r
+            }\r
+          } else {\r
+            SmmAddToDriverList (Fv, FvHandle, &NameGuid);\r
+          }\r
         }\r
       } while (!EFI_ERROR (GetNextFileStatus));\r
     }\r
@@ -1281,10 +1413,10 @@ SmmDriverDispatchHandler (
     // is only valid for the FV that it resided in.\r
     //\r
 \r
-    for (Index = 0; Index < AprioriEntryCount; Index++) {\r
+    for (AprioriIndex = 0; AprioriIndex < AprioriEntryCount; AprioriIndex++) {\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 (CompareGuid (&DriverEntry->FileName, &AprioriFile[Index]) &&\r
+        if (CompareGuid (&DriverEntry->FileName, &AprioriFile[AprioriIndex]) &&\r
             (FvHandle == DriverEntry->FvHandle)) {\r
           DriverEntry->Dependent = FALSE;\r
           DriverEntry->Scheduled = TRUE;\r
@@ -1299,17 +1431,44 @@ SmmDriverDispatchHandler (
     //\r
     // Free data allocated by Fv->ReadSection ()\r
     //\r
-    // The UEFI Boot Services FreePool() function must be used because Fv->ReadSection \r
+    // The UEFI Boot Services FreePool() function must be used because Fv->ReadSection\r
     // used the UEFI Boot Services AllocatePool() function\r
     //\r
     gBS->FreePool (AprioriFile);\r
   }\r
 \r
   //\r
-  // Execute the SMM Dispatcher on any newly discovered FVs and previously \r
+  // Execute the SMM Dispatcher on any newly discovered FVs and previously\r
   // discovered SMM drivers that have been discovered but not dispatched.\r
   //\r
-  return SmmDispatcher ();\r
+  Status = SmmDispatcher ();\r
+\r
+  //\r
+  // Check to see if CommBuffer and CommBufferSize are valid\r
+  //\r
+  if (CommBuffer != NULL && CommBufferSize != NULL) {\r
+    if (*CommBufferSize > 0) {\r
+      if (Status == EFI_NOT_READY) {\r
+        //\r
+        // If a the SMM Core Entry Point was just registered, then set flag to\r
+        // request the SMM Dispatcher to be restarted.\r
+        //\r
+        *(UINT8 *)CommBuffer = COMM_BUFFER_SMM_DISPATCH_RESTART;\r
+      } else if (!EFI_ERROR (Status)) {\r
+        //\r
+        // Set the flag to show that the SMM Dispatcher executed without errors\r
+        //\r
+        *(UINT8 *)CommBuffer = COMM_BUFFER_SMM_DISPATCH_SUCCESS;\r
+      } else {\r
+        //\r
+        // Set the flag to show that the SMM Dispatcher encountered an error\r
+        //\r
+        *(UINT8 *)CommBuffer = COMM_BUFFER_SMM_DISPATCH_ERROR;\r
+      }\r
+    }\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
 }\r
 \r
 /**\r