elfload.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. #include <uefi.h>
  2. /*** ELF64 defines and structs ***/
  3. #define ELFMAG "\177ELF"
  4. #define SELFMAG 4
  5. #define EI_CLASS 4 /* File class byte index */
  6. #define ELFCLASS64 2 /* 64-bit objects */
  7. #define EI_DATA 5 /* Data encoding byte index */
  8. #define ELFDATA2LSB 1 /* 2's complement, little endian */
  9. #define ET_EXEC 2 /* Executable file */
  10. #define PT_LOAD 1 /* Loadable program segment */
  11. #ifdef __x86_64__
  12. #define EM_MACH 62 /* AMD x86-64 architecture */
  13. #endif
  14. #ifdef __aarch64__
  15. #define EM_MACH 183 /* ARM aarch64 architecture */
  16. #endif
  17. typedef struct
  18. {
  19. uint8_t e_ident[16]; /* Magic number and other info */
  20. uint16_t e_type; /* Object file type */
  21. uint16_t e_machine; /* Architecture */
  22. uint32_t e_version; /* Object file version */
  23. uint64_t e_entry; /* Entry point virtual address */
  24. uint64_t e_phoff; /* Program header table file offset */
  25. uint64_t e_shoff; /* Section header table file offset */
  26. uint32_t e_flags; /* Processor-specific flags */
  27. uint16_t e_ehsize; /* ELF header size in bytes */
  28. uint16_t e_phentsize; /* Program header table entry size */
  29. uint16_t e_phnum; /* Program header table entry count */
  30. uint16_t e_shentsize; /* Section header table entry size */
  31. uint16_t e_shnum; /* Section header table entry count */
  32. uint16_t e_shstrndx; /* Section header string table index */
  33. } Elf64_Ehdr;
  34. typedef struct
  35. {
  36. uint32_t p_type; /* Segment type */
  37. uint32_t p_flags; /* Segment flags */
  38. uint64_t p_offset; /* Segment file offset */
  39. uint64_t p_vaddr; /* Segment virtual address */
  40. uint64_t p_paddr; /* Segment physical address */
  41. uint64_t p_filesz; /* Segment size in file */
  42. uint64_t p_memsz; /* Segment size in memory */
  43. uint64_t p_align; /* Segment alignment */
  44. } Elf64_Phdr;
  45. /**
  46. * Load an ELF executable
  47. */
  48. int main(int argc, char **argv)
  49. {
  50. (void)argc;
  51. (void)argv;
  52. FILE *f;
  53. char *buff;
  54. long int size;
  55. Elf64_Ehdr *elf;
  56. Elf64_Phdr *phdr;
  57. uintptr_t entry;
  58. int i;
  59. /* load the file */
  60. if((f = fopen("\\0E_elfload\\kernel.elf", "r"))) {
  61. fseek(f, 0, SEEK_END);
  62. size = ftell(f);
  63. fseek(f, 0, SEEK_SET);
  64. buff = malloc(size + 1);
  65. if(!buff) {
  66. fprintf(stderr, "unable to allocate memory\n");
  67. return 1;
  68. }
  69. fread(buff, size, 1, f);
  70. fclose(f);
  71. } else {
  72. fprintf(stderr, "Unable to open file\n");
  73. return 0;
  74. }
  75. /* is it a valid ELF executable for this architecture? */
  76. elf = (Elf64_Ehdr *)buff;
  77. if(!memcmp(elf->e_ident, ELFMAG, SELFMAG) && /* magic match? */
  78. elf->e_ident[EI_CLASS] == ELFCLASS64 && /* 64 bit? */
  79. elf->e_ident[EI_DATA] == ELFDATA2LSB && /* LSB? */
  80. elf->e_type == ET_EXEC && /* executable object? */
  81. elf->e_machine == EM_MACH && /* architecture match? */
  82. elf->e_phnum > 0) { /* has program headers? */
  83. /* load segments */
  84. for(phdr = (Elf64_Phdr *)(buff + elf->e_phoff), i = 0;
  85. i < elf->e_phnum;
  86. i++, phdr = (Elf64_Phdr *)((uint8_t *)phdr + elf->e_phentsize)) {
  87. if(phdr->p_type == PT_LOAD) {
  88. printf("ELF segment %p %d bytes (bss %d bytes)\n", phdr->p_vaddr, phdr->p_filesz,
  89. phdr->p_memsz - phdr->p_filesz);
  90. memcpy((void*)phdr->p_vaddr, buff + phdr->p_offset, phdr->p_filesz);
  91. memset((void*)(phdr->p_vaddr + phdr->p_filesz), 0, phdr->p_memsz - phdr->p_filesz);
  92. }
  93. }
  94. entry = elf->e_entry;
  95. } else {
  96. fprintf(stderr, "not a valid ELF executable for this architecture\n");
  97. return 0;
  98. }
  99. /* free resources */
  100. free(buff);
  101. /* execute the "kernel" */
  102. printf("ELF entry point %p\n", entry);
  103. i = (*((int(* __attribute__((sysv_abi)))(void))(entry)))();
  104. printf("ELF returned %d\n", i);
  105. return 0;
  106. }