From 7c4d43fec3dc2dff29a9c998ecd8f5c035f6e5d0 Mon Sep 17 00:00:00 2001 From: Alex Date: Sun, 9 Oct 2022 04:01:49 +0300 Subject: [PATCH] Implemented a kinda broken tty --- arch/CPU.cpp | 105 ++++++++++------ arch/amd64/Limine.c | 2 +- core/Memory/Memory.cpp | 2 +- core/Memory/VirtualMemoryManager.cpp | 9 +- core/Video/Display.cpp | 111 +++++++++++++++++ core/Video/Font.cpp | 54 ++++++++ include/cpu.hpp | 179 ++++++++++++++------------- include/display.hpp | 159 ++++++++++++++++++++++++ include/memory.hpp | 4 +- include/types.h | 2 + lib/printf.c | 2 +- 11 files changed, 496 insertions(+), 133 deletions(-) create mode 100644 core/Video/Display.cpp create mode 100644 core/Video/Font.cpp create mode 100644 include/display.hpp diff --git a/arch/CPU.cpp b/arch/CPU.cpp index d3d7dc5..6e8e058 100644 --- a/arch/CPU.cpp +++ b/arch/CPU.cpp @@ -1,63 +1,86 @@ #include +#include namespace CPU { - void Pause() - { + void Pause() + { #if defined(__amd64__) || defined(__i386__) - asmv("pause"); + asmv("pause"); #elif defined(__aarch64__) - asmv("yield"); + asmv("yield"); #endif - } + } - void Halt() - { + void Halt() + { #if defined(__amd64__) || defined(__i386__) - asmv("hlt"); + asmv("hlt"); #elif defined(__aarch64__) - asmv("wfe"); + asmv("wfe"); #endif - } + } - bool Interrupts(InterruptsType Type) - { - switch (Type) - { - case Check: - { + bool Interrupts(InterruptsType Type) + { + switch (Type) + { + case Check: + { #if defined(__amd64__) || defined(__i386__) - uint64_t rflags; - asmv("pushfq"); - asmv("popq %0" - : "=r"(rflags)); - return rflags & (1 << 9); + uint64_t rflags; + asmv("pushfq"); + asmv("popq %0" + : "=r"(rflags)); + return rflags & (1 << 9); #elif defined(__aarch64__) - uint64_t daif; - asmv("mrs %0, daif" - : "=r"(daif)); - return !(daif & (1 << 2)); + uint64_t daif; + asmv("mrs %0, daif" + : "=r"(daif)); + return !(daif & (1 << 2)); #endif - } - case Enable: - { + } + case Enable: + { #if defined(__amd64__) || defined(__i386__) - asmv("sti"); + asmv("sti"); #elif defined(__aarch64__) - asmv("msr daifclr, #2"); + asmv("msr daifclr, #2"); #endif - return true; - } - case Disable: - { + return true; + } + case Disable: + { #if defined(__amd64__) || defined(__i386__) - asmv("cli"); + asmv("cli"); #elif defined(__aarch64__) - asmv("msr daifset, #2"); + asmv("msr daifset, #2"); #endif - return true; - } - } - return false; - } + return true; + } + } + 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; + } } diff --git a/arch/amd64/Limine.c b/arch/amd64/Limine.c index 859a705..ea65c20 100644 --- a/arch/amd64/Limine.c +++ b/arch/amd64/Limine.c @@ -52,7 +52,7 @@ void init_limine() while (1) 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_memmap_response *MemmapResponse = MemmapRequest.response; diff --git a/core/Memory/Memory.cpp b/core/Memory/Memory.cpp index 00f7a9e..eb4d373 100644 --- a/core/Memory/Memory.cpp +++ b/core/Memory/Memory.cpp @@ -28,7 +28,7 @@ void tracepagetable(PageTable *pt) for (int i = 0; i < 512; i++) { 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.UserSupervisor, pt->Entries[i].Value.WriteThrough, pt->Entries[i].Value.CacheDisable, pt->Entries[i].Value.Accessed, diff --git a/core/Memory/VirtualMemoryManager.cpp b/core/Memory/VirtualMemoryManager.cpp index 5bdbb21..f011528 100644 --- a/core/Memory/VirtualMemoryManager.cpp +++ b/core/Memory/VirtualMemoryManager.cpp @@ -118,6 +118,13 @@ namespace Memory 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() {} } diff --git a/core/Video/Display.cpp b/core/Video/Display.cpp new file mode 100644 index 0000000..0518509 --- /dev/null +++ b/core/Video/Display.cpp @@ -0,0 +1,111 @@ +#include +#include +#include + +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); + } +} diff --git a/core/Video/Font.cpp b/core/Video/Font.cpp new file mode 100644 index 0000000..dd0f1f3 --- /dev/null +++ b/core/Video/Font.cpp @@ -0,0 +1,54 @@ +#include +#include +#include + +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(reinterpret_cast(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(reinterpret_cast(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() + { + } +} diff --git a/include/cpu.hpp b/include/cpu.hpp index cb1c1bd..9a8efcc 100644 --- a/include/cpu.hpp +++ b/include/cpu.hpp @@ -8,127 +8,134 @@ */ 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); - /** - * @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() + namespace MemBar { + static inline void Barrier() + { #if defined(__amd64__) || defined(__i386__) - asmv("" :: - : "memory"); + asmv("" :: + : "memory"); #elif defined(__aarch64__) - asmv("dmb ish" :: - : "memory"); + asmv("dmb ish" :: + : "memory"); #endif - } + } - static inline void Fence() - { + static inline void Fence() + { #if defined(__amd64__) || defined(__i386__) - asmv("mfence" :: - : "memory"); + asmv("mfence" :: + : "memory"); #elif defined(__aarch64__) - asmv("dmb ish" :: - : "memory"); + asmv("dmb ish" :: + : "memory"); #endif - } + } - static inline void StoreFence() - { + static inline void StoreFence() + { #if defined(__amd64__) || defined(__i386__) - asmv("sfence" :: - : "memory"); + asmv("sfence" :: + : "memory"); #elif defined(__aarch64__) - asmv("dmb ishst" :: - : "memory"); + asmv("dmb ishst" :: + : "memory"); #endif - } + } - static inline void LoadFence() - { + static inline void LoadFence() + { #if defined(__amd64__) || defined(__i386__) - asmv("lfence" :: - : "memory"); + asmv("lfence" :: + : "memory"); #elif defined(__aarch64__) - asmv("dmb ishld" :: - : "memory"); -#endif - } - } - - namespace x86 - { - static inline void lgdt(void *gdt) - { -#if defined(__amd64__) || defined(__i386__) - asmv("lgdt (%0)" - : - : "r"(gdt)); + asmv("dmb ishld" :: + : "memory"); #endif + } } - static inline void lidt(void *idt) + namespace x86 { + static inline void lgdt(void *gdt) + { #if defined(__amd64__) || defined(__i386__) - asmv("lidt (%0)" - : - : "r"(idt)); + asmv("lgdt (%0)" + : + : "r"(gdt)); #endif - } + } - static inline void ltr(uint16_t Segment) - { + static inline void lidt(void *idt) + { #if defined(__amd64__) || defined(__i386__) - asmv("ltr %0" - : - : "r"(Segment)); + asmv("lidt (%0)" + : + : "r"(idt)); #endif - } + } - static inline void invlpg(void *Address) - { + static inline void ltr(uint16_t Segment) + { #if defined(__amd64__) || defined(__i386__) - asmv("invlpg (%0)" - : - : "r"(Address) - : "memory"); + asmv("ltr %0" + : + : "r"(Segment)); #endif + } + + static inline void invlpg(void *Address) + { +#if defined(__amd64__) || defined(__i386__) + asmv("invlpg (%0)" + : + : "r"(Address) + : "memory"); +#endif + } } - } } #endif // !__FENNIX_KERNEL_CPU_H__ diff --git a/include/display.hpp b/include/display.hpp new file mode 100644 index 0000000..78bd478 --- /dev/null +++ b/include/display.hpp @@ -0,0 +1,159 @@ +#ifndef __FENNIX_KERNEL_DISPLAY_H__ +#define __FENNIX_KERNEL_DISPLAY_H__ + +#include + +#include +#include + +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__ diff --git a/include/memory.hpp b/include/memory.hpp index 2bfdbe8..f4cafb2 100644 --- a/include/memory.hpp +++ b/include/memory.hpp @@ -396,9 +396,9 @@ namespace Memory /** * @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 * diff --git a/include/types.h b/include/types.h index 74c0923..891a9dd 100644 --- a/include/types.h +++ b/include/types.h @@ -32,6 +32,8 @@ #define in : #endif +#define UNUSED(x) (void)(x) + #ifndef __va_list__ typedef __builtin_va_list va_list; #endif diff --git a/lib/printf.c b/lib/printf.c index 93d85ea..09a777e 100644 --- a/lib/printf.c +++ b/lib/printf.c @@ -911,7 +911,7 @@ static /* double */ unsigned long pow10_of_int(int floored_exp10) double_with_bit_access dwba; // int exp2 = bastardized_floor(floored_exp10 * 3.321928094887362 + 0.5); // 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 z2 = z * z; dwba.U = ((double_uint_t)(exp2) + DOUBLE_BASE_EXPONENT) << DOUBLE_STORED_MANTISSA_BITS;