From e9b1d553a1c16a70999cd2c98780a16786efba3f Mon Sep 17 00:00:00 2001 From: "Zone.N" Date: Mon, 4 Mar 2024 11:20:15 +0800 Subject: [PATCH] fix(boot): remove stdexcept in efi codes Signed-off-by: Zone.N --- cmake/compile_config.cmake | 1 - src/boot/boot.cpp | 105 +++++++++++++------------ src/boot/graphics.cpp | 38 +++++---- src/boot/include/load_elf.h | 11 ++- src/boot/load_elf.cpp | 151 +++++++++++++++++------------------- src/boot/memory.cpp | 22 ++++-- 6 files changed, 169 insertions(+), 159 deletions(-) diff --git a/cmake/compile_config.cmake b/cmake/compile_config.cmake index e035dd0c4..1ea71d8b7 100644 --- a/cmake/compile_config.cmake +++ b/cmake/compile_config.cmake @@ -19,7 +19,6 @@ list(APPEND COMMON_COMPILE_OPTIONS # 启用 free-standing 环境 -ffreestanding - # 目标平台编译选项 # @todo clang 交叉编译参数 $<$: diff --git a/src/boot/boot.cpp b/src/boot/boot.cpp index b15adba8d..c2f236f9c 100644 --- a/src/boot/boot.cpp +++ b/src/boot/boot.cpp @@ -14,9 +14,6 @@ * */ -#include -#include - #include "load_elf.h" #include "ostream.hpp" #include "project_config.h" @@ -28,59 +25,61 @@ efi_main(EFI_HANDLE _image_handle, [[maybe_unused]] EFI_SYSTEM_TABLE *_system_table) { EFI_STATUS status = EFI_SUCCESS; uint64_t kernel_addr = 0; - try { - // 输出 efi 信息 - EFI_LOADED_IMAGE *loaded_image = nullptr; - status = LibLocateProtocol(&LoadedImageProtocol, - reinterpret_cast(&loaded_image)); - if (EFI_ERROR(status)) { - debug << L"LibLocateProtocol: " << status << ostream::endl; - } - debug << L"Revision: " << ostream::hex_X << loaded_image->Revision - << ostream::endl; - debug << L"ParentHandle: " << ostream::hex_X - << loaded_image->ParentHandle << ostream::endl; - debug << L"SystemTable: " << ostream::hex_X << loaded_image->SystemTable - << ostream::endl; - debug << L"DeviceHandle: " << ostream::hex_X - << loaded_image->DeviceHandle << ostream::endl; - debug << L"FilePath: " << ostream::hex_X << loaded_image->FilePath - << ostream::endl; - debug << L"Reserved: " << ostream::hex_X << loaded_image->Reserved - << ostream::endl; - debug << L"LoadOptionsSize: " << ostream::hex_X - << loaded_image->LoadOptionsSize << ostream::endl; - debug << L"LoadOptions: " << ostream::hex_X << loaded_image->LoadOptions - << ostream::endl; - debug << L"ImageBase: " << ostream::hex_X << loaded_image->ImageBase - << ostream::endl; - debug << L"ImageSize: " << ostream::hex_X << loaded_image->ImageSize - << ostream::endl; - debug << L"ImageCodeType: " << ostream::hex_X - << loaded_image->ImageCodeType << ostream::endl; - debug << L"ImageDataType: " << ostream::hex_X - << loaded_image->ImageDataType << ostream::endl; - debug << L"Unload: " << ostream::hex_X << loaded_image->Unload - << ostream::endl; + // 输出 efi 信息 + EFI_LOADED_IMAGE *loaded_image = nullptr; + status = LibLocateProtocol(&LoadedImageProtocol, + reinterpret_cast(&loaded_image)); + if (EFI_ERROR(status)) { + debug << L"LibLocateProtocol: " << status << ostream::endl; + return status; + } + + debug << L"Revision: " << ostream::hex_X << loaded_image->Revision + << ostream::endl; + debug << L"ParentHandle: " << ostream::hex_X << loaded_image->ParentHandle + << ostream::endl; + debug << L"SystemTable: " << ostream::hex_X << loaded_image->SystemTable + << ostream::endl; + debug << L"DeviceHandle: " << ostream::hex_X << loaded_image->DeviceHandle + << ostream::endl; + debug << L"FilePath: " << ostream::hex_X << loaded_image->FilePath + << ostream::endl; + debug << L"Reserved: " << ostream::hex_X << loaded_image->Reserved + << ostream::endl; + debug << L"LoadOptionsSize: " << ostream::hex_X + << loaded_image->LoadOptionsSize << ostream::endl; + debug << L"LoadOptions: " << ostream::hex_X << loaded_image->LoadOptions + << ostream::endl; + debug << L"ImageBase: " << ostream::hex_X << loaded_image->ImageBase + << ostream::endl; + debug << L"ImageSize: " << ostream::hex_X << loaded_image->ImageSize + << ostream::endl; + debug << L"ImageCodeType: " << ostream::hex_X << loaded_image->ImageCodeType + << ostream::endl; + debug << L"ImageDataType: " << ostream::hex_X << loaded_image->ImageDataType + << ostream::endl; + debug << L"Unload: " << ostream::hex_X << loaded_image->Unload + << ostream::endl; - // 初始化 Graphics - auto graphics = Graphics(); - // 打印图形信息 - graphics.print_info(); - // 设置为 1920*1080 - graphics.set_mode(); - // 初始化 Memory - auto memory = Memory(); - memory.print_info(); - // 加载内核 - auto elf = Elf(KERNEL_NAME); - // kernel_addr = elf.load_kernel_image(); - kernel_addr = elf.load(); - } catch (const std::exception &_e) { - debug << L"Fatal Error: " << _e.what() << ostream::endl; + // 初始化 Graphics + auto graphics = Graphics(); + // 打印图形信息 + graphics.print_info(); + // 设置为 1920*1080 + graphics.set_mode(); + // 初始化 Memory + auto memory = Memory(); + memory.print_info(); + // 加载内核 + auto elf = Elf(KERNEL_NAME); + // kernel_addr = elf.load_kernel_image(); + kernel_addr = elf.load(); + if (kernel_addr == 0) { + debug << L"Failed to load kernel" << ostream::endl; return EFI_LOAD_ERROR; } + debug << L"Set Kernel Entry Point to: [" << ostream::hex_X << kernel_addr << L"]" << ostream::endl; // 退出 boot service @@ -92,12 +91,12 @@ efi_main(EFI_HANDLE _image_handle, memory_map = LibMemoryMap(&desc_count, &map_key, &desc_size, &desc_version); if (memory_map == nullptr) { debug << L"LibMemoryMap failed: memory_map == nullptr" << ostream::endl; - throw std::runtime_error("memory_map == nullptr"); } status = uefi_call_wrapper(gBS->ExitBootServices, 2, _image_handle, map_key); if (EFI_ERROR(status)) { debug << L"ExitBootServices failed, Memory Map has Changed " << status << ostream::endl; + return status; } auto kernel_entry = (void (*)())kernel_addr; diff --git a/src/boot/graphics.cpp b/src/boot/graphics.cpp index 235cc6560..c4cb91e42 100644 --- a/src/boot/graphics.cpp +++ b/src/boot/graphics.cpp @@ -14,8 +14,6 @@ * */ -#include - #include "load_elf.h" #include "ostream.hpp" @@ -23,14 +21,15 @@ Graphics::Graphics() { auto status = LibLocateProtocol(&GraphicsOutputProtocol, reinterpret_cast(&gop)); if (EFI_ERROR(status)) { - debug << L"Could not locate GOP: " << status << ostream::endl; - throw std::runtime_error("EFI_ERROR(status)"); + debug << L"Graphics::Graphics() Could not locate GOP: " << status + << ostream::endl; + return; } if (gop == nullptr) { - debug << L"LibLocateProtocol(GraphicsOutputProtocol, &gop) returned " + debug << L"Graphics::Graphics() LibLocateProtocol(GraphicsOutputProtocol, " + L"&gop) returned " << status << " but gop is nullptr" << ostream::endl; - - throw std::runtime_error("gop == nullptr"); + return; } } @@ -44,8 +43,9 @@ void Graphics::set_mode(EFI_GRAPHICS_PIXEL_FORMAT _format, uint32_t _width, status = uefi_call_wrapper(gop->QueryMode, 4, gop, i, &mode_info_size, &mode_info); if (EFI_ERROR(status)) { - debug << L"QueryMode failed: " << status << ostream::endl; - throw std::runtime_error("EFI_ERROR(status)"); + debug << L"Graphics::set_mode QueryMode failed: " << status + << ostream::endl; + return; } if ((mode_info->PixelFormat == _format) && @@ -53,14 +53,16 @@ void Graphics::set_mode(EFI_GRAPHICS_PIXEL_FORMAT _format, uint32_t _width, (mode_info->VerticalResolution == _height)) { status = uefi_call_wrapper(gop->SetMode, 2, gop, i); if (EFI_ERROR(status)) { - debug << L"SetMode failed: " << status << ostream::endl; - throw std::runtime_error("EFI_ERROR(status)"); + debug << L"Graphics::set_mode SetMode failed: " << status + << ostream::endl; + return; } } status = uefi_call_wrapper(gBS->FreePool, 1, mode_info); if (EFI_ERROR(status)) { - debug << L"FreePool failed: " << status << ostream::endl; - throw std::runtime_error("EFI_ERROR(status)"); + debug << L"Graphics::set_mode FreePool failed: " << status + << ostream::endl; + return; } } @@ -92,8 +94,9 @@ void Graphics::print_info() const { auto status = uefi_call_wrapper(gop->QueryMode, 4, gop, i, &mode_info_size, &mode_info); if (EFI_ERROR(status)) { - debug << L"QueryMode failed: " << status << ostream::endl; - throw std::runtime_error("EFI_ERROR(status)"); + debug << L"Graphics::print_info() QueryMode failed: " << status + << ostream::endl; + return; } debug << L"Mode: " << i << L", Version: " << ostream::hex_x @@ -105,8 +108,9 @@ void Graphics::print_info() const { status = uefi_call_wrapper(gBS->FreePool, 1, mode_info); if (EFI_ERROR(status)) { - debug << L"FreePool failed: " << status << ostream::endl; - throw std::runtime_error("EFI_ERROR(status)"); + debug << L"Graphics::print_info() FreePool failed: " << status + << ostream::endl; + return; } } } diff --git a/src/boot/include/load_elf.h b/src/boot/include/load_elf.h index 993ebf7d5..600506b73 100644 --- a/src/boot/include/load_elf.h +++ b/src/boot/include/load_elf.h @@ -122,8 +122,9 @@ class Memory { /** * 更新内存映射信息 + * @return 失败返回 false */ - void flush_desc(); + bool flush_desc(); }; /** @@ -152,12 +153,13 @@ class Elf { /** * 加载 elf 内核 - * @return 内核入口点 + * @return 成功返回内核入口地址,失败返回 0 */ [[nodiscard]] auto load_kernel_image() const -> uint64_t; /** * 将 elf 文件加载进内存 + * @return 成功返回内核入口地址,失败返回 0 */ auto load() const -> uintptr_t; @@ -229,12 +231,13 @@ class Elf { * 将 elf 段加载到内存 * @param _phdr 要加载的程序段 phdr */ - void load_sections(const Elf64_Phdr &_phdr) const; + bool load_sections(const Elf64_Phdr &_phdr) const; /** * 加载程序段 + * @return 失败返回 false */ - void load_program_sections() const; + bool load_program_sections() const; }; #endif /* SIMPLEKERNEL_LOAD_ELF_H */ diff --git a/src/boot/load_elf.cpp b/src/boot/load_elf.cpp index 243dcbeba..eb6891fda 100644 --- a/src/boot/load_elf.cpp +++ b/src/boot/load_elf.cpp @@ -55,16 +55,16 @@ Elf::Elf(wchar_t *_kernel_image_filename) { status = LibLocateProtocol(&FileSystemProtocol, reinterpret_cast(&file_system_protocol)); if (EFI_ERROR(status)) { - debug << L"LibLocateProtocol failed: " << status << ostream::endl; - throw std::runtime_error("EFI_ERROR(status)"); + debug << L"Elf::Elf LibLocateProtocol failed: " << status << ostream::endl; + return; } // 打开根文件系统 status = uefi_call_wrapper(file_system_protocol->OpenVolume, 2, file_system_protocol, &root_file_system); if (EFI_ERROR(status)) { - debug << L"OpenVolume failed: " << status << ostream::endl; - throw std::runtime_error("EFI_ERROR(status)"); + debug << L"Elf::Elf OpenVolume failed: " << status << ostream::endl; + return; } // 打开 elf 文件 @@ -73,17 +73,12 @@ Elf::Elf(wchar_t *_kernel_image_filename) { EFI_FILE_READ_ONLY); if (EFI_ERROR(status)) { - debug << L"Open failed: " << status << ostream::endl; - throw std::runtime_error("EFI_ERROR(status)"); + debug << L"Elf::Elf Open failed: " << status << ostream::endl; + return; } // 获取 elf 文件大小 - try { - elf_file_size = get_file_size(); - } catch (std::runtime_error &_e) { - debug << L"get_file_size failed: " << _e.what() << ostream::endl; - throw std::runtime_error(_e.what()); - } + elf_file_size = get_file_size(); debug << L"Kernel file size: " << elf_file_size << ostream::endl; // 分配 elf 文件缓存 @@ -91,16 +86,16 @@ Elf::Elf(wchar_t *_kernel_image_filename) { &elf_file_buffer); if (EFI_ERROR(status)) { - debug << L"AllocatePool failed: " << status << ostream::endl; - throw std::runtime_error("EFI_ERROR(status)"); + debug << L"Elf::Elf AllocatePool failed: " << status << ostream::endl; + return; } // 将内核文件读入内存 status = uefi_call_wrapper(elf->Read, 3, (EFI_FILE *)elf, &elf_file_size, elf_file_buffer); if (EFI_ERROR(status)) { - debug << L"Read failed: " << status << ostream::endl; - throw std::runtime_error("EFI_ERROR(status)"); + debug << L"Elf::Elf Read failed: " << status << ostream::endl; + return; } file = std::span(static_cast(elf_file_buffer), @@ -109,8 +104,8 @@ Elf::Elf(wchar_t *_kernel_image_filename) { // 检查 elf 头数据 auto check_elf_identity_ret = check_elf_identity(); if (!check_elf_identity_ret) { - debug << L"NOT valid ELF file" << ostream::endl; - throw std::runtime_error("check_elf_identity_ret == false"); + debug << L"Elf::Elf NOT valid ELF file" << ostream::endl; + return; } // 读取 ehdr @@ -125,52 +120,49 @@ Elf::Elf(wchar_t *_kernel_image_filename) { } Elf::~Elf() { - try { - EFI_STATUS status = EFI_SUCCESS; - // 关闭 elf 文件 - status = uefi_call_wrapper(elf->Close, 1, elf); - if (EFI_ERROR(status)) { - debug << L"Close failed: " << status << ostream::endl; - throw std::runtime_error("EFI_ERROR(status)"); - } - /// @note elf_file_buffer 不会被释放 - } catch (std::runtime_error &_e) { - debug << L"~Elf failed: " << _e.what() << ostream::endl; + EFI_STATUS status = EFI_SUCCESS; + // 关闭 elf 文件 + status = uefi_call_wrapper(elf->Close, 1, elf); + if (EFI_ERROR(status)) { + debug << L"Elf::~Elf() Close failed: " << status << ostream::endl; + return; } + /// @note elf_file_buffer 不会被释放 } auto Elf::load_kernel_image() const -> uint64_t { uintptr_t image_base = 0; uintptr_t image_begin = 0; - try { - // load_program_sections(); - size_t size = 0; - for (uint64_t i = 0; i < ehdr.e_phnum; i++) { - if (phdr[i].p_type != PT_LOAD) { - continue; - } - phdr[i].p_vaddr; - size += phdr[i].p_memsz; - } - auto section_page_count = EFI_SIZE_TO_PAGES(size); - auto status = - uefi_call_wrapper(gBS->AllocatePages, 4, AllocateAnyPages, - EfiLoaderCode, section_page_count, &image_base); - if (EFI_ERROR(status)) { - debug << L"AllocatePages failed: " << status << ostream::endl; - throw std::runtime_error("EFI_ERROR(status)"); - } - for (auto &i : phdr) { - if (i.p_type != PT_LOAD) { - continue; - } - memcpy((void *)(image_base + i.p_vaddr), file.data() + i.p_offset, - i.p_memsz); + // auto load_program_sections_ret = load_program_sections(); + // if (!load_program_sections_ret) { + // debug << L"load_program_sections failed" << ostream::endl; + // return 0; + // } + size_t size = 0; + for (uint64_t i = 0; i < ehdr.e_phnum; i++) { + if (phdr[i].p_type != PT_LOAD) { + continue; } + phdr[i].p_vaddr; + size += phdr[i].p_memsz; + } + auto section_page_count = EFI_SIZE_TO_PAGES(size); + auto status = + uefi_call_wrapper(gBS->AllocatePages, 4, AllocateAnyPages, EfiLoaderCode, + section_page_count, &image_base); + if (EFI_ERROR(status)) { + debug << L"Elf::load_kernel_image() AllocatePages failed: " << status + << ostream::endl; + return 0; + } - } catch (std::runtime_error &_e) { - debug << L"load_kernel_image: " << _e.what() << ostream::endl; + for (auto &i : phdr) { + if (i.p_type != PT_LOAD) { + continue; + } + memcpy((void *)(image_base + i.p_vaddr), file.data() + i.p_offset, + i.p_memsz); } debug << L"load_kernel_image: " << ostream::hex_X << image_base << L" " << ostream::hex_X << ehdr.e_entry << L" " << ostream::hex_X @@ -189,8 +181,8 @@ auto Elf::load() const -> uintptr_t { uefi_call_wrapper(gBS->AllocatePages, 4, AllocateAnyPages, EfiLoaderCode, section_page_count, &image_base); if (EFI_ERROR(status)) { - debug << L"AllocatePages failed: " << status << ostream::endl; - throw std::runtime_error("EFI_ERROR(status)"); + debug << L"Elf::load() AllocatePages failed: " << status << ostream::endl; + return 0; } // 将 elf 复制到分配的物理内存中 std::memcpy(reinterpret_cast(image_base), file.data(), @@ -813,7 +805,7 @@ void Elf::print_shdr() const { } } -void Elf::load_sections(const Elf64_Phdr &_phdr) const { +bool Elf::load_sections(const Elf64_Phdr &_phdr) const { EFI_STATUS status = EFI_SUCCESS; void *data = nullptr; // 计算使用的内存页数 @@ -822,8 +814,9 @@ void Elf::load_sections(const Elf64_Phdr &_phdr) const { // 设置文件偏移到 p_offset status = uefi_call_wrapper(elf->SetPosition, 2, elf, _phdr.p_offset); if (EFI_ERROR(status)) { - debug << L"SetPosition failed: " << status << ostream::endl; - throw std::runtime_error("memory_map == nullptr"); + debug << L"Elf::load_sections SetPosition failed: " << status + << ostream::endl; + return false; } uintptr_t aaa = 0; // status = uefi_call_wrapper(gBS->AllocatePages, 4, AllocateAddress, @@ -834,9 +827,9 @@ void Elf::load_sections(const Elf64_Phdr &_phdr) const { debug << L"_phdr.p_paddr: [" << status << L"] [" << section_page_count << L"] " << ostream::hex_X << aaa << ostream::endl; if (EFI_ERROR(status)) { - debug << L"AllocatePages AllocateAddress failed: " << status - << ostream::endl; - throw std::runtime_error("EFI_ERROR(status)"); + debug << L"Elf::load_sections AllocatePages AllocateAddress failed: " + << status << ostream::endl; + return false; } if (_phdr.p_filesz > 0) { @@ -845,15 +838,16 @@ void Elf::load_sections(const Elf64_Phdr &_phdr) const { status = uefi_call_wrapper(gBS->AllocatePool, 3, EfiLoaderCode, buffer_read_size, (void **)&data); if (EFI_ERROR(status)) { - debug << L"AllocatePool failed: " << status << ostream::endl; - throw std::runtime_error("EFI_ERROR(status)"); + debug << L"Elf::load_sections AllocatePool failed: " << status + << ostream::endl; + return false; } // 读数据 status = uefi_call_wrapper(elf->Read, 3, elf, &buffer_read_size, (void *)data); if (EFI_ERROR(status)) { - debug << L"Read failed: " << status << ostream::endl; - throw std::runtime_error("EFI_ERROR(status)"); + debug << L"Elf::load_sections Read failed: " << status << ostream::endl; + return false; } // 将读出来的数据复制到其对应的物理地址 @@ -864,8 +858,9 @@ void Elf::load_sections(const Elf64_Phdr &_phdr) const { // 释放 program_data status = uefi_call_wrapper(gBS->FreePool, 1, data); if (EFI_ERROR(status)) { - debug << L"FreePool failed: " << status << ostream::endl; - throw std::runtime_error("EFI_ERROR(status)"); + debug << L"Elf::load_sections FreePool failed: " << status + << ostream::endl; + return false; } } @@ -881,21 +876,21 @@ void Elf::load_sections(const Elf64_Phdr &_phdr) const { // 将填充部分置 0 uefi_call_wrapper(gBS->SetMem, 3, zero_fill_start, zero_fill_count, 0); } + return true; } -void Elf::load_program_sections() const { - uint64_t loaded = 0; +bool Elf::load_program_sections() const { for (uint64_t i = 0; i < ehdr.e_phnum; i++) { if (phdr[i].p_type != PT_LOAD) { continue; } - load_sections(phdr[i]); - loaded++; + auto load_sections_ret = load_sections(phdr[i]); + if (!load_sections_ret) { + debug << L"Elf::load_program_sections() load_sections failed " << i + << ostream::endl; + return false; + } } - if (loaded == 0) { - debug << L"Fatal Error: No loadable program segments found in Kernel image " - << ostream::endl; - throw std::runtime_error("loaded == 0"); - } + return true; } diff --git a/src/boot/memory.cpp b/src/boot/memory.cpp index 89e3de9ea..b1ef5e6ba 100644 --- a/src/boot/memory.cpp +++ b/src/boot/memory.cpp @@ -14,23 +14,33 @@ * */ -#include - #include "load_elf.h" #include "ostream.hpp" -void Memory::flush_desc() { +bool Memory::flush_desc() { memory_map = LibMemoryMap(&desc_count, &map_key, &desc_size, &desc_version); if (memory_map == nullptr) { debug << L"LibMemoryMap failed: memory_map == nullptr" << ostream::endl; - throw std::runtime_error("memory_map == nullptr"); + return false; } + return true; } -Memory::Memory() { flush_desc(); } +Memory::Memory() { + auto flush_desc_ret = flush_desc(); + if (!flush_desc_ret) { + debug << L"Memory::Memory() flush_desc failed." << ostream::endl; + return; + } +} void Memory::print_info() { - flush_desc(); + auto flush_desc_ret = flush_desc(); + if (!flush_desc_ret) { + debug << L"Memory::print_info() flush_desc failed." << ostream::endl; + return; + } + debug << L"Type\t\t\t\tPages\tPhysicalStart\tVirtualStart\tAttribute" << ostream::endl; for (uint64_t i = 0; i < desc_count; i++) {