Implemented a kinda broken tty

This commit is contained in:
Alex 2022-10-09 04:01:49 +03:00
parent e332fc57e0
commit 7c4d43fec3
Signed by untrusted user who does not match committer: enderice2
GPG Key ID: EACC3AD603BAB4DD
11 changed files with 496 additions and 133 deletions

View File

@ -1,63 +1,86 @@
#include <cpu.hpp> #include <cpu.hpp>
#include <memory.hpp>
namespace CPU namespace CPU
{ {
void Pause() void Pause()
{ {
#if defined(__amd64__) || defined(__i386__) #if defined(__amd64__) || defined(__i386__)
asmv("pause"); asmv("pause");
#elif defined(__aarch64__) #elif defined(__aarch64__)
asmv("yield"); asmv("yield");
#endif #endif
} }
void Halt() void Halt()
{ {
#if defined(__amd64__) || defined(__i386__) #if defined(__amd64__) || defined(__i386__)
asmv("hlt"); asmv("hlt");
#elif defined(__aarch64__) #elif defined(__aarch64__)
asmv("wfe"); asmv("wfe");
#endif #endif
} }
bool Interrupts(InterruptsType Type) bool Interrupts(InterruptsType Type)
{ {
switch (Type) switch (Type)
{ {
case Check: case Check:
{ {
#if defined(__amd64__) || defined(__i386__) #if defined(__amd64__) || defined(__i386__)
uint64_t rflags; uint64_t rflags;
asmv("pushfq"); asmv("pushfq");
asmv("popq %0" asmv("popq %0"
: "=r"(rflags)); : "=r"(rflags));
return rflags & (1 << 9); return rflags & (1 << 9);
#elif defined(__aarch64__) #elif defined(__aarch64__)
uint64_t daif; uint64_t daif;
asmv("mrs %0, daif" asmv("mrs %0, daif"
: "=r"(daif)); : "=r"(daif));
return !(daif & (1 << 2)); return !(daif & (1 << 2));
#endif #endif
} }
case Enable: case Enable:
{ {
#if defined(__amd64__) || defined(__i386__) #if defined(__amd64__) || defined(__i386__)
asmv("sti"); asmv("sti");
#elif defined(__aarch64__) #elif defined(__aarch64__)
asmv("msr daifclr, #2"); asmv("msr daifclr, #2");
#endif #endif
return true; return true;
} }
case Disable: case Disable:
{ {
#if defined(__amd64__) || defined(__i386__) #if defined(__amd64__) || defined(__i386__)
asmv("cli"); asmv("cli");
#elif defined(__aarch64__) #elif defined(__aarch64__)
asmv("msr daifset, #2"); asmv("msr daifset, #2");
#endif #endif
return true; return true;
} }
} }
return false; return false;
} }
void *PageTable(void *PT)
{
#if defined(__amd64__) || defined(__i386__)
if (PT)
asmv("movq %0, %%cr3"
:
: "r"(PT));
else
asmv("movq %%cr3, %0"
: "=r"(PT));
#elif defined(__aarch64__)
if (PT)
asmv("msr ttbr0_el1, %0"
:
: "r"(PT));
else
asmv("mrs %0, ttbr0_el1"
: "=r"(PT));
#endif
return PT;
}
} }

View File

@ -52,7 +52,7 @@ void init_limine()
while (1) while (1)
asmv("hlt"); asmv("hlt");
} }
TerminalResponse->write(TerminalResponse->terminals[0], "Please wait... ", 15); TerminalResponse->write(TerminalResponse->terminals[0], "\033[37mPlease wait... ", 20);
struct limine_framebuffer_response *FrameBufferResponse = FramebufferRequest.response; struct limine_framebuffer_response *FrameBufferResponse = FramebufferRequest.response;
struct limine_memmap_response *MemmapResponse = MemmapRequest.response; struct limine_memmap_response *MemmapResponse = MemmapRequest.response;

View File

