]> git.proxmox.com Git - mirror_edk2.git/blobdiff - EdkCompatibilityPkg/Foundation/Library/Pei/PeiLib/PeCoffLoader.c
Sync all bug fixes between EDK1.04 and EDK1.06 into EdkCompatibilityPkg.
[mirror_edk2.git] / EdkCompatibilityPkg / Foundation / Library / Pei / PeiLib / PeCoffLoader.c
index c276aa8bda1ec6be39228e0c56246644369fddba..1904902c7878c8868fbd8cbb34a5a306a806b2bb 100644 (file)
@@ -1,7 +1,7 @@
 /*++\r
 \r
-Copyright (c) 2005 - 2007, Intel Corporation                                                         \r
-All rights reserved. This program and the accompanying materials                          \r
+Copyright (c) 2005 - 2010, 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
 http://opensource.org/licenses/bsd-license.php                                            \r
@@ -434,7 +434,7 @@ Returns:
       ImageContext->ImageAddress = Hdr.Pe32Plus->OptionalHeader.ImageBase;\r
     }\r
   } else {\r
-    ImageContext->ImageAddress = (EFI_PHYSICAL_ADDRESS)(Hdr.Te->ImageBase);\r
+    ImageContext->ImageAddress = (EFI_PHYSICAL_ADDRESS)(Hdr.Te->ImageBase + Hdr.Te->StrippedSize - sizeof (EFI_TE_IMAGE_HEADER));\r
   }\r
 \r
   //\r
@@ -565,7 +565,10 @@ Returns:
     // Pe image and in Te image header there is not a field to describe the imagesize,\r
     // we use the largest VirtualAddress plus Size in each directory entry to describe the imagesize\r
     //\r
-    ImageContext->ImageSize         = (UINT64) (Hdr.Te->DataDirectory[0].VirtualAddress + Hdr.Te->DataDirectory[0].Size);\r
+    ImageContext->ImageSize = (UINT64) (Hdr.Te->DataDirectory[0].VirtualAddress + Hdr.Te->DataDirectory[0].Size);\r
+    if(Hdr.Te->DataDirectory[1].VirtualAddress > Hdr.Te->DataDirectory[0].VirtualAddress) {\r
+      ImageContext->ImageSize = (UINT64) (Hdr.Te->DataDirectory[1].VirtualAddress + Hdr.Te->DataDirectory[1].Size);\r
+    }\r
     ImageContext->SectionAlignment  = 4096;\r
     ImageContext->SizeOfHeaders     = sizeof (EFI_TE_IMAGE_HEADER) + (UINTN) Hdr.Te->BaseOfCode - (UINTN) Hdr.Te->StrippedSize;\r
 \r
@@ -785,12 +788,18 @@ Returns:
     // the optional header to verify a desired directory entry is there.\r
     //\r
 \r
-    if (NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {\r
+    if (NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC && RelocDir->Size > 0) {\r
       RelocBase = PeCoffLoaderImageAddress (ImageContext, RelocDir->VirtualAddress);\r
       RelocBaseEnd = PeCoffLoaderImageAddress (\r
                       ImageContext,\r
                       RelocDir->VirtualAddress + RelocDir->Size - 1\r
                       );\r
+      if ((RelocBase == NULL) || (RelocBaseEnd == NULL)) {\r
+        //\r
+        // If the base start or end address resolved to 0, then fail.\r
+        //\r
+        return EFI_LOAD_ERROR;\r
+      }\r
     } else {\r
       //\r
       // Set base and end to bypass processing below.\r
@@ -799,20 +808,28 @@ Returns:
     }\r
   } else {\r
     Hdr.Te             = (EFI_TE_IMAGE_HEADER *)(UINTN)(ImageContext->ImageAddress);\r
-    Adjust             = (UINT64) (BaseAddress - Hdr.Te->ImageBase);\r
-    Hdr.Te->ImageBase  = (UINT64) (BaseAddress);\r
+    Adjust             = (UINT64) (BaseAddress - Hdr.Te->StrippedSize + sizeof (EFI_TE_IMAGE_HEADER) - Hdr.Te->ImageBase);\r
+    Hdr.Te->ImageBase  = (UINT64) (BaseAddress - Hdr.Te->StrippedSize + sizeof (EFI_TE_IMAGE_HEADER));\r
 \r
     //\r
     // Find the relocation block\r
     //\r
     RelocDir = &Hdr.Te->DataDirectory[0];\r
-    RelocBase = (EFI_IMAGE_BASE_RELOCATION *)(UINTN)(\r
-                                    ImageContext->ImageAddress + \r
-                                    RelocDir->VirtualAddress +\r
-                                    sizeof(EFI_TE_IMAGE_HEADER) - \r
-                                    Hdr.Te->StrippedSize\r
-                                    );\r
-    RelocBaseEnd = (EFI_IMAGE_BASE_RELOCATION *) ((UINTN) RelocBase + (UINTN) RelocDir->Size - 1);\r
+    if (RelocDir->Size > 0) {\r
+      RelocBase = (EFI_IMAGE_BASE_RELOCATION *)(UINTN)(\r
+                                      ImageContext->ImageAddress +\r
+                                      RelocDir->VirtualAddress +\r
+                                      sizeof(EFI_TE_IMAGE_HEADER) -\r
+                                      Hdr.Te->StrippedSize\r
+                                      );\r
+      RelocBaseEnd = (EFI_IMAGE_BASE_RELOCATION *) ((UINTN) RelocBase + (UINTN) RelocDir->Size - 1);\r
+    } else {\r
+      //\r
+      // Set base and end to bypass processing below.\r
+      //\r
+      RelocBase = NULL;\r
+      RelocBaseEnd = NULL;\r
+    }\r
   }\r
   \r
   //\r
@@ -825,6 +842,13 @@ Returns:
     RelocEnd  = (UINT16 *) ((CHAR8 *) RelocBase + RelocBase->SizeOfBlock);\r
     if (!(ImageContext->IsTeImage)) {\r
       FixupBase = PeCoffLoaderImageAddress (ImageContext, RelocBase->VirtualAddress);\r
+\r
+      if (FixupBase == NULL) {\r
+        //\r
+        // If the FixupBase address resolved to 0, then fail.\r
+        //\r
+        return EFI_LOAD_ERROR;\r
+      }\r
     } else {\r
       FixupBase = (CHAR8 *)(UINTN)(ImageContext->ImageAddress +\r
                     RelocBase->VirtualAddress +\r
@@ -992,6 +1016,12 @@ Returns:
   UINT32                                TempDebugEntryRva;\r
   UINT32                                NumberOfRvaAndSizes;\r
   UINT16                                Magic;\r
+#if (EFI_SPECIFICATION_VERSION >= 0x0002000A)\r
+  EFI_IMAGE_RESOURCE_DIRECTORY          *ResourceDirectory;\r
+  EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY    *ResourceDirectoryEntry;\r
+  EFI_IMAGE_RESOURCE_DIRECTORY_STRING   *ResourceDirectoryString;\r
+  EFI_IMAGE_RESOURCE_DATA_ENTRY         *ResourceDataEntry;\r
+#endif\r
 \r
   if (NULL == ImageContext) {\r
     return EFI_INVALID_PARAMETER;\r
@@ -1347,6 +1377,73 @@ Returns:
     }\r
   }\r
 \r
+#if (EFI_SPECIFICATION_VERSION >= 0x0002000A)\r
+  //\r
+  // Get Image's HII resource section\r
+  //\r
+  if (!(ImageContext->IsTeImage)) {\r
+    if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+      //\r
+      // Use PE32 offset\r
+      //\r
+      DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE];\r
+    } else {\r
+      //\r
+      // Use PE32+ offset\r
+      //\r
+      DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE];\r
+    }\r
+\r
+    if (DirectoryEntry->Size != 0) {\r
+      Base = PeCoffLoaderImageAddress (ImageContext, DirectoryEntry->VirtualAddress);\r
+\r
+      ResourceDirectory = (EFI_IMAGE_RESOURCE_DIRECTORY *) Base;\r
+      ResourceDirectoryEntry = (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *) (ResourceDirectory + 1);\r
+\r
+      for (Index = 0; Index < ResourceDirectory->NumberOfNamedEntries; Index++) {\r
+        if (ResourceDirectoryEntry->u1.s.NameIsString) {\r
+          ResourceDirectoryString = (EFI_IMAGE_RESOURCE_DIRECTORY_STRING *) (Base + ResourceDirectoryEntry->u1.s.NameOffset);\r
+\r
+          if (ResourceDirectoryString->Length == 3 &&\r
+              ResourceDirectoryString->String[0] == L'H' &&\r
+              ResourceDirectoryString->String[1] == L'I' &&\r
+              ResourceDirectoryString->String[2] == L'I') {\r
+            //\r
+            // Resource Type "HII" found\r
+            //\r
+            if (ResourceDirectoryEntry->u2.s.DataIsDirectory) {\r
+              //\r
+              // Move to next level - resource Name\r
+              //\r
+              ResourceDirectory = (EFI_IMAGE_RESOURCE_DIRECTORY *) (Base + ResourceDirectoryEntry->u2.s.OffsetToDirectory);\r
+              ResourceDirectoryEntry = (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *) (ResourceDirectory + 1);\r
+\r
+              if (ResourceDirectoryEntry->u2.s.DataIsDirectory) {\r
+                //\r
+                // Move to next level - resource Language\r
+                //\r
+                ResourceDirectory = (EFI_IMAGE_RESOURCE_DIRECTORY *) (Base + ResourceDirectoryEntry->u2.s.OffsetToDirectory);\r
+                ResourceDirectoryEntry = (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *) (ResourceDirectory + 1);\r
+              }\r
+            }\r
+\r
+            //\r
+            // Now it ought to be resource Data\r
+            //\r
+            if (!ResourceDirectoryEntry->u2.s.DataIsDirectory) {\r
+              ResourceDataEntry = (EFI_IMAGE_RESOURCE_DATA_ENTRY *) (Base + ResourceDirectoryEntry->u2.OffsetToData);\r
+              ImageContext->HiiResourceData = (EFI_PHYSICAL_ADDRESS) (UINTN) PeCoffLoaderImageAddress (ImageContext, ResourceDataEntry->OffsetToData);\r
+              break;\r
+            }\r
+          }\r
+        }\r
+\r
+        ResourceDirectoryEntry++;\r
+      }\r
+    }\r
+  }\r
+#endif\r
+\r
 #if defined (EFI_DEBUG_ITP_BREAK) && !defined (_CONSOLE)\r
   AsmEfiSetBreakSupport ((UINTN)(ImageContext->ImageAddress));\r
 #endif\r