]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdePkg/Library/BasePeCoffLib/BasePeCoff.c
• BaseMemoryLib:
[mirror_edk2.git] / MdePkg / Library / BasePeCoffLib / BasePeCoff.c
index c7f33546372863ad1a693de17b516cebd5a014f7..6b8adc1fd63006ff021f862fa927a575a8c40c74 100644 (file)
 \r
 **/\r
 \r
+/**\r
+  Performs an Itanium-based specific relocation fixup.\r
 \r
+  @param  Reloc       Pointer to the relocation record.\r
+  @param  Fixup       Pointer to the address to fix up.\r
+  @param  FixupData   Pointer to a buffer to log the fixups.\r
+  @param  Adjust      The offset to adjust the fixup.\r
 \r
+  @return Status code.\r
 \r
-STATIC\r
-RETURN_STATUS\r
-PeCoffLoaderGetPeHeader (\r
-  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *ImageContext,\r
-  OUT    EFI_IMAGE_NT_HEADERS          *PeHdr,\r
-  OUT    EFI_TE_IMAGE_HEADER           *TeHdr\r
-  );\r
-\r
-STATIC\r
-RETURN_STATUS\r
-PeCoffLoaderCheckImageType (\r
-  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *ImageContext,\r
-  IN     EFI_IMAGE_NT_HEADERS          *PeHdr,\r
-  IN     EFI_TE_IMAGE_HEADER           *TeHdr\r
-  );\r
-\r
-STATIC\r
-VOID                            *\r
-PeCoffLoaderImageAddress (\r
-  IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *ImageContext,\r
-  IN     UINTN                         Address\r
-  );\r
-\r
+**/\r
 RETURN_STATUS\r
 PeCoffLoaderRelocateImageEx (\r
   IN UINT16      *Reloc,\r
@@ -53,15 +38,12 @@ PeCoffLoaderRelocateImageEx (
 /**\r
   Retrieves the PE or TE Header from a PE/COFF or TE image.\r
 \r
-  @param  ImageContext The context of the image being loaded.\r
-  \r
-  @param  PeHdr The buffer in which to return the PE header.\r
-  \r
-  @param  TeHdr The buffer in which to return the TE header.\r
+  @param  ImageContext    The context of the image being loaded.\r
+  @param  PeHdr           The buffer in which to return the PE header.\r
+  @param  TeHdr           The buffer in which to return the TE header.\r
 \r
-  @return\r
-  RETURN_SUCCESS if the PE or TE Header is read,\r
-  Otherwise, the error status from reading the PE/COFF or TE image using the ImageRead function.\r
+  @retval RETURN_SUCCESS  The PE or TE Header is read.\r
+  @retval Other           The error status from reading the PE/COFF or TE image using the ImageRead function.\r
 \r
 **/\r
 STATIC\r
@@ -72,7 +54,7 @@ PeCoffLoaderGetPeHeader (
   OUT    EFI_TE_IMAGE_HEADER           *TeHdr\r
   )\r
 {\r
-  RETURN_STATUS            Status;\r
+  RETURN_STATUS         Status;\r
   EFI_IMAGE_DOS_HEADER  DosHdr;\r
   UINTN                 Size;\r
 \r
@@ -82,11 +64,11 @@ PeCoffLoaderGetPeHeader (
   //\r
   Size = sizeof (EFI_IMAGE_DOS_HEADER);\r
   Status = ImageContext->ImageRead (\r
-                          ImageContext->Handle,\r
-                          0,\r
-                          &Size,\r
-                          &DosHdr\r
-                          );\r
+                           ImageContext->Handle,\r
+                           0,\r
+                           &Size,\r
+                           &DosHdr\r
+                           );\r
   if (RETURN_ERROR (Status)) {\r
     ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ;\r
     return Status;\r
@@ -104,11 +86,11 @@ PeCoffLoaderGetPeHeader (
   //\r
   Size = sizeof (EFI_IMAGE_NT_HEADERS);\r
   Status = ImageContext->ImageRead (\r
-                          ImageContext->Handle,\r
-                          ImageContext->PeCoffHeaderOffset,\r
-                          &Size,\r
-                          PeHdr\r
-                          );\r
+                           ImageContext->Handle,\r
+                           ImageContext->PeCoffHeaderOffset,\r
+                           &Size,\r
+                           PeHdr\r
+                           );\r
   if (RETURN_ERROR (Status)) {\r
     ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ;\r
     return Status;\r
@@ -119,11 +101,11 @@ PeCoffLoaderGetPeHeader (
   if (PeHdr->Signature != EFI_IMAGE_NT_SIGNATURE) {\r
     Size = sizeof (EFI_TE_IMAGE_HEADER);\r
     Status = ImageContext->ImageRead (\r
-                            ImageContext->Handle,\r
-                            0,\r
-                            &Size,\r
-                            TeHdr\r
-                            );\r
+                             ImageContext->Handle,\r
+                             0,\r
+                             &Size,\r
+                             TeHdr\r
+                             );\r
     if (TeHdr->Signature != EFI_TE_IMAGE_HEADER_SIGNATURE) {\r
       return RETURN_UNSUPPORTED;\r
     }\r
@@ -137,14 +119,12 @@ PeCoffLoaderGetPeHeader (
 /**\r
   Checks the PE or TE header of a PE/COFF or TE image to determine if it supported.\r
 \r
-  @param  ImageContext The context of the image being loaded.\r
-  \r
-  @param  PeHdr The buffer in which to return the PE header.\r
-  \r
-  @param  TeHdr The buffer in which to return the TE header.\r
+  @param  ImageContext        The context of the image being loaded.\r
+  @param  PeHdr               The buffer in which to return the PE header.\r
+  @param  TeHdr               The buffer in which to return the TE header.\r
 \r
-  @retval RETURN_SUCCESS if the PE/COFF or TE image is supported\r
-  @retval RETURN_UNSUPPORTED of the PE/COFF or TE image is not supported.\r
+  @retval RETURN_SUCCESS      The PE/COFF or TE image is supported.\r
+  @retval RETURN_UNSUPPORTED  The PE/COFF or TE image is not supported.\r
 \r
 **/\r
 STATIC\r
@@ -185,16 +165,22 @@ PeCoffLoaderCheckImageType (
 }\r
 \r
 /**\r
-  Retrieves information on a PE/COFF image.\r
+  Retrieves information about a PE/COFF image.\r
+\r
+  Computes the PeCoffHeaderOffset, ImageAddress, ImageSize, DestinationAddress, CodeView,\r
+  PdbPointer, RelocationsStripped, SectionAlignment, SizeOfHeaders, and DebugDirectoryEntryRva\r
+  fields of the ImageContext structure.  If ImageContext is NULL, then return RETURN_INVALID_PARAMETER.\r
+  If the PE/COFF image accessed through the ImageRead service in the ImageContext structure is not\r
+  a supported PE/COFF image type, then return RETURN_UNSUPPORTED.  If any errors occur while\r
+  computing the fields of ImageContext, then the error status is returned in the ImageError field of\r
+  ImageContext. \r
 \r
-  @param  This Calling context\r
-  @param  ImageContext The context of the image being loaded\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
 \r
-  @retval  RETURN_SUCCESS The information on the PE/COFF image was collected.\r
-  @retval  RETURN_INVALID_PARAMETER ImageContext is NULL.\r
-  @retval  RETURN_UNSUPPORTED The PE/COFF image is not supported.\r
-  @retval  Otherwise The error status from reading the PE/COFF image using the\r
-  ImageContext->ImageRead() function\r
+  @retval RETURN_SUCCESS            The information on the PE/COFF image was collected.\r
+  @retval RETURN_INVALID_PARAMETER  ImageContext is NULL.\r
+  @retval RETURN_UNSUPPORTED        The PE/COFF image is not supported.\r
 \r
 **/\r
 RETURN_STATUS\r
@@ -203,7 +189,7 @@ PeCoffLoaderGetImageInfo (
   IN OUT PE_COFF_LOADER_IMAGE_CONTEXT           *ImageContext\r
   )\r
 {\r
-  RETURN_STATUS                      Status;\r
+  RETURN_STATUS                   Status;\r
   EFI_IMAGE_NT_HEADERS            PeHdr;\r
   EFI_TE_IMAGE_HEADER             TeHdr;\r
   EFI_IMAGE_DATA_DIRECTORY        *DebugDirectoryEntry;\r
@@ -368,7 +354,7 @@ PeCoffLoaderGetImageInfo (
       //\r
       // Read section header from file\r
       //\r
-      Size = sizeof (EFI_IMAGE_SECTION_HEADER);\r
+      Size   = sizeof (EFI_IMAGE_SECTION_HEADER);\r
       Status = ImageContext->ImageRead (\r
                                ImageContext->Handle,\r
                                SectionHeaderOffset,\r
@@ -383,10 +369,10 @@ PeCoffLoaderGetImageInfo (
       if (DebugDirectoryEntryRva >= SectionHeader.VirtualAddress &&\r
           DebugDirectoryEntryRva < SectionHeader.VirtualAddress + SectionHeader.Misc.VirtualSize) {\r
         DebugDirectoryEntryFileOffset = DebugDirectoryEntryRva -\r
-          SectionHeader.VirtualAddress +\r
-          SectionHeader.PointerToRawData +\r
-          sizeof (EFI_TE_IMAGE_HEADER) -\r
-          TeHdr.StrippedSize;\r
+                                        SectionHeader.VirtualAddress +\r
+                                        SectionHeader.PointerToRawData +\r
+                                        sizeof (EFI_TE_IMAGE_HEADER) -\r
+                                        TeHdr.StrippedSize;\r
 \r
         //\r
         // File offset of the debug directory was found, if this is not the last\r
@@ -448,11 +434,10 @@ PeCoffLoaderGetImageInfo (
 /**\r
   Converts an image address to the loaded address.\r
 \r
-  @param  ImageContext The context of the image being loaded.\r
-  \r
-  @param  Address The address to be converted to the loaded address.\r
+  @param  ImageContext  The context of the image being loaded.\r
+  @param  Address       The address to be converted to the loaded address.\r
 \r
-  @return NULL if the address can not be converted, otherwise, the converted address\r
+  @return The converted address or NULL if the address can not be converted.\r
 \r
 **/\r
 STATIC\r
@@ -471,15 +456,23 @@ PeCoffLoaderImageAddress (
 }\r
 \r
 /**\r
-  Relocates a PE/COFF image in memory.\r
+  Applies relocation fixups to a PE/COFF image that was loaded with PeCoffLoaderLoadImage().\r
 \r
-  @param  This Calling context.\r
-  \r
-  @param  ImageContext Contains information on the loaded image to relocate.\r
+  If the DestinationAddress field of ImageContext is 0, then use the ImageAddress field of\r
+  ImageContext as the relocation base address.  Otherwise, use the DestinationAddress field\r
+  of ImageContext as the relocation base address.  The caller must allocate the relocation\r
+  fixup log buffer and fill in the FixupData field of ImageContext prior to calling this function.  \r
+  If ImageContext is NULL, then ASSERT().\r
+\r
+  @param  ImageContext        Pointer to the image context structure that describes the PE/COFF\r
+                              image that is being relocated.\r
 \r
-  @retval RETURN_SUCCESS      if the PE/COFF image was relocated.\r
-  @retval RETURN_LOAD_ERROR   if the image is not a valid PE/COFF image.\r
-  @retval RETURN_UNSUPPORTED  not support.\r
+  @retval RETURN_SUCCESS      The PE/COFF image was relocated.\r
+                              Extended status information is in the ImageError field of ImageContext.\r
+  @retval RETURN_LOAD_ERROR   The image in not a valid PE/COFF image.\r
+                              Extended status information is in the ImageError field of ImageContext.\r
+  @retval RETURN_UNSUPPORTED  A relocation record type is not supported.\r
+                              Extended status information is in the ImageError field of ImageContext.\r
 \r
 **/\r
 RETURN_STATUS\r
@@ -504,6 +497,8 @@ PeCoffLoaderRelocateImage (
   CHAR8                     *FixupData;\r
   PHYSICAL_ADDRESS          BaseAddress;\r
 \r
+  ASSERT (ImageContext != NULL);\r
+\r
   PeHdr = NULL;\r
   TeHdr = NULL;\r
   //\r
@@ -522,7 +517,7 @@ PeCoffLoaderRelocateImage (
   // If the destination address is not 0, use that rather than the\r
   // image address as the relocation target.\r
   //\r
-  if (ImageContext->DestinationAddress) {\r
+  if (ImageContext->DestinationAddress != 0) {\r
     BaseAddress = ImageContext->DestinationAddress;\r
   } else {\r
     BaseAddress = ImageContext->ImageAddress;\r
@@ -531,6 +526,7 @@ PeCoffLoaderRelocateImage (
   if (!(ImageContext->IsTeImage)) {\r
     PeHdr = (EFI_IMAGE_NT_HEADERS *)((UINTN)ImageContext->ImageAddress + \r
                                             ImageContext->PeCoffHeaderOffset);\r
+   \r
     Adjust = (UINT64) BaseAddress - PeHdr->OptionalHeader.ImageBase;\r
     PeHdr->OptionalHeader.ImageBase = (UINTN)BaseAddress;\r
 \r
@@ -564,11 +560,11 @@ PeCoffLoaderRelocateImage (
     //\r
     RelocDir = &TeHdr->DataDirectory[0];\r
     RelocBase = (EFI_IMAGE_BASE_RELOCATION *)(UINTN)(\r
-                                               ImageContext->ImageAddress + \r
-                                               RelocDir->VirtualAddress +\r
-                                               sizeof(EFI_TE_IMAGE_HEADER) - \r
-                                               TeHdr->StrippedSize\r
-                                               );\r
+                                    ImageContext->ImageAddress + \r
+                                    RelocDir->VirtualAddress +\r
+                                    sizeof(EFI_TE_IMAGE_HEADER) - \r
+                                    TeHdr->StrippedSize\r
+                                    );\r
     RelocBaseEnd = (EFI_IMAGE_BASE_RELOCATION *) ((UINTN) RelocBase + (UINTN) RelocDir->Size - 1);\r
   }\r
   \r
@@ -584,10 +580,10 @@ PeCoffLoaderRelocateImage (
       FixupBase = PeCoffLoaderImageAddress (ImageContext, RelocBase->VirtualAddress);\r
     } else {\r
       FixupBase = (CHAR8 *)(UINTN)(ImageContext->ImageAddress +\r
-                             RelocBase->VirtualAddress +\r
-                             sizeof(EFI_TE_IMAGE_HEADER) - \r
-                             TeHdr->StrippedSize\r
-                             );\r
+                    RelocBase->VirtualAddress +\r
+                    sizeof(EFI_TE_IMAGE_HEADER) - \r
+                    TeHdr->StrippedSize\r
+                    );\r
     }\r
 \r
     if ((CHAR8 *) RelocEnd < (CHAR8 *) ((UINTN) ImageContext->ImageAddress) ||\r
@@ -670,14 +666,24 @@ PeCoffLoaderRelocateImage (
 /**\r
   Loads a PE/COFF image into memory.\r
 \r
-  @param  This Calling context.\r
-  \r
-  @param  ImageContext Contains information on image to load into memory.\r
-\r
-  @retval RETURN_SUCCESS            if the PE/COFF image was loaded.\r
-  @retval RETURN_BUFFER_TOO_SMALL   if the caller did not provide a large enough buffer.\r
-  @retval RETURN_LOAD_ERROR         if the image is a runtime driver with no relocations.\r
-  @retval RETURN_INVALID_PARAMETER  if the image address is invalid.\r
+  Loads the PE/COFF image accessed through the ImageRead service of ImageContext into the buffer\r
+  specified by the ImageAddress and ImageSize fields of ImageContext.  The caller must allocate\r
+  the load buffer and fill in the ImageAddress and ImageSize fields prior to calling this function.\r
+  The EntryPoint, FixupDataSize, CodeView, and PdbPointer fields of ImageContext are computed.\r
+  If ImageContext is NULL, then ASSERT().\r
+\r
+  @param  ImageContext              Pointer to the image context structure that describes the PE/COFF\r
+                                    image that is being loaded.\r
+\r
+  @retval RETURN_SUCCESS            The PE/COFF image was loaded into the buffer specified by\r
+                                    the ImageAddress and ImageSize fields of ImageContext.\r
+                                    Extended status information is in the ImageError field of ImageContext.\r
+  @retval RETURN_BUFFER_TOO_SMALL   The caller did not provide a large enough buffer.\r
+                                    Extended status information is in the ImageError field of ImageContext.\r
+  @retval RETURN_LOAD_ERROR         The PE/COFF image is an EFI Runtime image with no relocations.\r
+                                    Extended status information is in the ImageError field of ImageContext.\r
+  @retval RETURN_INVALID_PARAMETER  The image address is invalid.\r
+                                    Extended status information is in the ImageError field of ImageContext.\r
 \r
 **/\r
 RETURN_STATUS\r
@@ -686,10 +692,10 @@ PeCoffLoaderLoadImage (
   IN OUT PE_COFF_LOADER_IMAGE_CONTEXT  *ImageContext\r
   )\r
 {\r
-  RETURN_STATUS                            Status;\r
+  RETURN_STATUS                         Status;\r
   EFI_IMAGE_NT_HEADERS                  *PeHdr;\r
   EFI_TE_IMAGE_HEADER                   *TeHdr;\r
-  PE_COFF_LOADER_IMAGE_CONTEXT  CheckContext;\r
+  PE_COFF_LOADER_IMAGE_CONTEXT          CheckContext;\r
   EFI_IMAGE_SECTION_HEADER              *FirstSection;\r
   EFI_IMAGE_SECTION_HEADER              *Section;\r
   UINTN                                 NumberOfSections;\r
@@ -702,8 +708,11 @@ PeCoffLoaderLoadImage (
   UINTN                                 Size;\r
   UINT32                                TempDebugEntryRva;\r
 \r
+  ASSERT (ImageContext != NULL);\r
+\r
   PeHdr = NULL;\r
   TeHdr = NULL;\r
+\r
   //\r
   // Assume success\r
   //\r
@@ -728,7 +737,13 @@ PeCoffLoaderLoadImage (
     ImageContext->ImageError = IMAGE_ERROR_INVALID_IMAGE_SIZE;\r
     return RETURN_BUFFER_TOO_SMALL;\r
   }\r
-\r
+  if (ImageContext->ImageAddress == 0) {\r
+    //\r
+    // Image cannot be loaded into 0 address.\r
+    //\r
+    ImageContext->ImageError = IMAGE_ERROR_INVALID_IMAGE_ADDRESS;\r
+    return RETURN_INVALID_PARAMETER;\r
+  }\r
   //\r
   // If there's no relocations, then make sure it's not a runtime driver,\r
   // and that it's being loaded at the linked address.\r
@@ -793,9 +808,9 @@ PeCoffLoaderLoadImage (
     TeHdr             = (EFI_TE_IMAGE_HEADER *) (UINTN) (ImageContext->ImageAddress);\r
 \r
     FirstSection = (EFI_IMAGE_SECTION_HEADER *) (\r
-                     (UINTN)ImageContext->ImageAddress +\r
-                     sizeof(EFI_TE_IMAGE_HEADER)\r
-                     );\r
+          (UINTN)ImageContext->ImageAddress +\r
+          sizeof(EFI_TE_IMAGE_HEADER)\r
+          );\r
     NumberOfSections  = (UINTN) (TeHdr->NumberOfSections);\r
 \r
   }\r
@@ -890,9 +905,9 @@ PeCoffLoaderLoadImage (
                                                                 );\r
   } else {\r
     ImageContext->EntryPoint =  (PHYSICAL_ADDRESS) (\r
-                                  (UINTN)ImageContext->ImageAddress +\r
-                                  (UINTN)TeHdr->AddressOfEntryPoint +\r
-                                  (UINTN)sizeof(EFI_TE_IMAGE_HEADER) -\r
+                       (UINTN)ImageContext->ImageAddress +\r
+                       (UINTN)TeHdr->AddressOfEntryPoint +\r
+                       (UINTN)sizeof(EFI_TE_IMAGE_HEADER) -\r
           (UINTN) TeHdr->StrippedSize\r
       );\r
   }\r
@@ -933,11 +948,11 @@ PeCoffLoaderLoadImage (
                     );\r
     } else {\r
       DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *)(UINTN)(\r
-                                                        ImageContext->ImageAddress +\r
-                                                        ImageContext->DebugDirectoryEntryRva +\r
-                                                        sizeof(EFI_TE_IMAGE_HEADER) -\r
-                                                        TeHdr->StrippedSize\r
-                                                        );\r
+                                               ImageContext->ImageAddress +\r
+                                               ImageContext->DebugDirectoryEntryRva +\r
+                                               sizeof(EFI_TE_IMAGE_HEADER) -\r
+                                               TeHdr->StrippedSize\r
+                                               );\r
     }\r
 \r
     if (DebugEntry != NULL) {\r
@@ -956,9 +971,9 @@ PeCoffLoaderLoadImage (
           ImageContext->CodeView = PeCoffLoaderImageAddress (ImageContext, TempDebugEntryRva);\r
         } else {\r
           ImageContext->CodeView = (VOID *)(\r
-                                     (UINTN)ImageContext->ImageAddress +\r
-                                     (UINTN)TempDebugEntryRva +\r
-                                     (UINTN)sizeof(EFI_TE_IMAGE_HEADER) -\r
+                      (UINTN)ImageContext->ImageAddress +\r
+                      (UINTN)TempDebugEntryRva +\r
+                      (UINTN)sizeof(EFI_TE_IMAGE_HEADER) -\r
                 (UINTN) TeHdr->StrippedSize\r
             );\r
         }\r