@ -28,7 +28,7 @@ void tracepagetable(PageTable *pt)
for (int i = 0; i < 512; i++) for (int i = 0; i < 512; i++)
{ {
if (pt->Entries[i].Value.Present) if (pt->Entries[i].Value.Present)
debug("Entry %d: %x %x %x %x %x %x %x %x %x %x %x %p-%#lx", i, debug("Entry %03d: %x %x %x %x %x %x %x %x %x %x %x %p-%#lx", i,
pt->Entries[i].Value.Present, pt->Entries[i].Value.ReadWrite, pt->Entries[i].Value.Present, pt->Entries[i].Value.ReadWrite,
pt->Entries[i].Value.UserSupervisor, pt->Entries[i].Value.WriteThrough, pt->Entries[i].Value.UserSupervisor, pt->Entries[i].Value.WriteThrough,
pt->Entries[i].Value.CacheDisable, pt->Entries[i].Value.Accessed, pt->Entries[i].Value.CacheDisable, pt->Entries[i].Value.Accessed,

View File

@ -118,6 +118,13 @@ namespace Memory
this->Unmap((void *)((uint64_t)VirtualAddress + (i * PAGE_SIZE))); this->Unmap((void *)((uint64_t)VirtualAddress + (i * PAGE_SIZE)));
} }
Virtual::Virtual(PageTable *Table) { this->Table = Table; } Virtual::Virtual(PageTable *Table)
{
if (Table)
this->Table = Table;
else
this->Table = (PageTable *)CPU::PageTable();
}
Virtual::~Virtual() {} Virtual::~Virtual() {}
} }

111
core/Video/Display.cpp Normal file
View File

@ -0,0 +1,111 @@
#include <display.hpp>
#include <lock.hpp>
#include <debug.h>
extern uint64_t _binary_files_ter_powerline_v12n_psf_start;
extern uint64_t _binary_files_ter_powerline_v12n_psf_end;
extern uint64_t _binary_files_ter_powerline_v12n_psf_size;
NEWLOCK(PrintLock);
namespace Video
{
char Display::Print(char Char, int Index)
{
SMARTLOCK(PrintLock);
switch (Char)
{
case '\b':
{
if (Buffers[Index]->CursorX > 0)
Buffers[Index]->CursorX -= this->GetCurrentFont()->GetInfo().Width;
return Char;
}
case '\t':
{
Buffers[Index]->CursorX = (Buffers[Index]->CursorX + 8) & ~(8 - 1);
return Char;
}
case '\r':
{
Buffers[Index]->CursorX = 0;
return Char;
}
case '\n':
{
Buffers[Index]->CursorX = 0;
Buffers[Index]->CursorY += this->GetCurrentFont()->GetInfo().Height;
return Char;
}
}
if (Buffers[Index]->CursorX + this->GetCurrentFont()->GetInfo().Width >= Buffers[Index]->Width)
{
Buffers[Index]->CursorX = 0;
Buffers[Index]->CursorY += this->GetCurrentFont()->GetInfo().Height;
}
if (Buffers[Index]->CursorY + this->GetCurrentFont()->GetInfo().Height >= Buffers[Index]->Height)
{
Buffers[Index]->CursorY = Buffers[Index]->Height - this->GetCurrentFont()->GetInfo().Height;
this->SetBuffer(Index);
Scroll(Index, 1);
}
if (CurrentFont->GetInfo().Type == FontType::PCScreenFont2)
{
// if (CurrentFont->PSF2Font->GlyphBuffer == (uint16_t *)0x01) // HAS UNICODE TABLE
// Char = CurrentFont->PSF2Font->GlyphBuffer[Char];
int bytesperline = (CurrentFont->GetInfo().PSF2Font->Header->width + 7) / 8;
char *FontPtr = (char *)CurrentFont->GetInfo().StartAddress +
CurrentFont->GetInfo().PSF2Font->Header->headersize +
(Char > 0 && (unsigned char)Char < CurrentFont->GetInfo().PSF2Font->Header->length ? Char : 0) *
CurrentFont->GetInfo().PSF2Font->Header->charsize;
for (unsigned long Y = Buffers[Index]->CursorY; Y < Buffers[Index]->CursorY + CurrentFont->GetInfo().PSF2Font->Header->height; Y++)
{
for (unsigned long X = Buffers[Index]->CursorX; X < Buffers[Index]->CursorX + CurrentFont->GetInfo().PSF2Font->Header->width; X++)
if ((*FontPtr & (0b10000000 >> (X - Buffers[Index]->CursorX))) > 0)
*(uint32_t *)((uint64_t)Buffers[Index]->Buffer + (Y * Buffers[Index]->Width + X) * (framebuffer.BitsPerPixel / 8)) = 0xFFFFFF;
FontPtr += bytesperline;
}
Buffers[Index]->CursorX += CurrentFont->GetInfo().PSF2Font->Header->width;
return Char;
}
else if (CurrentFont->GetInfo().Type == FontType::PCScreenFont1)
{
uint32_t *PixelPtr = (uint32_t *)Buffers[Index]->Buffer;
char *FontPtr = (char *)CurrentFont->GetInfo().PSF1Font->GlyphBuffer + (Char * CurrentFont->GetInfo().PSF1Font->Header->charsize);
for (unsigned long Y = Buffers[Index]->CursorY; Y < Buffers[Index]->CursorY + 16; Y++)
{
for (unsigned long X = Buffers[Index]->CursorX; X < Buffers[Index]->CursorX + 8; X++)
if ((*FontPtr & (0b10000000 >> (X - Buffers[Index]->CursorX))) > 0)
*(unsigned int *)(PixelPtr + X + (Y * Buffers[Index]->Width)) = Buffers[Index]->Color;
FontPtr++;
}
Buffers[Index]->CursorX += 8;
return Char;
}
return Char;
}
Display::Display(BootInfo::FramebufferInfo Info, bool LoadDefaultFont)
{
framebuffer = Info;
if (LoadDefaultFont)
{
CurrentFont = new Font(&_binary_files_ter_powerline_v12n_psf_start, &_binary_files_ter_powerline_v12n_psf_end, FontType::PCScreenFont2);
FontInfo Info = CurrentFont->GetInfo();
debug("Font loaded: %dx%d %s",
Info.Width, Info.Height, Info.Type == FontType::PCScreenFont1 ? "PSF1" : "PSF2");
}
this->CreateBuffer(Info.Width, Info.Height, 0);
}
Display::~Display()
{
for (int i = 0; i < 16; i++)
DeleteBuffer(i);
}
}

54
core/Video/Font.cpp Normal file
View File

@ -0,0 +1,54 @@
#include <display.hpp>
#include <debug.h>
#include <cstring>
namespace Video
{
Font::Font(uint64_t *Start, uint64_t *End, FontType Type)
{
trace("Initializing font with start %#llx and end %#llx Type: %d", Start, End, Type);
this->Info.StartAddress = Start;
this->Info.EndAddress = End;
this->Info.Type = Type;
if (Type == FontType::PCScreenFont2)
{
this->Info.PSF2Font = new PSF2_FONT;
uint64_t FontDataLength = End - Start;
PSF2_HEADER *font2 = (PSF2_HEADER *)KernelAllocator.RequestPages(FontDataLength / PAGE_SIZE + 1);
for (uint64_t i = 0; i < FontDataLength / PAGE_SIZE + 1; i++)
Memory::Virtual().Map((void *)(font2 + (i * PAGE_SIZE)), (void *)(font2 + (i * PAGE_SIZE)), Memory::PTFlag::RW);
memcpy((void *)font2, Start, FontDataLength);
this->Info.Width = font2->width;
this->Info.Height = font2->height;
if (font2->magic[0] != PSF2_MAGIC0 || font2->magic[1] != PSF2_MAGIC1 || font2->magic[2] != PSF2_MAGIC2 || font2->magic[3] != PSF2_MAGIC3)
error("Font2 magic mismatch.");
this->Info.PSF2Font->Header = font2;
this->Info.PSF2Font->GlyphBuffer = reinterpret_cast<void *>(reinterpret_cast<uint64_t>(Start) + sizeof(PSF2_HEADER));
}
else if (Type == FontType::PCScreenFont1)
{
this->Info.PSF1Font = new PSF1_FONT;
PSF1_HEADER *font1 = (PSF1_HEADER *)Start;
if (font1->magic[0] != PSF1_MAGIC0 || font1->magic[1] != PSF1_MAGIC1)
error("Font1 magic mismatch.");
uint32_t glyphBufferSize = font1->charsize * 256;
if (font1->mode == 1) // 512 glyph mode
glyphBufferSize = font1->charsize * 512;
void *glyphBuffer = reinterpret_cast<void *>(reinterpret_cast<uint64_t>(Start) + sizeof(PSF1_HEADER));
this->Info.PSF1Font->Header = font1;
this->Info.PSF1Font->GlyphBuffer = glyphBuffer;
UNUSED(glyphBufferSize); // TODO: Use this in the future?
// TODO: Get font size.
this->Info.Width = 16;
this->Info.Height = 8;
}
}
Font::~Font()
{
}
}

