⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pe.c

📁 Next BIOS Source code : Extensible Firmware Interface
💻 C
📖 第 1 页 / 共 2 页
字号:
                                        Image->Handle, 
                                        (VOID *)(UINTN)Image->EntryPoint, 
                                        (VOID **)&Image->EntryPoint);
    if (EFI_ERROR(Status)) {
      return Status;
    }
  }

  if (CodeViewEntry != NULL) {
#ifdef EFI_NT_EMULATOR
    //
    // Load NT DLL if we know the name
    //
    
    if (Image->Machine != EFI_IMAGE_MACHINE_EBC) {
      DllEntryPoint = NULL;
      if(CodeViewEntry->Signature == CODEVIEW_SIGNATURE_RSDS){
        Status = WinNtLoadAsDll ((CHAR8 *)( (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY*)CodeViewEntry + 1), &DllEntryPoint);
      }else if(CodeViewEntry->Signature == CODEVIEW_SIGNATURE_NB10){
        Status = WinNtLoadAsDll ((CHAR8 *)(CodeViewEntry + 1), &DllEntryPoint);
      }
      if (!EFI_ERROR(Status) && DllEntryPoint != NULL) {
        Image->EntryPoint = (EFI_IMAGE_ENTRY_POINT)(UINTN)DllEntryPoint;
      }
    }
#endif
  }
  return EFI_SUCCESS;
}

#define ALIGN_POINTER(p,s)  ((VOID *) (p + ((s - ((UINTN)p)) & (s-1))))

STATIC
EFI_STATUS
RUNTIMEFUNCTION
LoadPeRelocate (
  IN LOADED_IMAGE             *Image,
  IN IMAGE_DATA_DIRECTORY     *RelocDir,
  IN UINT64                   Adjust,
  IN BOOLEAN                  RelocsStripped
  )
{
  IMAGE_BASE_RELOCATION       *RelocBase, *RelocBaseEnd;
  UINT16                      *Reloc, *RelocEnd;
  CHAR8                       *Fixup, *FixupBase;
  UINT16                      *F16;
  UINT32                      *F32;
  CHAR8                       *FixupData;
  UINTN                       BufferSize;
  EFI_STATUS                  Status;

  //
  // Find the relocation block
  //

  RelocBase = (VOID *)RelocDir->VirtualAddress;
  RelocBaseEnd = (VOID *)(RelocDir->VirtualAddress + RelocDir->Size);
  
  // 
  // If no relocations, then make sure they weren't stripped.
  //
  if (!RelocDir || !RelocBase || !RelocBaseEnd) {

    if (RelocsStripped) {
      //
      // If the image is a runtime driver, then never load it with relocations
      // stripped. Otherwise, if the link address is the same as the load 
      // address, then it's ok.
      //
      return (Adjust == 0 && Image->Type != IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) ? EFI_SUCCESS : EFI_LOAD_ERROR;
    }
    //
    // PIC code 
    //
    return EFI_SUCCESS;
  }
  RelocBase = ImageAddress (Image, RelocDir->VirtualAddress);
  RelocBaseEnd = ImageAddress (Image, RelocDir->VirtualAddress + RelocDir->Size);

  //
  // Allocate a buffer large enough for the maximum fixup data size
  //

  Image->FixupData = AllocatePool (RelocDir->Size / sizeof(UINT16) * sizeof(UINTN));
  if (!Image->FixupData) {
    return EFI_OUT_OF_RESOURCES;
  }

  //
  // Run the relocation information and apply the fixups
  //

  Status = EFI_LOAD_ERROR;
  FixupData = Image->FixupData;
  while (RelocBase < RelocBaseEnd) {
         
    Reloc = (UINT16 *) ((CHAR8 *) RelocBase + sizeof(IMAGE_BASE_RELOCATION));
    RelocEnd = (UINT16 *) ((CHAR8 *) RelocBase + RelocBase->SizeOfBlock);
    FixupBase = ImageAddress (Image, RelocBase->VirtualAddress);
    if ((CHAR8 *) RelocEnd < Image->ImageBase || (CHAR8 *) RelocEnd > Image->ImageEof) {
      goto Done;
    }

    //
    // Run this relocation record
    //

    while (Reloc < RelocEnd) {

      Fixup = FixupBase + (*Reloc & 0xFFF);
      switch ((*Reloc) >> 12) {

      case IMAGE_REL_BASED_ABSOLUTE:
        break;

      case IMAGE_REL_BASED_HIGH:
        F16 = (UINT16 *) Fixup;
        *F16 = (*F16 << 16) + (UINT16) Adjust;
        *(UINT16 *) FixupData = *F16;
        FixupData = FixupData + sizeof(UINT16);
        break;

      case IMAGE_REL_BASED_LOW:
        F16 = (UINT16 *) Fixup;
        *F16 = *F16 + (UINT16) Adjust;
        *(UINT16 *) FixupData = *F16;
        FixupData = FixupData + sizeof(UINT16);
        break;

      case IMAGE_REL_BASED_HIGHLOW:
        F32 = (UINT32 *) Fixup;
        *F32 = *F32 + (UINT32) Adjust;
        FixupData = ALIGN_POINTER(FixupData, sizeof(UINT32));
        *(UINT32 *) FixupData = *F32;
        FixupData = FixupData + sizeof(UINT32);
        break;

      case IMAGE_REL_BASED_HIGHADJ:
        BREAKPOINT();                 // BUGBUG: not done
        break;

      default:
        Status = LoadPeRelocate_Ex (Reloc,Fixup,&FixupData,Adjust);
        if (EFI_ERROR (Status)) {
            goto Done;
        }
      }

      // Next reloc record
      Reloc += 1;
    }

    // next reloc block
    RelocBase = (IMAGE_BASE_RELOCATION *) RelocEnd;
  }

  Status = EFI_SUCCESS;

Done:

  //
  // If the image was loaded re-size the fixup data buffer (into
  // the proper type for the image)
  //

  if (!EFI_ERROR(Status)) {
    BufferSize = (UINTN) (FixupData - Image->FixupData);
    Status = BSAllocatePool(Image->Info.ImageCodeType, BufferSize, &FixupData);
    if (!EFI_ERROR(Status)) {
      CopyMem (FixupData, Image->FixupData, BufferSize);
      FreePool (Image->FixupData);
      Image->FixupData = FixupData;
    }
  }

  return Status;
}


