]> git.proxmox.com Git - mirror_edk2.git/blobdiff - EdkModulePkg/Core/Dxe/Image/Image.c
Add a lock to protect the critical region in UEFI Boot Service API: Exit() and Unload...
[mirror_edk2.git] / EdkModulePkg / Core / Dxe / Image / Image.c
index 9b9720d8975b1f5e698c8065f68fcf9a2a90dfc6..f1b2c7a1056a45459f3c92b5b8e0c0c4660eb166 100644 (file)
@@ -1,6 +1,6 @@
 /*++\r
 \r
-Copyright (c) 2006, Intel Corporation\r
+Copyright (c) 2006 - 2007, Intel Corporation\r
 All rights reserved. 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
@@ -24,10 +24,8 @@ Abstract:
 // Module Globals\r
 //\r
 \r
-//\r
-// LIST of runtime images that need to be relocated.\r
-//\r
-LIST_ENTRY                 mRuntimeImageList = INITIALIZE_LIST_HEAD_VARIABLE (mRuntimeImageList);\r
+EFI_LOCK mBsExitLock        = EFI_INITIALIZE_LOCK_VARIABLE(EFI_TPL_NOTIFY);\r
+EFI_LOCK mBsUnloadImageLock = EFI_INITIALIZE_LOCK_VARIABLE(EFI_TPL_NOTIFY);\r
 \r
 LOADED_IMAGE_PRIVATE_DATA  *mCurrentImage = NULL;\r
 \r
@@ -74,12 +72,11 @@ LOADED_IMAGE_PRIVATE_DATA mCorePrivateImage  = {
   EFI_SUCCESS,                // Status\r
   0,                          // ExitDataSize\r
   NULL,                       // ExitData\r
+  NULL,                       // JumpBuffer\r
   NULL,                       // JumpContext\r
   0,                          // Machine\r
   NULL,                       // Ebc\r
-  FALSE,                      // RuntimeFixupValid\r
-  NULL,                       // RuntimeFixup\r
-  { NULL, NULL },             // Link\r
+  NULL,                       // RuntimeData\r
 };\r
 \r
 \r
@@ -172,52 +169,6 @@ Returns:
            );\r
 }\r
 \r
-\r
-EFI_STATUS\r
-CoreShutdownImageServices (\r
-  VOID\r
-  )\r
-/*++\r
-\r
-Routine Description:\r
-\r
-  Transfer control of runtime images to runtime service\r
-\r
-Arguments:\r
-\r
-  None\r
-\r
-Returns:\r
-\r
-  EFI_SUCCESS       - Function successfully returned\r
-\r
---*/\r
-{\r
-  LIST_ENTRY                  *Link;\r
-  LOADED_IMAGE_PRIVATE_DATA   *Image;\r
-\r
-  //\r
-  // The Runtime AP is required for the core to function!\r
-  //\r
-  ASSERT (gRuntime != NULL);\r
-\r
-  for (Link = mRuntimeImageList.ForwardLink; Link != &mRuntimeImageList; Link = Link->ForwardLink) {\r
-    Image = CR (Link, LOADED_IMAGE_PRIVATE_DATA, Link, LOADED_IMAGE_PRIVATE_DATA_SIGNATURE);\r
-    if (Image->RuntimeFixupValid) {\r
-      gRuntime->RegisterImage (\r
-                  gRuntime,\r
-                  (UINT64)(UINTN)(Image->Info.ImageBase),\r
-                  (EFI_SIZE_TO_PAGES ((UINTN)Image->Info.ImageSize)),\r
-                  Image->RuntimeFixup\r
-                  );\r
-    }\r
-  }\r
-\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-\r
-\r
 EFI_STATUS\r
 CoreLoadPeImage (\r
   IN VOID                        *Pe32Handle,\r
@@ -252,8 +203,9 @@ Returns:
 \r
 --*/\r
 {\r
-  EFI_STATUS                            Status;\r
-  UINTN                                 Size;\r
+  EFI_STATUS      Status;\r
+  BOOLEAN         DstBufAlocated;\r
+  UINTN           Size;\r
 \r
   ZeroMem (&Image->ImageContext, sizeof (Image->ImageContext));\r
 \r
@@ -270,8 +222,8 @@ Returns:
 \r
   if (!EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Image->ImageContext.Machine)) {\r
     //\r
-    // The PE/COFF loader can support loading image types that can be executed. \r
-    // If we loaded an image type that we can not execute return EFI_UNSUPORTED. \r
+    // The PE/COFF loader can support loading image types that can be executed.\r
+    // If we loaded an image type that we can not execute return EFI_UNSUPORTED.\r
     //\r
     return EFI_UNSUPPORTED;\r
   }\r
@@ -280,7 +232,7 @@ Returns:
   //\r
   // Allocate memory of the correct memory type aligned on the required image boundry\r
   //\r
-\r
+  DstBufAlocated = FALSE;\r
   if (DstBuffer == 0) {\r
     //\r
     // Allocate Destination Buffer as caller did not pass it in\r
@@ -298,18 +250,30 @@ Returns:
     // If the image relocations have not been stripped, then load at any address.\r
     // Otherwise load at the address at which it was linked.\r
     //\r
-    Status = CoreAllocatePages (\r
-               (Image->ImageContext.RelocationsStripped) ? AllocateAddress : AllocateAnyPages,\r
-               Image->ImageContext.ImageCodeMemoryType,\r
-               Image->NumberOfPages,\r
-               &Image->ImageContext.ImageAddress\r
-               );\r
+    // Memory below 1MB should be treated reserved for CSM and there should be\r
+    // no modules whose preferred load addresses are below 1MB.\r
+    //\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    if (Image->ImageContext.ImageAddress >= 0x100000 || Image->ImageContext.RelocationsStripped) {\r
+      Status = CoreAllocatePages (\r
+                 AllocateAddress,\r
+                 (EFI_MEMORY_TYPE) (Image->ImageContext.ImageCodeMemoryType),\r
+                 Image->NumberOfPages,\r
+                 &Image->ImageContext.ImageAddress\r
+                 );\r
+    }\r
+    if (EFI_ERROR (Status) && !Image->ImageContext.RelocationsStripped) {\r
+      Status = CoreAllocatePages (\r
+                 AllocateAnyPages,\r
+                 (EFI_MEMORY_TYPE) (Image->ImageContext.ImageCodeMemoryType),\r
+                 Image->NumberOfPages,\r
+                 &Image->ImageContext.ImageAddress\r
+                 );\r
+    }\r
     if (EFI_ERROR (Status)) {\r
       return Status;\r
     }\r
-\r
-    Image->ImageBasePage = Image->ImageContext.ImageAddress;\r
-\r
+    DstBufAlocated = TRUE;\r
   } else {\r
     //\r
     // Caller provided the destination buffer\r
@@ -333,9 +297,9 @@ Returns:
 \r
     Image->NumberOfPages = EFI_SIZE_TO_PAGES ((UINTN)Image->ImageContext.ImageSize + Image->ImageContext.SectionAlignment);\r
     Image->ImageContext.ImageAddress = DstBuffer;\r
-    Image->ImageBasePage = Image->ImageContext.ImageAddress;\r
   }\r
 \r
+  Image->ImageBasePage = Image->ImageContext.ImageAddress;\r
   Image->ImageContext.ImageAddress =\r
       (Image->ImageContext.ImageAddress + Image->ImageContext.SectionAlignment - 1) &\r
       ~((UINTN)Image->ImageContext.SectionAlignment - 1);\r
@@ -345,7 +309,7 @@ Returns:
   //\r
   Status = gEfiPeiPeCoffLoader->LoadImage (gEfiPeiPeCoffLoader, &Image->ImageContext);\r
   if (EFI_ERROR (Status)) {\r
-    return Status;\r
+    goto Done;\r
   }\r
 \r
   //\r
@@ -360,13 +324,6 @@ Returns:
         Status = EFI_OUT_OF_RESOURCES;\r
         goto Done;\r
       }\r
