Clean-up loader and added fetching of the memory map.
This commit is contained in:
parent
8f6cc36637
commit
bf8949113b
@ -82,6 +82,10 @@ void* malloc(size_t size) noexcept
|
||||
{
|
||||
prevBlock->nextBlock = newBlock;
|
||||
}
|
||||
else
|
||||
{
|
||||
gNextBlock = newBlock;
|
||||
}
|
||||
AllocInfo* allocInfo = reinterpret_cast<AllocInfo*>(block);
|
||||
allocInfo->elements = requiredElements;
|
||||
return reinterpret_cast<max_align_t*>(block) + 1;
|
||||
|
@ -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
|
||||
|
66
targets/x86_64/include/boot.hpp
Normal file
66
targets/x86_64/include/boot.hpp
Normal file
@ -0,0 +1,66 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(BOOT_HPP_INCLUDED)
|
||||
#define BOOT_HPP_INCLUDED 1
|
||||
|
||||
#include <efi.h>
|
||||
|
||||
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<EFI_MEMORY_DESCRIPTOR*>(reinterpret_cast<UINT64>(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<EFI_MEMORY_DESCRIPTOR*>(reinterpret_cast<UINT64>(map) + totalMapSize),
|
||||
descriptorSize
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
#endif // BOOT_HPP_INCLUDED
|
@ -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
|
||||
|
@ -1,17 +1,17 @@
|
||||
|
||||
#include "os/tty.hpp"
|
||||
|
||||
#include <cassert>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#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<uint64_t>(&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<initfunc_t*>(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();
|
||||
|
||||
|
@ -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;
|
@ -2,14 +2,21 @@
|
||||
extern "C"
|
||||
{
|
||||
#include <efi.h>
|
||||
#include <efilib.h>
|
||||
}
|
||||
#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<void**>(&loadedImage));
|
||||
EFI_STATUS status = gBootServices->HandleProtocol(image, &lipGuid, reinterpret_cast<void**>(&loadedImage));
|
||||
if (EFI_ERROR(status)) {
|
||||
return status;
|
||||
}
|
||||
status = BS->HandleProtocol(loadedImage->DeviceHandle, &fsGuid, reinterpret_cast<void**>(&ioVolume));
|
||||
status = gBootServices->HandleProtocol(loadedImage->DeviceHandle, &fsGuid, reinterpret_cast<void**>(&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<CHAR16*>(text));
|
||||
gSystemTable->ConOut->OutputString(gSystemTable->ConOut, const_cast<CHAR16*>(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<EFI_FILE_INFO*>(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<EFI_MEMORY_DESCRIPTOR*>(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<int>(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<int>(header.type));
|
||||
printf("entry: 0x%X\n", static_cast<unsigned>(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<int>(programHeader.type));
|
||||
printf(" flags: %d\n", static_cast<int>(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<int>(programHeader.fileSize));
|
||||
printf(" memSize: %d\n", static_cast<int>(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<void*>(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<EFI_MEMORY_TYPE>(descriptor->Type))) {
|
||||
if (descriptor.Type != EfiConventionalMemory) {
|
||||
continue;
|
||||
}
|
||||
printf(
|
||||
"Entry %d: type: %d, physicalStart: 0x%lX, numberOfPages: %ld\n",
|
||||
entry,
|
||||
static_cast<int>(descriptor.Type),
|
||||
static_cast<unsigned long>(descriptor.PhysicalStart),
|
||||
static_cast<long>(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;
|
||||
|
@ -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 <stdint.h>
|
||||
|
||||
@ -107,4 +107,4 @@ struct Efi64ProgramHeader
|
||||
uint64_t align;
|
||||
} __attribute__((packed));
|
||||
|
||||
#endif // MINIEFI_HPP_INCLUDED
|
||||
#endif // MINIELF_HPP_INCLUDED
|
@ -52,7 +52,8 @@ void* malloc(size_t size) noexcept
|
||||
newBlock = reinterpret_cast<MallocBlock*>(reinterpret_cast<max_align_t*>(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<AllocInfo*>(block);
|
||||
allocInfo->elements = requiredElements;
|
||||
return reinterpret_cast<max_align_t*>(block) + 1;
|
||||
|
@ -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.");
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user