-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added
bootloader.laye
back and fixed some bugs
- Loading branch information
Showing
5 changed files
with
132 additions
and
4 deletions.
There are no files selected for viewing
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
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
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
import * from "efi.h"; | ||
import * from "efilib.h"; | ||
import * from "elf.h"; | ||
|
||
alias kernel_start_function = callconv(sysv) i32(); | ||
|
||
i32 memcmp(readonly rawptr a, rawptr b, uint n) | ||
{ | ||
var a_ = cast(u8[*]) a; | ||
var b_ = cast(u8[*]) b; | ||
|
||
for (uint i = 0; i < n; i++) | ||
{ | ||
if (a_[i] < b_[i]) return -1; | ||
if (a_[i] > b_[i]) return 1; | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
EFI_FILE*? load_file(EFI_FILE* directory, CHAR16[*] path, | ||
EFI_HANDLE image_handle, EFI_SYSTEM_TABLE* system_table) | ||
{ | ||
EFI_FILE*? loaded_file; | ||
|
||
EFI_LOADED_IMAGE_PROTOCOL*? loaded_image; | ||
system_table->BootServices->HandleProtocol(image_handle, | ||
&gEfiLoadedImageProtocolGuid, &loaded_image); | ||
|
||
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL*? file_system; | ||
system_table->BootServices->HandleProtocol(loaded_image->DeviceHandle, | ||
&gEfiSimpleFileSystemProtocolGuid, &file_system); | ||
|
||
if (directory is nil) | ||
file_system->OpenVolume(file_system, &directory); | ||
|
||
var status = directory->Open(directory, &loaded_file, path, EFI_FILE_MODE_READ, EFI_FILE_READ_ONLY); | ||
if (status != EFI_SUCCESS) return nil; | ||
|
||
return loaded_file; | ||
} | ||
|
||
EFI_STATUS efi_main(EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *system_table) { | ||
InitializeLib(image_handle, system_table); | ||
|
||
var kernel_file = load_file(nil, "kernel.elf", image_handle, system_table); | ||
if (kernel_file is nil) | ||
{ | ||
Print("Could not load kernel.elf\n\r"); | ||
return EFI_ABORTED; | ||
} | ||
|
||
Print("Successfully loaded kernel.elf\n\r"); | ||
|
||
Elf64_Ehdr kernel_header; | ||
{ | ||
UINTN file_info_size; | ||
EFI_FILE_INFO*? file_info; | ||
kernel_file->GetInfo(kernel_file, &gEfiFileInfoGuid, &file_info_size, nil); | ||
system_table->BootServices->AllocatePool(EfiLoaderData, file_info_size, file_info); | ||
kernel_file->GetInfo(kernel_file, &gEfiFileInfoGuid, &file_info_size, &file_info); | ||
|
||
UINTN kernel_header_size = sizeof(Elf64_Ehdr); | ||
kernel_file->Read(kernel_file, &kernel_header_size, &kernel_header); | ||
} | ||
|
||
bool check_magic = 0 == memcmp(&kernel_header.e_ident[EI_MAG0], ELFMAG, SELFMAG); | ||
bool check_class = kernel_header.e_ident[EI_CLASS] == ELFCLASS64; | ||
bool check_data = kernel_header.e_ident[EI_DATA] == ELFDATA2LSB; | ||
bool check_type = kernel_header.e_type == ET_EXEC; | ||
bool check_machine = kernel_header.e_machine == EM_X86_64; | ||
bool check_version = kernel_header.e_version == EV_CURRENT; | ||
|
||
if (not check_magic or not check_class or not check_data or | ||
not check_type or not check_machine or not check_version) | ||
{ | ||
Print("kernel.elf format is bad\n\r"); | ||
return EFI_ABORTED; | ||
} | ||
|
||
Print("kernel.elf format successfully verified\n\r"); | ||
|
||
Elf64_Phdr[*] program_headers; | ||
{ | ||
kernel_file->SetPosition(kernel_file, kernel_header.e_phoff); | ||
var program_header_size = kernel_header.e_phnum * kernel_header.e_phentsize; | ||
system_table->BootServices->AllocatePool(EfiLoaderData, program_header_size, (void**)&program_headers); | ||
kernel_file->Read(kernel_file, &program_header_size, program_headers); | ||
} | ||
|
||
for (int i = 0; i < kernel_header.e_phnum; i++) | ||
{ | ||
var program_header = cast(Elf64_Phdr*) (cast(rawptr) program_header + i * kernel_header.e_phentsize); | ||
switch (program_header->p_type) | ||
{ | ||
case PT_LOAD: | ||
{ | ||
int page_count = (program_header->p_memsz + 16#1000 - 1) / 16#1000; | ||
var segment = program_header->p_paddr; | ||
system_table->BootServices->AllocatePages(AllocateAddress, EfiLoaderData, page_count, &segment); | ||
kernel_file->SetPosition(kernel_file, program_header->p_offset); | ||
var program_header_file_size = program_header->p_filesz; | ||
kernel_file->Read(kernel_file, &program_header_file_size, cast(rawptr) segment); | ||
} break; | ||
} | ||
} | ||
|
||
Print("kernel.elf loaded\n\r"); | ||
|
||
var kernel_start = cast(kernel_start_function) kernel_header.e_entry; | ||
int kernel_result = kernel_start(); | ||
|
||
Print("%d\n\r", kernel_result); | ||
|
||
return EFI_SUCCESS; | ||
} |
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