View File

@ -8,127 +8,134 @@
*/ */
namespace CPU namespace CPU
{ {
/**
* @brief Enum for CPU::Interrupts() function.
*/
enum InterruptsType
{
/** /**
* @brief Check if interrupts are enabled. * @brief Enum for CPU::Interrupts() function.
*/ */
Check, enum InterruptsType
{
/**
* @brief Check if interrupts are enabled.
*/
Check,
/**
* @brief Enable interrupts.
*/
Enable,
/**
* @brief Disable interrupts.
*/
Disable
};
/** /**
* @brief Enable interrupts. * @brief Pause the CPU
*/ */
Enable, void Pause();
/** /**
* @brief Disable interrupts. * @brief Halt the CPU
*/ */
Disable void Halt();
}; /**
* @brief Check if interrupts are enabled
*
* @return true If InterruptsType::Check and interrupts are enabled, or if other InterruptsType were executed successfully
* @return false If InterruptsType::Check and interrupts are disabled, or if other InterruptsType failed
*/
bool Interrupts(InterruptsType Type = Check);
/**
* @brief Get/Set the CPU's page table
*
* @param PT The new page table, if empty, the current page table will be returned
* @return void* The current page table
*/
void *PageTable(void *PT = nullptr);
/** namespace MemBar
* @brief Pause the CPU
*/
void Pause();
/**
* @brief Halt the CPU
*/
void Halt();
/**
* @brief Check if interrupts are enabled
*
* @return true If InterruptsType::Check and interrupts are enabled, or if other InterruptsType were executed successfully
* @return false If InterruptsType::Check and interrupts are disabled, or if other InterruptsType failed
*/
bool Interrupts(InterruptsType Type = Check);
namespace MemBar
{
static inline void Barrier()
{ {
static inline void Barrier()
{
#if defined(__amd64__) || defined(__i386__) #if defined(__amd64__) || defined(__i386__)
asmv("" :: asmv("" ::
: "memory"); : "memory");
#elif defined(__aarch64__) #elif defined(__aarch64__)
asmv("dmb ish" :: asmv("dmb ish" ::
: "memory"); : "memory");
#endif #endif
} }
static inline void Fence() static inline void Fence()
{ {
#if defined(__amd64__) || defined(__i386__) #if defined(__amd64__) || defined(__i386__)
asmv("mfence" :: asmv("mfence" ::
: "memory"); : "memory");
#elif defined(__aarch64__) #elif defined(__aarch64__)
asmv("dmb ish" :: asmv("dmb ish" ::
: "memory"); : "memory");
#endif #endif
} }
static inline void StoreFence() static inline void StoreFence()
{ {
#if defined(__amd64__) || defined(__i386__) #if defined(__amd64__) || defined(__i386__)
asmv("sfence" :: asmv("sfence" ::
: "memory"); : "memory");
#elif defined(__aarch64__) #elif defined(__aarch64__)
asmv("dmb ishst" :: asmv("dmb ishst" ::
: "memory"); : "memory");
#endif #endif
} }
static inline void LoadFence() static inline void LoadFence()
{ {
#if defined(__amd64__) || defined(__i386__) #if defined(__amd64__) || defined(__i386__)
asmv("lfence" :: asmv("lfence" ::
: "memory"); : "memory");
#elif defined(__aarch64__) #elif defined(__aarch64__)
asmv("dmb ishld" :: asmv("dmb ishld" ::
: "memory"); : "memory");
#endif
}
}
namespace x86
{
static inline void lgdt(void *gdt)
{
#if defined(__amd64__) || defined(__i386__)
asmv("lgdt (%0)"
:
: "r"(gdt));
#endif #endif
}
} }
static inline void lidt(void *idt) namespace x86
{ {
static inline void lgdt(void *gdt)
{
#if defined(__amd64__) || defined(__i386__) #if defined(__amd64__) || defined(__i386__)
asmv("lidt (%0)" asmv("lgdt (%0)"
: :
: "r"(idt)); : "r"(gdt));
#endif #endif
} }
static inline void ltr(uint16_t Segment) static inline void lidt(void *idt)
{ {
#if defined(__amd64__) || defined(__i386__) #if defined(__amd64__) || defined(__i386__)
asmv("ltr %0" asmv("lidt (%0)"
: :
: "r"(Segment)); : "r"(idt));
#endif #endif
} }
static inline void invlpg(void *Address) static inline void ltr(uint16_t Segment)
{ {
#if defined(__amd64__) || defined(__i386__) #if defined(__amd64__) || defined(__i386__)
asmv("invlpg (%0)" asmv("ltr %0"
: :
: "r"(Address) : "r"(Segment));
: "memory");
#endif #endif
}
static inline void invlpg(void *Address)
{
#if defined(__amd64__) || defined(__i386__)
asmv("invlpg (%0)"
:
: "r"(Address)
: "memory");
#endif
}
} }
}
} }
#endif // !__FENNIX_KERNEL_CPU_H__ #endif // !__FENNIX_KERNEL_CPU_H__

159
include/display.hpp Normal file
View File

@ -0,0 +1,159 @@
#ifndef __FENNIX_KERNEL_DISPLAY_H__
#define __FENNIX_KERNEL_DISPLAY_H__
#include <types.h>
#include <boot/binfo.h>
#include <memory.hpp>
namespace Video
{
#define PSF1_MAGIC0 0x36
#define PSF1_MAGIC1 0x04
#define PSF2_MAGIC0 0x72
#define PSF2_MAGIC1 0xb5
#define PSF2_MAGIC2 0x4a
#define PSF2_MAGIC3 0x86
struct PSF1_HEADER
{
uint8_t magic[2];
uint8_t mode;
uint8_t charsize;
};
struct PSF2_HEADER
{
uint8_t magic[4];
uint32_t version;
uint32_t headersize;
uint32_t flags;
uint32_t length;
uint32_t charsize;
uint32_t height, width;
};
typedef struct _PSF1_FONT
{
PSF1_HEADER *Header;
void *GlyphBuffer;
} PSF1_FONT;
typedef struct _PSF2_FONT
{
PSF2_HEADER *Header;
void *GlyphBuffer;
} PSF2_FONT;
enum FontType
{
None,
PCScreenFont1,
PCScreenFont2
};
struct FontInfo
{
uint64_t *StartAddress;
uint64_t *EndAddress;
PSF1_FONT *PSF1Font;
PSF2_FONT *PSF2Font;
uint32_t Width, Height;
FontType Type;
};
class Font
{
private:
FontInfo Info;
public:
FontInfo GetInfo() { return Info; }
Font(uint64_t *Start, uint64_t *End, FontType Type);
~Font();
};
struct ScreenBuffer
{
void *Buffer;
uint32_t Width, Height;
uint64_t Size;
uint32_t Color;
uint32_t CursorX, CursorY;
};
class Display
{
private:
BootInfo::FramebufferInfo framebuffer;
Font *CurrentFont;
ScreenBuffer *Buffers[16];
public:
Font *GetCurrentFont() { return CurrentFont; }
void SetCurrentFont(Font *Font) { CurrentFont = Font; }
void CreateBuffer(uint32_t Width, uint32_t Height, int Index)
{
uint64_t Size = framebuffer.Pitch * Height;
ScreenBuffer *buffer = new ScreenBuffer;
buffer->Buffer = KernelAllocator.RequestPages(TO_PAGES(Size));
buffer->Width = Width;
buffer->Height = Height;
buffer->Size = Size;
buffer->Color = 0x000000;
buffer->CursorX = 0;
buffer->CursorY = 0;
Buffers[Index] = buffer;
__builtin_memset(buffer->Buffer, 0, Size);
}
void SetBuffer(int Index) { __builtin_memcpy(framebuffer.BaseAddress, Buffers[Index]->Buffer, Buffers[Index]->Size); }
void ClearBuffer(int Index) { __builtin_memset(Buffers[Index]->Buffer, 0, Buffers[Index]->Size); }
void DeleteBuffer(int Index)
{
if (Buffers[Index] == nullptr)
return;
KernelAllocator.FreePages(Buffers[Index]->Buffer, TO_PAGES(Buffers[Index]->Size));
delete Buffers[Index];
}
void SetPixel(uint32_t X, uint32_t Y, uint32_t Color, int Index)
{
if (X >= Buffers[Index]->Width || Y >= Buffers[Index]->Height)
return;
uint32_t *Pixel = (uint32_t *)((uint64_t)Buffers[Index]->Buffer + (Y * Buffers[Index]->Width + X) * (framebuffer.BitsPerPixel / 8));
*Pixel = Color;
}
uint32_t GetPixel(uint32_t X, uint32_t Y, int Index)
{
if (X >= Buffers[Index]->Width || Y >= Buffers[Index]->Height)
return 0;
uint32_t *Pixel = (uint32_t *)((uint64_t)Buffers[Index]->Buffer + (Y * Buffers[Index]->Width + X) * (framebuffer.BitsPerPixel / 8));
return *Pixel;
}
void Scroll(int Index, int Lines)
{
if (Lines == 0)
return;
if (Lines > 0)
{
__builtin_memmove(Buffers[Index]->Buffer,
(uint8_t *)Buffers[Index]->Buffer + (Buffers[Index]->Width * (framebuffer.BitsPerPixel / 8) * Lines),
Buffers[Index]->Size - (Buffers[Index]->Width * (framebuffer.BitsPerPixel / 8) * Lines));
__builtin_memset((uint8_t *)Buffers[Index]->Buffer + (Buffers[Index]->Size - (Buffers[Index]->Width * (framebuffer.BitsPerPixel / 8) * Lines)),
0,
Buffers[Index]->Width * (framebuffer.BitsPerPixel / 8) * Lines);
}
}
char Print(char Char, int Index);
Display(BootInfo::FramebufferInfo Info, bool LoadDefaultFont = true);
~Display();
};
}
#endif // !__FENNIX_KERNEL_DISPLAY_H__

