]> git.proxmox.com Git - mirror_edk2.git/blobdiff - EdkModulePkg/Core/Pei/Image/Image.c
Fix PeiLoadImage() for compressed peim to print the correct image address and entrypoint.
[mirror_edk2.git] / EdkModulePkg / Core / Pei / Image / Image.c
index 9df12f8ab3ef3f0da77fcffc658249293522718e..6a26bb2ab41787e9581f1fb72344f491e21e471c 100644 (file)
@@ -105,10 +105,10 @@ Returns:
       }\r
 \r
       //\r
-      // Got the entry point from ImageEntryPoint\r
+      // Got the entry point from ImageEntryPoint and ImageStartAddress\r
       //\r
+      Pe32Data    = (VOID *) ((UINTN) ImageAddress);\r
       *EntryPoint = (VOID *) ((UINTN) ImageEntryPoint);\r
-      return EFI_SUCCESS;\r
     } else {\r
       //\r
       // Retrieve the entry point from the TE image header\r
@@ -131,35 +131,122 @@ Returns:
   //\r
   // Print debug message: Loading PEIM at 0x12345678 EntryPoint=0x12345688 Driver.efi\r
   //\r
-  DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Loading PEIM at 0x%08x EntryPoint=0x%08x ", Pe32Data, *EntryPoint));\r
+  DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Loading PEIM at 0x%08x EntryPoint=0x%08x ", (UINTN) ImageAddress, *EntryPoint));\r
   DEBUG_CODE_BEGIN ();\r
-    PE_COFF_LOADER_IMAGE_CONTEXT          ImageContext;\r
-    UINTN                                 Index;\r
-    CHAR8                                 *PdbStr;\r
-    CHAR8                                 AsciiBuffer[512];\r
+    EFI_IMAGE_DATA_DIRECTORY            *DirectoryEntry;\r
+    EFI_IMAGE_DEBUG_DIRECTORY_ENTRY     *DebugEntry;\r
+    UINTN                               DirCount;\r
+    UINTN                               Index;\r
+    UINTN                               Index1;\r
+    BOOLEAN                             FileNameFound;\r
+    CHAR8                               *AsciiString;\r
+    CHAR8                               AsciiBuffer[512];\r
+    VOID                                *CodeViewEntryPointer;\r
+    INTN                                TEImageAdjust;\r
+    EFI_IMAGE_DOS_HEADER                *DosHeader;\r
+    EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr;\r
+    UINT32                              NumberOfRvaAndSizes;\r
+\r
+    Hdr.Pe32 = NULL;\r
+    if (TEImageHeader == NULL) {\r
+      DosHeader = (EFI_IMAGE_DOS_HEADER *)Pe32Data;\r
+      if (DosHeader->e_magic == EFI_IMAGE_DOS_SIGNATURE) {\r
+        //\r
+        // DOS image header is present, so read the PE header after the DOS image header\r
+        //\r
+        Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINTN)Pe32Data + (UINTN)((DosHeader->e_lfanew) & 0x0ffff));\r
+      } else {\r
+        //\r
+        // DOS image header is not present, so PE header is at the image base\r
+        //\r
+        Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)Pe32Data;\r
+      }\r
+    }\r
 \r
+    //\r
+    // Find the codeview info in the image and display the file name\r
+    // being loaded.\r
+    //\r
+    // Per the PE/COFF spec, you can't assume that a given data directory\r
+    // is present in the image. You have to check the NumberOfRvaAndSizes in\r
+    // the optional header to verify a desired directory entry is there.\r
+    //\r
+    DebugEntry          = NULL;\r
+    DirectoryEntry      = NULL;\r
+    NumberOfRvaAndSizes = 0;\r
+    TEImageAdjust       = 0;\r
+    \r
+    if (TEImageHeader == NULL) {\r
+      if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+        //     \r
+        // Use PE32 offset get Debug Directory Entry\r
+        //\r
+        NumberOfRvaAndSizes = Hdr.Pe32->OptionalHeader.NumberOfRvaAndSizes;\r
+        DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&(Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]);\r
+        DebugEntry     = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *) ((UINTN) Pe32Data + DirectoryEntry->VirtualAddress);\r
+      } else if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {\r
+        //     \r
+        // Use PE32+ offset get Debug Directory Entry\r
+        //\r
+        NumberOfRvaAndSizes = Hdr.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes;\r
+        DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&(Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]);\r
+        DebugEntry     = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *) ((UINTN) Pe32Data + DirectoryEntry->VirtualAddress);\r
+      }\r
 \r