-\r
-      //\r
-      // Make a list off all the RT images so we can let the RT AP know about them\r
-      //\r
-      Image->RuntimeFixupValid = TRUE;\r
-      Image->RuntimeFixup = Image->ImageContext.FixupData;\r
-      InsertTailList (&mRuntimeImageList, &Image->Link);\r
     }\r
   }\r
 \r
@@ -375,7 +332,7 @@ Returns:
   //\r
   Status = gEfiPeiPeCoffLoader->RelocateImage (gEfiPeiPeCoffLoader, &Image->ImageContext);\r
   if (EFI_ERROR (Status)) {\r
-    return Status;\r
+    goto Done;\r
   }\r
 \r
   //\r
@@ -435,8 +392,24 @@ Returns:
   Image->Type               = Image->ImageContext.ImageType;\r
   Image->Info.ImageBase     = (VOID *)(UINTN)Image->ImageContext.ImageAddress;\r
   Image->Info.ImageSize     = Image->ImageContext.ImageSize;\r
-  Image->Info.ImageCodeType = Image->ImageContext.ImageCodeMemoryType;\r
-  Image->Info.ImageDataType = Image->ImageContext.ImageDataMemoryType;\r
+  Image->Info.ImageCodeType = (EFI_MEMORY_TYPE) (Image->ImageContext.ImageCodeMemoryType);\r
+  Image->Info.ImageDataType = (EFI_MEMORY_TYPE) (Image->ImageContext.ImageDataMemoryType);\r
+  if (Attribute & EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION) {\r
+    if (Image->ImageContext.ImageType == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) {\r
+      //\r
+      // Make a list off all the RT images so we can let the RT AP know about them.\r
+      //\r
+      Image->RuntimeData = CoreAllocateRuntimePool (sizeof(EFI_RUNTIME_IMAGE_ENTRY));\r
+      if (Image->RuntimeData == NULL) {\r
+        goto Done;\r
+      }\r
+      Image->RuntimeData->ImageBase      = Image->Info.ImageBase;\r
+      Image->RuntimeData->ImageSize      = (UINT64) (Image->Info.ImageSize);\r
+      Image->RuntimeData->RelocationData = Image->ImageContext.FixupData;\r
+      Image->RuntimeData->Handle         = Image->Handle;\r
+      InsertTailList (&gRuntime->ImageHead, &Image->RuntimeData->Link);\r
+    }\r
+  }\r
 \r
   //\r
   // Fill in the entry point of the image if it is available\r
