]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Core/Dxe/Image/Image.c
MdeModulePkg: Add CoreInitializeMemoryAttributesTable() to header file.
[mirror_edk2.git] / MdeModulePkg / Core / Dxe / Image / Image.c
index 9a143284e7854772bb4958edb32e8c40b5ea7127..5355940b58d775002c5604bb05c55d81fc2735b4 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   Core image handling services to load and unload PeImage.\r
 \r
-Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>\r
 This program and the accompanying materials\r
 are licensed and made available under the terms and conditions of the BSD License\r
 which accompanies this distribution.  The full text of the license may be found at\r
@@ -389,7 +389,10 @@ GetPeCoffImageFixLoadingAssignedAddress(
      if (EFI_ERROR (Status)) {\r
        return Status;\r
      }\r
-     \r
+     if (Size != sizeof (EFI_IMAGE_SECTION_HEADER)) {\r
+       return EFI_NOT_FOUND;\r
+     }\r
+\r
      Status = EFI_NOT_FOUND;\r
      \r
      if ((SectionHeader.Characteristics & EFI_IMAGE_SCN_CNT_CODE) == 0) {\r
@@ -707,6 +710,7 @@ CoreLoadPeImage (
       Image->RuntimeData->RelocationData = Image->ImageContext.FixupData;\r
       Image->RuntimeData->Handle         = Image->Handle;\r
       InsertTailList (&gRuntime->ImageHead, &Image->RuntimeData->Link);\r
+      InsertImageRecord (Image->RuntimeData);\r
     }\r
   }\r
 \r
@@ -851,6 +855,13 @@ CoreUnloadAndCloseImage (
   UINTN                               OpenInfoCount;\r
   UINTN                               OpenInfoIndex;\r
 \r
+  HandleBuffer = NULL;\r
+  ProtocolGuidArray = NULL;\r
+\r
+  if (Image->Started) {\r
+    UnregisterMemoryProfileImage (Image);\r
+  }\r
+\r
   if (Image->Ebc != NULL) {\r
     //\r
     // If EBC protocol exists we must perform cleanups for this image.\r
@@ -946,6 +957,7 @@ CoreUnloadAndCloseImage (
       // Remove the Image from the Runtime Image list as we are about to Free it!\r
       //\r
       RemoveEntryList (&Image->RuntimeData->Link);\r
+      RemoveImageRecord (Image->RuntimeData);\r
     }\r
     CoreFreePool (Image->RuntimeData);\r
   }\r
@@ -1043,7 +1055,11 @@ CoreLoadImageCommon (
   UINT32                     AuthenticationStatus;\r
   EFI_DEVICE_PATH_PROTOCOL   *OriginalFilePath;\r
   EFI_DEVICE_PATH_PROTOCOL   *HandleFilePath;\r
+  EFI_DEVICE_PATH_PROTOCOL   *InputFilePath;\r
+  EFI_DEVICE_PATH_PROTOCOL   *Node;\r
   UINTN                      FilePathSize;\r
+  BOOLEAN                    ImageIsFromFv;\r
+  BOOLEAN                    ImageIsFromLoadFile;\r
 \r
   SecurityStatus = EFI_SUCCESS;\r
 \r
@@ -1066,17 +1082,24 @@ CoreLoadImageCommon (
   ZeroMem (&FHand, sizeof (IMAGE_FILE_HANDLE));\r
   FHand.Signature  = IMAGE_FILE_HANDLE_SIGNATURE;\r
   OriginalFilePath = FilePath;\r
+  InputFilePath    = FilePath;\r
   HandleFilePath   = FilePath;\r
   DeviceHandle     = NULL;\r
   Status           = EFI_SUCCESS;\r
   AuthenticationStatus = 0;\r
+  ImageIsFromFv        = FALSE;\r
+  ImageIsFromLoadFile  = FALSE;\r
+\r
   //\r
   // If the caller passed a copy of the file, then just use it\r
   //\r
   if (SourceBuffer != NULL) {\r
     FHand.Source     = SourceBuffer;\r
     FHand.SourceSize = SourceSize;\r
-    CoreLocateDevicePath (&gEfiDevicePathProtocolGuid, &HandleFilePath, &DeviceHandle);\r
+    Status = CoreLocateDevicePath (&gEfiDevicePathProtocolGuid, &HandleFilePath, &DeviceHandle);\r
+    if (EFI_ERROR (Status)) {\r
+      DeviceHandle = NULL;\r
+    }\r
     if (SourceSize > 0) {\r
       Status = EFI_SUCCESS;\r
     } else {\r
@@ -1086,6 +1109,33 @@ CoreLoadImageCommon (
     if (FilePath == NULL) {\r
       return EFI_INVALID_PARAMETER;\r
     }\r
+\r
+    //\r
+    // Try to get the image device handle by checking the match protocol.\r
+    //\r
+    Node   = NULL;\r
+    Status = CoreLocateDevicePath (&gEfiFirmwareVolume2ProtocolGuid, &HandleFilePath, &DeviceHandle);\r
+    if (!EFI_ERROR (Status)) {\r
+      ImageIsFromFv = TRUE;\r
+    } else {\r
+      HandleFilePath = FilePath;\r
+      Status = CoreLocateDevicePath (&gEfiSimpleFileSystemProtocolGuid, &HandleFilePath, &DeviceHandle);\r
+      if (EFI_ERROR (Status)) {\r
+        if (!BootPolicy) {\r
+          HandleFilePath = FilePath;\r
+          Status = CoreLocateDevicePath (&gEfiLoadFile2ProtocolGuid, &HandleFilePath, &DeviceHandle);\r
+        }\r
+        if (EFI_ERROR (Status)) {\r
+          HandleFilePath = FilePath;\r
+          Status = CoreLocateDevicePath (&gEfiLoadFileProtocolGuid, &HandleFilePath, &DeviceHandle);\r
+          if (!EFI_ERROR (Status)) {\r
+            ImageIsFromLoadFile = TRUE;\r
+            Node = HandleFilePath;\r
+          }\r
+        }\r
+      }\r
+    }\r
+\r
     //\r
     // Get the source file buffer by its device path.\r
     //\r
@@ -1098,65 +1148,82 @@ CoreLoadImageCommon (
     if (FHand.Source == NULL) {\r
       Status = EFI_NOT_FOUND;\r
     } else {\r
-      //\r
-      // Try to get the image device handle by checking the match protocol.\r
-      //\r
       FHand.FreeBuffer = TRUE;\r
-      Status = CoreLocateDevicePath (&gEfiFirmwareVolume2ProtocolGuid, &HandleFilePath, &DeviceHandle);\r
-      if (EFI_ERROR (Status)) {\r
-        HandleFilePath = FilePath;\r
-        Status = CoreLocateDevicePath (&gEfiSimpleFileSystemProtocolGuid, &HandleFilePath, &DeviceHandle);\r
-        if (EFI_ERROR (Status)) {\r
-          if (!BootPolicy) {\r
-            HandleFilePath = FilePath;\r
-            Status = CoreLocateDevicePath (&gEfiLoadFile2ProtocolGuid, &HandleFilePath, &DeviceHandle);\r
-          }\r
-          if (EFI_ERROR (Status)) {\r
-            HandleFilePath = FilePath;\r
-            Status = CoreLocateDevicePath (&gEfiLoadFileProtocolGuid, &HandleFilePath, &DeviceHandle);\r
-          }\r
-        }\r
+      if (ImageIsFromLoadFile) {\r
+        //\r
+        // LoadFile () may cause the device path of the Handle be updated.\r
+        //\r
+        OriginalFilePath = AppendDevicePath (DevicePathFromHandle (DeviceHandle), Node);\r
       }\r
     }\r
   }\r
 \r
-  if (Status == EFI_ALREADY_STARTED) {\r
+  if (EFI_ERROR (Status)) {\r
     Image = NULL;\r
     goto Done;\r
-  } else if (EFI_ERROR (Status)) {\r
-    return Status;\r
   }\r
 \r
-  //\r
-  // Verify the Authentication Status through the Security Architectural Protocol\r
-  //\r
-  if ((gSecurity != NULL) && (OriginalFilePath != NULL)) {\r
+  if (gSecurity2 != NULL) {\r
+    //\r
+    // Verify File Authentication through the Security2 Architectural Protocol\r
+    //\r
+    SecurityStatus = gSecurity2->FileAuthentication (\r
+                                  gSecurity2,\r
+                                  OriginalFilePath,\r
+                                  FHand.Source,\r
+                                  FHand.SourceSize,\r
+                                  BootPolicy\r
+                                  );\r
+    if (!EFI_ERROR (SecurityStatus) && ImageIsFromFv) {\r
+      //\r
+      // When Security2 is installed, Security Architectural Protocol must be published.\r
+      //\r
+      ASSERT (gSecurity != NULL);\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
+      //\r
+      SecurityStatus = gSecurity->FileAuthenticationState (\r
+                                    gSecurity,\r
+                                    AuthenticationStatus,\r
+                                    OriginalFilePath\r
+                                    );\r
+    }\r
+  } else if ((gSecurity != NULL) && (OriginalFilePath != NULL)) {\r
+    //\r
+    // Verify the Authentication Status through the Security Architectural Protocol\r
+    //\r
     SecurityStatus = gSecurity->FileAuthenticationState (\r
                                   gSecurity,\r
                                   AuthenticationStatus,\r
                                   OriginalFilePath\r
                                   );\r
-    if (EFI_ERROR (SecurityStatus) && SecurityStatus != EFI_SECURITY_VIOLATION) {\r
-      if (SecurityStatus == EFI_ACCESS_DENIED) {\r
-        //\r
-        // Image was not loaded because the platform policy prohibits the image from being loaded.\r
-        // It's the only place we could meet EFI_ACCESS_DENIED.\r
-        //\r
-        *ImageHandle = NULL;\r
-      }\r
-      Status = SecurityStatus;\r
-      Image = NULL;\r
-      goto Done;\r
-    }\r
   }\r
 \r
+  //\r
+  // Check Security Status.\r
+  //\r
+  if (EFI_ERROR (SecurityStatus) && SecurityStatus != EFI_SECURITY_VIOLATION) {\r
+    if (SecurityStatus == EFI_ACCESS_DENIED) {\r
+      //\r
+      // Image was not loaded because the platform policy prohibits the image from being loaded.\r
+      // It's the only place we could meet EFI_ACCESS_DENIED.\r
+      //\r
+      *ImageHandle = NULL;\r
+    }\r
+    Status = SecurityStatus;\r
+    Image = NULL;\r
+    goto Done;\r
+  }\r
 \r
   //\r
   // Allocate a new image structure\r
   //\r
   Image = AllocateZeroPool (sizeof(LOADED_IMAGE_PRIVATE_DATA));\r
   if (Image == NULL) {\r
-    return EFI_OUT_OF_RESOURCES;\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto Done;\r
   }\r
 \r
   //\r
@@ -1288,6 +1355,9 @@ Done:
   if (FHand.FreeBuffer) {\r
     CoreFreePool (FHand.Source);\r
   }\r
+  if (OriginalFilePath != InputFilePath) {\r
+    CoreFreePool (OriginalFilePath);\r
+  }\r
 \r
   //\r
   // There was an error.  If there's an Image structure, free it\r
@@ -1295,11 +1365,19 @@ Done:
   if (EFI_ERROR (Status)) {\r
     if (Image != NULL) {\r
       CoreUnloadAndCloseImage (Image, (BOOLEAN)(DstBuffer == 0));\r
+      Image = NULL;\r
     }\r
   } else if (EFI_ERROR (SecurityStatus)) {\r
     Status = SecurityStatus;\r
   }\r
 \r
+  //\r
+  // Track the return status from LoadImage.\r
+  //\r
+  if (Image != NULL) {\r
+    Image->LoadImageStatus = Status;\r
+  }\r
+\r
   return Status;\r
 }\r
 \r
@@ -1441,7 +1519,16 @@ CoreLoadImageEx (
   IN  UINT32                           Attribute\r
   )\r
 {\r
-  return CoreLoadImageCommon (\r
+  EFI_STATUS    Status;\r
+  UINT64        Tick;\r
+  EFI_HANDLE    Handle;\r
+\r
+  Tick = 0;\r
+  PERF_CODE (\r
+    Tick = GetPerformanceCounter ();\r
+  );\r
+\r
+  Status = CoreLoadImageCommon (\r
            TRUE,\r
            ParentImageHandle,\r
            FilePath,\r
@@ -1453,6 +1540,19 @@ CoreLoadImageEx (
            EntryPoint,\r
            Attribute\r
            );\r
+\r
+  Handle = NULL; \r
+  if (!EFI_ERROR (Status)) {\r
+    //\r
+    // ImageHandle will be valid only Status is success. \r
+    //\r
+    Handle = *ImageHandle;\r
+  }\r
+\r
+  PERF_START (Handle, "LoadImage:", NULL, Tick);\r
+  PERF_END (Handle, "LoadImage:", NULL, 0);\r
+\r
+  return Status;\r
 }\r
 \r
 \r
@@ -1470,6 +1570,7 @@ CoreLoadImageEx (
 \r
   @retval EFI_INVALID_PARAMETER   Invalid parameter\r
   @retval EFI_OUT_OF_RESOURCES    No enough buffer to allocate\r
+  @retval EFI_SECURITY_VIOLATION  The current platform policy specifies that the image should not be started.\r
   @retval EFI_SUCCESS             Successfully transfer control to the image's\r
                                   entry point.\r
 \r
@@ -1487,11 +1588,19 @@ CoreStartImage (
   LOADED_IMAGE_PRIVATE_DATA     *LastImage;\r
   UINT64                        HandleDatabaseKey;\r
   UINTN                         SetJumpFlag;\r
+  UINT64                        Tick;\r
+  EFI_HANDLE                    Handle;\r
+\r
+  Tick = 0;\r
+  Handle = ImageHandle;\r
 \r
   Image = CoreLoadedImageInfo (ImageHandle);\r
   if (Image == NULL  ||  Image->Started) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
+  if (EFI_ERROR (Image->LoadImageStatus)) {\r
+    return Image->LoadImageStatus;\r
+  }\r
 \r
   //\r
   // The image to be started must have the machine type supported by DxeCore.\r
@@ -1506,10 +1615,9 @@ CoreStartImage (
     return EFI_UNSUPPORTED;\r
   }\r
 \r
-  //\r
-  // Don't profile Objects or invalid start requests\r
-  //\r
-  PERF_START (ImageHandle, "StartImage:", NULL, 0);\r
+  PERF_CODE (\r
+    Tick = GetPerformanceCounter ();\r
+  );\r
 \r
 \r
   //\r
@@ -1529,7 +1637,12 @@ CoreStartImage (
   //\r
   Image->JumpBuffer = AllocatePool (sizeof (BASE_LIBRARY_JUMP_BUFFER) + BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT);\r
   if (Image->JumpBuffer == NULL) {\r
-    PERF_END (ImageHandle, "StartImage:", NULL, 0);\r
+    //\r
+    // Image may be unloaded after return with failure,\r
+    // then ImageHandle may be invalid, so use NULL handle to record perf log.\r
+    //\r
+    PERF_START (NULL, "StartImage:", NULL, Tick);\r
+    PERF_END (NULL, "StartImage:", NULL, 0);\r
     return EFI_OUT_OF_RESOURCES;\r
   }\r
   Image->JumpContext = ALIGN_POINTER (Image->JumpBuffer, BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT);\r
@@ -1540,6 +1653,7 @@ CoreStartImage (
   // Subsequent calls to LongJump() cause a non-zero value to be returned by SetJump().\r
   //\r
   if (SetJumpFlag == 0) {\r
+    RegisterMemoryProfileImage (Image, (Image->ImageContext.ImageType == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION ? EFI_FV_FILETYPE_APPLICATION : EFI_FV_FILETYPE_DRIVER));\r
     //\r
     // Call the image's entry point\r
     //\r
@@ -1620,12 +1734,17 @@ CoreStartImage (
   //\r
   if (EFI_ERROR (Image->Status) || Image->Type == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION) {\r
     CoreUnloadAndCloseImage (Image, TRUE);\r
+    //\r
+    // ImageHandle may be invalid after the image is unloaded, so use NULL handle to record perf log.\r
+    //\r
+    Handle = NULL;\r
   }\r
 \r
   //\r
   // Done\r
   //\r
-  PERF_END (ImageHandle, "StartImage:", NULL, 0);\r
+  PERF_START (Handle, "StartImage:", NULL, Tick);\r
+  PERF_END (Handle, "StartImage:", NULL, 0);\r
   return Status;\r
 }\r
 \r