diff --git a/bastl/include/algorithm b/bastl/include/algorithm index 820a0b9..0ff3a3e 100644 --- a/bastl/include/algorithm +++ b/bastl/include/algorithm @@ -6,7 +6,17 @@ namespace std { +template +constexpr const T& min(const T& left, const T& right) +{ + return right < left ? right : left; +} +template +constexpr const T& max(const T& left, const T& right) +{ + return right > left ? right : left; +} } #endif // !defined(BAD_APPLE_OS_ALGORITHM_INCLUDED) diff --git a/targets/_any/SConscript b/targets/_any/SConscript index 162da52..cee2793 100644 --- a/targets/_any/SConscript +++ b/targets/_any/SConscript @@ -3,6 +3,7 @@ Import('env') any_target_sources = Split(''' src/app/main.cpp + src/os/draw.cpp src/os/panic.cpp src/os/tty.cpp diff --git a/targets/_any/include/os/draw.hpp b/targets/_any/include/os/draw.hpp new file mode 100644 index 0000000..b5de46c --- /dev/null +++ b/targets/_any/include/os/draw.hpp @@ -0,0 +1,69 @@ + +#pragma once + +#if !defined(BAD_APPLE_OS_DRAW_HPP_INCLUDED) +#define BAD_APPLE_OS_DRAW_HPP_INCLUDED + +#include +#include + +namespace draw +{ +const unsigned SIZE_FULL = static_cast(-1); + +struct Pixel +{ + uint8_t blue = 0; + uint8_t green = 0; + uint8_t red = 0; + uint8_t reserved_ = 0; +}; + +class Framebuffer +{ +protected: + Pixel* mBase = nullptr; + unsigned mWidth = 0; + unsigned mHeight = 0; + unsigned mPitch = 0; +public: + Framebuffer() = default; + Framebuffer(const Framebuffer&) = default; + Framebuffer(Pixel* base, unsigned width, unsigned height, unsigned pitch) noexcept + : mBase(base), mWidth(width), mHeight(height), mPitch(pitch) {} + + [[nodiscard]] Pixel* getBase() const noexcept { return mBase; } + [[nodiscard]] unsigned getWidth() const noexcept { return mWidth; } + [[nodiscard]] unsigned getHeight() const noexcept { return mHeight; } + [[nodiscard]] unsigned getPitch() const noexcept { return mPitch; } + [[nodiscard]] unsigned getBufferSize() const noexcept { return mPitch * mHeight * sizeof(Pixel); } + + void setPixel(unsigned posX, unsigned posY, Pixel pixel) noexcept; +}; + +class OwningFramebuffer : public Framebuffer +{ +private: + std::vector mPixels; +public: + OwningFramebuffer() = default; + OwningFramebuffer(const OwningFramebuffer&) noexcept = default; + OwningFramebuffer(OwningFramebuffer&&) noexcept = default; + OwningFramebuffer(unsigned width, unsigned height, unsigned pitch) noexcept; + + OwningFramebuffer& operator=(const OwningFramebuffer&) noexcept = default; + OwningFramebuffer& operator=(OwningFramebuffer&&) noexcept = default; + + static OwningFramebuffer makeFrom(const Framebuffer& other) noexcept + { + return OwningFramebuffer(other.getWidth(), other.getHeight(), other.getPitch()); + } +}; + +void initializeDefaultFramebuffer(const Framebuffer& framebuffer) noexcept; +void setPixelDirect(unsigned posX, unsigned posY, Pixel pixel) noexcept; +void setPixel(unsigned posX, unsigned posY, Pixel pixel) noexcept; +void flushPixels() noexcept; +} + +#endif // !defined(BAD_APPLE_OS_FRAMEBUFFER_HPP_INCLUDED) diff --git a/targets/_any/src/cstdlib/stdlib.cpp b/targets/_any/src/cstdlib/stdlib.cpp index 6780b56..b184f97 100644 --- a/targets/_any/src/cstdlib/stdlib.cpp +++ b/targets/_any/src/cstdlib/stdlib.cpp @@ -106,4 +106,15 @@ void free(void* memory) noexcept block->nextBlock = gNextBlock; gNextBlock = block; } + +int __cxa_atexit(void (*func)(void*), void* arg, void* dsoHandle) +{ + (void) func; + (void) arg; + (void) dsoHandle; + + // NOOP for now + // TODO + return 0; +} } // extern "C" \ No newline at end of file diff --git a/targets/_any/src/os/draw.cpp b/targets/_any/src/os/draw.cpp new file mode 100644 index 0000000..01797c8 --- /dev/null +++ b/targets/_any/src/os/draw.cpp @@ -0,0 +1,52 @@ + +#include "os/draw.hpp" + +#include + +namespace draw +{ +namespace +{ +Framebuffer gFramebuffer; +OwningFramebuffer gDoubleBuffer; +} + +OwningFramebuffer::OwningFramebuffer(unsigned width, unsigned height, unsigned pitch) noexcept + : Framebuffer(nullptr, width, height, pitch) +{ + mPixels.resize(height * pitch); + mBase = mPixels.data(); +} + +void Framebuffer::setPixel(unsigned int posX, unsigned int posY, Pixel pixel) noexcept +{ + if (posX >= mWidth || posY > mHeight) { + return; + } + mBase[posY * mPitch + posX] = pixel; +} + + +void initializeDefaultFramebuffer(const Framebuffer& framebuffer) noexcept +{ + gFramebuffer = framebuffer; + gDoubleBuffer = OwningFramebuffer::makeFrom(gFramebuffer); +} + +void setPixelDirect(unsigned posX, unsigned posY, Pixel pixel) noexcept +{ + gFramebuffer.setPixel(posX, posY, pixel); + // also set it in the double buffer, otherwise it will be lost on flush + gDoubleBuffer.setPixel(posX, posY, pixel); +} + +void setPixel(unsigned posX, unsigned posY, Pixel pixel) noexcept +{ + gDoubleBuffer.setPixel(posX, posY, pixel); +} + +void flushPixels() noexcept +{ + std::memcpy(gFramebuffer.getBase(), gDoubleBuffer.getBase(), gFramebuffer.getBufferSize()); +} +} \ No newline at end of file diff --git a/targets/x86_64/src/kernel/startup.cpp b/targets/x86_64/src/kernel/startup.cpp index 3c8791b..0cdcea6 100644 --- a/targets/x86_64/src/kernel/startup.cpp +++ b/targets/x86_64/src/kernel/startup.cpp @@ -1,16 +1,41 @@ -#include "os/tty.hpp" - #include -#include #include "boot.hpp" +#include "os/draw.hpp" +#include "os/tty.hpp" + extern "C" int gKernelEnd; namespace { void initHeapFromEfiMemoryMap(const EfiMemoryMap& memoryMap) noexcept { + const uint64_t minAddr = reinterpret_cast(&gKernelEnd); + for (const EFI_MEMORY_DESCRIPTOR& descriptor : memoryMap) + { + // TODO: what about other types? + if (descriptor.Type != EfiConventionalMemory) + { + continue; + } + + uint64_t addr = descriptor.PhysicalStart; + uint64_t len = descriptor.NumberOfPages * 4096; // TODO: is this the correct page size? + // anything before the kernel we ignore + if (addr < minAddr) + { + // if the entire entry is before the kernel, continue + if (addr + len <= minAddr) + { + continue; + } + // otherwise shrink it and use the rest + len -= (minAddr - addr); + addr = minAddr; + } + __ba_registerAllocatableMemory(reinterpret_cast(addr), len); + } #if 0 const uint64_t minAddr = reinterpret_cast(&gKernelEnd); for (uint32_t addr = firstEntryAddr; addr < firstEntryAddr + bufferLength;) @@ -71,35 +96,34 @@ void kernel_main() { initGlobals(); - /* Initialize terminal interface */ - tty::initialize(); + // init the heap (required for the double buffer) + initHeapFromEfiMemoryMap(gBootInfo->memoryMap); - std::printf("Kernel End: %p\n", &gKernelEnd); + // initialize the framebuffer + draw::initializeDefaultFramebuffer({ + /* base = */ static_cast(gBootInfo->displayInfo.frameBufferBase), + /* width = */ gBootInfo->displayInfo.frameBufferWidth, + /* height = */ gBootInfo->displayInfo.frameBufferHeight, + /* pitch = */ gBootInfo->displayInfo.frameBufferPitch / 4 + }); + + // initialize terminal interface + // tty::initialize(); + + // std::printf("Kernel End: %p\n", &gKernelEnd); - struct Pixel - { - uint8_t blue = 0; - uint8_t green = 0; - uint8_t red = 0; - uint8_t reserved = 0; - }; - auto setPixel = [](unsigned x, unsigned y, Pixel color) - { - Pixel* framebuffer = static_cast(gBootInfo->displayInfo.frameBufferBase); - framebuffer[y * gBootInfo->displayInfo.frameBufferPitch / 4 + x] = color; - }; for (int x = 0; x < 100; ++x) { for (int y = 0; y < 100; ++y) { - setPixel(x, y, {.red = 255}); + draw::setPixel(x, y, {.red = 255}); } } + draw::flushPixels(); /* Initialize the heap */ // assert(gMultibootHeader->flags & MULTIBOOT_INFO_MEM_MAP); // initHeapFromMultibootHeader(gMultibootHeader->mmap_addr, gMultibootHeader->mmap_length); - initHeapFromEfiMemoryMap(gBootInfo->memoryMap); main();