@@ -450,12 +423,12 @@ Returns:
   //\r
 \r
   DEBUG_CODE_BEGIN ();\r
\r
+\r
     UINTN Index;\r
     UINTN StartIndex;\r
     CHAR8 EfiFileName[256];\r
 \r
-    DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Loading driver at 0x%08x EntryPoint=0x%08x ", (UINTN)Image->ImageContext.ImageAddress, (UINTN)Image->ImageContext.EntryPoint));\r
+    DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Loading driver at 0x%10p EntryPoint=0x%10p ", (VOID *)(UINTN)Image->ImageContext.ImageAddress, (VOID *)(UINTN)Image->ImageContext.EntryPoint));\r
     if (Image->ImageContext.PdbPointer != NULL) {\r
       StartIndex = 0;\r
       for (Index = 0; Image->ImageContext.PdbPointer[Index] != 0; Index++) {\r
@@ -482,16 +455,25 @@ Returns:
       DEBUG ((EFI_D_INFO | EFI_D_LOAD, "%a", EfiFileName)); // &Image->ImageContext.PdbPointer[StartIndex]));\r
     }\r
     DEBUG ((EFI_D_INFO | EFI_D_LOAD, "\n"));\r
-  \r
+\r
   DEBUG_CODE_END ();\r
 \r
   return EFI_SUCCESS;\r
 \r
 Done:\r
+\r
   //\r
-  // Free memory\r
+  // Free memory.\r
   //\r
-  CoreFreePages (Image->ImageContext.ImageAddress, Image->NumberOfPages);\r
+\r
+  if (DstBufAlocated) {\r
+    CoreFreePages (Image->ImageContext.ImageAddress, Image->NumberOfPages);\r
+  }\r
+\r
+  if (Image->ImageContext.FixupData != NULL) {\r
+    CoreFreePool (Image->ImageContext.FixupData);\r
+  }\r
+\r
   return Status;\r
 }\r
 \r