VOID
RUNTIMEFUNCTION INTERNAL
ConvertPeImage (
  IN LOADED_IMAGE             *Image
  )
// Reapply fixups to move an image to a new address
{
  CHAR8                       *OldBase, *NewBase;
  IMAGE_DOS_HEADER            *DosHdr;
  IMAGE_NT_HEADERS            *PeHdr;
  IMAGE_DATA_DIRECTORY        *RelocDir;
  IMAGE_BASE_RELOCATION       *RelocBase, *RelocBaseEnd;
  UINT16                      *Reloc, *RelocEnd;
  CHAR8                       *Fixup, *FixupBase;
  UINT16                      *F16;
  UINT32                      *F32;
  CHAR8                       *FixupData;
  UINTN                       Adjust;
  EFI_STATUS                  Status;

  OldBase = Image->ImageBase;
  NewBase = Image->ImageBase;
  RT->ConvertPointer (0, &NewBase);

  DEBUG ((D_INIT, "ConvertPeImage: Changing image base from %x to %x\n", OldBase, NewBase));
  Adjust = (UINTN) NewBase - (UINTN) OldBase;

  //
  // Find the image's relocate dir info
  //

  DosHdr = (IMAGE_DOS_HEADER *) Image->ImageBase;
  ASSERT (DosHdr->e_magic == IMAGE_DOS_SIGNATURE);
  PeHdr = (IMAGE_NT_HEADERS *) (((CHAR8 *) DosHdr) + DosHdr->e_lfanew);
  ASSERT (PeHdr->Signature == IMAGE_NT_SIGNATURE);

  if (IMAGE_DIRECTORY_ENTRY_BASERELOC < PeHdr->OptionalHeader.NumberOfRvaAndSizes) {
    RelocDir = &PeHdr->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];
    RelocBase = ImageAddress(Image, RelocDir->VirtualAddress);
    RelocBaseEnd = ImageAddress(Image, RelocDir->VirtualAddress + RelocDir->Size);
    ASSERT (RelocBase && RelocBaseEnd);
  } else {
    //
    // No relocation directory entry
    //
    RelocBase = NULL;
    RelocBaseEnd = NULL;
  }
  //
  // Run the whole relocation block
  //

  FixupData = Image->FixupData;
  while (RelocBase < RelocBaseEnd) {
         
    Reloc = (UINT16 *) ((CHAR8 *) RelocBase + sizeof(IMAGE_BASE_RELOCATION));
    RelocEnd = (UINT16 *) ((CHAR8 *) RelocBase + RelocBase->SizeOfBlock);
    ASSERT ((CHAR8 *) RelocEnd >= Image->ImageBase && (CHAR8 *) RelocEnd <= Image->ImageEof);
    FixupBase = ImageAddress (Image, RelocBase->VirtualAddress);

    //
    // Run this relocation record
    //

    while (Reloc < RelocEnd) {

      Fixup = FixupBase + (*Reloc & 0xFFF);
      switch ((*Reloc) >> 12) {

      case IMAGE_REL_BASED_ABSOLUTE:
        break;

      case IMAGE_REL_BASED_HIGH:
        F16 = (UINT16 *) Fixup;
        if (*(UINT16 *) FixupData == *F16) {
            *F16 = (*F16 << 16) + (UINT16) Adjust;
        }
        FixupData = FixupData + sizeof(UINT16);
        break;

      case IMAGE_REL_BASED_LOW:
        F16 = (UINT16 *) Fixup;
        if (*(UINT16 *) FixupData == *F16) {
            *F16 = *F16 + (UINT16) Adjust;
        }
        FixupData = FixupData + sizeof(UINT16);
        break;

      case IMAGE_REL_BASED_HIGHLOW:
        F32 = (UINT32 *) Fixup;
        FixupData = ALIGN_POINTER(FixupData, sizeof(UINT32));
        if (*(UINT32 *) FixupData == *F32) {
            *F32 = *F32 + (UINT32) Adjust;
        }
        FixupData = FixupData + sizeof(UINT32);
        break;

      case IMAGE_REL_BASED_HIGHADJ:
        BREAKPOINT();                 // BUGBUG: not done
        break;

      default:
        Status = ConvertPeImage_Ex (Reloc,Fixup,&FixupData,Adjust);
        if (EFI_ERROR (Status)) {
            return;
        }
      }

        // Next reloc record
        Reloc += 1;
    }

    // next reloc block
    RelocBase = (IMAGE_BASE_RELOCATION *) RelocEnd;
  }

  if (PL->FlushCache) {
    //
    // On some machines I-caches do not maintain coherency so you need to 
    //  flush the data that we loaded out of any D-cache.
    //
    PL->FlushCache (Image->ImageBase, Image->ImageEof);
  }
}

