From bf8949113bf5f6d10c612e4960e195d5bbd3861a Mon Sep 17 00:00:00 2001 From: Patrick Wuttke Date: Mon, 15 Jan 2024 14:21:25 +0100 Subject: [PATCH] Clean-up loader and added fetching of the memory map. --- targets/_any/src/cstdlib/stdlib.cpp | 4 + targets/x86_64/SConscript | 5 +- targets/x86_64/include/boot.hpp | 66 ++++++ targets/x86_64/src/kernel/boot.s | 4 +- targets/x86_64/src/kernel/startup.cpp | 16 +- targets/x86_64/src/loader/data.c | 218 ------------------ targets/x86_64/src/loader/main.cpp | 133 +++++++++-- .../src/loader/{miniefi.hpp => minielf.hpp} | 6 +- targets/x86_64/src/loader/minimalloc.cpp | 7 +- targets/x86_64/src/loader/miniprintf.cpp | 1 + targets/x86_64/src/loader/miniprintf.hpp | 2 +- 11 files changed, 210 insertions(+), 252 deletions(-) create mode 100644 targets/x86_64/include/boot.hpp delete mode 100644 targets/x86_64/src/loader/data.c rename targets/x86_64/src/loader/{miniefi.hpp => minielf.hpp} (94%) diff --git a/targets/_any/src/cstdlib/stdlib.cpp b/targets/_any/src/cstdlib/stdlib.cpp index fda76ad..6780b56 100644 --- a/targets/_any/src/cstdlib/stdlib.cpp +++ b/targets/_any/src/cstdlib/stdlib.cpp @@ -82,6 +82,10 @@ void* malloc(size_t size) noexcept { prevBlock->nextBlock = newBlock; } + else + { + gNextBlock = newBlock; + } AllocInfo* allocInfo = reinterpret_cast(block); allocInfo->elements = requiredElements; return reinterpret_cast(block) + 1; diff --git a/targets/x86_64/SConscript b/targets/x86_64/SConscript index 282c419..ce738bc 100644 --- a/targets/x86_64/SConscript +++ b/targets/x86_64/SConscript @@ -10,7 +10,7 @@ kernel_env['LD'] = 'x86_64-elf-g++' kernel_env.Append(CFLAGS = ['-ffreestanding']) kernel_env.Append(CXXFLAGS = ['-ffreestanding', '-fno-exceptions', '-fno-rtti', '-std=c++20']) kernel_env.Append(LINKFLAGS = ['-T', kernel_env.File('linker.ld').abspath, '-ffreestanding', '-nostdlib', '-mcmodel=large', '-mno-red-zone', '-mno-mmx', '-mno-sse', '-mno-sse2']) -kernel_env.Append(CPPPATH = ['#targets/_any/include', '#bastl/include']) +kernel_env.Append(CPPPATH = ['#targets/_any/include', '#bastl/include', 'include', '/usr/include/efi']) def get_crt_object(name: str) -> str: import subprocess @@ -65,10 +65,9 @@ uefi_env['LD'] = 'x86_64-w64-mingw32-g++' uefi_env.Append(CFLAGS = ['-ffreestanding']) uefi_env.Append(CXXFLAGS = ['-ffreestanding', '-fno-exceptions', '-fno-rtti', '-std=c++20']) uefi_env.Append(LINKFLAGS = ['-nostdlib', '-Wl,-dll', '-shared', '-Wl,--subsystem,10', '-e', 'efi_main']) -uefi_env.Append(CPPPATH = ['/usr/include/efi']) +uefi_env.Append(CPPPATH = ['/usr/include/efi', 'include']) loader_sources = Split(''' - src/loader/data.c src/loader/main.cpp src/loader/minimalloc.cpp src/loader/miniprintf.cpp diff --git a/targets/x86_64/include/boot.hpp b/targets/x86_64/include/boot.hpp new file mode 100644 index 0000000..e02b6c9 --- /dev/null +++ b/targets/x86_64/include/boot.hpp @@ -0,0 +1,66 @@ + +#pragma once + +#if !defined(BOOT_HPP_INCLUDED) +#define BOOT_HPP_INCLUDED 1 + +#include + +class EfiMemoryMapIterator +{ +private: + EFI_MEMORY_DESCRIPTOR* mDescriptor; + UINTN mDescriptorSize; +public: + EfiMemoryMapIterator(EFI_MEMORY_DESCRIPTOR* descriptor, UINTN descriptorSize) noexcept : mDescriptor(descriptor), mDescriptorSize(descriptorSize) {} + EfiMemoryMapIterator(const EfiMemoryMapIterator&) noexcept = default; + + EfiMemoryMapIterator& operator=(const EfiMemoryMapIterator&) noexcept = default; + + bool operator==(const EfiMemoryMapIterator& other) const noexcept + { + return mDescriptor == other.mDescriptor && mDescriptorSize == other.mDescriptorSize; + } + bool operator!=(const EfiMemoryMapIterator& other) const noexcept + { + return !(*this == other); + } + + EFI_MEMORY_DESCRIPTOR& operator*() const noexcept { return *mDescriptor; } + EfiMemoryMapIterator& operator++() noexcept + { + mDescriptor = reinterpret_cast(reinterpret_cast(mDescriptor) + mDescriptorSize); + return *this; + } + EfiMemoryMapIterator operator++(int) noexcept + { + EfiMemoryMapIterator copy(*this); + ++(*this); + return copy; + } +}; + +struct EfiMemoryMap +{ + UINTN mapSize = 0; + EFI_MEMORY_DESCRIPTOR* map = nullptr; + UINTN mapKey = 0; + UINTN descriptorSize = 0; + UINT32 descriptorVersion = 0; + + EfiMemoryMapIterator begin() const noexcept + { + return EfiMemoryMapIterator(map, descriptorSize); + } + EfiMemoryMapIterator end() const noexcept + { + // just in case + const UINTN totalMapSize = (mapSize / descriptorSize) * descriptorSize; + return EfiMemoryMapIterator( + reinterpret_cast(reinterpret_cast(map) + totalMapSize), + descriptorSize + ); + } +}; + +#endif // BOOT_HPP_INCLUDED diff --git a/targets/x86_64/src/kernel/boot.s b/targets/x86_64/src/kernel/boot.s index c89fb4f..deb3204 100644 --- a/targets/x86_64/src/kernel/boot.s +++ b/targets/x86_64/src/kernel/boot.s @@ -11,8 +11,8 @@ stack_top: .global _start .type _start, @function _start: - // store the multiboot info - mov %rbx, (gMultibootHeader) + // store the memory map + mov %rbx, (gMemoryMap) // setup stack mov $stack_top, %rsp diff --git a/targets/x86_64/src/kernel/startup.cpp b/targets/x86_64/src/kernel/startup.cpp index 7c41c22..d39a002 100644 --- a/targets/x86_64/src/kernel/startup.cpp +++ b/targets/x86_64/src/kernel/startup.cpp @@ -1,17 +1,17 @@ #include "os/tty.hpp" -#include #include #include -#include "./multiboot.h" +#include "boot.hpp" extern "C" int gKernelEnd; namespace { -void initHeapFromMultibootHeader(const uint32_t firstEntryAddr, const size_t bufferLength) noexcept +void initHeapFromEfiMemoryMap(const EfiMemoryMap& memoryMap) noexcept { +#if 0 const uint64_t minAddr = reinterpret_cast(&gKernelEnd); for (uint32_t addr = firstEntryAddr; addr < firstEntryAddr + bufferLength;) { @@ -39,15 +39,16 @@ void initHeapFromMultibootHeader(const uint32_t firstEntryAddr, const size_t buf } addr += sizeof(entry.size) + entry.size; } +#endif } using initfunc_t = void *(); -extern "C" initfunc_t** start_ctors; -extern "C" initfunc_t** end_ctors; +extern "C" initfunc_t* start_ctors; +extern "C" initfunc_t* end_ctors; void initGlobals() { - for (initfunc_t** initFunc = start_ctors; initFunc != end_ctors; ++initFunc) + for (initfunc_t** initFunc = &start_ctors; initFunc != &end_ctors; ++initFunc) { // TODO: this confuses me if (*initFunc == reinterpret_cast(0xffffffffffffffff)) { @@ -60,7 +61,7 @@ void initGlobals() extern "C" { -multiboot_info_t* gMultibootHeader; +EfiMemoryMap* gMemoryMap; void _init(); void _fini(); @@ -78,6 +79,7 @@ void kernel_main() /* Initialize the heap */ // assert(gMultibootHeader->flags & MULTIBOOT_INFO_MEM_MAP); // initHeapFromMultibootHeader(gMultibootHeader->mmap_addr, gMultibootHeader->mmap_length); + initHeapFromEfiMemoryMap(*gMemoryMap); main(); diff --git a/targets/x86_64/src/loader/data.c b/targets/x86_64/src/loader/data.c deleted file mode 100644 index bc14572..0000000 --- a/targets/x86_64/src/loader/data.c +++ /dev/null @@ -1,218 +0,0 @@ -/*++ - -Copyright (c) 1998 Intel Corporation - -Module Name: - - data.c - -Abstract: - - EFI library global data - - - -Revision History - ---*/ - -#include "lib.h" - -// -// LibInitialized - TRUE once InitializeLib() is called for the first time -// - -BOOLEAN LibInitialized = FALSE; - -// -// ImageHandle - Current ImageHandle, as passed to InitializeLib -// -EFI_HANDLE LibImageHandle; - -// -// ST - pointer to the EFI system table -// - -EFI_SYSTEM_TABLE *ST; - -// -// BS - pointer to the boot services table -// - -EFI_BOOT_SERVICES *BS; - - -// -// Default pool allocation type -// - -EFI_MEMORY_TYPE PoolAllocationType = EfiBootServicesData; - -// -// Unicode collation functions that are in use -// - -EFI_UNICODE_COLLATION_INTERFACE LibStubUnicodeInterface = { - NULL, // LibStubStriCmp, - NULL, // LibStubMetaiMatch, - NULL, // LibStubStrLwrUpr, - NULL, // LibStubStrLwrUpr, - NULL, // FatToStr - NULL, // StrToFat - NULL // SupportedLanguages -}; - -EFI_UNICODE_COLLATION_INTERFACE *UnicodeInterface = &LibStubUnicodeInterface; - -// -// Root device path -// - -EFI_DEVICE_PATH RootDevicePath[] = { - {END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, {END_DEVICE_PATH_LENGTH,0}} -}; - -EFI_DEVICE_PATH EndDevicePath[] = { - {END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, {END_DEVICE_PATH_LENGTH, 0}} -}; - -EFI_DEVICE_PATH EndInstanceDevicePath[] = { - {END_DEVICE_PATH_TYPE, END_INSTANCE_DEVICE_PATH_SUBTYPE, {END_DEVICE_PATH_LENGTH, 0}} -}; - - -// -// EFI IDs -// - -EFI_GUID gEfiGlobalVariableGuid = EFI_GLOBAL_VARIABLE; -EFI_GUID NullGuid = { 0,0,0,{0,0,0,0,0,0,0,0} }; - -// -// Protocol IDs -// - -EFI_GUID gEfiDevicePathProtocolGuid = EFI_DEVICE_PATH_PROTOCOL_GUID; -EFI_GUID gEfiDevicePathToTextProtocolGuid = EFI_DEVICE_PATH_TO_TEXT_PROTOCOL_GUID; -EFI_GUID gEfiDevicePathFromTextProtocolGuid = EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL_GUID; -EFI_GUID gEfiDevicePathUtilitiesProtocolGuid = EFI_DEVICE_PATH_UTILITIES_PROTOCOL_GUID; -EFI_GUID gEfiLoadedImageProtocolGuid = EFI_LOADED_IMAGE_PROTOCOL_GUID; -EFI_GUID gEfiSimpleTextInProtocolGuid = EFI_SIMPLE_TEXT_INPUT_PROTOCOL_GUID; -EFI_GUID gEfiSimpleTextOutProtocolGuid = EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL_GUID; -EFI_GUID gEfiBlockIoProtocolGuid = EFI_BLOCK_IO_PROTOCOL_GUID; -EFI_GUID gEfiBlockIo2ProtocolGuid = EFI_BLOCK_IO2_PROTOCOL_GUID; -EFI_GUID gEfiDiskIoProtocolGuid = EFI_DISK_IO_PROTOCOL_GUID; -EFI_GUID gEfiDiskIo2ProtocolGuid = EFI_DISK_IO2_PROTOCOL_GUID; -EFI_GUID gEfiSimpleFileSystemProtocolGuid = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID; -EFI_GUID gEfiLoadFileProtocolGuid = EFI_LOAD_FILE_PROTOCOL_GUID; -EFI_GUID gEfiDeviceIoProtocolGuid = EFI_DEVICE_IO_PROTOCOL_GUID; -EFI_GUID gEfiUnicodeCollationProtocolGuid = EFI_UNICODE_COLLATION_PROTOCOL_GUID; -EFI_GUID gEfiSerialIoProtocolGuid = EFI_SERIAL_IO_PROTOCOL_GUID; -EFI_GUID gEfiSimpleNetworkProtocolGuid = EFI_SIMPLE_NETWORK_PROTOCOL_GUID; -EFI_GUID gEfiPxeBaseCodeProtocolGuid = EFI_PXE_BASE_CODE_PROTOCOL_GUID; -EFI_GUID gEfiPxeBaseCodeCallbackProtocolGuid = EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL_GUID; -EFI_GUID gEfiNetworkInterfaceIdentifierProtocolGuid = EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_GUID; -EFI_GUID gEFiUiInterfaceProtocolGuid = EFI_UI_INTERFACE_PROTOCOL_GUID; -EFI_GUID gEfiPciIoProtocolGuid = EFI_PCI_IO_PROTOCOL_GUID; -EFI_GUID gEfiPciRootBridgeIoProtocolGuid = EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_GUID; -EFI_GUID gEfiDriverBindingProtocolGuid = EFI_DRIVER_BINDING_PROTOCOL_GUID; -EFI_GUID gEfiComponentNameProtocolGuid = EFI_COMPONENT_NAME_PROTOCOL_GUID; -EFI_GUID gEfiComponentName2ProtocolGuid = EFI_COMPONENT_NAME2_PROTOCOL_GUID; -EFI_GUID gEfiHashProtocolGuid = EFI_HASH_PROTOCOL_GUID; -EFI_GUID gEfiPlatformDriverOverrideProtocolGuid = EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL_GUID; -EFI_GUID gEfiBusSpecificDriverOverrideProtocolGuid = EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL_GUID; -EFI_GUID gEfiDriverFamilyOverrideProtocolGuid = EFI_DRIVER_FAMILY_OVERRIDE_PROTOCOL_GUID; -EFI_GUID gEfiEbcProtocolGuid = EFI_EBC_PROTOCOL_GUID; - -// -// File system information IDs -// - -EFI_GUID gEfiFileInfoGuid = EFI_FILE_INFO_ID; -EFI_GUID gEfiFileSystemInfoGuid = EFI_FILE_SYSTEM_INFO_ID; -EFI_GUID gEfiFileSystemVolumeLabelInfoIdGuid = EFI_FILE_SYSTEM_VOLUME_LABEL_ID; - -// -// Reference implementation public protocol IDs -// - -EFI_GUID InternalShellProtocol = INTERNAL_SHELL_GUID; -EFI_GUID VariableStoreProtocol = VARIABLE_STORE_PROTOCOL; -EFI_GUID LegacyBootProtocol = LEGACY_BOOT_PROTOCOL; -EFI_GUID VgaClassProtocol = VGA_CLASS_DRIVER_PROTOCOL; - -EFI_GUID TextOutSpliterProtocol = TEXT_OUT_SPLITER_PROTOCOL; -EFI_GUID ErrorOutSpliterProtocol = ERROR_OUT_SPLITER_PROTOCOL; -EFI_GUID TextInSpliterProtocol = TEXT_IN_SPLITER_PROTOCOL; -/* Added for GOP support */ -EFI_GUID gEfiGraphicsOutputProtocolGuid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID; -EFI_GUID gEfiEdidDiscoveredProtocolGuid = EFI_EDID_DISCOVERED_PROTOCOL_GUID; -EFI_GUID gEfiEdidActiveProtocolGuid = EFI_EDID_ACTIVE_PROTOCOL_GUID; -EFI_GUID gEfiEdidOverrideProtocolGuid = EFI_EDID_OVERRIDE_PROTOCOL_GUID; - -EFI_GUID AdapterDebugProtocol = ADAPTER_DEBUG_PROTOCOL; - -// -// Device path media protocol IDs -// -EFI_GUID gEfiPcAnsiGuid = EFI_PC_ANSI_GUID; -EFI_GUID gEfiVT100Guid = EFI_VT_100_GUID; -EFI_GUID gEfiVT100PlusGuid = EFI_VT_100_PLUS_GUID; -EFI_GUID gEfiVTUTF8Guid = EFI_VT_UTF8_GUID; - -// -// EFI GPT Partition Type GUIDs -// -EFI_GUID EfiPartTypeSystemPartitionGuid = EFI_PART_TYPE_EFI_SYSTEM_PART_GUID; -EFI_GUID EfiPartTypeLegacyMbrGuid = EFI_PART_TYPE_LEGACY_MBR_GUID; - - -// -// Reference implementation Vendor Device Path Guids -// -EFI_GUID UnknownDevice = UNKNOWN_DEVICE_GUID; - -// -// Configuration Table GUIDs -// - -EFI_GUID MpsTableGuid = MPS_TABLE_GUID; -EFI_GUID AcpiTableGuid = ACPI_TABLE_GUID; -EFI_GUID SMBIOSTableGuid = SMBIOS_TABLE_GUID; -EFI_GUID SMBIOS3TableGuid = SMBIOS3_TABLE_GUID; -EFI_GUID SalSystemTableGuid = SAL_SYSTEM_TABLE_GUID; -EFI_GUID EfiDtbTableGuid = EFI_DTB_TABLE_GUID; - -// -// Network protocol GUIDs -// -EFI_GUID Ip4ServiceBindingProtocol = EFI_IP4_SERVICE_BINDING_PROTOCOL; -EFI_GUID Ip4Protocol = EFI_IP4_PROTOCOL; -EFI_GUID Udp4ServiceBindingProtocol = EFI_UDP4_SERVICE_BINDING_PROTOCOL; -EFI_GUID Udp4Protocol = EFI_UDP4_PROTOCOL; -EFI_GUID Tcp4ServiceBindingProtocol = EFI_TCP4_SERVICE_BINDING_PROTOCOL; -EFI_GUID Tcp4Protocol = EFI_TCP4_PROTOCOL; - -// -// Pointer protocol GUIDs -// -EFI_GUID SimplePointerProtocol = EFI_SIMPLE_POINTER_PROTOCOL_GUID; -EFI_GUID AbsolutePointerProtocol = EFI_ABSOLUTE_POINTER_PROTOCOL_GUID; - -// -// Debugger protocol GUIDs -// -EFI_GUID gEfiDebugImageInfoTableGuid = EFI_DEBUG_IMAGE_INFO_TABLE_GUID; -EFI_GUID gEfiDebugSupportProtocolGuid = EFI_DEBUG_SUPPORT_PROTOCOL_GUID; - -// -// Console extension protocol GUIDs -// -EFI_GUID SimpleTextInputExProtocol = EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID; - -// -// Shell protocol GUIDs -// -EFI_GUID ShellProtocolGuid = EFI_SHELL_PROTOCOL_GUID; -EFI_GUID ShellParametersProtocolGuid = EFI_SHELL_PARAMETERS_PROTOCOL_GUID; -EFI_GUID ShellDynamicCommandProtocolGuid = EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL_GUID; diff --git a/targets/x86_64/src/loader/main.cpp b/targets/x86_64/src/loader/main.cpp index c87c0a0..881ed47 100644 --- a/targets/x86_64/src/loader/main.cpp +++ b/targets/x86_64/src/loader/main.cpp @@ -2,14 +2,21 @@ extern "C" { #include -#include } -#include "miniefi.hpp" +#include "boot.hpp" +#include "minielf.hpp" #include "minimalloc.hpp" #include "miniprintf.hpp" +// debug stuff +// #define DUMP_MEMORY_MAP +// #define DUMP_ELF + namespace { +EFI_SYSTEM_TABLE* gSystemTable; +EFI_BOOT_SERVICES* gBootServices; + EFI_STATUS openImageVolume(EFI_HANDLE image, EFI_FILE_HANDLE& outHandle) { EFI_LOADED_IMAGE* loadedImage = nullptr; @@ -18,11 +25,11 @@ EFI_STATUS openImageVolume(EFI_HANDLE image, EFI_FILE_HANDLE& outHandle) EFI_GUID fsGuid = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID; EFI_FILE_HANDLE volume = nullptr; - EFI_STATUS status = BS->HandleProtocol(image, &lipGuid, reinterpret_cast(&loadedImage)); + EFI_STATUS status = gBootServices->HandleProtocol(image, &lipGuid, reinterpret_cast(&loadedImage)); if (EFI_ERROR(status)) { return status; } - status = BS->HandleProtocol(loadedImage->DeviceHandle, &fsGuid, reinterpret_cast(&ioVolume)); + status = gBootServices->HandleProtocol(loadedImage->DeviceHandle, &fsGuid, reinterpret_cast(&ioVolume)); if (EFI_ERROR(status)) { return status; } @@ -37,7 +44,7 @@ EFI_STATUS openImageVolume(EFI_HANDLE image, EFI_FILE_HANDLE& outHandle) void print(const CHAR16* text) { - ST->ConOut->OutputString(ST->ConOut, const_cast(text)); + gSystemTable->ConOut->OutputString(gSystemTable->ConOut, const_cast(text)); } void putchar(char c) @@ -58,14 +65,14 @@ void waitForKey() EFI_INPUT_KEY Key; // reset input buffer to flush previous key strokes - EFI_STATUS status = ST->ConIn->Reset(ST->ConIn, FALSE); + EFI_STATUS status = gSystemTable->ConIn->Reset(gSystemTable->ConIn, FALSE); if (EFI_ERROR(status)) { return; } // now wait for a key - while ((status = ST->ConIn->ReadKeyStroke(ST->ConIn, &Key)) == EFI_NOT_READY); + while ((status = gSystemTable->ConIn->ReadKeyStroke(gSystemTable->ConIn, &Key)) == EFI_NOT_READY); } void printAndWait(const CHAR16* text) @@ -95,6 +102,60 @@ EFI_STATUS getEfiFileInfo(EFI_FILE_HANDLE fileHandle, EFI_FILE_INFO*& outFileInf outFileInfo = static_cast(buffer); return EFI_SUCCESS; } + +EFI_STATUS getEfiMemoryMap(EfiMemoryMap& outMemoryMap) +{ + UINTN mapSize = 0; + EFI_MEMORY_DESCRIPTOR* map = nullptr; + UINTN mapKey = 0; + UINTN descriptorSize = 0; + UINT32 descriptorVersion = 0; + EFI_STATUS status = gBootServices->GetMemoryMap(&mapSize, nullptr, &mapKey, &descriptorSize, &descriptorVersion); + if (status != EFI_BUFFER_TOO_SMALL) { + return status; + } + map = static_cast(malloc(mapSize)); + if (map == nullptr) { + return EFI_OUT_OF_RESOURCES; + } + status = gBootServices->GetMemoryMap(&mapSize, map, &mapKey, &descriptorSize, &descriptorVersion); + if (EFI_ERROR(status)) + { + free(map); + return status; + } + outMemoryMap.mapSize = mapSize; + outMemoryMap.map = map; + outMemoryMap.mapKey = mapKey; + outMemoryMap.descriptorSize = descriptorSize; + outMemoryMap.descriptorVersion = descriptorVersion; + return EFI_SUCCESS; +} + +bool isEfiMemoryTypeUsable(EFI_MEMORY_TYPE type) +{ + switch (type) + { + case EfiLoaderCode: + case EfiLoaderData: + case EfiBootServicesCode: + case EfiBootServicesData: + case EfiConventionalMemory: + return true; + case EfiReservedMemoryType: + case EfiRuntimeServicesCode: + case EfiRuntimeServicesData: + case EfiUnusableMemory: + case EfiACPIReclaimMemory: + case EfiACPIMemoryNVS: + case EfiMemoryMappedIO: + case EfiMemoryMappedIOPortSpace: + case EfiPalCode: + case EfiMaxMemoryType: + default: + return false; + } +} } #define DIE_ON_ERROR(message) \ @@ -107,13 +168,13 @@ if (EFI_ERROR(status)) \ extern "C" EFI_STATUS efi_main(EFI_HANDLE imageHandle, EFI_SYSTEM_TABLE* systemTable) { /* Store the system table for future use in other functions */ - ST = systemTable; - BS = systemTable->BootServices; + gSystemTable = systemTable; + gBootServices = systemTable->BootServices; initMiniMalloc(); initMiniPrintf(&putchar); - ST->ConOut->ClearScreen(ST->ConOut); + gSystemTable->ConOut->ClearScreen(gSystemTable->ConOut); EFI_FILE_HANDLE volume; EFI_STATUS status = openImageVolume(imageHandle, volume); @@ -126,16 +187,20 @@ extern "C" EFI_STATUS efi_main(EFI_HANDLE imageHandle, EFI_SYSTEM_TABLE* systemT EFI_FILE_INFO* info = nullptr; status = getEfiFileInfo(fileHandle, info); DIE_ON_ERROR(L"Error getting file info."); - printf("File size: %d.\n", static_cast(info->FileSize)); free(info); Elf64Header header = {}; UINTN bufferSize = sizeof(Elf64Header); status = fileHandle->Read(fileHandle, &bufferSize, &header); - DIE_ON_ERROR("Error reading EFI64 header."); + DIE_ON_ERROR("Error reading ELF64 header."); + +#if defined(DUMP_ELF) printf("headerSize: %d\n", static_cast(header.type)); printf("entry: 0x%X\n", static_cast(header.entry)); +#endif // defined(DUMP_ELF) + // TODO: we currently just assume we can write at that memory location (2M) without checking + // shouldn't be too much of a problem but may be at some point for (uint16_t phtEntry = 0; phtEntry < header.phtEntryCount; ++phtEntry) { status = fileHandle->SetPosition(fileHandle, header.phtOffset + phtEntry * header.phtEntrySize); @@ -143,7 +208,8 @@ extern "C" EFI_STATUS efi_main(EFI_HANDLE imageHandle, EFI_SYSTEM_TABLE* systemT Efi64ProgramHeader programHeader = {}; bufferSize = sizeof(Efi64ProgramHeader); status = fileHandle->Read(fileHandle, &bufferSize, &programHeader); - DIE_ON_ERROR("Error reading EFI64 program header."); + DIE_ON_ERROR("Error reading ELF64 program header."); +#if defined(DUMP_ELF) printf("Program Header %d:\n", phtEntry); printf(" type: %d\n", static_cast(programHeader.type)); printf(" flags: %d\n", static_cast(programHeader.flags)); @@ -151,27 +217,60 @@ extern "C" EFI_STATUS efi_main(EFI_HANDLE imageHandle, EFI_SYSTEM_TABLE* systemT printf(" paddr: 0x%X\n", programHeader.paddr); printf(" fileSize: %d\n", static_cast(programHeader.fileSize)); printf(" memSize: %d\n", static_cast(programHeader.memSize)); +#endif // defined(DUMP_ELF) if (programHeader.type != ElfProgramHeaderType::LOAD) { continue; } - print(L"Loading segment...\r\n"); status = fileHandle->SetPosition(fileHandle, programHeader.offset); - DIE_ON_ERROR("Error seeking to EFI64 section."); + DIE_ON_ERROR("Error seeking to ELF64 section."); void* targetAddr = reinterpret_cast(programHeader.paddr); bufferSize = programHeader.fileSize; status = fileHandle->Read(fileHandle, &bufferSize, targetAddr); - DIE_ON_ERROR("Error reading EFI64 section."); + DIE_ON_ERROR("Error reading ELF64 section."); } + EfiMemoryMap* memoryMap = new EfiMemoryMap; + status = getEfiMemoryMap(*memoryMap); + DIE_ON_ERROR("Error getting EFI memory map."); + +#if defined(DUMP_MEMORY_MAP) + int entry = -1; + for (const EFI_MEMORY_DESCRIPTOR& descriptor : *memoryMap) + { + ++entry; + + // if (!isEfiMemoryTypeUsable(static_cast(descriptor->Type))) { + if (descriptor.Type != EfiConventionalMemory) { + continue; + } + printf( + "Entry %d: type: %d, physicalStart: 0x%lX, numberOfPages: %ld\n", + entry, + static_cast(descriptor.Type), + static_cast(descriptor.PhysicalStart), + static_cast(descriptor.NumberOfPages) + ); + } + + // printing may have invalidated the map, get it again + status = getEfiMemoryMap(*memoryMap); + DIE_ON_ERROR("Error getting EFI memory map."); +#undef DUMP_MEMORY_MAP +#endif // defined(DUMP_MEMORY_MAP) + + status = gBootServices->ExitBootServices(imageHandle, memoryMap->mapKey); + DIE_ON_ERROR("Error exiting EFI boot services."); + // up up and away! __asm__ __volatile__ ( "jmp %0" : - : "a"(header.entry) + : "a"(header.entry), "b"(memoryMap) ); + // we should never get here waitForKey(); return EFI_SUCCESS; diff --git a/targets/x86_64/src/loader/miniefi.hpp b/targets/x86_64/src/loader/minielf.hpp similarity index 94% rename from targets/x86_64/src/loader/miniefi.hpp rename to targets/x86_64/src/loader/minielf.hpp index b0d269c..9ec8131 100644 --- a/targets/x86_64/src/loader/miniefi.hpp +++ b/targets/x86_64/src/loader/minielf.hpp @@ -1,8 +1,8 @@ #pragma once -#if !defined(MINIEFI_HPP_INCLUDED) -#define MINIEFI_HPP_INCLUDED 1 +#if !defined(MINIELF_HPP_INCLUDED) +#define MINIELF_HPP_INCLUDED 1 #include @@ -107,4 +107,4 @@ struct Efi64ProgramHeader uint64_t align; } __attribute__((packed)); -#endif // MINIEFI_HPP_INCLUDED +#endif // MINIELF_HPP_INCLUDED diff --git a/targets/x86_64/src/loader/minimalloc.cpp b/targets/x86_64/src/loader/minimalloc.cpp index a1bb875..339f15a 100644 --- a/targets/x86_64/src/loader/minimalloc.cpp +++ b/targets/x86_64/src/loader/minimalloc.cpp @@ -52,7 +52,8 @@ void* malloc(size_t size) noexcept newBlock = reinterpret_cast(reinterpret_cast(block) + requiredElements); newBlock->nextBlock = block->nextBlock; newBlock->elements = block->elements - requiredElements; - } else + } + else { newBlock = block->nextBlock; } @@ -60,6 +61,10 @@ void* malloc(size_t size) noexcept { prevBlock->nextBlock = newBlock; } + else + { + gNextBlock = newBlock; + } AllocInfo* allocInfo = reinterpret_cast(block); allocInfo->elements = requiredElements; return reinterpret_cast(block) + 1; diff --git a/targets/x86_64/src/loader/miniprintf.cpp b/targets/x86_64/src/loader/miniprintf.cpp index afdd27a..261d53f 100644 --- a/targets/x86_64/src/loader/miniprintf.cpp +++ b/targets/x86_64/src/loader/miniprintf.cpp @@ -207,6 +207,7 @@ int vprintf(const char* format, va_list vlist) default: return -1; } + break; default: // TODO // assert(!"Invalid format string, unknown format identifier."); diff --git a/targets/x86_64/src/loader/miniprintf.hpp b/targets/x86_64/src/loader/miniprintf.hpp index ff2f509..092ebcf 100644 --- a/targets/x86_64/src/loader/miniprintf.hpp +++ b/targets/x86_64/src/loader/miniprintf.hpp @@ -11,7 +11,7 @@ using putchar_t = void (*)(char c); void initMiniPrintf(putchar_t putcharFn) noexcept; extern "C" { -int printf(const char* format, ...) noexcept; +int printf(const char* format, ...) noexcept __attribute__((format (printf, 1, 2))); int vprintf(const char* format, va_list vlist); }