[WIP] Implementing "console" output and stuff.
This commit is contained in:
parent
e938f76823
commit
6ec9e0d320
@ -15,6 +15,7 @@ target = GetOption('target')
|
|||||||
|
|
||||||
env = Environment(tools = ['default', 'compilation_db'])
|
env = Environment(tools = ['default', 'compilation_db'])
|
||||||
env.Append(CCFLAGS = ['-g', '-O0'])
|
env.Append(CCFLAGS = ['-g', '-O0'])
|
||||||
|
# env.Append(CCFLAGS = ['-O2'])
|
||||||
|
|
||||||
env['ISO_FILES'] = []
|
env['ISO_FILES'] = []
|
||||||
env = SConscript('bastl/SConscript', exports = 'env')
|
env = SConscript('bastl/SConscript', exports = 'env')
|
||||||
|
@ -24,7 +24,7 @@ public:
|
|||||||
using iterator = pointer;
|
using iterator = pointer;
|
||||||
using const_iterator = const_pointer;
|
using const_iterator = const_pointer;
|
||||||
|
|
||||||
T _elements;
|
T _elements[N];
|
||||||
|
|
||||||
constexpr reference operator[](size_type pos) noexcept
|
constexpr reference operator[](size_type pos) noexcept
|
||||||
{
|
{
|
||||||
|
@ -1,17 +1,54 @@
|
|||||||
Import('env')
|
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 <stdint.h>
|
||||||
|
|
||||||
|
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('''
|
any_target_sources = Split('''
|
||||||
src/app/main.cpp
|
src/app/main.cpp
|
||||||
|
|
||||||
|
src/libs/psf.cpp
|
||||||
|
|
||||||
src/os/draw.cpp
|
src/os/draw.cpp
|
||||||
src/os/panic.cpp
|
src/os/panic.cpp
|
||||||
src/os/tty.cpp
|
src/os/tty.cpp
|
||||||
|
src/os/resources/lat9-08.psf.s
|
||||||
|
|
||||||
src/cstdlib/assert.cpp
|
src/cstdlib/assert.cpp
|
||||||
src/cstdlib/stdio.cpp
|
src/cstdlib/stdio.cpp
|
||||||
src/cstdlib/stdlib.cpp
|
src/cstdlib/stdlib.cpp
|
||||||
src/cstdlib/string.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])
|
env.Append(KERNEL_SOURCES = [env.File(f) for f in any_target_sources])
|
||||||
|
|
||||||
|
77
targets/_any/include/libs/psf.hpp
Normal file
77
targets/_any/include/libs/psf.hpp
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#if !defined(BAD_APPLE_OS_PSF_HPP_INCLUDED)
|
||||||
|
#define BAD_APPLE_OS_PSF_HPP_INCLUDED
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
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<typename TColor, typename TDrawFn>
|
||||||
|
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<typename TColor, typename TDrawFn>
|
||||||
|
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<const uint8_t*>(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)
|
@ -5,8 +5,13 @@
|
|||||||
#define BAD_APPLE_OS_DRAW_HPP_INCLUDED
|
#define BAD_APPLE_OS_DRAW_HPP_INCLUDED
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <array>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
namespace psf
|
||||||
|
{
|
||||||
|
class Font;
|
||||||
|
}
|
||||||
namespace draw
|
namespace draw
|
||||||
{
|
{
|
||||||
const unsigned SIZE_FULL = static_cast<unsigned>(-1);
|
const unsigned SIZE_FULL = static_cast<unsigned>(-1);
|
||||||
@ -19,6 +24,10 @@ struct Pixel
|
|||||||
uint8_t reserved_ = 0;
|
uint8_t reserved_ = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
inline Pixel PIXEL_WHITE = {255, 255, 255};
|
||||||
|
inline Pixel PIXEL_BLACK = {0, 0, 0};
|
||||||
|
extern const std::array<Pixel, 16> VGA_PIXELS;
|
||||||
|
|
||||||
class Framebuffer
|
class Framebuffer
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
@ -38,6 +47,7 @@ public:
|
|||||||
[[nodiscard]] unsigned getPitch() const noexcept { return mPitch; }
|
[[nodiscard]] unsigned getPitch() const noexcept { return mPitch; }
|
||||||
[[nodiscard]] unsigned getBufferSize() const noexcept { return mPitch * mHeight * sizeof(Pixel); }
|
[[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;
|
void setPixel(unsigned posX, unsigned posY, Pixel pixel) noexcept;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -61,9 +71,15 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
void initializeDefaultFramebuffer(const Framebuffer& framebuffer) noexcept;
|
void initializeDefaultFramebuffer(const Framebuffer& framebuffer) noexcept;
|
||||||
|
[[nodiscard]] const Framebuffer& getPrimaryFramebuffer() noexcept;
|
||||||
|
|
||||||
void setPixelDirect(unsigned posX, unsigned posY, Pixel pixel) noexcept;
|
void setPixelDirect(unsigned posX, unsigned posY, Pixel pixel) noexcept;
|
||||||
void setPixel(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)
|
#endif // !defined(BAD_APPLE_OS_FRAMEBUFFER_HPP_INCLUDED)
|
||||||
|
1
targets/_any/include/os/resources/.gitignore
vendored
Normal file
1
targets/_any/include/os/resources/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
*.hpp
|
@ -35,12 +35,14 @@ struct VgaDoubleColor
|
|||||||
VgaColor background : 4 = VgaColor::BLACK;
|
VgaColor background : 4 = VgaColor::BLACK;
|
||||||
};
|
};
|
||||||
|
|
||||||
void initialize();
|
void initialize() noexcept;
|
||||||
void setColor(VgaDoubleColor color);
|
void setColor(VgaDoubleColor color) noexcept;
|
||||||
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;
|
||||||
void putChar(char chr);
|
void putChar(char chr) noexcept;
|
||||||
void write(const char* data, size_t size);
|
void write(const char* data, size_t size) noexcept;
|
||||||
void write(const char* data);
|
void write(const char* data) noexcept;
|
||||||
|
|
||||||
|
bool setPSFFont(const void* data, size_t length) noexcept;
|
||||||
} // namespace tty
|
} // namespace tty
|
||||||
|
|
||||||
#endif // OS_TTY_HPP_INCLUDED
|
#endif // OS_TTY_HPP_INCLUDED
|
||||||
|
@ -11,7 +11,7 @@ BA_EXTERN_C_BEGIN
|
|||||||
|
|
||||||
int putchar(int chr) BA_CXX_NOEXCEPT;
|
int putchar(int chr) BA_CXX_NOEXCEPT;
|
||||||
int puts(const char* str) 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;
|
int vprintf(const char* format, va_list vlist) BA_CXX_NOEXCEPT;
|
||||||
|
|
||||||
BA_EXTERN_C_END
|
BA_EXTERN_C_END
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
namespace
|
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);
|
inline const size_t INIT_MALLOC_SPACE_BYTES = INIT_MALLOC_SPACE_ELEMENTS * sizeof(max_align_t);
|
||||||
|
|
||||||
max_align_t gInitMallocSpace[INIT_MALLOC_SPACE_ELEMENTS];
|
max_align_t gInitMallocSpace[INIT_MALLOC_SPACE_ELEMENTS];
|
||||||
|
@ -19,6 +19,7 @@ int memcmp(const void* lhs, const void* rhs, size_t count) noexcept
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !defined(__x86_64__)
|
||||||
void memcpy(void* dest, const void* src, size_t count) noexcept
|
void memcpy(void* dest, const void* src, size_t count) noexcept
|
||||||
{
|
{
|
||||||
for (size_t pos = 0; pos < count; ++pos)
|
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<uint8_t*>(dest) + pos) = *(static_cast<const uint8_t*>(src) + pos);
|
*(static_cast<uint8_t*>(dest) + pos) = *(static_cast<const uint8_t*>(src) + pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void memmove(void* dest, const void* src, size_t count) noexcept
|
void memmove(void* dest, const void* src, size_t count) noexcept
|
||||||
{
|
{
|
||||||
|
18
targets/_any/src/libs/psf.cpp
Normal file
18
targets/_any/src/libs/psf.cpp
Normal file
@ -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<const Header*>(data);
|
||||||
|
if (header->magic != MAGIC) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
outFont = Font(header, size);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
@ -2,6 +2,7 @@
|
|||||||
#include "os/draw.hpp"
|
#include "os/draw.hpp"
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include "libs/psf.hpp"
|
||||||
|
|
||||||
namespace draw
|
namespace draw
|
||||||
{
|
{
|
||||||
@ -9,7 +10,39 @@ namespace
|
|||||||
{
|
{
|
||||||
Framebuffer gFramebuffer;
|
Framebuffer gFramebuffer;
|
||||||
OwningFramebuffer gDoubleBuffer;
|
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<Pixel, 16> 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
|
OwningFramebuffer::OwningFramebuffer(unsigned width, unsigned height, unsigned pitch) noexcept
|
||||||
: Framebuffer(nullptr, width, height, pitch)
|
: Framebuffer(nullptr, width, height, pitch)
|
||||||
@ -18,6 +51,14 @@ OwningFramebuffer::OwningFramebuffer(unsigned width, unsigned height, unsigned p
|
|||||||
mBase = mPixels.data();
|
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
|
void Framebuffer::setPixel(unsigned int posX, unsigned int posY, Pixel pixel) noexcept
|
||||||
{
|
{
|
||||||
if (posX >= mWidth || posY > mHeight) {
|
if (posX >= mWidth || posY > mHeight) {
|
||||||
@ -33,6 +74,11 @@ void initializeDefaultFramebuffer(const Framebuffer& framebuffer) noexcept
|
|||||||
gDoubleBuffer = OwningFramebuffer::makeFrom(gFramebuffer);
|
gDoubleBuffer = OwningFramebuffer::makeFrom(gFramebuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const Framebuffer& getPrimaryFramebuffer() noexcept
|
||||||
|
{
|
||||||
|
return gFramebuffer;
|
||||||
|
}
|
||||||
|
|
||||||
void setPixelDirect(unsigned posX, unsigned posY, Pixel pixel) noexcept
|
void setPixelDirect(unsigned posX, unsigned posY, Pixel pixel) noexcept
|
||||||
{
|
{
|
||||||
gFramebuffer.setPixel(posX, posY, pixel);
|
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
|
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<int>(gFramebuffer.getHeight());
|
||||||
|
const int height = static_cast<int>(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<int>(posX) + scrollX;
|
||||||
|
int readY = static_cast<int>(posY) + scrollY;
|
||||||
|
|
||||||
|
if (readX < 0 || readX >= width || readY < 0 || readY >= height)
|
||||||
|
{
|
||||||
|
setPixel(posX, posY, fillColor);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
setPixel(posX, posY, getPixel(readX, readY));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
3
targets/_any/src/os/resources/.gitignore
vendored
Normal file
3
targets/_any/src/os/resources/.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# these are generated from the resources
|
||||||
|
*.hpp
|
||||||
|
*.s
|
BIN
targets/_any/src/os/resources/lat9-08.psf
Normal file
BIN
targets/_any/src/os/resources/lat9-08.psf
Normal file
Binary file not shown.
@ -2,18 +2,23 @@
|
|||||||
#include "os/tty.hpp"
|
#include "os/tty.hpp"
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <vector>
|
||||||
|
#include "libs/psf.hpp"
|
||||||
|
#include "os/draw.hpp"
|
||||||
|
#include "os/resources/lat9-08.psf.hpp"
|
||||||
|
|
||||||
namespace tty
|
namespace tty
|
||||||
{
|
{
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
inline const size_t VGA_WIDTH = 80;
|
|
||||||
inline const size_t VGA_HEIGHT = 25;
|
|
||||||
|
|
||||||
size_t gTerminalRow = 0;
|
size_t gTerminalRow = 0;
|
||||||
size_t gTerminalColumn = 0;
|
size_t gTerminalColumn = 0;
|
||||||
|
size_t gTerminalWidth = 0;
|
||||||
|
size_t gTerminalHeight = 0;
|
||||||
VgaDoubleColor gTerminalColor = VgaDoubleColor();
|
VgaDoubleColor gTerminalColor = VgaDoubleColor();
|
||||||
uint16_t* gTerminalBuffer = reinterpret_cast<uint16_t*>(0xB8000);
|
// uint16_t* gTerminalBuffer = reinterpret_cast<uint16_t*>(0xB8000);
|
||||||
|
std::vector<uint16_t> gTerminalBuffer;
|
||||||
|
psf::Font gTerminalFont;
|
||||||
|
|
||||||
constexpr uint8_t vgaEntryColor(VgaDoubleColor color)
|
constexpr uint8_t vgaEntryColor(VgaDoubleColor color)
|
||||||
{
|
{
|
||||||
@ -28,42 +33,40 @@ constexpr uint16_t vgaEntry(const unsigned char chr, const VgaDoubleColor color)
|
|||||||
void newline()
|
void newline()
|
||||||
{
|
{
|
||||||
gTerminalColumn = 0;
|
gTerminalColumn = 0;
|
||||||
if (gTerminalRow < VGA_HEIGHT - 1)
|
if (gTerminalRow < gTerminalHeight - 1)
|
||||||
{
|
{
|
||||||
++gTerminalRow;
|
++gTerminalRow;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// scrolling up
|
draw::scrollBy(0, static_cast<int>(gTerminalFont.getGlyphHeight()) + 1);
|
||||||
std::memmove(&gTerminalBuffer[0], &gTerminalBuffer[VGA_WIDTH], VGA_WIDTH * (VGA_HEIGHT - 1) * sizeof(uint16_t));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void initialize()
|
void initialize() noexcept
|
||||||
{
|
{
|
||||||
for (size_t y = 0; y < VGA_HEIGHT; y++)
|
setPSFFont(&LAT9_08[0], LAT9_08_SIZE);
|
||||||
{
|
|
||||||
for (size_t x = 0; x < VGA_WIDTH; x++)
|
|
||||||
{
|
|
||||||
const size_t index = y * VGA_WIDTH + x;
|
|
||||||
gTerminalBuffer[index] = vgaEntry(' ', gTerminalColor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void setColor(VgaDoubleColor color)
|
void setColor(VgaDoubleColor color) noexcept
|
||||||
{
|
{
|
||||||
gTerminalColor = color;
|
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;
|
draw::character(
|
||||||
gTerminalBuffer[index] = vgaEntry(chr, color);
|
/* posX = */ (gTerminalFont.getGlyphWidth() + 1) * posX,
|
||||||
|
/* posY = */ (gTerminalFont.getGlyphHeight() + 1) * posY,
|
||||||
|
/* font = */ gTerminalFont,
|
||||||
|
/* chr = */ chr,
|
||||||
|
/* fgColor = */ draw::VGA_PIXELS[static_cast<uint8_t>(color.foreground)],
|
||||||
|
/* bgColor = */ draw::VGA_PIXELS[static_cast<uint8_t>(color.background)]
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void putChar(char chr)
|
void putChar(char chr) noexcept
|
||||||
{
|
{
|
||||||
if (chr == '\n')
|
if (chr == '\n')
|
||||||
{
|
{
|
||||||
@ -72,13 +75,13 @@ void putChar(char chr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
putEntryAt(chr, gTerminalColor, gTerminalColumn, gTerminalRow);
|
putEntryAt(chr, gTerminalColor, gTerminalColumn, gTerminalRow);
|
||||||
if (++gTerminalColumn == VGA_WIDTH)
|
if (++gTerminalColumn == gTerminalWidth)
|
||||||
{
|
{
|
||||||
newline();
|
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++)
|
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));
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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_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('''
|
kernel_sources = env['KERNEL_SOURCES'] + Split('''
|
||||||
|
src/cstdlib/memory.s
|
||||||
|
|
||||||
src/kernel/boot.s
|
src/kernel/boot.s
|
||||||
src/kernel/startup.cpp
|
src/kernel/startup.cpp
|
||||||
''')
|
''')
|
||||||
@ -37,7 +39,7 @@ prog_kernel = kernel_env.Program(
|
|||||||
target = kernel_target,
|
target = kernel_target,
|
||||||
source = kernel_sources
|
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)
|
kernel_env.Default(prog_kernel)
|
||||||
|
|
||||||
x86_64_iso_files = [
|
x86_64_iso_files = [
|
||||||
@ -69,7 +71,6 @@ uefi_env.Append(CPPPATH = ['/usr/include/efi', 'include'])
|
|||||||
|
|
||||||
loader_sources = Split('''
|
loader_sources = Split('''
|
||||||
src/loader/main.cpp
|
src/loader/main.cpp
|
||||||
src/loader/minimalloc.cpp
|
|
||||||
src/loader/miniprintf.cpp
|
src/loader/miniprintf.cpp
|
||||||
''')
|
''')
|
||||||
loader_target = uefi_env.File('#loader.x86_64.efi')
|
loader_target = uefi_env.File('#loader.x86_64.efi')
|
||||||
|
@ -75,7 +75,34 @@ struct EfiDisplayInfo
|
|||||||
struct EfiBootInfo
|
struct EfiBootInfo
|
||||||
{
|
{
|
||||||
EfiMemoryMap memoryMap;
|
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
|
#endif // BOOT_HPP_INCLUDED
|
||||||
|
27
targets/x86_64/src/cstdlib/memory.s
Normal file
27
targets/x86_64/src/cstdlib/memory.s
Normal file
@ -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
|
@ -1,5 +1,6 @@
|
|||||||
|
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
#include <cstring>
|
||||||
#include "boot.hpp"
|
#include "boot.hpp"
|
||||||
|
|
||||||
#include "os/draw.hpp"
|
#include "os/draw.hpp"
|
||||||
@ -14,8 +15,7 @@ void initHeapFromEfiMemoryMap(const EfiMemoryMap& memoryMap) noexcept
|
|||||||
const uint64_t minAddr = reinterpret_cast<uint64_t>(&gKernelEnd);
|
const uint64_t minAddr = reinterpret_cast<uint64_t>(&gKernelEnd);
|
||||||
for (const EFI_MEMORY_DESCRIPTOR& descriptor : memoryMap)
|
for (const EFI_MEMORY_DESCRIPTOR& descriptor : memoryMap)
|
||||||
{
|
{
|
||||||
// TODO: what about other types?
|
if (!isEfiMemoryTypeUsable(descriptor.Type))
|
||||||
if (descriptor.Type != EfiConventionalMemory)
|
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -97,7 +97,7 @@ void kernel_main()
|
|||||||
initGlobals();
|
initGlobals();
|
||||||
|
|
||||||
// init the heap (required for the double buffer)
|
// init the heap (required for the double buffer)
|
||||||
initHeapFromEfiMemoryMap(gBootInfo->memoryMap);
|
// initHeapFromEfiMemoryMap(gBootInfo->memoryMap);
|
||||||
|
|
||||||
// initialize the framebuffer
|
// initialize the framebuffer
|
||||||
draw::initializeDefaultFramebuffer({
|
draw::initializeDefaultFramebuffer({
|
||||||
@ -108,18 +108,27 @@ void kernel_main()
|
|||||||
});
|
});
|
||||||
|
|
||||||
// initialize terminal interface
|
// initialize terminal interface
|
||||||
// tty::initialize();
|
tty::initialize();
|
||||||
|
|
||||||
// std::printf("Kernel End: %p\n", &gKernelEnd);
|
// 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 x = 0; x < 100; ++x)
|
||||||
{
|
{
|
||||||
for (int y = 0; y < 100; ++y)
|
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 */
|
/* Initialize the heap */
|
||||||
// assert(gMultibootHeader->flags & MULTIBOOT_INFO_MEM_MAP);
|
// assert(gMultibootHeader->flags & MULTIBOOT_INFO_MEM_MAP);
|
||||||
|
@ -5,13 +5,15 @@ extern "C"
|
|||||||
}
|
}
|
||||||
#include "boot.hpp"
|
#include "boot.hpp"
|
||||||
#include "minielf.hpp"
|
#include "minielf.hpp"
|
||||||
#include "minimalloc.hpp"
|
|
||||||
#include "miniprintf.hpp"
|
#include "miniprintf.hpp"
|
||||||
|
|
||||||
// debug stuff
|
// debug stuff
|
||||||
// #define DUMP_DISPLAY_MODES
|
// #define DUMP_DISPLAY_MODES
|
||||||
// #define DUMP_MEMORY_MAP
|
// #define DUMP_MEMORY_MAP
|
||||||
// #define DUMP_ELF
|
// #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
|
namespace
|
||||||
{
|
{
|
||||||
@ -19,6 +21,21 @@ EFI_SYSTEM_TABLE* gSystemTable;
|
|||||||
EFI_BOOT_SERVICES* gBootServices;
|
EFI_BOOT_SERVICES* gBootServices;
|
||||||
EFI_GRAPHICS_OUTPUT_PROTOCOL* gGraphicsOutputProtocol;
|
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_STATUS openImageVolume(EFI_HANDLE image, EFI_FILE_HANDLE& outHandle)
|
||||||
{
|
{
|
||||||
EFI_LOADED_IMAGE* loadedImage = nullptr;
|
EFI_LOADED_IMAGE* loadedImage = nullptr;
|
||||||
@ -112,18 +129,29 @@ EFI_STATUS getEfiMemoryMap(EfiMemoryMap& outMemoryMap)
|
|||||||
UINTN mapKey = 0;
|
UINTN mapKey = 0;
|
||||||
UINTN descriptorSize = 0;
|
UINTN descriptorSize = 0;
|
||||||
UINT32 descriptorVersion = 0;
|
UINT32 descriptorVersion = 0;
|
||||||
EFI_STATUS status = gBootServices->GetMemoryMap(&mapSize, nullptr, &mapKey, &descriptorSize, &descriptorVersion);
|
|
||||||
if (status != EFI_BUFFER_TOO_SMALL) {
|
EFI_STATUS status = EFI_BUFFER_TOO_SMALL;
|
||||||
return status;
|
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<EFI_MEMORY_DESCRIPTOR*>(malloc(mapSize));
|
||||||
|
if (map == nullptr) {
|
||||||
|
return EFI_OUT_OF_RESOURCES;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
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))
|
if (EFI_ERROR(status))
|
||||||
{
|
{
|
||||||
free(map);
|
if (map != nullptr)
|
||||||
|
{
|
||||||
|
gBootServices->FreePool(map);
|
||||||
|
}
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
outMemoryMap.mapSize = mapSize;
|
outMemoryMap.mapSize = mapSize;
|
||||||
@ -150,7 +178,7 @@ EFI_STATUS getEfiGraphicsOutputProtocol(EFI_GRAPHICS_OUTPUT_PROTOCOL*& outGOP)
|
|||||||
EFI_STATUS queryEfiDisplayModes(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION*& outModes)
|
EFI_STATUS queryEfiDisplayModes(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION*& outModes)
|
||||||
{
|
{
|
||||||
UINTN sizeOfInfo = gGraphicsOutputProtocol->Mode->SizeOfInfo;
|
UINTN sizeOfInfo = gGraphicsOutputProtocol->Mode->SizeOfInfo;
|
||||||
outModes = new EFI_GRAPHICS_OUTPUT_MODE_INFORMATION[gGraphicsOutputProtocol->Mode->MaxMode];
|
outModes = static_cast<EFI_GRAPHICS_OUTPUT_MODE_INFORMATION*>(malloc(gGraphicsOutputProtocol->Mode->MaxMode * sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION)));
|
||||||
EFI_GRAPHICS_OUTPUT_MODE_INFORMATION* buffer = static_cast<EFI_GRAPHICS_OUTPUT_MODE_INFORMATION*>(malloc(sizeOfInfo));
|
EFI_GRAPHICS_OUTPUT_MODE_INFORMATION* buffer = static_cast<EFI_GRAPHICS_OUTPUT_MODE_INFORMATION*>(malloc(sizeOfInfo));
|
||||||
|
|
||||||
for (UINT32 modeIdx = 0; modeIdx < gGraphicsOutputProtocol->Mode->MaxMode; ++modeIdx)
|
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);
|
EFI_STATUS status = gGraphicsOutputProtocol->QueryMode(gGraphicsOutputProtocol, modeIdx, &sizeOfInfo, &buffer);
|
||||||
if (EFI_ERROR(status))
|
if (EFI_ERROR(status))
|
||||||
{
|
{
|
||||||
delete[] outModes;
|
free(outModes);
|
||||||
free(buffer);
|
free(buffer);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
@ -187,37 +215,86 @@ UINT32 findBestDisplayMode(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION* displayModes)
|
|||||||
return bestMode;
|
return bestMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isEfiMemoryTypeUsable(EFI_MEMORY_TYPE type)
|
const char* efiStatusToString(EFI_STATUS status)
|
||||||
{
|
{
|
||||||
switch (type)
|
switch (status)
|
||||||
{
|
{
|
||||||
case EfiLoaderCode:
|
case EFI_SUCCESS:
|
||||||
case EfiLoaderData:
|
return "EFI_SUCCESS";
|
||||||
case EfiBootServicesCode:
|
case EFI_LOAD_ERROR:
|
||||||
case EfiBootServicesData:
|
return "EFI_LOAD_ERROR";
|
||||||
case EfiConventionalMemory:
|
case EFI_INVALID_PARAMETER:
|
||||||
return true;
|
return "EFI_INVALID_PARAMETER";
|
||||||
case EfiReservedMemoryType:
|
case EFI_UNSUPPORTED:
|
||||||
case EfiRuntimeServicesCode:
|
return "EFI_UNSUPPORTED";
|
||||||
case EfiRuntimeServicesData:
|
case EFI_BAD_BUFFER_SIZE:
|
||||||
case EfiUnusableMemory:
|
return "EFI_BAD_BUFFER_SIZE";
|
||||||
case EfiACPIReclaimMemory:
|
case EFI_BUFFER_TOO_SMALL:
|
||||||
case EfiACPIMemoryNVS:
|
return "EFI_BUFFER_TOO_SMALL";
|
||||||
case EfiMemoryMappedIO:
|
case EFI_NOT_READY:
|
||||||
case EfiMemoryMappedIOPortSpace:
|
return "EFI_NOT_READY";
|
||||||
case EfiPalCode:
|
case EFI_DEVICE_ERROR:
|
||||||
case EfiMaxMemoryType:
|
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:
|
default:
|
||||||
return false;
|
return "UNKNOWN";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define DIE_ON_ERROR(message) \
|
#define DIE_ON_ERROR(message) \
|
||||||
if (EFI_ERROR(status)) \
|
if (EFI_ERROR(status)) \
|
||||||
{ \
|
{ \
|
||||||
printAndWait(message L"\r\n"); \
|
printf("Status: %s\n", efiStatusToString(status)); \
|
||||||
return status; \
|
printAndWait(message L"\r\n"); \
|
||||||
|
return 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)
|
||||||
@ -226,11 +303,10 @@ extern "C" EFI_STATUS efi_main(EFI_HANDLE imageHandle, EFI_SYSTEM_TABLE* systemT
|
|||||||
gSystemTable = systemTable;
|
gSystemTable = systemTable;
|
||||||
gBootServices = systemTable->BootServices;
|
gBootServices = systemTable->BootServices;
|
||||||
|
|
||||||
initMiniMalloc();
|
|
||||||
initMiniPrintf(&putchar);
|
initMiniPrintf(&putchar);
|
||||||
|
|
||||||
// this will be passed to the OS
|
// this will be passed to the OS
|
||||||
EfiBootInfo* bootInfo = new EfiBootInfo;
|
EfiBootInfo* bootInfo = static_cast<EfiBootInfo*>(malloc(sizeof(EfiBootInfo)));
|
||||||
|
|
||||||
gSystemTable->ConOut->ClearScreen(gSystemTable->ConOut);
|
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);
|
status = gGraphicsOutputProtocol->SetMode(gGraphicsOutputProtocol, bestModeIdx);
|
||||||
DIE_ON_ERROR(L"Error setting display mode.");
|
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 = {
|
bootInfo->displayInfo = {
|
||||||
.frameBufferBase = reinterpret_cast<void*>(gGraphicsOutputProtocol->Mode->FrameBufferBase),
|
.frameBufferBase = reinterpret_cast<void*>(gGraphicsOutputProtocol->Mode->FrameBufferBase),
|
||||||
.frameBufferSize = gGraphicsOutputProtocol->Mode->FrameBufferSize,
|
.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)
|
#if defined(DUMP_MEMORY_MAP)
|
||||||
int entry = -1;
|
int entry = -1;
|
||||||
for (const EFI_MEMORY_DESCRIPTOR& descriptor : *memoryMap)
|
|
||||||
{
|
|
||||||
++entry;
|
|
||||||
|
|
||||||
// if (!isEfiMemoryTypeUsable(static_cast<EFI_MEMORY_TYPE>(descriptor->Type))) {
|
UINTN leftThisPage = consoleRows - 1;
|
||||||
if (descriptor.Type != EfiConventionalMemory) {
|
printf("ltp: %d\n", static_cast<int>(leftThisPage));
|
||||||
|
for (const EFI_MEMORY_DESCRIPTOR& descriptor : bootInfo->memoryMap)
|
||||||
|
{
|
||||||
|
if (!isEfiMemoryTypeUsable(descriptor.Type)) {
|
||||||
|
// if (descriptor.Type != EfiBootServicesCode) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
++entry;
|
||||||
|
if (leftThisPage == 0)
|
||||||
|
{
|
||||||
|
printAndWait(L"-- Any key to continue --\r\n");
|
||||||
|
leftThisPage = consoleRows;
|
||||||
|
}
|
||||||
|
--leftThisPage;
|
||||||
|
|
||||||
printf(
|
printf(
|
||||||
"Entry %d: type=%d, physicalStart=0x%lX, numberOfPages=%ld\n",
|
"Entry %d: type=%d, physicalStart=0x%lX, numberOfPages=%ld\n",
|
||||||
entry,
|
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
|
// printing may have invalidated the map, get it again
|
||||||
status = getEfiMemoryMap(*memoryMap);
|
status = getEfiMemoryMap(bootInfo->memoryMap);
|
||||||
DIE_ON_ERROR("Error getting EFI memory map.");
|
DIE_ON_ERROR("Error getting EFI memory map.");
|
||||||
#undef DUMP_MEMORY_MAP
|
#undef DUMP_MEMORY_MAP
|
||||||
#endif // defined(DUMP_MEMORY_MAP)
|
#endif // defined(DUMP_MEMORY_MAP)
|
||||||
|
@ -1,126 +0,0 @@
|
|||||||
|
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
|
|
||||||
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<MallocBlock*>(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<MallocBlock*>(reinterpret_cast<max_align_t*>(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<AllocInfo*>(block);
|
|
||||||
allocInfo->elements = requiredElements;
|
|
||||||
return reinterpret_cast<max_align_t*>(block) + 1;
|
|
||||||
}
|
|
||||||
prevBlock = block;
|
|
||||||
}
|
|
||||||
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void free(void* memory) noexcept
|
|
||||||
{
|
|
||||||
if (memory == nullptr)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
MallocBlock* block = reinterpret_cast<MallocBlock*>(static_cast<max_align_t*>(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);
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user