// BUGBUG -- function no longer used?

STATIC
VOID *
GetPeProcAddress (
  IN LOADED_IMAGE         *Image,
  IN IMAGE_NT_HEADERS     *PeHdr,
  IN CHAR8                *FunctionName
  )
{
  IMAGE_DATA_DIRECTORY        *DataDir;    
  IMAGE_EXPORT_DIRECTORY      *ExportDir, *ExportDirEnd;
  CHAR8                       *Name;
  UINT32                      *Fncs, *Names;
  UINTN                        Index;

  //
  // If we have a directory entry for the exports, search it
  //
  if (IMAGE_DIRECTORY_ENTRY_EXPORT < PeHdr->OptionalHeader.NumberOfRvaAndSizes) {
  
    DataDir = &PeHdr->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];

    //
    // Locate the export directory table
    //

    ExportDir = ImageAddress (Image, DataDir->VirtualAddress);
    ExportDirEnd = ImageAddress (Image, DataDir->VirtualAddress + DataDir->Size);
    if (!ExportDir || !ExportDirEnd || ExportDir == ExportDirEnd) {
        return NULL;
    }

    //
    // Locate the export function table
    //

    Fncs = ImageAddress (Image, (UINTN) ExportDir->AddressOfFunctions);
    Names = ImageAddress (Image, (UINTN) ExportDir->AddressOfNames);
    if (!Fncs || !Names) {
      return NULL;
    }

    //
    // Scan the export directory looking for a match
    //

    for (Index=0; Index < ExportDir->NumberOfNames; Index++) {
      Name = ImageAddress(Image, Names[Index]);
      if (Name &&  strcmpa (Name, FunctionName) == 0) {
        break;
      }
    }
  
    //
    // If found, return the address of the function
    //

    if (Index < ExportDir->NumberOfNames && Index < ExportDir->NumberOfFunctions) {
      return ImageAddress (Image, Fncs[Index]);
    }
  }
  // 
  // Not found
  //

  return NULL;
}



STATIC
EFI_STATUS
ImageRead (
  IN SIMPLE_READ_FILE     FHand,
  IN UINTN                Offset,
  IN OUT UINTN            ReadSize,
  OUT VOID                *Buffer
  )
// Load some data from the image
{
    UINTN                   OrigReadSize;
    EFI_STATUS              Status;

    //
    // Read the data
    //

    OrigReadSize = ReadSize;
    Status = ReadSimpleReadFile (FHand, Offset, &ReadSize, Buffer);

    //
    // If we didn't get it all, then there is an error
    //

    if (OrigReadSize != ReadSize) {
        Status = EFI_LOAD_ERROR;
    }

    //
    // If there's an error, zero the buffer
    //

    if (EFI_ERROR(Status)) {
        ZeroMem (Buffer, OrigReadSize);
    }
    return Status;
}


STATIC
VOID *
RUNTIMEFUNCTION
ImageAddress (
  IN LOADED_IMAGE     *Image,
  IN UINTN            Address
  )
// Convert an image address to the loaded address
{
  CHAR8        *p;

  p = Image->ImageAdjust + Address;

  if (p < Image->ImageBase || p > Image->ImageEof) {
    DEBUG((D_LOAD|D_ERROR, "ImageAddress: pointer is outside of image\n"));
    p = NULL;
  }

//    DEBUG((D_LOAD, "ImageAddress: ImageBase %x, ImageEof %x, Address %x, p %x\n", 
//                                Image->ImageBase, Image->ImageEof,
//                                Address, p));
  return p;
}

//
// This callback function is used by the EBC interpreter driver to flush the 
// processor instruction cache after creating thunks. We're simply hiding
// the "this" pointer that must be passed into the real flush function.
//
STATIC
EFI_STATUS
FlushICache (
  IN EFI_PHYSICAL_ADDRESS     Start,
  IN UINT64                   Length
  )
{
  if (PL->FlushCache) {
    //
    // On some machines I-caches do not maintain coherency so you need to 
    //  flush the data that we loaded out of any D-cache.
    //
    PL->FlushCache ((VOID *)Start, (CHAR8 *)(Start+Length));
    DEBUG((D_LOAD, "LoadPe: Cache Flush Done\n"));
  }
  return EFI_SUCCESS;
}

   

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -