Last active
September 14, 2018 15:02
-
-
Save naoki9911/2807a4c1ec511f11ee0ce7df3f9e54da to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <Uefi.h> | |
#include <Library/UefiLib.h> | |
#include <Library/UefiBootServicesTableLib.h> | |
#include <Protocol/BlockIo.h> | |
#include <Protocol/LoadedImage.h> | |
#include <Protocol/SimpleFileSystem.h> | |
#include <Library/DevicePathLib.h> | |
#include <Guid/FileInfo.h> | |
#include <Library/MemoryAllocationLib.h> | |
#include <Library/BaseMemoryLib.h> | |
#include "elf.h" | |
#include "relocate.h" | |
#include "file_loader.h" | |
EFI_STATUS RelocateELF(CHAR16* KernelPath, EFI_PHYSICAL_ADDRESS* RelocateAddr){ | |
EFI_STATUS Status; | |
EFI_PHYSICAL_ADDRESS BufferAddress; | |
UINTN BufferPageSize; | |
//Load ELF file on temporary area | |
Status = LoadFile(KernelPath,&BufferAddress,&BufferPageSize); | |
if(EFI_ERROR(Status)){ | |
Print(L"Failed to Load File: %s\n",KernelPath); | |
return Status; | |
} | |
//Parse elf header with Elf32_Ehdr struct | |
Elf32_Ehdr *Ehdr = (Elf32_Ehdr*)BufferAddress; | |
Elf32_Phdr *Phdr = (Elf32_Phdr*)(BufferAddress + Ehdr->e_phoff); | |
Print(L"Ehdr Address:%x\n",Ehdr); | |
Print(L"Phdr Address:%x\n",Phdr); | |
UINTN i; | |
EFI_PHYSICAL_ADDRESS alloc_start_address; | |
EFI_PHYSICAL_ADDRESS alloc_end_address; | |
UINT8 init = 0; | |
//Parse all program header | |
for(i=0; i<Ehdr->e_phnum;i++){ | |
if(Phdr[i].p_type == PT_LOAD){ | |
EFI_PHYSICAL_ADDRESS start_address = Phdr[i].p_paddr; | |
EFI_PHYSICAL_ADDRESS end_address = start_address + Phdr[i].p_memsz; | |
UINTN mask = Phdr[i].p_align-1; | |
end_address = (end_address + mask) & ~mask; | |
Print(L"Start Address:%x\n",start_address); | |
Print(L"End Address:%x\n",end_address); | |
if(init == 0){ | |
alloc_start_address = start_address; | |
alloc_end_address = end_address; | |
init = 1; | |
}else{ | |
//Calculate lowest and highest executable program header address | |
if(start_address < alloc_start_address) alloc_start_address = start_address; | |
if(end_address > alloc_end_address) alloc_end_address = end_address; | |
} | |
} | |
} | |
Print(L"Allocate Start Address:%x\n",alloc_start_address); | |
Print(L"Allocate End Address:%x\n",alloc_end_address); | |
Print(L"Entry Address:%x\n",Ehdr->e_entry); | |
//Allocate memory area to locate binary | |
UINTN page_size = ((alloc_end_address - alloc_start_address)/4096)+1; | |
Status = gBS->AllocatePages( | |
AllocateAddress, | |
EfiLoaderData, | |
page_size, | |
&alloc_start_address); | |
Print(L"AllocatePages=%d\n",Status); | |
if (EFI_ERROR(Status)) { | |
Print(L"Could not allocate pages at %08lx \n", &alloc_start_address); | |
return Status; | |
} | |
//Locate all executable program | |
for(i=0; i<Ehdr->e_phnum; i++){ | |
if(Phdr[i].p_type == PT_LOAD){ | |
EFI_PHYSICAL_ADDRESS start_address = Phdr[i].p_paddr; | |
EFI_PHYSICAL_ADDRESS end_address = start_address + Phdr[i].p_memsz; | |
UINTN mask = Phdr[i].p_align-1; | |
end_address = (end_address + mask) & ~mask; | |
CopyMem((VOID *)start_address,(VOID *)(BufferAddress + Phdr[i].p_offset),Phdr[i].p_filesz); | |
if(Phdr[i].p_memsz > Phdr[i].p_filesz){ | |
//Zero clear bss area | |
SetMem((VOID *)(start_address + Phdr[i].p_filesz),Phdr[i].p_memsz - Phdr[i].p_filesz,0); | |
Print(L"Zero Clear at %x - %x\n",start_address + Phdr[i].p_filesz,end_address); | |
} | |
Print(L"Relocated at %x - %x\n",start_address,end_address); | |
} | |
} | |
*RelocateAddr = (EFI_PHYSICAL_ADDRESS)Ehdr->e_entry; | |
//Free buffer pages | |
FreePages((VOID *)BufferAddress,BufferPageSize); | |
return Status; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment