peloader.c

来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 594 行 · 第 1/2 页

C
594
字号

    //
    // If raw size is less then virt size, zero fill the remaining
    //

    if (Section->SizeOfRawData < Section->Misc.VirtualSize) {
      EfiCommonLibZeroMem (
        Base + Section->SizeOfRawData, 
        Section->Misc.VirtualSize - Section->SizeOfRawData
        );
    }

    //
    // Next Section
    //

    Section += 1;
  }

  //
  // Copy in CodeView information if it exists
  //
  if (CodeViewSize != 0) {
    Status = EfiLdrPeCoffImageRead (FHand, CodeViewFileOffset, CodeViewSize, Image->ImageBase + CodeViewOffset);
    DebugEntry->RVA = (UINT32) (CodeViewOffset);
  }

  //
  // Apply relocations only if needed
  //
  if (PeHdr.Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
    ImageBase = (UINT64)PeHdr.Pe32.OptionalHeader.ImageBase;
  } else {
    ImageBase = PeHdr.Pe32Plus.OptionalHeader.ImageBase;
  }
  if ((UINTN)(Image->ImageBase) != (UINTN) (ImageBase)) {
    Status = EfiLdrPeCoffLoadPeRelocate (
               Image,
               &DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC],
               (UINTN) Image->ImageBase - (UINTN)ImageBase,
               NumberOfMemoryMapEntries,
               EfiMemoryDescriptor
               );

    if (EFI_ERROR(Status)) {
PrintHeader ('N');
      return Status;
    }
  }

  //
  // Use exported EFI specific interface if present, else use the image's entry point
  //
  Image->EntryPoint = (EFI_IMAGE_ENTRY_POINT)(UINTN)
                        (EfiLdrPeCoffImageAddress(
                           Image, 
                           PeHdr.Pe32.OptionalHeader.AddressOfEntryPoint
                           ));

  return Status;
}

STATIC
EFI_STATUS
EfiLdrPeCoffLoadPeRelocate (
  IN EFILDR_LOADED_IMAGE      *Image,
  IN EFI_IMAGE_DATA_DIRECTORY *RelocDir,
  IN UINTN                     Adjust,
  IN UINTN                    *NumberOfMemoryMapEntries,
  IN EFI_MEMORY_DESCRIPTOR    *EfiMemoryDescriptor
  )
{
  EFI_IMAGE_BASE_RELOCATION   *RelocBase;
  EFI_IMAGE_BASE_RELOCATION   *RelocBaseEnd;
  UINT16                      *Reloc;
  UINT16                      *RelocEnd;
  UINT8                       *Fixup;
  UINT8                       *FixupBase;
  UINT16                      *F16;
  UINT32                      *F32;
  UINT64                      *F64;
  UINT8                       *FixupData;
  UINTN                       NoFixupPages;

  //
  // Find the relocation block
  //

  RelocBase = EfiLdrPeCoffImageAddress (Image, RelocDir->VirtualAddress);
  RelocBaseEnd = EfiLdrPeCoffImageAddress (Image, RelocDir->VirtualAddress + RelocDir->Size);
  if (!RelocBase || !RelocBaseEnd) {
PrintHeader ('O');
    return EFI_LOAD_ERROR;
  }

  NoFixupPages = EFI_SIZE_TO_PAGES(RelocDir->Size / sizeof(UINT16) * sizeof(UINTN));
  Image->FixupData = (UINT8*) FindSpace (NoFixupPages, NumberOfMemoryMapEntries, EfiMemoryDescriptor, EfiRuntimeServicesData, EFI_MEMORY_WB);
  if (Image->FixupData == 0) {
    return EFI_OUT_OF_RESOURCES;
  }

  //
  // Run the whole relocation block
  //

  FixupData = Image->FixupData;
  while (RelocBase < RelocBaseEnd) {
           
    Reloc = (UINT16 *) ((UINT8 *) RelocBase + sizeof(EFI_IMAGE_BASE_RELOCATION));
    RelocEnd = (UINT16 *) ((UINT8 *) RelocBase + RelocBase->SizeOfBlock);
    FixupBase = EfiLdrPeCoffImageAddress (Image, RelocBase->VirtualAddress);
    if ((UINT8 *) RelocEnd < Image->ImageBase || (UINT8 *) RelocEnd > Image->ImageEof) {
PrintHeader ('P');
      return EFI_LOAD_ERROR;
    }

    //
    // Run this relocation record
    //

    while (Reloc < RelocEnd) {

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

      case EFI_IMAGE_REL_BASED_ABSOLUTE:
        break;

      case EFI_IMAGE_REL_BASED_HIGH:
        F16 = (UINT16 *) Fixup;
        *F16  = (UINT16) (*F16 + (UINT16)(((UINT32)Adjust) >> 16));
        if (FixupData != NULL) {
          *(UINT16 *) FixupData = *F16;
          FixupData = FixupData + sizeof(UINT16);
        }
        break;

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

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

      case EFI_IMAGE_REL_BASED_DIR64:
        F64 = (UINT64 *) Fixup;
        *F64 = *F64 + (UINT64) Adjust;
        if (FixupData != NULL) {
          FixupData = ALIGN_POINTER(FixupData, sizeof(UINT64));
          *(UINT64 *) FixupData = *F64;
          FixupData = FixupData + sizeof(UINT64);
        }
        break;

      case EFI_IMAGE_REL_BASED_HIGHADJ:
        EFI_DEADLOOP();                 // BUGBUG: not done
        break;

      default:
//        DEBUG((D_LOAD|D_ERROR, "PeRelocate: unknown fixed type\n"));
PrintHeader ('Q');
        EFI_DEADLOOP();
        return EFI_LOAD_ERROR;
      }

      // Next reloc record
      Reloc += 1;
    }

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

  return EFI_SUCCESS;
}

