33 auto char2wchar(
wchar_t *_dst,
const char *_src) ->
size_t {
35 while (_src[idx] !=
'\0') {
36 _dst[idx] = _src[idx];
43 constexpr
const uint32_t ONE_TAB_SIZE = 8;
45 constexpr
const uint32_t TWO_TAB_SIZE = 16;
47 constexpr
const uint32_t ALIGN_TWO = 10;
52 EFI_STATUS status = EFI_SUCCESS;
54 status = LibLocateProtocol(&FileSystemProtocol,
56 if (EFI_ERROR(status)) {
58 throw std::runtime_error(
"EFI_ERROR(status)");
64 if (EFI_ERROR(status)) {
66 throw std::runtime_error(
"EFI_ERROR(status)");
71 _kernel_image_filename, EFI_FILE_MODE_READ,
74 if (EFI_ERROR(status)) {
76 throw std::runtime_error(
"EFI_ERROR(status)");
82 }
catch (std::runtime_error &_e) {
84 throw std::runtime_error(_e.what());
89 status = uefi_call_wrapper(gBS->AllocatePool, 3, EfiLoaderData,
elf_file_size,
92 if (EFI_ERROR(status)) {
94 throw std::runtime_error(
"EFI_ERROR(status)");
100 if (EFI_ERROR(status)) {
102 throw std::runtime_error(
"EFI_ERROR(status)");
110 if (!check_elf_identity_ret) {
112 throw std::runtime_error(
"check_elf_identity_ret == false");
128 EFI_STATUS status = EFI_SUCCESS;
130 status = uefi_call_wrapper(
elf->Close, 1,
elf);
131 if (EFI_ERROR(status)) {
133 throw std::runtime_error(
"EFI_ERROR(status)");
136 }
catch (std::runtime_error &_e) {
142 uintptr_t image_base = 0;
143 uintptr_t image_begin = 0;
147 for (uint64_t i = 0; i <
ehdr.e_phnum; i++) {
148 if (
phdr[i].p_type != PT_LOAD) {
152 size +=
phdr[i].p_memsz;
154 auto section_page_count = EFI_SIZE_TO_PAGES(size);
156 uefi_call_wrapper(gBS->AllocatePages, 4, AllocateAnyPages,
157 EfiLoaderCode, section_page_count, &image_base);
158 if (EFI_ERROR(status)) {
160 throw std::runtime_error(
"EFI_ERROR(status)");
163 for (
auto &i :
phdr) {
164 if (i.p_type != PT_LOAD) {
167 memcpy((
void *)(image_base + i.p_vaddr),
file.data() + i.p_offset,
171 }
catch (std::runtime_error &_e) {
178 return image_base +
ehdr.e_entry - image_begin;
183 uintptr_t image_base = 0;
188 uefi_call_wrapper(gBS->AllocatePages, 4, AllocateAnyPages, EfiLoaderCode,
189 section_page_count, &image_base);
190 if (EFI_ERROR(status)) {
192 throw std::runtime_error(
"EFI_ERROR(status)");
195 std::memcpy(
reinterpret_cast<void *
>(image_base),
file.data(),
196 section_page_count * EFI_PAGE_SIZE);
198 debug << L
"AllocatePages section_page_count: " << section_page_count
200 return image_base +
ehdr.e_entry;
205 auto *elf_file_info = LibFileInfo(
elf);
206 auto file_size = elf_file_info->FileSize;
211 if ((
file[EI_MAG0] != ELFMAG0) || (
file[EI_MAG1] != ELFMAG1) ||
212 (
file[EI_MAG2] != ELFMAG2) || (
file[EI_MAG3] != ELFMAG3)) {
216 if (
file[EI_CLASS] == ELFCLASS32) {
220 if (
file[EI_CLASS] == ELFCLASS64) {
230 ehdr = *
reinterpret_cast<const Elf64_Ehdr *
>(
file.data());
234 debug << L
" Magic: ";
235 for (
auto idx :
ehdr.e_ident) {
240 debug << L
" Class: ";
241 switch (
ehdr.e_ident[EI_CLASS]) {
243 debug << L
"Invalid class";
262 switch (
ehdr.e_ident[EI_DATA]) {
264 debug << L
"Invalid data encoding";
268 debug << L
"2's complement, little endian";
272 debug << L
"2's complement, big endian";
282 debug << L
" Version: "
283 <<
ehdr.e_ident[EI_VERSION] << L
" ";
284 switch (
ehdr.e_ident[EI_VERSION]) {
286 debug << L
"Invalid ELF version";
290 debug << L
"Current version";
300 debug << L
" OS/ABI: ";
301 switch (
ehdr.e_ident[EI_OSABI]) {
302 case ELFOSABI_SYSV: {
303 debug << L
"UNIX System V ABI";
313 debug << L
" ABI Version: "
317 switch (
ehdr.e_type) {
319 debug << L
"No file type";
323 debug << L
"Relocatable file";
327 debug << L
"Executable file";
331 debug << L
"DYN (Shared object file)";
335 debug << L
"Core file";
345 debug << L
" Machine: ";
346 switch (
ehdr.e_machine) {
348 debug << L
"AMD x86-64 architecture";
356 debug << L
"ARM AARCH64";
370 debug << L
" Start of program headers: " <<
ehdr.e_phoff
372 debug << L
" Start of section headers: " <<
ehdr.e_shoff
376 debug << L
" Size of this header: " <<
ehdr.e_ehsize
378 debug << L
" Size of program headers: " <<
ehdr.e_phentsize
380 debug << L
" Number of program headers: " <<
ehdr.e_phnum
382 debug << L
" Size of section headers: " <<
ehdr.e_shentsize
384 debug << L
" Number of section headers: " <<
ehdr.e_shnum
386 debug << L
" Section header string table index: " <<
ehdr.e_shstrndx
391 phdr = std::span<Elf64_Phdr>(
392 reinterpret_cast<Elf64_Phdr *
>(
file.data() +
ehdr.e_phoff),
ehdr.e_phnum);
398 L
"Type\t\tOffset\t\tVirtAddr\tPhysAddr\tFileSiz\t\tMemSiz\t\tFlags"
401 for (uint64_t i = 0; i <
ehdr.e_phnum; i++) {
402 switch (
phdr[i].p_type) {
404 debug << L
" NULL\t\t";
409 debug << L
" LOAD\t\t";
413 debug << L
" DYNAMIC\t";
417 debug << L
" INTERP\t";
421 debug << L
" NOTE\t\t";
425 debug << L
" SHLIB\t\t";
429 debug << L
" PHDR\t\t";
433 debug << L
" TLS\t\t";
437 debug << L
" NUM\t\t";
441 debug << L
" LOOS\t\t";
444 case PT_GNU_EH_FRAME: {
445 debug << L
" GNU_EH_FRAME\t";
449 debug << L
" GNU_STACK\t";
453 debug << L
" GNU_RELRO\t";
456 case PT_GNU_PROPERTY: {
457 debug << L
" GNU_PROPERTY\t";
461 debug << L
" SUNWBSS\t\t";
465 debug << L
" SUNWSTACK\t";
469 debug << L
" HIOS\t\t";
473 debug << L
" LOPROC\t\t";
477 debug << L
" HIPROC\t\t";
492 switch (
phdr[i].p_flags) {
506 debug << L
"OS-specific\t";
510 debug << L
"Processor-specific\t";
513 case (PF_X | PF_R): {
517 case (PF_W | PF_R): {
531 shdr = std::span<Elf64_Shdr>(
532 reinterpret_cast<Elf64_Shdr *
>(
file.data() +
ehdr.e_shoff),
ehdr.e_shnum);
542 L
"Name\t\t\tType\t\tAddress\t\tOffset\t\tSize\t\tEntSize\t\tFl"
543 L
"ags\tLink\tInfo\tAlign"
545 for (uint64_t i = 0; i <
ehdr.e_shnum; i++) {
553 std::array<wchar_t, SECTION_BUF_SIZE> buf = {0};
554 auto char2wchar_ret = char2wchar(
557 debug << (
const wchar_t *)buf.data() << L
"\t";
559 if (char2wchar_ret <= TWO_TAB_SIZE) {
562 if (char2wchar_ret <= ONE_TAB_SIZE) {
565 if (char2wchar_ret <= 1) {
568 switch (
shdr[i].sh_type) {
570 debug << L
"NULL\t\t";
574 debug << L
"PROGBITS\t";
578 debug << L
"SYMTAB\t\t";
582 debug << L
"STRTAB\t\t";
586 debug << L
"RELA\t\t";
590 debug << L
"HASH\t\t";
594 debug << L
"DYNAMIC\t\t";
598 debug << L
"NOTE\t\t";
602 debug << L
"NOBITS\t\t";
610 debug << L
"SHLIB\t\t";
614 debug << L
"DYNSYM\t\t";
617 case SHT_INIT_ARRAY: {
618 debug << L
"INIT_ARRAY\t";
621 case SHT_FINI_ARRAY: {
622 debug << L
"FINI_ARRAY\t";
625 case SHT_PREINIT_ARRAY: {
626 debug << L
"PREINIT_ARRAY\t\t";
630 debug << L
"GROUP\t\t";
633 case SHT_SYMTAB_SHNDX: {
634 debug << L
"SYMTAB_SHNDX\t\t";
638 debug << L
"RELR\t\t";
646 debug << L
"LOOS\t\t";
649 case SHT_GNU_ATTRIBUTES: {
650 debug << L
"GNU_ATTRIBUTE\t\t";
654 debug << L
"GNU_HASH\t";
657 case SHT_GNU_LIBLIST: {
658 debug << L
"GNU_LIBLIST\t\t";
662 debug << L
"CHECKSUM\t\t";
665 case SHT_SUNW_move: {
666 debug << L
"SUNW_move\t\t";
669 case SHT_SUNW_COMDAT: {
670 debug << L
"SUNW_COMDAT\t\t";
673 case SHT_SUNW_syminfo: {
674 debug << L
"SUNW_syminfo\t\t";
677 case SHT_GNU_verdef: {
678 debug << L
"GNU_verdef\t\t";
681 case SHT_GNU_verneed: {
682 debug << L
"GNU_verneed\t";
685 case SHT_GNU_versym: {
686 debug << L
"GNU_versym\t";
690 debug << L
"LOPROC\t\t";
694 debug << L
"HIPROC\t\t";
698 debug << L
"LOUSER\t\t";
702 debug << L
"HIUSER\t\t";
717 switch (
shdr[i].sh_flags) {
730 case SHF_EXECINSTR: {
731 debug << L
"EXECINSTR\t";
739 debug << L
"STRINGS\t";
742 case SHF_INFO_LINK: {
743 debug << L
"INFO_LINK\t";
746 case SHF_LINK_ORDER: {
747 debug << L
"LINK_ORDER\t";
750 case SHF_OS_NONCONFORMING: {
751 debug << L
"OS_NONCONFORMING\t";
762 case SHF_COMPRESSED: {
763 debug << L
"COMPRESSED\t";
767 debug << L
"MASKOS\t";
771 debug << L
"MASKPROC\t";
774 case SHF_GNU_RETAIN: {
775 debug << L
"GNU_RETAIN\t";
779 debug << L
"ORDERED\t";
783 debug << L
"EXCLUDE\t";
786 case (SHF_WRITE | SHF_ALLOC): {
790 case (SHF_ALLOC | SHF_MERGE): {
794 case (SHF_ALLOC | SHF_EXECINSTR): {
798 case (SHF_MERGE | SHF_STRINGS): {
816 EFI_STATUS status = EFI_SUCCESS;
817 void *data =
nullptr;
819 auto section_page_count = EFI_SIZE_TO_PAGES(_phdr.p_memsz);
822 status = uefi_call_wrapper(
elf->SetPosition, 2,
elf, _phdr.p_offset);
823 if (EFI_ERROR(status)) {
825 throw std::runtime_error(
"memory_map == nullptr");
831 status = uefi_call_wrapper(gBS->AllocatePages, 4, AllocateAnyPages,
832 EfiLoaderData, section_page_count, &aaa);
833 debug << L
"_phdr.p_paddr: [" << status << L
"] [" << section_page_count
835 if (EFI_ERROR(status)) {
836 debug << L
"AllocatePages AllocateAddress failed: " << status
838 throw std::runtime_error(
"EFI_ERROR(status)");
841 if (_phdr.p_filesz > 0) {
842 auto buffer_read_size = _phdr.p_filesz;
844 status = uefi_call_wrapper(gBS->AllocatePool, 3, EfiLoaderCode,
845 buffer_read_size, (
void **)&data);
846 if (EFI_ERROR(status)) {
848 throw std::runtime_error(
"EFI_ERROR(status)");
852 uefi_call_wrapper(
elf->Read, 3,
elf, &buffer_read_size, (
void *)data);
853 if (EFI_ERROR(status)) {
855 throw std::runtime_error(
"EFI_ERROR(status)");
859 uefi_call_wrapper(gBS->CopyMem, 3,
860 reinterpret_cast<void *
>(aaa + _phdr.p_paddr), data,
864 status = uefi_call_wrapper(gBS->FreePool, 1, data);
865 if (EFI_ERROR(status)) {
867 throw std::runtime_error(
"EFI_ERROR(status)");
872 auto *zero_fill_start =
873 reinterpret_cast<void *
>(aaa + _phdr.p_paddr + _phdr.p_filesz);
874 auto zero_fill_count = _phdr.p_memsz - _phdr.p_filesz;
875 if (zero_fill_count > 0) {
876 debug << L
"Debug: Zero-filling " << zero_fill_count
877 << L
" bytes at address '" <<
ostream::hex_x << zero_fill_start << L
"'"
881 uefi_call_wrapper(gBS->SetMem, 3, zero_fill_start, zero_fill_count, 0);
887 for (uint64_t i = 0; i <
ehdr.e_phnum; i++) {
888 if (
phdr[i].p_type != PT_LOAD) {
896 debug << L
"Fatal Error: No loadable program segments found in Kernel image "
898 throw std::runtime_error(
"loaded == 0");
Elf(wchar_t *_kernel_image_filename)
auto check_elf_identity() const -> bool
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL * file_system_protocol
void load_sections(const Elf64_Phdr &_phdr) const
auto get_file_size() const -> size_t
EFI_FILE * root_file_system
size_t elf_file_size
elf 文件大小
void load_program_sections() const
std::span< Elf64_Phdr > phdr
void * elf_file_buffer
elf 文件内容缓冲区
std::span< Elf64_Shdr > shdr
auto load_kernel_image() const -> uint64_t
std::array< uint8_t, SECTION_BUF_SIZE > shstrtab_buf
shstrtab 缓冲
auto load() const -> uintptr_t
std::span< uint8_t > file
elf 文件访问
static auto endl(ostream &_ostream) -> ostream &
static auto hex_x(ostream &_ostream) -> ostream &
static auto hex_X(ostream &_ostream) -> ostream &
static ostream debug
全局输出流