#include #include typedef struct { UINT8 e_ident[16]; UINT16 e_type; UINT16 e_machine; UINT32 e_version; UINT64 e_entry; UINT64 e_phoff; UINT64 e_shoff; UINT32 e_flags; UINT16 e_ehsize; UINT16 e_phentsize; UINT16 e_phnum; UINT16 e_shentsize; UINT16 e_shnum; UINT16 e_shstrndx; } Elf64_Ehdr; typedef struct { UINT32 p_type; UINT32 p_flags; UINT64 p_offset; UINT64 p_vaddr; UINT64 p_paddr; UINT64 p_filesz; UINT64 p_memsz; UINT64 p_align; } Elf64_Phdr; #define PT_LOAD 1 #define ELFMAG 0x464C457F #define PAGE_SIZE_4K 4096 static void load_kernel(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) { EFI_STATUS status; EFI_GUID loadedImageGuid = EFI_LOADED_IMAGE_PROTOCOL_GUID; EFI_GUID fsGuid = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID; EFI_LOADED_IMAGE_PROTOCOL *loadedImage = NULL; EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *fs = NULL; EFI_FILE_PROTOCOL *root = NULL; EFI_FILE_PROTOCOL *kernelFile = NULL; VOID *phdrBuf = NULL; Elf64_Phdr *phdrs = NULL; Elf64_Ehdr ehdr; UINTN readSize; UINT16 i; status = uefi_call_wrapper(BS->OpenProtocol, 6, ImageHandle, &loadedImageGuid, (void**)&loadedImage, ImageHandle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL); if (EFI_ERROR(status)) { uefi_call_wrapper(SystemTable->ConOut->OutputString, 2, SystemTable->ConOut, L"ERR: loaded_image proto\n"); goto halt; } status = uefi_call_wrapper(BS->OpenProtocol, 6, loadedImage->DeviceHandle, &fsGuid, (void**)&fs, ImageHandle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL); if (EFI_ERROR(status)) { uefi_call_wrapper(SystemTable->ConOut->OutputString, 2, SystemTable->ConOut, L"ERR: file system proto\n"); goto halt; } status = uefi_call_wrapper(fs->OpenVolume, 1, fs, &root); if (EFI_ERROR(status)) { uefi_call_wrapper(SystemTable->ConOut->OutputString, 2, SystemTable->ConOut, L"ERR: open volume\n"); goto halt; } status = uefi_call_wrapper(root->Open, 5, root, &kernelFile, L"Kernel.elf", EFI_FILE_MODE_READ, 0); if (EFI_ERROR(status)) { uefi_call_wrapper(SystemTable->ConOut->OutputString, 2, SystemTable->ConOut, L"ERR: open Kernel.elf\n"); goto close_root; } readSize = sizeof(ehdr); status = uefi_call_wrapper(kernelFile->Read, 3, kernelFile, &readSize, &ehdr); if (EFI_ERROR(status) || readSize != sizeof(ehdr)) { uefi_call_wrapper(SystemTable->ConOut->OutputString, 2, SystemTable->ConOut, L"ERR: read ELF hdr\n"); goto close_all; } if (*(UINT32*)ehdr.e_ident != ELFMAG) { uefi_call_wrapper(SystemTable->ConOut->OutputString, 2, SystemTable->ConOut, L"ERR: bad ELF magic\n"); goto close_all; } { UINTN phdrSize = ehdr.e_phnum * ehdr.e_phentsize; phdrBuf = AllocatePool(phdrSize); if (!phdrBuf) { uefi_call_wrapper(SystemTable->ConOut->OutputString, 2, SystemTable->ConOut, L"ERR: alloc PHDRs\n"); goto close_all; } uefi_call_wrapper(kernelFile->SetPosition, 2, kernelFile, ehdr.e_phoff); readSize = phdrSize; status = uefi_call_wrapper(kernelFile->Read, 3, kernelFile, &readSize, phdrBuf); if (EFI_ERROR(status) || readSize != phdrSize) { uefi_call_wrapper(SystemTable->ConOut->OutputString, 2, SystemTable->ConOut, L"ERR: read PHDRs\n"); goto free_phdr; } phdrs = (Elf64_Phdr *)phdrBuf; } { UINT64 minAddr = ~0ULL; UINT64 maxAddr = 0; for (i = 0; i < ehdr.e_phnum; i++) { if (phdrs[i].p_type == PT_LOAD) { UINT64 end = phdrs[i].p_vaddr + phdrs[i].p_memsz; if (phdrs[i].p_vaddr < minAddr) minAddr = phdrs[i].p_vaddr; if (end > maxAddr) maxAddr = end; } } UINT64 base = minAddr & ~(PAGE_SIZE_4K - 1); UINT64 top = (maxAddr + PAGE_SIZE_4K - 1) & ~(PAGE_SIZE_4K - 1); UINTN numPages = (UINTN)((top - base) / PAGE_SIZE_4K); EFI_PHYSICAL_ADDRESS allocAddr = (EFI_PHYSICAL_ADDRESS)base; status = uefi_call_wrapper(BS->AllocatePages, 4, AllocateAddress, EfiLoaderData, numPages, &allocAddr); if (EFI_ERROR(status)) { uefi_call_wrapper(SystemTable->ConOut->OutputString, 2, SystemTable->ConOut, L"ERR: alloc kernel mem\n"); goto free_phdr; } } for (i = 0; i < ehdr.e_phnum; i++) { if (phdrs[i].p_type != PT_LOAD) continue; uefi_call_wrapper(kernelFile->SetPosition, 2, kernelFile, phdrs[i].p_offset); readSize = (UINTN)phdrs[i].p_filesz; uefi_call_wrapper(kernelFile->Read, 3, kernelFile, &readSize, (VOID*)(UINTN)phdrs[i].p_vaddr); if (phdrs[i].p_memsz > phdrs[i].p_filesz) { UINT8 *bss = (UINT8*)(UINTN)(phdrs[i].p_vaddr + phdrs[i].p_filesz); UINTN bssSize = (UINTN)(phdrs[i].p_memsz - phdrs[i].p_filesz); for (UINTN j = 0; j < bssSize; j++) bss[j] = 0; } } FreePool(phdrBuf); phdrBuf = NULL; uefi_call_wrapper(kernelFile->Close, 1, kernelFile); kernelFile = NULL; uefi_call_wrapper(root->Close, 1, root); root = NULL; uefi_call_wrapper(SystemTable->ConOut->OutputString, 2, SystemTable->ConOut, L"* Jumping to kernel...\n"); { typedef void (*KernelEntry)(EFI_HANDLE, EFI_SYSTEM_TABLE *); KernelEntry entry = (KernelEntry)(UINTN)ehdr.e_entry; entry(ImageHandle, SystemTable); } uefi_call_wrapper(SystemTable->ConOut->OutputString, 2, SystemTable->ConOut, L"ERR: kernel returned\n"); goto halt; free_phdr: if (phdrBuf) FreePool(phdrBuf); close_all: if (kernelFile) uefi_call_wrapper(kernelFile->Close, 1, kernelFile); close_root: if (root) uefi_call_wrapper(root->Close, 1, root); halt: while (1) __asm__ volatile("hlt"); } EFI_STATUS EFIAPI efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) { InitializeLib(ImageHandle, SystemTable); uefi_call_wrapper(SystemTable->ConOut->ClearScreen, 1, SystemTable->ConOut); uefi_call_wrapper(SystemTable->ConOut->SetCursorPosition, 3, SystemTable->ConOut, 0, 1); uefi_call_wrapper(SystemTable->ConOut->OutputString, 2, SystemTable->ConOut, L"Welcome to SYLVA OS!\n"); uefi_call_wrapper(SystemTable->ConOut->SetCursorPosition, 3, SystemTable->ConOut, 0, 2); uefi_call_wrapper(SystemTable->ConOut->OutputString, 2, SystemTable->ConOut, L"* The system has booted successfully.\n"); uefi_call_wrapper(SystemTable->ConOut->SetCursorPosition, 3, SystemTable->ConOut, 0, 3); uefi_call_wrapper(SystemTable->ConOut->OutputString, 2, SystemTable->ConOut, L"* Loading kernel...\n"); load_kernel(ImageHandle, SystemTable); return EFI_SUCCESS; }