STATIC
EFI_STATUS
EfiLdrPeCoffImageRead (
  IN VOID                 *FHand,
  IN UINTN                Offset,
  IN OUT UINTN            ReadSize,
  OUT VOID                *Buffer
  )
{
  EfiCommonLibCopyMem (Buffer, (VOID *)((UINTN)FHand + Offset), ReadSize);

  return EFI_SUCCESS;
}

STATIC
VOID *
EfiLdrPeCoffImageAddress (
  IN EFILDR_LOADED_IMAGE     *Image,
  IN UINTN                   Address
  )
{
  UINT8        *FixedAddress;

  FixedAddress = Image->ImageAdjust + Address;

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

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


EFI_STATUS
EfiLdrPeCoffSetImageType (
  IN OUT EFILDR_LOADED_IMAGE      *Image,
  IN UINTN                        ImageType
  )
{
  EFI_MEMORY_TYPE                 CodeType;
  EFI_MEMORY_TYPE                 DataType;

  switch (ImageType) {
  case EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION:
    CodeType = EfiLoaderCode;
    DataType = EfiLoaderData;
    break;

  case EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER:
    CodeType = EfiBootServicesCode;
    DataType = EfiBootServicesData;
    break;

  case EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER:
    CodeType = EfiRuntimeServicesCode;
    DataType = EfiRuntimeServicesData;
    break;

  default:
    return EFI_INVALID_PARAMETER;
  }

  Image->Type = ImageType;
  Image->Info.ImageCodeType = CodeType;    
  Image->Info.ImageDataType = DataType;

  return EFI_SUCCESS;
}

EFI_STATUS
EfiLdrPeCoffCheckImageMachineType (
  IN UINT16           MachineType
  )
{
  EFI_STATUS          Status;

  Status = EFI_UNSUPPORTED;

#if EFI32
  if (MachineType == EFI_IMAGE_MACHINE_IA32) {
    Status = EFI_SUCCESS;
  }
#endif

#if EFIX64
  if (MachineType == EFI_IMAGE_MACHINE_X64) {
    Status = EFI_SUCCESS;
  }
#endif

#if EFI64
  if (MachineType == EFI_IMAGE_MACHINE_IA64) {
    Status = EFI_SUCCESS;
  }
#endif

  return Status;
}

⌨️ 快捷键说明

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