@@ -535,7 +517,7 @@ Returns:
   return Image;\r
 }\r
 \r
-\r
+STATIC\r
 EFI_STATUS\r
 CoreLoadImageCommon (\r
   IN  BOOLEAN                          BootPolicy,\r
@@ -595,6 +577,7 @@ Returns:
   EFI_DEVICE_PATH_PROTOCOL   *HandleFilePath;\r
   UINTN                      FilePathSize;\r
 \r
+  SecurityStatus = EFI_SUCCESS;\r
 \r
   ASSERT (gEfiCurrentTpl < EFI_TPL_NOTIFY);\r
   ParentImage = NULL;\r
@@ -753,6 +736,8 @@ Done:
       CoreUnloadAndCloseImage (Image, (BOOLEAN)(DstBuffer == 0));\r
       *ImageHandle = NULL;\r
     }\r
+  } else if (EFI_ERROR (SecurityStatus)) {\r
+    Status = SecurityStatus;\r
   }\r
 \r
   return Status;\r
@@ -946,17 +931,20 @@ Returns:
 \r
   //\r
   // Set long jump for Exit() support\r
+  // JumpContext must be aligned on a CPU specific boundary.\r
+  // Overallocate the buffer and force the required alignment\r
   //\r
-  Image->JumpContext = CoreAllocateBootServicesPool (sizeof (*Image->JumpContext));\r
-  if (Image->JumpContext == NULL) {\r
+  Image->JumpBuffer = CoreAllocateBootServicesPool (sizeof (BASE_LIBRARY_JUMP_BUFFER) + BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT);\r
+  if (Image->JumpBuffer == NULL) {\r
     PERF_END (ImageHandle, START_IMAGE_TOK, NULL, 0);\r
     return EFI_OUT_OF_RESOURCES;\r
   }\r
+  Image->JumpContext = ALIGN_POINTER (Image->JumpBuffer, BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT);\r
 \r
   SetJumpFlag = SetJump (Image->JumpContext);\r
   //\r
-  // The initial call to SetJump() must always return 0.  \r
-  // Subsequent calls to LongJump() cause a non-zero value to be returned by SetJump(). \r
+  // The initial call to SetJump() must always return 0.\r
+  // Subsequent calls to LongJump() cause a non-zero value to be returned by SetJump().\r
   //\r
   if (!SetJumpFlag) {\r
     //\r
@@ -972,7 +960,7 @@ Returns:
     //\r
     DEBUG_CODE_BEGIN ();\r
       if (EFI_ERROR (Image->Status)) {\r
-        DEBUG ((EFI_D_ERROR, "Error: Image at %08X start failed: %x\n", Image->Info.ImageBase, Image->Status));\r
+        DEBUG ((EFI_D_ERROR, "Error: Image at %10p start failed: %r\n", Image->Info.ImageBase, Image->Status));\r
       }\r
     DEBUG_CODE_END ();\r
 \r
@@ -988,7 +976,7 @@ Returns:
   ASSERT (Image->Tpl == gEfiCurrentTpl);\r
   CoreRestoreTpl (Image->Tpl);\r
 \r
-  CoreFreePool (Image->JumpContext);\r
+  CoreFreePool (Image->JumpBuffer);\r
 \r
   //\r
   // Pop the current start image context\r
@@ -1161,11 +1149,14 @@ Returns:
                );\r
   }\r
 \r
