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;
|
prevBlock->nextBlock = newBlock;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gNextBlock = newBlock;
|
||||||
|
}
|
||||||
AllocInfo* allocInfo = reinterpret_cast<AllocInfo*>(block);
|
AllocInfo* allocInfo = reinterpret_cast<AllocInfo*>(block);
|
||||||
allocInfo->elements = requiredElements;
|
allocInfo->elements = requiredElements;
|
||||||
return reinterpret_cast<max_align_t*>(block) + 1;
|
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(CFLAGS = ['-ffreestanding'])
|
||||||
kernel_env.Append(CXXFLAGS = ['-ffreestanding', '-fno-exceptions', '-fno-rtti', '-std=c++20'])
|
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(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:
|
def get_crt_object(name: str) -> str:
|
||||||
import subprocess
|
import subprocess
|
||||||
@ -65,10 +65,9 @@ uefi_env['LD'] = 'x86_64-w64-mingw32-g++'
|
|||||||
uefi_env.Append(CFLAGS = ['-ffreestanding'])
|
uefi_env.Append(CFLAGS = ['-ffreestanding'])
|
||||||
uefi_env.Append(CXXFLAGS = ['-ffreestanding', '-fno-exceptions', '-fno-rtti', '-std=c++20'])
|
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(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('''
|
loader_sources = Split('''
|
||||||
src/loader/data.c
|
|
||||||
src/loader/main.cpp
|
src/loader/main.cpp
|
||||||
src/loader/minimalloc.cpp
|
src/loader/minimalloc.cpp
|
||||||
src/loader/miniprintf.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
|
.global _start
|
||||||
.type _start, @function
|
.type _start, @function
|
||||||
_start:
|
_start:
|
||||||
// store the multiboot info
|
// store the memory map
|
||||||
mov %rbx, (gMultibootHeader)
|
mov %rbx, (gMemoryMap)
|
||||||
|
|
||||||
// setup stack
|
// setup stack
|
||||||
mov $stack_top, %rsp
|
mov $stack_top, %rsp
|
||||||
|
@ -1,17 +1,17 @@
|
|||||||
|
|
||||||
#include "os/tty.hpp"
|
#include "os/tty.hpp"
|
||||||
|
|
||||||
#include <cassert>
|
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include "./multiboot.h"
|
#include "boot.hpp"
|
||||||
|
|
||||||
extern "C" int gKernelEnd;
|
extern "C" int gKernelEnd;
|
||||||
|
|
||||||
namespace
|
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);
|
const uint64_t minAddr = reinterpret_cast<uint64_t>(&gKernelEnd);
|
||||||
for (uint32_t addr = firstEntryAddr; addr < firstEntryAddr + bufferLength;)
|
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;
|
addr += sizeof(entry.size) + entry.size;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
using initfunc_t = void *();
|
using initfunc_t = void *();
|
||||||
extern "C" initfunc_t** start_ctors;
|
extern "C" initfunc_t* start_ctors;
|
||||||
extern "C" initfunc_t** end_ctors;
|
extern "C" initfunc_t* end_ctors;
|
||||||
|
|
||||||
void initGlobals()
|
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
|
// TODO: this confuses me
|
||||||
if (*initFunc == reinterpret_cast<initfunc_t*>(0xffffffffffffffff)) {
|
if (*initFunc == reinterpret_cast<initfunc_t*>(0xffffffffffffffff)) {
|
||||||
@ -60,7 +61,7 @@ void initGlobals()
|
|||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
{
|
{
|
||||||
multiboot_info_t* gMultibootHeader;
|
EfiMemoryMap* gMemoryMap;
|
||||||
|
|
||||||
void _init();
|
void _init();
|
||||||
void _fini();
|
void _fini();
|
||||||
@ -78,6 +79,7 @@ void kernel_main()
|
|||||||
/* Initialize the heap */
|
/* Initialize the heap */
|
||||||
// assert(gMultibootHeader->flags & MULTIBOOT_INFO_MEM_MAP);
|
// assert(gMultibootHeader->flags & MULTIBOOT_INFO_MEM_MAP);
|
||||||
// initHeapFromMultibootHeader(gMultibootHeader->mmap_addr, gMultibootHeader->mmap_length);
|
// initHeapFromMultibootHeader(gMultibootHeader->mmap_addr, gMultibootHeader->mmap_length);
|
||||||
|
initHeapFromEfiMemoryMap(*gMemoryMap);
|
||||||
|
|
||||||
main();
|
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"
|
extern "C"
|
||||||
{
|
{
|
||||||
#include <efi.h>
|
#include <efi.h>
|
||||||
#include <efilib.h>
|
|
||||||
}
|
}
|
||||||
#include "miniefi.hpp"
|
#include "boot.hpp"
|
||||||
|
#include "minielf.hpp"
|
||||||
#include "minimalloc.hpp"
|
#include "minimalloc.hpp"
|
||||||
#include "miniprintf.hpp"
|
#include "miniprintf.hpp"
|
||||||
|
|
||||||
|
// debug stuff
|
||||||
|
// #define DUMP_MEMORY_MAP
|
||||||
|
// #define DUMP_ELF
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
EFI_SYSTEM_TABLE* gSystemTable;
|
||||||
|
EFI_BOOT_SERVICES* gBootServices;
|
||||||
|
|
||||||
EFI_STATUS openImageVolume(EFI_HANDLE image, EFI_FILE_HANDLE& outHandle)
|
EFI_STATUS openImageVolume(EFI_HANDLE image, EFI_FILE_HANDLE& outHandle)
|
||||||
{
|
{
|
||||||
EFI_LOADED_IMAGE* loadedImage = nullptr;
|
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_GUID fsGuid = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID;
|
||||||
EFI_FILE_HANDLE volume = nullptr;
|
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)) {
|
if (EFI_ERROR(status)) {
|
||||||
return 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)) {
|
if (EFI_ERROR(status)) {
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
@ -37,7 +44,7 @@ EFI_STATUS openImageVolume(EFI_HANDLE image, EFI_FILE_HANDLE& outHandle)
|
|||||||
|
|
||||||
void print(const CHAR16* text)
|
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)
|
void putchar(char c)
|
||||||
@ -58,14 +65,14 @@ void waitForKey()
|
|||||||
EFI_INPUT_KEY Key;
|
EFI_INPUT_KEY Key;
|
||||||
|
|
||||||
// reset input buffer to flush previous key strokes
|
// 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))
|
if (EFI_ERROR(status))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// now wait for a key
|
// 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)
|
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);
|
outFileInfo = static_cast<EFI_FILE_INFO*>(buffer);
|
||||||
return EFI_SUCCESS;
|
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) \
|
#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)
|
extern "C" EFI_STATUS efi_main(EFI_HANDLE imageHandle, EFI_SYSTEM_TABLE* systemTable)
|
||||||
{
|
{
|
||||||
/* Store the system table for future use in other functions */
|
/* Store the system table for future use in other functions */
|
||||||
ST = systemTable;
|
gSystemTable = systemTable;
|
||||||
BS = systemTable->BootServices;
|
gBootServices = systemTable->BootServices;
|
||||||
|
|
||||||
initMiniMalloc();
|
initMiniMalloc();
|
||||||
initMiniPrintf(&putchar);
|
initMiniPrintf(&putchar);
|
||||||
|
|
||||||
ST->ConOut->ClearScreen(ST->ConOut);
|
gSystemTable->ConOut->ClearScreen(gSystemTable->ConOut);
|
||||||
|
|
||||||
EFI_FILE_HANDLE volume;
|
EFI_FILE_HANDLE volume;
|
||||||
EFI_STATUS status = openImageVolume(imageHandle, 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;
|
EFI_FILE_INFO* info = nullptr;
|
||||||
status = getEfiFileInfo(fileHandle, info);
|
status = getEfiFileInfo(fileHandle, info);
|
||||||
DIE_ON_ERROR(L"Error getting file info.");
|
DIE_ON_ERROR(L"Error getting file info.");
|
||||||
printf("File size: %d.\n", static_cast<int>(info->FileSize));
|
|
||||||
free(info);
|
free(info);
|
||||||
|
|
||||||
Elf64Header header = {};
|
Elf64Header header = {};
|
||||||
UINTN bufferSize = sizeof(Elf64Header);
|
UINTN bufferSize = sizeof(Elf64Header);
|
||||||
status = fileHandle->Read(fileHandle, &bufferSize, &header);
|
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("headerSize: %d\n", static_cast<int>(header.type));
|
||||||
printf("entry: 0x%X\n", static_cast<unsigned>(header.entry));
|
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)
|
for (uint16_t phtEntry = 0; phtEntry < header.phtEntryCount; ++phtEntry)
|
||||||
{
|
{
|
||||||
status = fileHandle->SetPosition(fileHandle, header.phtOffset + phtEntry * header.phtEntrySize);
|
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 = {};
|
Efi64ProgramHeader programHeader = {};
|
||||||
bufferSize = sizeof(Efi64ProgramHeader);
|
bufferSize = sizeof(Efi64ProgramHeader);
|
||||||
status = fileHandle->Read(fileHandle, &bufferSize, &programHeader);
|
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("Program Header %d:\n", phtEntry);
|
||||||
printf(" type: %d\n", static_cast<int>(programHeader.type));
|
printf(" type: %d\n", static_cast<int>(programHeader.type));
|
||||||
printf(" flags: %d\n", static_cast<int>(programHeader.flags));
|
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(" paddr: 0x%X\n", programHeader.paddr);
|
||||||
printf(" fileSize: %d\n", static_cast<int>(programHeader.fileSize));
|
printf(" fileSize: %d\n", static_cast<int>(programHeader.fileSize));
|
||||||
printf(" memSize: %d\n", static_cast<int>(programHeader.memSize));
|
printf(" memSize: %d\n", static_cast<int>(programHeader.memSize));
|
||||||
|
#endif // defined(DUMP_ELF)
|
||||||
|
|
||||||
if (programHeader.type != ElfProgramHeaderType::LOAD) {
|
if (programHeader.type != ElfProgramHeaderType::LOAD) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
print(L"Loading segment...\r\n");
|
|
||||||
status = fileHandle->SetPosition(fileHandle, programHeader.offset);
|
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);
|
void* targetAddr = reinterpret_cast<void*>(programHeader.paddr);
|
||||||
bufferSize = programHeader.fileSize;
|
bufferSize = programHeader.fileSize;
|
||||||
status = fileHandle->Read(fileHandle, &bufferSize, targetAddr);
|
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!
|
// up up and away!
|
||||||
__asm__ __volatile__
|
__asm__ __volatile__
|
||||||
(
|
(
|
||||||
"jmp %0"
|
"jmp %0"
|
||||||
:
|
:
|
||||||
: "a"(header.entry)
|
: "a"(header.entry), "b"(memoryMap)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// we should never get here
|
||||||
waitForKey();
|
waitForKey();
|
||||||
|
|
||||||
return EFI_SUCCESS;
|
return EFI_SUCCESS;
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#if !defined(MINIEFI_HPP_INCLUDED)
|
#if !defined(MINIELF_HPP_INCLUDED)
|
||||||
#define MINIEFI_HPP_INCLUDED 1
|
#define MINIELF_HPP_INCLUDED 1
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
@ -107,4 +107,4 @@ struct Efi64ProgramHeader
|
|||||||
uint64_t align;
|
uint64_t align;
|
||||||
} __attribute__((packed));
|
} __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 = reinterpret_cast<MallocBlock*>(reinterpret_cast<max_align_t*>(block) + requiredElements);
|
||||||
newBlock->nextBlock = block->nextBlock;
|
newBlock->nextBlock = block->nextBlock;
|
||||||
newBlock->elements = block->elements - requiredElements;
|
newBlock->elements = block->elements - requiredElements;
|
||||||
} else
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
newBlock = block->nextBlock;
|
newBlock = block->nextBlock;
|
||||||
}
|
}
|
||||||
@ -60,6 +61,10 @@ void* malloc(size_t size) noexcept
|
|||||||
{
|
{
|
||||||
prevBlock->nextBlock = newBlock;
|
prevBlock->nextBlock = newBlock;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gNextBlock = newBlock;
|
||||||
|
}
|
||||||
AllocInfo* allocInfo = reinterpret_cast<AllocInfo*>(block);
|
AllocInfo* allocInfo = reinterpret_cast<AllocInfo*>(block);
|
||||||
allocInfo->elements = requiredElements;
|
allocInfo->elements = requiredElements;
|
||||||
return reinterpret_cast<max_align_t*>(block) + 1;
|
return reinterpret_cast<max_align_t*>(block) + 1;
|
||||||
|
@ -207,6 +207,7 @@ int vprintf(const char* format, va_list vlist)
|
|||||||
default:
|
default:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
// TODO
|
// TODO
|
||||||
// assert(!"Invalid format string, unknown format identifier.");
|
// assert(!"Invalid format string, unknown format identifier.");
|
||||||
|
@ -11,7 +11,7 @@ using putchar_t = void (*)(char c);
|
|||||||
void initMiniPrintf(putchar_t putcharFn) noexcept;
|
void initMiniPrintf(putchar_t putcharFn) noexcept;
|
||||||
extern "C"
|
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);
|
int vprintf(const char* format, va_list vlist);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user