From 164f05bd59793efebf1d73bb519b532c450f96f4 Mon Sep 17 00:00:00 2001 From: Patrick Wuttke Date: Thu, 11 Jan 2024 22:54:41 +0100 Subject: [PATCH] Using the memory map for the heap. --- SConstruct | 3 +- include/cstdlib | 2 + linker.ld | 1 + src/kernel/startup.cpp | 28 +++++++++-- src/stdlib/stdio.cpp | 108 +++++++++++++++++++++++++++++++++++++---- src/stdlib/stdlib.cpp | 12 +++++ 6 files changed, 139 insertions(+), 15 deletions(-) diff --git a/SConstruct b/SConstruct index f0818d0..9c503cd 100644 --- a/SConstruct +++ b/SConstruct @@ -42,7 +42,8 @@ env['LINKCOM'] = env['LINKCOM'].replace('$_LIBFLAGS', f'{crti_o[0]} {crtbegin_o} prog_os = env.Program( target = 'os.bin', - source = os_sources + source = os_sources, + LIBS = ['gcc'] ) env.Depends(prog_os, [crti_o, crtn_o]) env.Default(prog_os) diff --git a/include/cstdlib b/include/cstdlib index d53df3f..e635339 100644 --- a/include/cstdlib +++ b/include/cstdlib @@ -13,4 +13,6 @@ using ::malloc; using ::free; } +void __ba_registerAllocatableMemory(void* memory, size_t size) noexcept; + #endif // !defined(BAD_APPLE_OS_CSTDLIB_INCLUDED) diff --git a/linker.ld b/linker.ld index cc52870..8c1bd32 100644 --- a/linker.ld +++ b/linker.ld @@ -57,4 +57,5 @@ SECTIONS /* The compiler may produce other sections, by default it will put them in a segment with the same name. Simply add stuff here as needed. */ + gKernelEnd = .; } \ No newline at end of file diff --git a/src/kernel/startup.cpp b/src/kernel/startup.cpp index 9ddcb80..e51c816 100644 --- a/src/kernel/startup.cpp +++ b/src/kernel/startup.cpp @@ -3,21 +3,39 @@ #include #include +#include #include "./multiboot.h" +extern "C" int gKernelEnd; + namespace { void initHeapFromMultibootHeader(const uint32_t firstEntryAddr, const size_t bufferLength) noexcept { + const uint64_t minAddr = reinterpret_cast(&gKernelEnd); for (uint32_t addr = firstEntryAddr; addr < firstEntryAddr + bufferLength;) { - const multiboot_memory_map_t& entry = *reinterpret_cast(addr); + multiboot_memory_map_t entry = *reinterpret_cast(addr); if(entry.type == MULTIBOOT_MEMORY_AVAILABLE) { - std::printf("Start Addr: %d | Length: %d | Size: %d | Type: %d\n", - static_cast(entry.addr), static_cast(entry.len), - static_cast(entry.size), static_cast(entry.type)); + std::printf("Start Addr: %X | Length: %b\n", + static_cast(entry.addr), static_cast(entry.len)); + + // anything before the kernel we ignore + if (entry.addr < minAddr) + { + // if the entire entry is before the kernel, continue + if (entry.addr + entry.len <= minAddr) + { + addr += sizeof(entry.size) + entry.size; + continue; + } + // otherwise shrink it and use the rest + entry.len -= (minAddr - entry.addr); + entry.addr = minAddr; + } + __ba_registerAllocatableMemory(reinterpret_cast(entry.addr), entry.len); } addr += sizeof(entry.size) + entry.size; } @@ -39,6 +57,8 @@ void kernel_main() /* Initialize terminal interface */ tty::initialize(); + std::printf("Kernel End: %p\n", &gKernelEnd); + /* Initialize the heap */ assert(gMultibootHeader->flags & MULTIBOOT_INFO_MEM_MAP); initHeapFromMultibootHeader(gMultibootHeader->mmap_addr, gMultibootHeader->mmap_length); diff --git a/src/stdlib/stdio.cpp b/src/stdlib/stdio.cpp index 046d6fc..c63337f 100644 --- a/src/stdlib/stdio.cpp +++ b/src/stdlib/stdio.cpp @@ -38,6 +38,94 @@ int printInt(int value) } return pos - digits; } + +int printUInt(uint64_t value) +{ + if (value == 0) + { + putchar('0'); + return 1; + } + + char digits[20]; // 18,446,744,073,709,551,615 has 20 digits + char* pos = &digits[0]; + + while (value > 0) + { + *pos = static_cast('0' + (value % 10)); + value /= 10; + ++pos; + } + for (char* chr = pos - 1; chr >= digits; --chr) + { + putchar(*chr); + } + return pos - digits; +} + +int printHexInt(uint64_t value) +{ + if (value == 0) + { + putchar('0'); + return 1; + } + + char digits[16]; // FFFFFFFFFFFFFFFF has 16 digits + char* pos = &digits[0]; + + while (value > 0) + { + const uint64_t digit = (value % 16); + if (digit < 10) + { + *pos = static_cast('0' + digit); + } + else + { + *pos = static_cast('A' + digit - 10); + } + value /= 16; + ++pos; + } + for (char* chr = pos - 1; chr >= digits; --chr) + { + putchar(*chr); + } + return pos - digits; +} + +int printPointer(void* ptr) +{ + return printHexInt(reinterpret_cast(ptr)); +} + +int printString(const char* str) +{ + const size_t len = std::strlen(str); + + for (size_t idx = 0; idx < len; ++idx) + { + putchar(str[idx]); + } + return static_cast(len); +} + +int printByteSize(size_t bytes) +{ + const char* suffixes[] = { + "B", "KiB", "MiB", "GiB", "TiB" + }; + int suffixIdx = 0; + for (; suffixIdx < sizeof(suffixes) / sizeof(suffixes[0]); ++suffixIdx) + { + if (bytes < 1024) { + break; + } + bytes /= 1024; + } + return printUInt(bytes) + printString(suffixes[suffixIdx]); +} } int putchar(int chr) noexcept @@ -81,6 +169,9 @@ int vprintf(const char* format, std::va_list vlist) BA_CXX_NOEXCEPT // TODO: invalid format string, do something assert(!"Invalid format string, ends with %."); return -1; + case 'b': + result += printByteSize(va_arg(vlist, size_t)); + break; case 'c': { const char chr = static_cast(va_arg(vlist, int)); @@ -89,20 +180,17 @@ int vprintf(const char* format, std::va_list vlist) BA_CXX_NOEXCEPT break; } case 's': - { - const char* str = va_arg(vlist, const char*); - const size_t len = std::strlen(str); - - for (size_t idx = 0; idx < len; ++idx) - { - putchar(str[idx]); - } - result += static_cast(len); + result += printString(va_arg(vlist, const char*)); break; - } case 'd': result += printInt(va_arg(vlist, int)); break; + case 'p': + result += printPointer(va_arg(vlist, void*)); + break; + case 'X': + result += printHexInt(va_arg(vlist, unsigned)); + break; default: assert(!"Invalid format string, unknown format identifier."); return -1; diff --git a/src/stdlib/stdlib.cpp b/src/stdlib/stdlib.cpp index 3be7c37..fda76ad 100644 --- a/src/stdlib/stdlib.cpp +++ b/src/stdlib/stdlib.cpp @@ -32,6 +32,18 @@ MallocBlock* gNextBlock = []() }(); } +void __ba_registerAllocatableMemory(void* memory, size_t size) noexcept +{ + if (size < sizeof(max_align_t)) + { + return; + } + MallocBlock* newBlock = static_cast(memory); + newBlock->nextBlock = gNextBlock; + newBlock->elements = size / sizeof(max_align_t); + gNextBlock = newBlock; +} + extern "C" { void abort()