-  if (Image->RuntimeFixupValid) {\r
-    //\r
-    // Remove the Image from the Runtime Image list as we are about to Free it!\r
-    //\r
-    RemoveEntryList (&Image->Link);\r
+  if (Image->RuntimeData != NULL) {\r
+    if (Image->RuntimeData->Link.ForwardLink != NULL) {\r
+      //\r
+      // Remove the Image from the Runtime Image list as we are about to Free it!\r
+      //\r
+      RemoveEntryList (&Image->RuntimeData->Link);\r
+    }\r
+    CoreFreePool (Image->RuntimeData);\r
   }\r
 \r
   //\r
@@ -1231,9 +1222,12 @@ Returns:
 {\r
   LOADED_IMAGE_PRIVATE_DATA  *Image;\r
 \r
+  EfiAcquireLock (&mBsExitLock);\r
+  \r
   Image = CoreLoadedImageInfo (ImageHandle);\r
   if (Image == NULL_HANDLE) {\r
-    return EFI_INVALID_PARAMETER;\r
+    Status = EFI_INVALID_PARAMETER;\r
+    goto Done;\r
   }\r
 \r
   if (!Image->Started) {\r
@@ -1241,7 +1235,8 @@ Returns:
     // The image has not been started so just free its resources\r
     //\r
     CoreUnloadAndCloseImage (Image, TRUE);\r
-    return EFI_SUCCESS;\r
+    Status = EFI_SUCCESS;\r
+    goto Done;\r
   }\r
 \r
   //\r
@@ -1249,7 +1244,8 @@ Returns:
   //\r
   if (Image != mCurrentImage) {\r
     DEBUG ((EFI_D_LOAD|EFI_D_ERROR, "Exit: Image is not exitable image\n"));\r
-    return EFI_INVALID_PARAMETER;\r
+    Status = EFI_INVALID_PARAMETER;\r
+    goto Done;\r
   }\r
 \r
   //\r
@@ -1264,11 +1260,13 @@ Returns:
     Image->ExitDataSize = ExitDataSize;\r
     Image->ExitData = CoreAllocateBootServicesPool (Image->ExitDataSize);\r
     if (Image->ExitData == NULL) {\r
-      return EFI_OUT_OF_RESOURCES;\r
+      Status = EFI_OUT_OF_RESOURCES;\r
+      goto Done;\r
     }\r
     CopyMem (Image->ExitData, ExitData, Image->ExitDataSize);\r
   }\r
 \r
+  EfiReleaseLock (&mBsExitLock);\r
   //\r
   // return to StartImage\r
   //\r
@@ -1278,7 +1276,10 @@ Returns:
   // If we return from LongJump, then it is an error\r
   //\r
   ASSERT (FALSE);\r
-  return EFI_ACCESS_DENIED;\r
+  Status = EFI_ACCESS_DENIED;\r
+Done:\r
+  EfiReleaseLock (&mBsExitLock);\r
+  return Status;\r
 }\r
 \r
 \r
@@ -1309,12 +1310,15 @@ Returns:
   EFI_STATUS                 Status;\r
   LOADED_IMAGE_PRIVATE_DATA  *Image;\r
 \r
+  EfiAcquireLock (&mBsUnloadImageLock);\r
+  \r
   Image = CoreLoadedImageInfo (ImageHandle);\r
   if (Image == NULL ) {\r
     //\r
     // The image handle is not valid\r
     //\r
-    return EFI_INVALID_PARAMETER;\r
+    Status = EFI_INVALID_PARAMETER;\r
+    goto Done;\r
   }\r
 \r
   if (Image->Started) {\r
@@ -1341,6 +1345,8 @@ Returns:
     CoreUnloadAndCloseImage (Image, TRUE);\r
   }\r
 \r
+Done:\r
+  EfiReleaseLock (&mBsUnloadImageLock);\r
   return Status;\r
 }\r
 \r