diff --git a/SConstruct b/SConstruct index 675644e..ee7bdb0 100644 --- a/SConstruct +++ b/SConstruct @@ -15,6 +15,7 @@ target = GetOption('target') env = Environment(tools = ['default', 'compilation_db']) env.Append(CCFLAGS = ['-g', '-O0']) +# env.Append(CCFLAGS = ['-O2']) env['ISO_FILES'] = [] env = SConscript('bastl/SConscript', exports = 'env') diff --git a/bastl/include/array b/bastl/include/array index af5d771..f8f730b 100644 --- a/bastl/include/array +++ b/bastl/include/array @@ -24,7 +24,7 @@ public: using iterator = pointer; using const_iterator = const_pointer; - T _elements; + T _elements[N]; constexpr reference operator[](size_type pos) noexcept { diff --git a/targets/_any/SConscript b/targets/_any/SConscript index cee2793..914ecc2 100644 --- a/targets/_any/SConscript +++ b/targets/_any/SConscript @@ -1,17 +1,54 @@ Import('env') +def _resource(env, res, symbol): + def _generate_s(target, source, env): + with open(target[0].abspath, 'w') as f: + f.write(f''' + .section .rodata + .global {symbol} + .type {symbol} @object + + .section .rodata + .global {symbol}_SIZE + .type {symbol}_SIZE @object +{symbol}: + .incbin "{res}" +{symbol}_END: +{symbol}_SIZE: + .int {symbol}_END - {symbol} +''') + with open(target[1].abspath, 'w') as f: + f.write(f''' +#pragma once + +#include + +extern "C" +{{ +extern const uint8_t {symbol}[]; +extern const unsigned {symbol}_SIZE; +}} + +''') + env.Command([f'{res}.s', f'{res}.hpp'.replace('src/', 'include/')], res, action = _generate_s) +env.AddMethod(_resource, 'Resource') + any_target_sources = Split(''' src/app/main.cpp + src/libs/psf.cpp + src/os/draw.cpp src/os/panic.cpp src/os/tty.cpp + src/os/resources/lat9-08.psf.s src/cstdlib/assert.cpp src/cstdlib/stdio.cpp src/cstdlib/stdlib.cpp src/cstdlib/string.cpp ''') +env.Resource(env.File('src/os/resources/lat9-08.psf').abspath, 'LAT9_08') env.Append(KERNEL_SOURCES = [env.File(f) for f in any_target_sources]) diff --git a/targets/_any/include/libs/psf.hpp b/targets/_any/include/libs/psf.hpp new file mode 100644 index 0000000..175bb3c --- /dev/null +++ b/targets/_any/include/libs/psf.hpp @@ -0,0 +1,77 @@ + +#pragma once + +#if !defined(BAD_APPLE_OS_PSF_HPP_INCLUDED) +#define BAD_APPLE_OS_PSF_HPP_INCLUDED + +#include +#include + +namespace psf +{ +inline const uint32_t MAGIC = 0x864ab572; + +struct Header +{ + uint32_t magic; /* magic bytes to identify PSF */ + uint32_t version; /* zero */ + uint32_t headersize; /* offset of bitmaps in file, 32 */ + uint32_t flags; /* 0 if there's no unicode table */ + uint32_t numglyph; /* number of glyphs */ + uint32_t bytesperglyph; /* size of each glyph */ + uint32_t height; /* height in pixels */ + uint32_t width; /* width in pixels */ +}; + +class Font +{ +private: + const Header* mMemory = nullptr; + size_t mSize = 0; +public: + Font() noexcept = default; + Font(const Font&) = default; +private: + Font(const Header* memory, size_t size) noexcept : mMemory(memory), mSize(size) {} +public: + Font& operator=(const Font&) noexcept = default; + + [[nodiscard]] uint32_t getGlyphWidth() const noexcept { return mMemory->width; } + [[nodiscard]] uint32_t getGlyphHeight() const noexcept { return mMemory->height; } + template + void writeGlyph(char chr, const TColor& fgColor, const TColor& bgColor, TDrawFn draw) const noexcept; +public: + [[nodiscard]] static bool create(const void* data, size_t size, Font& outFont) noexcept; +}; + +template +void Font::writeGlyph(char chr, const TColor& fgColor, const TColor& bgColor, TDrawFn draw) const noexcept +{ + if (chr > mMemory->numglyph) { + chr = 0; + } + + const uint8_t* glyphData = reinterpret_cast(mMemory) + mMemory->headersize + chr * mMemory->bytesperglyph; + + for (unsigned y = 0; y < mMemory->height; ++y) + { + for (unsigned x = 0; x < mMemory->width; ++x) + { + const unsigned idx = y * mMemory->width + x; + const unsigned byte = idx / 8; + const unsigned bit = idx % 8; + + if (glyphData[byte] & (0b10000000 >> bit)) + { + draw(x, y, fgColor); + } + else + { + draw(x, y, bgColor); + } + } + } +} +} + +#endif // !defined(BAD_APPLE_OS_PSF_HPP_INCLUDED) diff --git a/targets/_any/include/os/draw.hpp b/targets/_any/include/os/draw.hpp index b5de46c..ecc1ca2 100644 --- a/targets/_any/include/os/draw.hpp +++ b/targets/_any/include/os/draw.hpp @@ -5,8 +5,13 @@ #define BAD_APPLE_OS_DRAW_HPP_INCLUDED #include +#include #include +namespace psf +{ +class Font; +} namespace draw { const unsigned SIZE_FULL = static_cast(-1); @@ -19,6 +24,10 @@ struct Pixel uint8_t reserved_ = 0; }; +inline Pixel PIXEL_WHITE = {255, 255, 255}; +inline Pixel PIXEL_BLACK = {0, 0, 0}; +extern const std::array VGA_PIXELS; + class Framebuffer { protected: @@ -38,6 +47,7 @@ public: [[nodiscard]] unsigned getPitch() const noexcept { return mPitch; } [[nodiscard]] unsigned getBufferSize() const noexcept { return mPitch * mHeight * sizeof(Pixel); } + const Pixel& getPixel(unsigned posX, unsigned posY) noexcept; void setPixel(unsigned posX, unsigned posY, Pixel pixel) noexcept; }; @@ -61,9 +71,15 @@ public: }; void initializeDefaultFramebuffer(const Framebuffer& framebuffer) noexcept; +[[nodiscard]] const Framebuffer& getPrimaryFramebuffer() noexcept; + void setPixelDirect(unsigned posX, unsigned posY, Pixel pixel) noexcept; void setPixel(unsigned posX, unsigned posY, Pixel pixel) noexcept; -void flushPixels() noexcept; +const Pixel& getPixel(unsigned posX, unsigned posY) noexcept; + +void character(unsigned posX, unsigned posY, const psf::Font& font, char chr, const Pixel& fgColor = PIXEL_WHITE, const Pixel& bgColor = PIXEL_BLACK) noexcept; + +void scrollBy(int scrollX, int scrollY, const Pixel& fillColor = PIXEL_BLACK) noexcept; } #endif // !defined(BAD_APPLE_OS_FRAMEBUFFER_HPP_INCLUDED) diff --git a/targets/_any/include/os/resources/.gitignore b/targets/_any/include/os/resources/.gitignore new file mode 100644 index 0000000..fa23c79 --- /dev/null +++ b/targets/_any/include/os/resources/.gitignore @@ -0,0 +1 @@ +*.hpp diff --git a/targets/_any/include/os/tty.hpp b/targets/_any/include/os/tty.hpp index ea5f62f..ce539cc 100644 --- a/targets/_any/include/os/tty.hpp +++ b/targets/_any/include/os/tty.hpp @@ -35,12 +35,14 @@ struct VgaDoubleColor VgaColor background : 4 = VgaColor::BLACK; }; -void initialize(); -void setColor(VgaDoubleColor color); -void putEntryAt(char chr, VgaDoubleColor color, size_t posX, size_t posY); -void putChar(char chr); -void write(const char* data, size_t size); -void write(const char* data); +void initialize() noexcept; +void setColor(VgaDoubleColor color) noexcept; +void putEntryAt(char chr, VgaDoubleColor color, size_t posX, size_t posY) noexcept; +void putChar(char chr) noexcept; +void write(const char* data, size_t size) noexcept; +void write(const char* data) noexcept; + +bool setPSFFont(const void* data, size_t length) noexcept; } // namespace tty #endif // OS_TTY_HPP_INCLUDED diff --git a/targets/_any/include/stdio.h b/targets/_any/include/stdio.h index 83536ef..fe7564b 100644 --- a/targets/_any/include/stdio.h +++ b/targets/_any/include/stdio.h @@ -11,7 +11,7 @@ BA_EXTERN_C_BEGIN int putchar(int chr) BA_CXX_NOEXCEPT; int puts(const char* str) BA_CXX_NOEXCEPT; -int printf(const char* format, ...) BA_CXX_NOEXCEPT; +int printf(const char* format, ...) BA_CXX_NOEXCEPT __attribute__((format(printf, 1, 2))); int vprintf(const char* format, va_list vlist) BA_CXX_NOEXCEPT; BA_EXTERN_C_END diff --git a/targets/_any/src/cstdlib/stdlib.cpp b/targets/_any/src/cstdlib/stdlib.cpp index b184f97..97b2e4e 100644 --- a/targets/_any/src/cstdlib/stdlib.cpp +++ b/targets/_any/src/cstdlib/stdlib.cpp @@ -6,7 +6,7 @@ namespace { -inline const size_t INIT_MALLOC_SPACE_ELEMENTS = 1024; +inline const size_t INIT_MALLOC_SPACE_ELEMENTS = 1024 * 1024; inline const size_t INIT_MALLOC_SPACE_BYTES = INIT_MALLOC_SPACE_ELEMENTS * sizeof(max_align_t); max_align_t gInitMallocSpace[INIT_MALLOC_SPACE_ELEMENTS]; diff --git a/targets/_any/src/cstdlib/string.cpp b/targets/_any/src/cstdlib/string.cpp index 825ee5e..6ba9dcc 100644 --- a/targets/_any/src/cstdlib/string.cpp +++ b/targets/_any/src/cstdlib/string.cpp @@ -19,6 +19,7 @@ int memcmp(const void* lhs, const void* rhs, size_t count) noexcept return 0; } +#if !defined(__x86_64__) void memcpy(void* dest, const void* src, size_t count) noexcept { for (size_t pos = 0; pos < count; ++pos) @@ -26,6 +27,7 @@ void memcpy(void* dest, const void* src, size_t count) noexcept *(static_cast(dest) + pos) = *(static_cast(src) + pos); } } +#endif void memmove(void* dest, const void* src, size_t count) noexcept { diff --git a/targets/_any/src/libs/psf.cpp b/targets/_any/src/libs/psf.cpp new file mode 100644 index 0000000..b4b9169 --- /dev/null +++ b/targets/_any/src/libs/psf.cpp @@ -0,0 +1,18 @@ + +#include "libs/psf.hpp" + +namespace psf +{ +bool Font::create(const void* data, size_t size, Font& outFont) noexcept +{ + if (size < sizeof(Header)) { + return false; + } + const Header* header = static_cast(data); + if (header->magic != MAGIC) { + return false; + } + outFont = Font(header, size); + return true; +} +} diff --git a/targets/_any/src/os/draw.cpp b/targets/_any/src/os/draw.cpp index 01797c8..f6a1d9a 100644 --- a/targets/_any/src/os/draw.cpp +++ b/targets/_any/src/os/draw.cpp @@ -2,6 +2,7 @@ #include "os/draw.hpp" #include +#include "libs/psf.hpp" namespace draw { @@ -9,7 +10,39 @@ namespace { Framebuffer gFramebuffer; OwningFramebuffer gDoubleBuffer; + +void scrollVertical(int scrollY, const Pixel& fillColor) noexcept +{ + if (scrollY == 0) { + return; + } + const std::ptrdiff_t pixelOffset = scrollY * gFramebuffer.getPitch(); + if (scrollY > 0) + { + // std::memmove(gFramebuffer.getBase(), gFramebuffer.getBase() + pixelOffset, gFramebuffer.getBufferSize() - (4 * pixelOffset)); + // std::memset(gFramebuffer.getBase() + pixelOffset, 0, ) + } } +} + +const std::array VGA_PIXELS = { + Pixel{0, 0, 0}, + Pixel{0, 0, 170}, + Pixel{0, 170, 0}, + Pixel{170, 170, 0}, + Pixel{170, 0, 0}, + Pixel{170, 0, 170}, + Pixel{170, 85, 0}, + Pixel{170, 170, 170}, + Pixel{85, 85, 85}, + Pixel{85, 85, 255}, + Pixel{85, 255, 85}, + Pixel{85, 255, 255}, + Pixel{255, 85, 85}, + Pixel{255, 85, 255}, + Pixel{255, 255, 85}, + Pixel{255, 255, 255} +}; OwningFramebuffer::OwningFramebuffer(unsigned width, unsigned height, unsigned pitch) noexcept : Framebuffer(nullptr, width, height, pitch) @@ -18,6 +51,14 @@ OwningFramebuffer::OwningFramebuffer(unsigned width, unsigned height, unsigned p mBase = mPixels.data(); } +const Pixel& Framebuffer::getPixel(unsigned posX, unsigned posY) noexcept +{ + if (posX >= mWidth || posY >= mHeight) { + return VGA_PIXELS[0]; // black + } + return mBase[posY * mPitch + posX]; +} + void Framebuffer::setPixel(unsigned int posX, unsigned int posY, Pixel pixel) noexcept { if (posX >= mWidth || posY > mHeight) { @@ -33,6 +74,11 @@ void initializeDefaultFramebuffer(const Framebuffer& framebuffer) noexcept gDoubleBuffer = OwningFramebuffer::makeFrom(gFramebuffer); } +const Framebuffer& getPrimaryFramebuffer() noexcept +{ + return gFramebuffer; +} + void setPixelDirect(unsigned posX, unsigned posY, Pixel pixel) noexcept { gFramebuffer.setPixel(posX, posY, pixel); @@ -42,11 +88,58 @@ void setPixelDirect(unsigned posX, unsigned posY, Pixel pixel) noexcept void setPixel(unsigned posX, unsigned posY, Pixel pixel) noexcept { - gDoubleBuffer.setPixel(posX, posY, pixel); + setPixelDirect(posX, posY, pixel); + //gDoubleBuffer.setPixel(posX, posY, pixel); } -void flushPixels() noexcept +const Pixel& getPixel(unsigned posX, unsigned posY) noexcept { - std::memcpy(gFramebuffer.getBase(), gDoubleBuffer.getBase(), gFramebuffer.getBufferSize()); + return gDoubleBuffer.getPixel(posX, posY); +} + +void character(unsigned posX, unsigned posY, const psf::Font& font, char chr, const Pixel& fgColor, const Pixel& bgColor) noexcept +{ + auto draw = [&](unsigned pxX, unsigned pxY, const Pixel& pixel) + { + setPixel(posX + pxX, posY + pxY, pixel); + }; + font.writeGlyph(chr, fgColor, bgColor, draw); +} + +void scrollBy(int scrollX, int scrollY, const Pixel& fillColor) noexcept +{ + // if (scrollX == 0) + // { + // scrollVertical(scrollY, fillColor); + // return; + // } + const int width = static_cast(gFramebuffer.getHeight()); + const int height = static_cast(gFramebuffer.getHeight()); + const bool reverseX = scrollX < 0; + const bool reverseY = scrollY < 0; + + for (int posY = 0; posY < height; ++posY) + { + if (reverseY) { + posY = height - posY - 1; + } + for (int posX = 0; posX < width; ++posX) + { + if (reverseX) { + posX = width - posX - 1; + } + int readX = static_cast(posX) + scrollX; + int readY = static_cast(posY) + scrollY; + + if (readX < 0 || readX >= width || readY < 0 || readY >= height) + { + setPixel(posX, posY, fillColor); + } + else + { + setPixel(posX, posY, getPixel(readX, readY)); + } + } + } } } \ No newline at end of file diff --git a/targets/_any/src/os/resources/.gitignore b/targets/_any/src/os/resources/.gitignore new file mode 100644 index 0000000..c6aecae --- /dev/null +++ b/targets/_any/src/os/resources/.gitignore @@ -0,0 +1,3 @@ +# these are generated from the resources +*.hpp +*.s \ No newline at end of file diff --git a/targets/_any/src/os/resources/lat9-08.psf b/targets/_any/src/os/resources/lat9-08.psf new file mode 100644 index 0000000..75791ce Binary files /dev/null and b/targets/_any/src/os/resources/lat9-08.psf differ diff --git a/targets/_any/src/os/tty.cpp b/targets/_any/src/os/tty.cpp index ce008fe..8fb56c8 100644 --- a/targets/_any/src/os/tty.cpp +++ b/targets/_any/src/os/tty.cpp @@ -2,18 +2,23 @@ #include "os/tty.hpp" #include +#include +#include "libs/psf.hpp" +#include "os/draw.hpp" +#include "os/resources/lat9-08.psf.hpp" namespace tty { namespace { -inline const size_t VGA_WIDTH = 80; -inline const size_t VGA_HEIGHT = 25; - size_t gTerminalRow = 0; size_t gTerminalColumn = 0; +size_t gTerminalWidth = 0; +size_t gTerminalHeight = 0; VgaDoubleColor gTerminalColor = VgaDoubleColor(); -uint16_t* gTerminalBuffer = reinterpret_cast(0xB8000); +// uint16_t* gTerminalBuffer = reinterpret_cast(0xB8000); +std::vector gTerminalBuffer; +psf::Font gTerminalFont; constexpr uint8_t vgaEntryColor(VgaDoubleColor color) { @@ -28,42 +33,40 @@ constexpr uint16_t vgaEntry(const unsigned char chr, const VgaDoubleColor color) void newline() { gTerminalColumn = 0; - if (gTerminalRow < VGA_HEIGHT - 1) + if (gTerminalRow < gTerminalHeight - 1) { ++gTerminalRow; } else { - // scrolling up - std::memmove(&gTerminalBuffer[0], &gTerminalBuffer[VGA_WIDTH], VGA_WIDTH * (VGA_HEIGHT - 1) * sizeof(uint16_t)); + draw::scrollBy(0, static_cast(gTerminalFont.getGlyphHeight()) + 1); } } } -void initialize() +void initialize() noexcept { - for (size_t y = 0; y < VGA_HEIGHT; y++) - { - for (size_t x = 0; x < VGA_WIDTH; x++) - { - const size_t index = y * VGA_WIDTH + x; - gTerminalBuffer[index] = vgaEntry(' ', gTerminalColor); - } - } + setPSFFont(&LAT9_08[0], LAT9_08_SIZE); } -void setColor(VgaDoubleColor color) +void setColor(VgaDoubleColor color) noexcept { gTerminalColor = color; } -void putEntryAt(char chr, VgaDoubleColor color, size_t posX, size_t posY) +void putEntryAt(char chr, VgaDoubleColor color, size_t posX, size_t posY) noexcept { - const size_t index = posY * VGA_WIDTH + posX; - gTerminalBuffer[index] = vgaEntry(chr, color); + draw::character( + /* posX = */ (gTerminalFont.getGlyphWidth() + 1) * posX, + /* posY = */ (gTerminalFont.getGlyphHeight() + 1) * posY, + /* font = */ gTerminalFont, + /* chr = */ chr, + /* fgColor = */ draw::VGA_PIXELS[static_cast(color.foreground)], + /* bgColor = */ draw::VGA_PIXELS[static_cast(color.background)] + ); } -void putChar(char chr) +void putChar(char chr) noexcept { if (chr == '\n') { @@ -72,13 +75,13 @@ void putChar(char chr) } putEntryAt(chr, gTerminalColor, gTerminalColumn, gTerminalRow); - if (++gTerminalColumn == VGA_WIDTH) + if (++gTerminalColumn == gTerminalWidth) { newline(); } } -void write(const char* data, size_t size) +void write(const char* data, size_t size) noexcept { for (size_t idx = 0; idx < size; idx++) { @@ -86,8 +89,20 @@ void write(const char* data, size_t size) } } -void write(const char* data) +void write(const char* data) noexcept { write(data, std::strlen(data)); } + +bool setPSFFont(const void* data, size_t length) noexcept +{ + psf::Font newFont; + if (!psf::Font::create(data, length, newFont)) { + return false; + } + gTerminalFont = newFont; + gTerminalWidth = draw::getPrimaryFramebuffer().getWidth() / (gTerminalFont.getGlyphWidth() + 1); + gTerminalHeight = draw::getPrimaryFramebuffer().getHeight() / (gTerminalFont.getGlyphHeight() + 1); + return true; +} } diff --git a/targets/x86_64/SConscript b/targets/x86_64/SConscript index ce738bc..1cba6a8 100644 --- a/targets/x86_64/SConscript +++ b/targets/x86_64/SConscript @@ -28,6 +28,8 @@ crtn_o = kernel_env.Object('src/crt/crtn.s') kernel_env['LINKCOM'] = env['LINKCOM'].replace('$_LIBFLAGS', f'{crti_o[0].abspath} {crtbegin_o} $_LIBFLAGS -lgcc {crtend_o} {crtn_o[0].abspath}') kernel_sources = env['KERNEL_SOURCES'] + Split(''' + src/cstdlib/memory.s + src/kernel/boot.s src/kernel/startup.cpp ''') @@ -37,7 +39,7 @@ prog_kernel = kernel_env.Program( target = kernel_target, source = kernel_sources ) -kernel_env.Depends(prog_kernel, [crti_o, crtn_o]) +kernel_env.Depends(prog_kernel, [crti_o, crtn_o] + kernel_sources) kernel_env.Default(prog_kernel) x86_64_iso_files = [ @@ -69,7 +71,6 @@ uefi_env.Append(CPPPATH = ['/usr/include/efi', 'include']) loader_sources = Split(''' src/loader/main.cpp - src/loader/minimalloc.cpp src/loader/miniprintf.cpp ''') loader_target = uefi_env.File('#loader.x86_64.efi') diff --git a/targets/x86_64/include/boot.hpp b/targets/x86_64/include/boot.hpp index 032d265..91f81f3 100644 --- a/targets/x86_64/include/boot.hpp +++ b/targets/x86_64/include/boot.hpp @@ -75,7 +75,34 @@ struct EfiDisplayInfo struct EfiBootInfo { EfiMemoryMap memoryMap; - EfiDisplayInfo displayInfo; + EfiDisplayInfo displayInfo = {}; }; + +inline bool isEfiMemoryTypeUsable(UINT32 type) noexcept +{ + 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; + } +} + + #endif // BOOT_HPP_INCLUDED diff --git a/targets/x86_64/src/cstdlib/memory.s b/targets/x86_64/src/cstdlib/memory.s new file mode 100644 index 0000000..753676c --- /dev/null +++ b/targets/x86_64/src/cstdlib/memory.s @@ -0,0 +1,27 @@ + +.section .text +.global memcpy +.type memcpy @function + +// int memcpy(void* dest [%rdi], void* src [%rsi], size_t count [%rdx]) +// +memcpy: + cmpq %rdx, 4 + jl memcpy_bytes + movq (%rsi), %rax + movq %rax, (%rdi) + addq $4, %rsi + addq $4, %rdi + subq $4, %rdx + jmp memcpy +memcpy_bytes: + cmpq %rdx, 0 + je memcpy_end + movb (%rsi), %ah + movb %ah, (%rdi) + addq $1, %rsi + addq $1, %rdi + subq $1, %rdx + jmp memcpy_bytes +memcpy_end: + ret diff --git a/targets/x86_64/src/kernel/startup.cpp b/targets/x86_64/src/kernel/startup.cpp index 0cdcea6..7cf7bad 100644 --- a/targets/x86_64/src/kernel/startup.cpp +++ b/targets/x86_64/src/kernel/startup.cpp @@ -1,5 +1,6 @@ #include +#include #include "boot.hpp" #include "os/draw.hpp" @@ -14,8 +15,7 @@ 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) + if (!isEfiMemoryTypeUsable(descriptor.Type)) { continue; } @@ -97,7 +97,7 @@ void kernel_main() initGlobals(); // init the heap (required for the double buffer) - initHeapFromEfiMemoryMap(gBootInfo->memoryMap); + // initHeapFromEfiMemoryMap(gBootInfo->memoryMap); // initialize the framebuffer draw::initializeDefaultFramebuffer({ @@ -108,18 +108,27 @@ void kernel_main() }); // initialize terminal interface - // tty::initialize(); + tty::initialize(); // std::printf("Kernel End: %p\n", &gKernelEnd); + uint8_t test[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + uint8_t dest[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + std::memcpy(&dest[1], &test[3], 2); + for (int i = 0; i < 400; ++i) + { + std::printf("Hello font %d!\n", i); + } +#if 0 for (int x = 0; x < 100; ++x) { for (int y = 0; y < 100; ++y) { - draw::setPixel(x, y, {.red = 255}); + draw::setPixelDirect(x, y, {.red = 255}); } } - draw::flushPixels(); +#endif + //draw::flushPixels(); /* Initialize the heap */ // assert(gMultibootHeader->flags & MULTIBOOT_INFO_MEM_MAP); diff --git a/targets/x86_64/src/loader/main.cpp b/targets/x86_64/src/loader/main.cpp index c0677f4..0ad7f3a 100644 --- a/targets/x86_64/src/loader/main.cpp +++ b/targets/x86_64/src/loader/main.cpp @@ -5,13 +5,15 @@ extern "C" } #include "boot.hpp" #include "minielf.hpp" -#include "minimalloc.hpp" #include "miniprintf.hpp" // debug stuff // #define DUMP_DISPLAY_MODES // #define DUMP_MEMORY_MAP // #define DUMP_ELF +#define PRINTLINE3(file, line) print(L"At: " file L":" #line L"\r\n") +#define PRINTLINE2(file, line) PRINTLINE3(file, line) +#define PRINTLINE() PRINTLINE2(__FILE__, __LINE__) namespace { @@ -19,6 +21,21 @@ EFI_SYSTEM_TABLE* gSystemTable; EFI_BOOT_SERVICES* gBootServices; EFI_GRAPHICS_OUTPUT_PROTOCOL* gGraphicsOutputProtocol; +void* malloc(size_t size) noexcept +{ + void* ptr = nullptr; + gBootServices->AllocatePool(EfiLoaderData, size, &ptr); + return ptr; +} + +void free(void* ptr) noexcept +{ + // if (ptr != nullptr) + // { + // gBootServices->FreePool(ptr); + // } +} + EFI_STATUS openImageVolume(EFI_HANDLE image, EFI_FILE_HANDLE& outHandle) { EFI_LOADED_IMAGE* loadedImage = nullptr; @@ -112,18 +129,29 @@ EFI_STATUS getEfiMemoryMap(EfiMemoryMap& outMemoryMap) 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; + + EFI_STATUS status = EFI_BUFFER_TOO_SMALL; + while (true) + { + status = gBootServices->GetMemoryMap(&mapSize, map, &mapKey, &descriptorSize, &descriptorVersion); + if (status != EFI_BUFFER_TOO_SMALL) { + break; + } + if (map != nullptr) + { + free(map); + } + map = static_cast(malloc(mapSize)); + if (map == nullptr) { + return EFI_OUT_OF_RESOURCES; + } } - 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); + if (map != nullptr) + { + gBootServices->FreePool(map); + } return status; } outMemoryMap.mapSize = mapSize; @@ -150,7 +178,7 @@ EFI_STATUS getEfiGraphicsOutputProtocol(EFI_GRAPHICS_OUTPUT_PROTOCOL*& outGOP) EFI_STATUS queryEfiDisplayModes(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION*& outModes) { UINTN sizeOfInfo = gGraphicsOutputProtocol->Mode->SizeOfInfo; - outModes = new EFI_GRAPHICS_OUTPUT_MODE_INFORMATION[gGraphicsOutputProtocol->Mode->MaxMode]; + outModes = static_cast(malloc(gGraphicsOutputProtocol->Mode->MaxMode * sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION))); EFI_GRAPHICS_OUTPUT_MODE_INFORMATION* buffer = static_cast(malloc(sizeOfInfo)); for (UINT32 modeIdx = 0; modeIdx < gGraphicsOutputProtocol->Mode->MaxMode; ++modeIdx) @@ -158,7 +186,7 @@ EFI_STATUS queryEfiDisplayModes(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION*& outModes) EFI_STATUS status = gGraphicsOutputProtocol->QueryMode(gGraphicsOutputProtocol, modeIdx, &sizeOfInfo, &buffer); if (EFI_ERROR(status)) { - delete[] outModes; + free(outModes); free(buffer); return status; } @@ -187,37 +215,86 @@ UINT32 findBestDisplayMode(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION* displayModes) return bestMode; } -bool isEfiMemoryTypeUsable(EFI_MEMORY_TYPE type) +const char* efiStatusToString(EFI_STATUS status) { - switch (type) + switch (status) { - 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: + case EFI_SUCCESS: + return "EFI_SUCCESS"; + case EFI_LOAD_ERROR: + return "EFI_LOAD_ERROR"; + case EFI_INVALID_PARAMETER: + return "EFI_INVALID_PARAMETER"; + case EFI_UNSUPPORTED: + return "EFI_UNSUPPORTED"; + case EFI_BAD_BUFFER_SIZE: + return "EFI_BAD_BUFFER_SIZE"; + case EFI_BUFFER_TOO_SMALL: + return "EFI_BUFFER_TOO_SMALL"; + case EFI_NOT_READY: + return "EFI_NOT_READY"; + case EFI_DEVICE_ERROR: + return "EFI_DEVICE_ERROR"; + case EFI_WRITE_PROTECTED: + return "EFI_WRITE_PROTECTED"; + case EFI_OUT_OF_RESOURCES: + return "EFI_OUT_OF_RESOURCES"; + case EFI_VOLUME_CORRUPTED: + return "EFI_VOLUME_CORRUPTED"; + case EFI_VOLUME_FULL: + return "EFI_VOLUME_FULL"; + case EFI_NO_MEDIA: + return "EFI_NO_MEDIA"; + case EFI_MEDIA_CHANGED: + return "EFI_MEDIA_CHANGED"; + case EFI_NOT_FOUND: + return "EFI_NOT_FOUND"; + case EFI_ACCESS_DENIED: + return "EFI_ACCESS_DENIED"; + case EFI_NO_RESPONSE: + return "EFI_NO_RESPONSE"; + case EFI_NO_MAPPING: + return "EFI_NO_MAPPING"; + case EFI_TIMEOUT: + return "EFI_TIMEOUT"; + case EFI_NOT_STARTED: + return "EFI_NOT_STARTED"; + case EFI_ALREADY_STARTED: + return "EFI_ALREADY_STARTED"; + case EFI_ABORTED: + return "EFI_ABORTED"; + case EFI_ICMP_ERROR: + return "EFI_ICMP_ERROR"; + case EFI_TFTP_ERROR: + return "EFI_TFTP_ERROR"; + case EFI_PROTOCOL_ERROR: + return "EFI_PROTOCOL_ERROR"; + case EFI_INCOMPATIBLE_VERSION: + return "EFI_INCOMPATIBLE_VERSION"; + case EFI_SECURITY_VIOLATION: + return "EFI_SECURITY_VIOLATION"; + case EFI_CRC_ERROR: + return "EFI_CRC_ERROR"; + case EFI_END_OF_MEDIA: + return "EFI_END_OF_MEDIA"; + case EFI_END_OF_FILE: + return "EFI_END_OF_FILE"; + case EFI_INVALID_LANGUAGE: + return "EFI_INVALID_LANGUAGE"; + case EFI_COMPROMISED_DATA: + return "EFI_COMPROMISED_DATA"; default: - return false; + return "UNKNOWN"; } } } -#define DIE_ON_ERROR(message) \ -if (EFI_ERROR(status)) \ -{ \ - printAndWait(message L"\r\n"); \ - return status; \ +#define DIE_ON_ERROR(message) \ +if (EFI_ERROR(status)) \ +{ \ + printf("Status: %s\n", efiStatusToString(status)); \ + printAndWait(message L"\r\n"); \ + return status; \ } extern "C" EFI_STATUS efi_main(EFI_HANDLE imageHandle, EFI_SYSTEM_TABLE* systemTable) @@ -226,11 +303,10 @@ extern "C" EFI_STATUS efi_main(EFI_HANDLE imageHandle, EFI_SYSTEM_TABLE* systemT gSystemTable = systemTable; gBootServices = systemTable->BootServices; - initMiniMalloc(); initMiniPrintf(&putchar); // this will be passed to the OS - EfiBootInfo* bootInfo = new EfiBootInfo; + EfiBootInfo* bootInfo = static_cast(malloc(sizeof(EfiBootInfo))); gSystemTable->ConOut->ClearScreen(gSystemTable->ConOut); @@ -246,6 +322,10 @@ extern "C" EFI_STATUS efi_main(EFI_HANDLE imageHandle, EFI_SYSTEM_TABLE* systemT status = gGraphicsOutputProtocol->SetMode(gGraphicsOutputProtocol, bestModeIdx); DIE_ON_ERROR(L"Error setting display mode."); + UINTN consoleColumns, consoleRows; + status = gSystemTable->ConOut->QueryMode(gSystemTable->ConOut, gSystemTable->ConOut->Mode->Mode, &consoleColumns, &consoleRows); + DIE_ON_ERROR(L"Error fetching console mode."); + bootInfo->displayInfo = { .frameBufferBase = reinterpret_cast(gGraphicsOutputProtocol->Mode->FrameBufferBase), .frameBufferSize = gGraphicsOutputProtocol->Mode->FrameBufferSize, @@ -329,14 +409,24 @@ extern "C" EFI_STATUS efi_main(EFI_HANDLE imageHandle, EFI_SYSTEM_TABLE* systemT #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) { + UINTN leftThisPage = consoleRows - 1; + printf("ltp: %d\n", static_cast(leftThisPage)); + for (const EFI_MEMORY_DESCRIPTOR& descriptor : bootInfo->memoryMap) + { + if (!isEfiMemoryTypeUsable(descriptor.Type)) { + // if (descriptor.Type != EfiBootServicesCode) { continue; } + + ++entry; + if (leftThisPage == 0) + { + printAndWait(L"-- Any key to continue --\r\n"); + leftThisPage = consoleRows; + } + --leftThisPage; + printf( "Entry %d: type=%d, physicalStart=0x%lX, numberOfPages=%ld\n", entry, @@ -347,7 +437,7 @@ extern "C" EFI_STATUS efi_main(EFI_HANDLE imageHandle, EFI_SYSTEM_TABLE* systemT } // printing may have invalidated the map, get it again - status = getEfiMemoryMap(*memoryMap); + status = getEfiMemoryMap(bootInfo->memoryMap); DIE_ON_ERROR("Error getting EFI memory map."); #undef DUMP_MEMORY_MAP #endif // defined(DUMP_MEMORY_MAP) diff --git a/targets/x86_64/src/loader/minimalloc.cpp b/targets/x86_64/src/loader/minimalloc.cpp deleted file mode 100644 index 339f15a..0000000 --- a/targets/x86_64/src/loader/minimalloc.cpp +++ /dev/null @@ -1,126 +0,0 @@ - - -#include - -namespace -{ -inline const size_t INIT_MALLOC_SPACE_ELEMENTS = 1024; -inline const size_t INIT_MALLOC_SPACE_BYTES = INIT_MALLOC_SPACE_ELEMENTS * sizeof(max_align_t); - -max_align_t gInitMallocSpace[INIT_MALLOC_SPACE_ELEMENTS]; - -struct MallocBlock -{ - size_t elements; - MallocBlock* nextBlock; -}; -struct AllocInfo -{ - size_t elements; -}; -static_assert(sizeof(MallocBlock) <= sizeof(max_align_t)); -static_assert(sizeof(AllocInfo) <= sizeof(max_align_t)); - -MallocBlock* gNextBlock; -} - -void initMiniMalloc() -{ - gNextBlock = reinterpret_cast(gInitMallocSpace); - gNextBlock->elements = INIT_MALLOC_SPACE_ELEMENTS; - gNextBlock->nextBlock = nullptr; -} - -extern "C" -{ -void* malloc(size_t size) noexcept -{ - if (size == 0) - { - return nullptr; - } - - const size_t requiredElements = (size + sizeof(max_align_t) - 1) / sizeof(max_align_t) + 1; - MallocBlock* prevBlock = nullptr; - for (MallocBlock* block = gNextBlock; block != nullptr; block = block->nextBlock) - { - if (block->elements >= requiredElements) - { - MallocBlock* newBlock = nullptr; - if (block->elements > requiredElements) - { - newBlock = reinterpret_cast(reinterpret_cast(block) + requiredElements); - newBlock->nextBlock = block->nextBlock; - newBlock->elements = block->elements - requiredElements; - } - else - { - newBlock = block->nextBlock; - } - if (prevBlock != nullptr) - { - prevBlock->nextBlock = newBlock; - } - else - { - gNextBlock = newBlock; - } - AllocInfo* allocInfo = reinterpret_cast(block); - allocInfo->elements = requiredElements; - return reinterpret_cast(block) + 1; - } - prevBlock = block; - } - - return nullptr; -} - -void free(void* memory) noexcept -{ - if (memory == nullptr) - { - return; - } - MallocBlock* block = reinterpret_cast(static_cast(memory) - 1); - block->nextBlock = gNextBlock; - gNextBlock = block; -} -} - -void* operator new(size_t count) -{ - if (void* ptr = malloc(count); ptr != nullptr) - { - return ptr; - } - // TODO: some kind of abort -} - -void operator delete(void* data) noexcept -{ - free(data); -} - -void* operator new[](size_t count) -{ - if (void* ptr = malloc(count); ptr != nullptr) - { - return ptr; - } - // TODO: some kind of abort -} - -void operator delete[](void* data) noexcept -{ - free(data); -} - -void operator delete(void* data, size_t /* size */) noexcept -{ - free(data); -} - -void operator delete[](void* data, size_t /* size */) noexcept -{ - free(data); -}