aboutsummaryrefslogtreecommitdiffstats
path: root/bootloader/ELF.c
blob: dd2bc629b244ee80fc07972e291271ea1f349cb6 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
#include "ELF.h"
#include "memorytypes.h"

#include <efi.h>
#include <efilib.h>
#include <efidef.h>

UINTN EFIAPI elf_ceil2(float x)
{
  UINTN ret = x;
  if (x - (int)x > 0) {
      x += 1;
      ret = (int)x;
  }

  return ret;
}

void EFIAPI PrintELFInfo(ELF * file)
{
  Print(L"LoadAddress: 0x%x\n", file);

  Print(L"Kernel Entry Point: 0x%llx\n", file->e_entry);

  Print(L"program Header offset: %d\n", file->e_phoff);
  Print(L"Program Header Size: %d\n", file->e_phentsize);
  Print(L"Program Header number: %d\n", file->e_phnum);
  Print(L"== FILE PH START: 0x%llx ==\n", (uint64_t)file + file->e_phoff);

  for(uint64_t i = 0; i < file->e_phnum; i++)
  {
    Print(L"====== PH %d\n", (uint64_t)(i+1));
    PH* ph = (PH*)(((uint64_t)file) + file->e_phoff+i*file->e_phentsize);
    Print(L"TOTAL LOAD offset: 0x%llx\n", (uint64_t)(file) + ph->p_offset);
    Print(L"UNCAST LOAD offset: 0x%llx\n", (uint64_t)(file + ph->p_offset));
    Print(L"LOAD offset: 0x%llx\n", ph->p_offset);
    Print(L"LOAD vaddr: 0x%llx\n", ph->p_vaddr);
    Print(L"LOAD paddr: 0x%llx\n", ph->p_paddr);
    Print(L"LOAD size in file: 0x%llx\n", ph->p_filesz);
    Print(L"LOAD size in memory: 0x%llx\n", ph->p_memsz);
  }
}

Loaded_ELF* EFIAPI LoadELF(ELF* file)
{
  Print(L"Loading ELF file into memory\n");
  Loaded_ELF* loaded_elf;

  uefi_call_wrapper(BS->AllocatePool, 3, EfiLoaderData, sizeof(Loaded_ELF), (void**)&loaded_elf);

  loaded_elf->ph_num = file->e_phnum;
  loaded_elf->entry = file->e_entry;
  uefi_call_wrapper(BS->AllocatePool, 3, EfiLoaderData, file->e_phnum*sizeof(Loaded_PH), (void**)&(loaded_elf->ph));

  Print(L"Loading Program Segments...\n");
  for(uint32_t i = 0; i < file->e_phnum; i++)
  {
    PH* ph = (PH*)(((uint64_t)file) + file->e_phoff+i*file->e_phentsize);
    loaded_elf->ph[i].mem_size = ph->p_memsz;
    loaded_elf->ph[i].vaddr = ph->p_vaddr;

    uint64_t pages = (ph->p_memsz/1024)/4;

    // uefi_call_wrapper(BS->AllocatePool, 3, EfiLoaderData, ph->p_memsz, (void**)&(loaded_elf->ph[i].data)); // <- wrong, need to allocate aligned pages
    UINTN ipages = elf_ceil2(pages);
    EFI_PHYSICAL_ADDRESS tmp;

    /*EFI_STATUS allocstatus = */uefi_call_wrapper(BS->AllocatePages, 4, AllocateAnyPages, MEM_KERNEL, ipages, &tmp);
    loaded_elf->ph[i].data = (void*)tmp;

    // Print(L"PH: %d Addr: 0x%llX\n", i, file + ph->p_offset);
    Print(L"LOADED PH: %d Addr: 0x%llX\n", i, loaded_elf->ph[i].data);
    uefi_call_wrapper(BS->CopyMem, 3, loaded_elf->ph[i].data, (void*)((uint64_t)(file) + ph->p_offset), ph->p_filesz);
  }
  Print(L"\nFinished Loading ELF file into memory\n\n");

  return loaded_elf;
}