View File

@ -396,9 +396,9 @@ namespace Memory
/** /**
* @brief Construct a new Virtual object * @brief Construct a new Virtual object
* *
* @param Table Page table * @param Table Page table. If null, it will use the current page table.
*/ */
Virtual(PageTable *Table); Virtual(PageTable *Table = nullptr);
/** /**
* @brief Destroy the Virtual object * @brief Destroy the Virtual object
* *

View File

@ -32,6 +32,8 @@
#define in : #define in :
#endif #endif
#define UNUSED(x) (void)(x)
#ifndef __va_list__ #ifndef __va_list__
typedef __builtin_va_list va_list; typedef __builtin_va_list va_list;
#endif #endif

View File

@ -911,7 +911,7 @@ static /* double */ unsigned long pow10_of_int(int floored_exp10)
double_with_bit_access dwba; double_with_bit_access dwba;
// int exp2 = bastardized_floor(floored_exp10 * 3.321928094887362 + 0.5); // int exp2 = bastardized_floor(floored_exp10 * 3.321928094887362 + 0.5);
// const /* double */ unsigned long z = floored_exp10 * 2.302585092994046 - exp2 * 0.6931471805599453; // const /* double */ unsigned long z = floored_exp10 * 2.302585092994046 - exp2 * 0.6931471805599453;
int exp2 = bastardized_floor(floored_exp10 * 3 + 1/* 0.5 */); int exp2 = bastardized_floor(floored_exp10 * 3 + 1 /* 0.5 */);
const /* double */ unsigned long z = floored_exp10 * 2 - exp2 * 0; const /* double */ unsigned long z = floored_exp10 * 2 - exp2 * 0;
const /* double */ unsigned long z2 = z * z; const /* double */ unsigned long z2 = z * z;
dwba.U = ((double_uint_t)(exp2) + DOUBLE_BASE_EXPONENT) << DOUBLE_STORED_MANTISSA_BITS; dwba.U = ((double_uint_t)(exp2) + DOUBLE_BASE_EXPONENT) << DOUBLE_STORED_MANTISSA_BITS;