-    ZeroMem (&ImageContext, sizeof (ImageContext));\r
-    ImageContext.Handle    = Pe32Data;\r
-    ImageContext.ImageRead = PeCoffLoaderImageReadFromMemory;\r
+      if (NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) {\r
+        DirectoryEntry = NULL;\r
+        DebugEntry = NULL;\r
+      }\r
+    } else {\r
+      if (TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress != 0) {\r
+        DirectoryEntry  = &TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG];\r
+        TEImageAdjust   = sizeof (EFI_TE_IMAGE_HEADER) - TEImageHeader->StrippedSize;\r
+        DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *)((UINTN) TEImageHeader +\r
+                      TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress +\r
+                      TEImageAdjust);\r
+      }\r
+    }\r
 \r
-    PeCoffLoaderGetImageInfo (&ImageContext);\r
-    \r
-    if (ImageContext.PdbPointer != NULL) {\r
-      //\r
-      // Copy PDB pointer to AsciiBuffer and replace .PDB with .EFI\r
-      //\r
-      PdbStr = ImageContext.PdbPointer;\r
-      for (Index = 0; PdbStr != 0; Index++, PdbStr++) {\r
-        AsciiBuffer[Index] = *PdbStr;\r
-        if (*PdbStr == '.') {\r
-          AsciiBuffer[Index] = '\0';  \r
+    if (DebugEntry != NULL && DirectoryEntry != NULL) {\r
+      for (DirCount = 0; DirCount < DirectoryEntry->Size; DirCount++, DebugEntry++) {\r
+        if (DebugEntry->Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) {\r
+          if (DebugEntry->SizeOfData > 0) {\r
+            CodeViewEntryPointer = (VOID *) ((UINTN) DebugEntry->RVA + (UINTN) ImageAddress + (UINTN)TEImageAdjust);\r
+            switch (* (UINT32 *) CodeViewEntryPointer) {\r
+              case CODEVIEW_SIGNATURE_NB10:\r
+                AsciiString = (CHAR8 *)CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY);\r
+                break;\r
+\r
+              case CODEVIEW_SIGNATURE_RSDS:\r
+                AsciiString = (CHAR8 *)CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY);\r
+                break;\r
+\r
+              default:\r
+                AsciiString = NULL;\r
+                break;\r
+            }\r
+            if (AsciiString != NULL) {\r
+              FileNameFound = FALSE;\r
+              for (Index = 0, Index1 = 0; (AsciiString[Index] != 0) && (Index < sizeof (AsciiString)); Index++) {\r
+                if (AsciiString[Index] == '\\') {\r
+                  Index1 = Index;\r
+                  FileNameFound = TRUE;\r
+                }\r
+              }\r
+\r
+              if (FileNameFound) {\r
+                for (Index = Index1 + 1; AsciiString[Index] != '.'; Index++) {\r
+                  AsciiBuffer[Index - (Index1 + 1)] = AsciiString[Index];\r
+                }\r
+                AsciiBuffer[Index - (Index1 + 1)] = 0;\r
+                DEBUG ((EFI_D_INFO | EFI_D_LOAD, "%a.efi", AsciiBuffer));\r
+                break;\r
+              }\r
+            }\r
+          }\r
         }\r
       }\r
-      \r
-      DEBUG ((EFI_D_INFO | EFI_D_LOAD, "%a.efi", AsciiBuffer));\r
     }\r
-\r
   DEBUG_CODE_END ();\r
 \r
   DEBUG ((EFI_D_INFO | EFI_D_LOAD, "\n"));\r