mirror of
https://github.com/EnderIce2/Fennix.git
synced 2025-05-28 15:34:31 +00:00
Implement Virtual Terminal and fix /dev/kcon
This commit is contained in:
parent
6f8e486740
commit
85b6fdef80
@ -12,6 +12,9 @@ License information can be found in the [LICENSES.md](LICENSES.md) file.
|
||||
- [ToaruOS](https://github.com/klange/toaruos)
|
||||
- [Various SIMD functions](https://wiki.osdev.org/User:01000101/optlib/)
|
||||
|
||||
## Virtual terminal
|
||||
- [vtconsole](https://github.com/sleepy-monax/vtconsole)
|
||||
|
||||
## Font
|
||||
- [Tamsyn Font](http://www.fial.com/~scott/tamsyn-font/)
|
||||
|
||||
@ -111,6 +114,9 @@ License information can be found in the [LICENSES.md](LICENSES.md) file.
|
||||
- [PS/2 Controller on OSDev](https://wiki.osdev.org/%228042%22_PS/2_Controller)
|
||||
- [AIP on OSDev](https://wiki.osdev.org/Advanced_Integrated_Peripheral)
|
||||
|
||||
## UART
|
||||
- [Interfacing the Serial / RS232 Port V5.0](http://www.senet.com.au/~cpeacock)
|
||||
|
||||
---
|
||||
|
||||
Special thanks to all contributors and the creators of the referenced projects and resources!
|
||||
|
@ -478,7 +478,7 @@ namespace APIC
|
||||
|
||||
trace("%d APIC Timer %d ticks in.",
|
||||
GetCurrentCPU()->ID, Ticks);
|
||||
KPrint("APIC Timer: \e8888FF%ld\eCCCCCC ticks.", Ticks);
|
||||
KPrint("APIC Timer: \x1b[1;32m%ld\x1b[0m ticks.", Ticks);
|
||||
}
|
||||
|
||||
Timer::~Timer()
|
||||
|
@ -577,7 +577,7 @@ namespace InterruptDescriptorTable
|
||||
#ifdef DEBUG
|
||||
EnableISRs = !DebuggerIsAttached;
|
||||
if (!EnableISRs)
|
||||
KPrint("\eFFA500The debugger is attached, disabling all ISRs.");
|
||||
KPrint("\x1b[34mThe debugger is attached, disabling all ISRs.");
|
||||
#endif
|
||||
|
||||
/* ISR */
|
||||
|
@ -89,7 +89,7 @@ extern "C" void StartCPU()
|
||||
asmv("mov %0, %%rsp" ::"r"((&CPUs[CoreID])->Stack));
|
||||
|
||||
CPU::Interrupts(CPU::Enable);
|
||||
KPrint("\e058C19CPU \e8888FF%d \e058C19is online", CoreID);
|
||||
KPrint("CPU %d is online", CoreID);
|
||||
CPUEnabled.store(true, std::memory_order_release);
|
||||
CPU::Halt(true);
|
||||
}
|
||||
@ -177,7 +177,7 @@ namespace SMP
|
||||
if (TimeManager->GetCounter() > Timeout)
|
||||
{
|
||||
error("CPU %d failed to load!", lapic->APICId);
|
||||
KPrint("\eFF8C19CPU \e8888FF%d \eFF8C19failed to load!",
|
||||
KPrint("\x1b[1;37;41mCPU %d failed to load!",
|
||||
lapic->APICId);
|
||||
break;
|
||||
}
|
||||
@ -187,7 +187,7 @@ namespace SMP
|
||||
CPUEnabled.store(false, std::memory_order_release);
|
||||
}
|
||||
else
|
||||
KPrint("\e058C19CPU \e8888FF%d \e058C19is the BSP", lapic->APICId);
|
||||
KPrint("CPU %d is the BSP", lapic->APICId);
|
||||
}
|
||||
|
||||
KernelAllocator.FreePages(CPUTmpStack, TO_PAGES(STACK_SIZE + 1));
|
||||
|
@ -46,7 +46,7 @@ namespace ACPI
|
||||
if (ptr[4] & 1)
|
||||
{
|
||||
lapic.push_back((LocalAPIC *)ptr);
|
||||
KPrint("Local APIC \e8888FF%d\eCCCCCC (APIC \e8888FF%d\eCCCCCC) found.", lapic.back()->ACPIProcessorId, lapic.back()->APICId);
|
||||
KPrint("Local APIC %d (APIC %d) found.", lapic.back()->ACPIProcessorId, lapic.back()->APICId);
|
||||
CPUCores++;
|
||||
}
|
||||
break;
|
||||
@ -54,34 +54,34 @@ namespace ACPI
|
||||
case 1:
|
||||
{
|
||||
ioapic.push_back((MADTIOApic *)ptr);
|
||||
KPrint("I/O APIC \e8888FF%d\eCCCCCC (Address \e8888FF%#lx\eCCCCCC) found.", ioapic.back()->APICID, ioapic.back()->Address);
|
||||
KPrint("I/O APIC %d (Address %#lx) found.", ioapic.back()->APICID, ioapic.back()->Address);
|
||||
Memory::Virtual(KernelPageTable).Map((void *)(uintptr_t)ioapic.back()->Address, (void *)(uintptr_t)ioapic.back()->Address, Memory::PTFlag::RW | Memory::PTFlag::PCD); // Make sure that the address is mapped.
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
iso.push_back((MADTIso *)ptr);
|
||||
KPrint("ISO (IRQ:\e8888FF%#lx\eCCCCCC, BUS:\e8888FF%#lx\eCCCCCC, GSI:\e8888FF%#lx\eCCCCCC, %s\eCCCCCC/%s\eCCCCCC) found.",
|
||||
KPrint("ISO (IRQ:%#lx, BUS:%#lx, GSI:%#lx, %s/%s) found.",
|
||||
iso.back()->IRQSource, iso.back()->BuSSource, iso.back()->GSI,
|
||||
iso.back()->Flags & 0x00000004 ? "\e1770FFActive High" : "\e475EFFActive Low",
|
||||
iso.back()->Flags & 0x00000100 ? "\e00962DEdge Triggered" : "\e008F58Level Triggered");
|
||||
iso.back()->Flags & 0x00000004 ? "Active High" : "Active Low",
|
||||
iso.back()->Flags & 0x00000100 ? "Edge Triggered" : "Level Triggered");
|
||||
break;
|
||||
}
|
||||
case 4:
|
||||
{
|
||||
nmi.push_back((MADTNmi *)ptr);
|
||||
KPrint("NMI \e8888FF%#lx\eCCCCCC (lint:\e8888FF%#lx\eCCCCCC) found.", nmi.back()->processor, nmi.back()->lint);
|
||||
KPrint("NMI %#lx (lint:%#lx) found.", nmi.back()->processor, nmi.back()->lint);
|
||||
break;
|
||||
}
|
||||
case 5:
|
||||
{
|
||||
LAPICAddress = (LAPIC *)ptr;
|
||||
KPrint("APIC found at \e8888FF%#lx\eCCCCCC", LAPICAddress);
|
||||
KPrint("APIC found at %#lx", LAPICAddress);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
KPrint("Unknown MADT entry \e8888FF%#lx\eCCCCCC", *(ptr));
|
||||
KPrint("Unknown MADT entry %#lx", *(ptr));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -400,7 +400,7 @@ namespace APIC
|
||||
this->lapic->Write(APIC_TICR, s_cst(uint32_t, Ticks));
|
||||
this->lapic->Write(APIC_TIMER, s_cst(uint32_t, timer.raw));
|
||||
trace("%d APIC Timer %d ticks in.", GetCurrentCPU()->ID, Ticks);
|
||||
KPrint("APIC Timer: \e8888FF%ld\eCCCCCC ticks.", Ticks);
|
||||
KPrint("APIC Timer: \x1b[1;32m%ld\x1b[0m ticks.", Ticks);
|
||||
}
|
||||
|
||||
Timer::~Timer()
|
||||
|
@ -464,7 +464,7 @@ namespace InterruptDescriptorTable
|
||||
// #ifdef DEBUG
|
||||
EnableISRs = !DebuggerIsAttached;
|
||||
if (!EnableISRs)
|
||||
KPrint("\eFFA500The debugger is attached, disabling all ISRs.");
|
||||
KPrint("\x1b[34mThe debugger is attached, disabling all ISRs.");
|
||||
// #endif
|
||||
|
||||
SetEntry(0x0, InterruptHandler_0x0, TRAP_GATE_32BIT, RING0, EnableISRs, GDT_KERNEL_CODE);
|
||||
|
@ -40,7 +40,7 @@ namespace ACPI
|
||||
if (ptr[4] & 1)
|
||||
{
|
||||
lapic.push_back((LocalAPIC *)ptr);
|
||||
KPrint("Local APIC \e8888FF%d\eCCCCCC (APIC \e8888FF%d\eCCCCCC) found.", lapic.back()->ACPIProcessorId, lapic.back()->APICId);
|
||||
KPrint("Local APIC %d (APIC %d) found.", lapic.back()->ACPIProcessorId, lapic.back()->APICId);
|
||||
CPUCores++;
|
||||
}
|
||||
break;
|
||||
@ -48,34 +48,34 @@ namespace ACPI
|
||||
case 1:
|
||||
{
|
||||
ioapic.push_back((MADTIOApic *)ptr);
|
||||
KPrint("I/O APIC \e8888FF%d\eCCCCCC (Address \e8888FF%#lx\eCCCCCC) found.", ioapic.back()->APICID, ioapic.back()->Address);
|
||||
KPrint("I/O APIC %d (Address %#lx) found.", ioapic.back()->APICID, ioapic.back()->Address);
|
||||
Memory::Virtual(KernelPageTable).Map((void *)(uintptr_t)ioapic.back()->Address, (void *)(uintptr_t)ioapic.back()->Address, Memory::PTFlag::RW | Memory::PTFlag::PCD); // Make sure that the address is mapped.
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
iso.push_back((MADTIso *)ptr);
|
||||
KPrint("ISO (IRQ:\e8888FF%#lx\eCCCCCC, BUS:\e8888FF%#lx\eCCCCCC, GSI:\e8888FF%#lx\eCCCCCC, %s\eCCCCCC/%s\eCCCCCC) found.",
|
||||
KPrint("ISO (IRQ:%#lx, BUS:%#lx, GSI:%#lx, %s/%s) found.",
|
||||
iso.back()->IRQSource, iso.back()->BuSSource, iso.back()->GSI,
|
||||
iso.back()->Flags & 0x00000004 ? "\e1770FFActive High" : "\e475EFFActive Low",
|
||||
iso.back()->Flags & 0x00000100 ? "\e00962DEdge Triggered" : "\e008F58Level Triggered");
|
||||
iso.back()->Flags & 0x00000004 ? "Active High" : "Active Low",
|
||||
iso.back()->Flags & 0x00000100 ? "Edge Triggered" : "Level Triggered");
|
||||
break;
|
||||
}
|
||||
case 4:
|
||||
{
|
||||
nmi.push_back((MADTNmi *)ptr);
|
||||
KPrint("NMI \e8888FF%#lx\eCCCCCC (lint:\e8888FF%#lx\eCCCCCC) found.", nmi.back()->processor, nmi.back()->lint);
|
||||
KPrint("NMI %#lx (lint:%#lx) found.", nmi.back()->processor, nmi.back()->lint);
|
||||
break;
|
||||
}
|
||||
case 5:
|
||||
{
|
||||
LAPICAddress = (LAPIC *)ptr;
|
||||
KPrint("APIC found at \e8888FF%#lx\eCCCCCC", LAPICAddress);
|
||||
KPrint("APIC found at %#lx", LAPICAddress);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
KPrint("Unknown MADT entry \e8888FF%#lx\eCCCCCC", *(ptr));
|
||||
KPrint("Unknown MADT entry %#lx", *(ptr));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
368
core/console.cpp
368
core/console.cpp
@ -21,32 +21,21 @@
|
||||
#include <memory.hpp>
|
||||
#include <stropts.h>
|
||||
#include <string.h>
|
||||
#include <ini.h>
|
||||
|
||||
#include "../kernel.h"
|
||||
|
||||
namespace KernelConsole
|
||||
{
|
||||
termios term{};
|
||||
winsize termSize{};
|
||||
|
||||
ssize_t KConRead(struct Inode *Node, void *Buffer, size_t Size, off_t Offset)
|
||||
{
|
||||
fixme("Reading %d bytes... \"%.*s\"", Size, Size, (char *)Buffer);
|
||||
return Size;
|
||||
}
|
||||
|
||||
ssize_t KConWrite(struct Inode *Node, const void *Buffer, size_t Size, off_t Offset)
|
||||
{
|
||||
fixme("Writing %d bytes... \"%.*s\"", Size, Size, (char *)Buffer);
|
||||
return Size;
|
||||
}
|
||||
|
||||
int KConIoctl(struct Inode *Node, unsigned long Request, void *Argp)
|
||||
{
|
||||
fixme("KConIoctl");
|
||||
switch (Request)
|
||||
{
|
||||
case TCGETS:
|
||||
{
|
||||
struct termios *t = (struct termios *)Argp;
|
||||
memcpy(t, &term, sizeof(struct termios));
|
||||
// memcpy(t, &term, sizeof(struct termios));
|
||||
return 0;
|
||||
}
|
||||
case TCSETS:
|
||||
@ -55,7 +44,7 @@ namespace KernelConsole
|
||||
return -EINVAL;
|
||||
|
||||
struct termios *t = (struct termios *)Argp;
|
||||
memcpy(&term, t, sizeof(struct termios));
|
||||
// memcpy(&term, t, sizeof(struct termios));
|
||||
return 0;
|
||||
}
|
||||
case TIOCGPGRP:
|
||||
@ -71,7 +60,7 @@ namespace KernelConsole
|
||||
case TIOCGWINSZ:
|
||||
{
|
||||
struct winsize *ws = (struct winsize *)Argp;
|
||||
memcpy(ws, &termSize, sizeof(struct winsize));
|
||||
// memcpy(ws, &termSize, sizeof(struct winsize));
|
||||
return 0;
|
||||
}
|
||||
case TIOCSWINSZ:
|
||||
@ -80,7 +69,7 @@ namespace KernelConsole
|
||||
return -EINVAL;
|
||||
|
||||
struct winsize *ws = (struct winsize *)Argp;
|
||||
memcpy(&termSize, ws, sizeof(struct winsize));
|
||||
// memcpy(&termSize, ws, sizeof(struct winsize));
|
||||
return 0;
|
||||
}
|
||||
case TCSETSW:
|
||||
@ -132,41 +121,324 @@ namespace KernelConsole
|
||||
return 0;
|
||||
}
|
||||
|
||||
int TermColors[] = {
|
||||
[TerminalColor::BLACK] = 0x000000,
|
||||
[TerminalColor::RED] = 0xAA0000,
|
||||
[TerminalColor::GREEN] = 0x00AA00,
|
||||
[TerminalColor::YELLOW] = 0xAA5500,
|
||||
[TerminalColor::BLUE] = 0x0000AA,
|
||||
[TerminalColor::MAGENTA] = 0xAA00AA,
|
||||
[TerminalColor::CYAN] = 0x00AAAA,
|
||||
[TerminalColor::GREY] = 0xAAAAAA,
|
||||
};
|
||||
|
||||
int TermBrightColors[] = {
|
||||
[TerminalColor::BLACK] = 0x858585,
|
||||
[TerminalColor::RED] = 0xFF5555,
|
||||
[TerminalColor::GREEN] = 0x55FF55,
|
||||
[TerminalColor::YELLOW] = 0xFFFF55,
|
||||
[TerminalColor::BLUE] = 0x5555FF,
|
||||
[TerminalColor::MAGENTA] = 0xFF55FF,
|
||||
[TerminalColor::CYAN] = 0x55FFFF,
|
||||
[TerminalColor::GREY] = 0xFFFFFF,
|
||||
};
|
||||
|
||||
__no_sanitize("undefined") char FontRenderer::Paint(long CellX, long CellY, char Char, uint32_t Foreground, uint32_t Background)
|
||||
{
|
||||
uint64_t x = CellX * CurrentFont->GetInfo().Width;
|
||||
uint64_t y = CellY * CurrentFont->GetInfo().Height;
|
||||
|
||||
switch (CurrentFont->GetInfo().Type)
|
||||
{
|
||||
case Video::FontType::PCScreenFont1:
|
||||
{
|
||||
uint32_t *PixelPtr = (uint32_t *)Display->GetBuffer;
|
||||
char *FontPtr = (char *)CurrentFont->GetInfo().PSF1Font->GlyphBuffer + (Char * CurrentFont->GetInfo().PSF1Font->Header->charsize);
|
||||
for (uint64_t Y = 0; Y < 16; Y++)
|
||||
{
|
||||
for (uint64_t X = 0; X < 8; X++)
|
||||
{
|
||||
if ((*FontPtr & (0b10000000 >> X)) > 0)
|
||||
*(unsigned int *)(PixelPtr + (x + X) + ((y + Y) * Display->GetWidth)) = Foreground;
|
||||
else
|
||||
*(unsigned int *)(PixelPtr + (x + X) + ((y + Y) * Display->GetWidth)) = Background;
|
||||
}
|
||||
FontPtr++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Video::FontType::PCScreenFont2:
|
||||
{
|
||||
Video::FontInfo fInfo = CurrentFont->GetInfo();
|
||||
|
||||
int BytesPerLine = (fInfo.PSF2Font->Header->width + 7) / 8;
|
||||
char *FontAddress = (char *)fInfo.StartAddress;
|
||||
uint32_t FontHeaderSize = fInfo.PSF2Font->Header->headersize;
|
||||
uint32_t FontCharSize = fInfo.PSF2Font->Header->charsize;
|
||||
uint32_t FontLength = fInfo.PSF2Font->Header->length;
|
||||
char *FontPtr = FontAddress + FontHeaderSize + (Char > 0 && (uint32_t)Char < FontLength ? Char : 0) * FontCharSize;
|
||||
|
||||
uint32_t FontHdrWidth = fInfo.PSF2Font->Header->width;
|
||||
uint32_t FontHdrHeight = fInfo.PSF2Font->Header->height;
|
||||
|
||||
for (uint32_t Y = 0; Y < FontHdrHeight; Y++)
|
||||
{
|
||||
for (uint32_t X = 0; X < FontHdrWidth; X++)
|
||||
{
|
||||
void *FramebufferAddress = (void *)((uintptr_t)Display->GetBuffer +
|
||||
((y + Y) * Display->GetWidth + (x + X)) *
|
||||
(Display->GetFramebufferStruct().BitsPerPixel / 8));
|
||||
|
||||
if ((*FontPtr & (0b10000000 >> (X % 8))) > 0)
|
||||
*(uint32_t *)FramebufferAddress = Foreground;
|
||||
else
|
||||
*(uint32_t *)FramebufferAddress = Background;
|
||||
}
|
||||
FontPtr += BytesPerLine;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
warn("Unsupported font type");
|
||||
break;
|
||||
}
|
||||
return Char;
|
||||
}
|
||||
|
||||
FontRenderer Renderer;
|
||||
|
||||
void paint_callback(TerminalCell *cell, long x, long y)
|
||||
{
|
||||
if (cell->attr.Bright)
|
||||
Renderer.Paint(x, y, cell->c, TermBrightColors[cell->attr.Foreground], TermColors[cell->attr.Background]);
|
||||
else
|
||||
Renderer.Paint(x, y, cell->c, TermColors[cell->attr.Foreground], TermColors[cell->attr.Background]);
|
||||
}
|
||||
|
||||
void cursor_callback(TerminalCursor *cur)
|
||||
{
|
||||
Renderer.Cursor = {cur->X, cur->Y};
|
||||
}
|
||||
|
||||
VirtualTerminal *Terminals[16] = {nullptr};
|
||||
std::atomic<VirtualTerminal *> CurrentTerminal = nullptr;
|
||||
|
||||
bool SetTheme(std::string Theme)
|
||||
{
|
||||
FileNode *rn = fs->GetByPath("/etc/term", thisProcess->Info.RootNode);
|
||||
if (rn == nullptr)
|
||||
return false;
|
||||
|
||||
kstat st{};
|
||||
rn->Stat(&st);
|
||||
|
||||
char *sh = new char[st.Size];
|
||||
rn->Read(sh, st.Size, 0);
|
||||
|
||||
ini_t *ini = ini_load(sh, NULL);
|
||||
int themeSection, c0, c1, c2, c3, c4, c5, c6, c7, colorsIdx;
|
||||
const char *colors[8];
|
||||
|
||||
debug("Loading terminal theme: \"%s\"", Theme.c_str());
|
||||
themeSection = ini_find_section(ini, Theme.c_str(), NULL);
|
||||
if (themeSection == INI_NOT_FOUND)
|
||||
{
|
||||
ini_destroy(ini);
|
||||
delete[] sh;
|
||||
return false;
|
||||
}
|
||||
|
||||
auto getColorComponent = [](const char *str, int &index) -> int
|
||||
{
|
||||
int value = 0;
|
||||
while (str[index] >= '0' && str[index] <= '9')
|
||||
{
|
||||
value = value * 10 + (str[index] - '0');
|
||||
++index;
|
||||
}
|
||||
return value;
|
||||
};
|
||||
|
||||
auto parseColor = [getColorComponent](const char *colorStr) -> unsigned int
|
||||
{
|
||||
int index = 0;
|
||||
int r = getColorComponent(colorStr, index);
|
||||
if (colorStr[index] == ',')
|
||||
++index;
|
||||
int g = getColorComponent(colorStr, index);
|
||||
if (colorStr[index] == ',')
|
||||
++index;
|
||||
int b = getColorComponent(colorStr, index);
|
||||
return (r << 16) | (g << 8) | b;
|
||||
};
|
||||
|
||||
c0 = ini_find_property(ini, themeSection, "color0", NULL);
|
||||
c1 = ini_find_property(ini, themeSection, "color1", NULL);
|
||||
c2 = ini_find_property(ini, themeSection, "color2", NULL);
|
||||
c3 = ini_find_property(ini, themeSection, "color3", NULL);
|
||||
c4 = ini_find_property(ini, themeSection, "color4", NULL);
|
||||
c5 = ini_find_property(ini, themeSection, "color5", NULL);
|
||||
c6 = ini_find_property(ini, themeSection, "color6", NULL);
|
||||
c7 = ini_find_property(ini, themeSection, "color7", NULL);
|
||||
|
||||
colors[0] = ini_property_value(ini, themeSection, c0);
|
||||
colors[1] = ini_property_value(ini, themeSection, c1);
|
||||
colors[2] = ini_property_value(ini, themeSection, c2);
|
||||
colors[3] = ini_property_value(ini, themeSection, c3);
|
||||
colors[4] = ini_property_value(ini, themeSection, c4);
|
||||
colors[5] = ini_property_value(ini, themeSection, c5);
|
||||
colors[6] = ini_property_value(ini, themeSection, c6);
|
||||
colors[7] = ini_property_value(ini, themeSection, c7);
|
||||
|
||||
colorsIdx = 0;
|
||||
for (auto color : colors)
|
||||
{
|
||||
colorsIdx++;
|
||||
if (color == 0)
|
||||
continue;
|
||||
|
||||
char *delimiterPos = strchr(color, ':');
|
||||
if (delimiterPos == NULL)
|
||||
continue;
|
||||
|
||||
char colorStr[20], colorBrightStr[20];
|
||||
strncpy(colorStr, color, delimiterPos - color);
|
||||
colorStr[delimiterPos - color] = '\0';
|
||||
strcpy(colorBrightStr, delimiterPos + 1);
|
||||
|
||||
TermColors[colorsIdx - 1] = parseColor(colorStr);
|
||||
TermBrightColors[colorsIdx - 1] = parseColor(colorBrightStr);
|
||||
}
|
||||
|
||||
ini_destroy(ini);
|
||||
delete[] sh;
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
void __test_themes()
|
||||
{
|
||||
printf("\x1b[H\x1b[2J");
|
||||
auto testTheme = [](const char *theme)
|
||||
{
|
||||
KernelConsole::SetTheme("vga");
|
||||
printf("== Theme: \"%s\" ==\n", theme);
|
||||
KernelConsole::SetTheme(theme);
|
||||
const char *txtColors[] = {
|
||||
"30", "31", "32", "33", "34", "35", "36", "37", "39"};
|
||||
const char *bgColors[] = {
|
||||
"40", "41", "42", "43", "44", "45", "46", "47", "49"};
|
||||
const int numTxtColors = sizeof(txtColors) / sizeof(txtColors[0]);
|
||||
const int numBgColors = sizeof(bgColors) / sizeof(bgColors[0]);
|
||||
|
||||
const char *msg = "H";
|
||||
for (int i = 0; i < numTxtColors; i++)
|
||||
for (int j = 0; j < numBgColors; j++)
|
||||
printf("\x1b[%sm\x1b[%sm%s\x1b[0m", txtColors[i], bgColors[j], msg);
|
||||
|
||||
for (int i = 0; i < numTxtColors; i++)
|
||||
for (int j = 0; j < numBgColors; j++)
|
||||
printf("\x1b[1;%sm\x1b[1;%sm%s\x1b[0m", txtColors[i], bgColors[j], msg);
|
||||
|
||||
KernelConsole::SetTheme("vga");
|
||||
printf("\n");
|
||||
};
|
||||
testTheme("vga");
|
||||
testTheme("breeze");
|
||||
testTheme("coolbreeze");
|
||||
testTheme("softlight");
|
||||
testTheme("calmsea");
|
||||
testTheme("warmember");
|
||||
// CPU::Stop();
|
||||
}
|
||||
#endif
|
||||
|
||||
void EarlyInit()
|
||||
{
|
||||
/*
|
||||
- ICRNL - Map Carriage Return to New Line
|
||||
- IXON - Enable XON/XOFF flow control
|
||||
Renderer.CurrentFont = new Video::Font(&_binary_files_tamsyn_font_1_11_Tamsyn7x14r_psf_start,
|
||||
&_binary_files_tamsyn_font_1_11_Tamsyn7x14r_psf_end,
|
||||
Video::FontType::PCScreenFont2);
|
||||
|
||||
- OPOST - Enable output processing
|
||||
- ONLCR - Map New Line to Carriage Return - New Line
|
||||
|
||||
- CS8 - 8-bit characters
|
||||
- CREAD - Enable receiver
|
||||
- HUPCL - Hang up on last close
|
||||
|
||||
- ECHO - Echo input characters
|
||||
- ICANON - Enable canonical input (enable line editing)
|
||||
*/
|
||||
term.c_iflag = /*ICRNL |*/ IXON;
|
||||
term.c_oflag = OPOST | ONLCR;
|
||||
term.c_cflag = CS8 | CREAD | HUPCL;
|
||||
term.c_lflag = ECHO | ICANON;
|
||||
term.c_cc[VEOF] = 0x04; /* ^D */
|
||||
term.c_cc[VEOL] = 0x00; /* NUL */
|
||||
term.c_cc[VERASE] = 0x7f; /* DEL */
|
||||
term.c_cc[VINTR] = 0x03; /* ^C */
|
||||
term.c_cc[VKILL] = 0x15; /* ^U */
|
||||
term.c_cc[VMIN] = 1; /* Minimum number of characters for non-canonical read */
|
||||
term.c_cc[VQUIT] = 0x1c; /* ^\ */
|
||||
term.c_cc[VSTART] = 0x11; /* ^Q */
|
||||
term.c_cc[VSTOP] = 0x13; /* ^S */
|
||||
term.c_cc[VSUSP] = 0x1a; /* ^Z */
|
||||
term.c_cc[VTIME] = 0; /* Timeout for non-canonical read */
|
||||
term.c_cc[VWERASE] = 0x17; /* ^W */
|
||||
size_t Cols = Display->GetWidth / Renderer.CurrentFont->GetInfo().Width;
|
||||
size_t Rows = Display->GetHeight / Renderer.CurrentFont->GetInfo().Height;
|
||||
Terminals[0] = new VirtualTerminal(Cols, Rows, Display->GetWidth, Display->GetHeight, paint_callback, cursor_callback);
|
||||
Terminals[0]->Clear(0, 0, Cols, Rows - 1);
|
||||
CurrentTerminal.store(Terminals[0], std::memory_order_release);
|
||||
}
|
||||
|
||||
void LateInit()
|
||||
{
|
||||
new vfs::PTMXDevice;
|
||||
|
||||
FileNode *rn = fs->GetByPath("/etc/term", thisProcess->Info.RootNode);
|
||||
if (rn == nullptr)
|
||||
return;
|
||||
|
||||
kstat st{};
|
||||
rn->Stat(&st);
|
||||
|
||||
char *sh = new char[st.Size];
|
||||
rn->Read(sh, st.Size, 0);
|
||||
|
||||
ini_t *ini = ini_load(sh, NULL);
|
||||
int general = ini_find_section(ini, "general", NULL);
|
||||
int cursor = ini_find_section(ini, "cursor", NULL);
|
||||
assert(general != INI_NOT_FOUND && cursor != INI_NOT_FOUND);
|
||||
|
||||
int themeIndex = ini_find_property(ini, general, "theme", NULL);
|
||||
assert(themeIndex != INI_NOT_FOUND);
|
||||
|
||||
int cursorColor = ini_find_property(ini, cursor, "color", NULL);
|
||||
int cursorBlink = ini_find_property(ini, cursor, "blink", NULL);
|
||||
assert(cursorColor != INI_NOT_FOUND && cursorBlink != INI_NOT_FOUND);
|
||||
|
||||
const char *colorThemeStr = ini_property_value(ini, general, themeIndex);
|
||||
const char *cursorColorStr = ini_property_value(ini, cursor, cursorColor);
|
||||
const char *cursorBlinkStr = ini_property_value(ini, cursor, cursorBlink);
|
||||
debug("colorThemeStr=%s", colorThemeStr);
|
||||
debug("cursorColorStr=%s", cursorColorStr);
|
||||
debug("cursorBlinkStr=%s", cursorBlinkStr);
|
||||
|
||||
auto getColorComponent = [](const char *str, int &index) -> int
|
||||
{
|
||||
int value = 0;
|
||||
while (str[index] >= '0' && str[index] <= '9')
|
||||
{
|
||||
value = value * 10 + (str[index] - '0');
|
||||
++index;
|
||||
}
|
||||
return value;
|
||||
};
|
||||
|
||||
auto parseColor = [getColorComponent](const char *colorStr) -> unsigned int
|
||||
{
|
||||
int index = 0;
|
||||
int r = getColorComponent(colorStr, index);
|
||||
if (colorStr[index] == ',')
|
||||
++index;
|
||||
int g = getColorComponent(colorStr, index);
|
||||
if (colorStr[index] == ',')
|
||||
++index;
|
||||
int b = getColorComponent(colorStr, index);
|
||||
return (r << 16) | (g << 8) | b;
|
||||
};
|
||||
|
||||
if (colorThemeStr != 0)
|
||||
SetTheme(colorThemeStr);
|
||||
|
||||
if (cursorBlinkStr != 0 && strncmp(cursorBlinkStr, "true", 4) == 0)
|
||||
{
|
||||
uint32_t blinkColor = 0xFFFFFF;
|
||||
if (cursorColorStr != 0)
|
||||
blinkColor = parseColor(cursorColorStr);
|
||||
fixme("cursor blink with colors %X", blinkColor);
|
||||
}
|
||||
|
||||
ini_destroy(ini);
|
||||
delete[] sh;
|
||||
|
||||
#ifdef DEBUG
|
||||
// __test_themes();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
@ -38,10 +38,12 @@ namespace Driver
|
||||
* maj = 0
|
||||
* min:
|
||||
* 0 - <ROOT>
|
||||
* 1 - /dev/null
|
||||
* 2 - /dev/zero
|
||||
* 3 - /dev/random
|
||||
* 4 - /dev/mem
|
||||
* 1 - /proc/self
|
||||
* 2 - /dev/null
|
||||
* 3 - /dev/zero
|
||||
* 4 - /dev/random
|
||||
* 5 - /dev/mem
|
||||
* 6 - /dev/kcon
|
||||
*
|
||||
* maj = 1
|
||||
* min:
|
||||
@ -103,11 +105,11 @@ namespace Driver
|
||||
{
|
||||
switch (Node->GetMinor())
|
||||
{
|
||||
case 1: /* /dev/null */
|
||||
case 2: /* /dev/null */
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
case 2: /* /dev/zero */
|
||||
case 3: /* /dev/zero */
|
||||
{
|
||||
if (Size <= 0)
|
||||
return 0;
|
||||
@ -115,7 +117,7 @@ namespace Driver
|
||||
memset(Buffer, 0, Size);
|
||||
return Size;
|
||||
}
|
||||
case 3: /* /dev/random */
|
||||
case 4: /* /dev/random */
|
||||
{
|
||||
if (Size <= 0)
|
||||
return 0;
|
||||
@ -133,7 +135,12 @@ namespace Driver
|
||||
buf[i] = Random::rand64();
|
||||
return Size;
|
||||
}
|
||||
case 4: /* /dev/mem */
|
||||
case 5: /* /dev/mem */
|
||||
{
|
||||
stub;
|
||||
return 0;
|
||||
}
|
||||
case 6: /* /dev/kcon */
|
||||
{
|
||||
stub;
|
||||
return 0;
|
||||
@ -209,23 +216,31 @@ namespace Driver
|
||||
{
|
||||
switch (Node->GetMinor())
|
||||
{
|
||||
case 1: /* /dev/null */
|
||||
case 2: /* /dev/null */
|
||||
{
|
||||
return Size;
|
||||
}
|
||||
case 2: /* /dev/zero */
|
||||
case 3: /* /dev/zero */
|
||||
{
|
||||
return Size;
|
||||
}
|
||||
case 3: /* /dev/random */
|
||||
case 4: /* /dev/random */
|
||||
{
|
||||
return Size;
|
||||
}
|
||||
case 4: /* /dev/mem */
|
||||
case 5: /* /dev/mem */
|
||||
{
|
||||
stub;
|
||||
return 0;
|
||||
}
|
||||
case 6: /* /dev/kcon */
|
||||
{
|
||||
char *buf = (char *)Buffer;
|
||||
KernelConsole::VirtualTerminal *vt = KernelConsole::CurrentTerminal.load();
|
||||
for (size_t i = 0; i < Size; i++)
|
||||
vt->Process(buf[i]);
|
||||
return Size;
|
||||
}
|
||||
default:
|
||||
return -ENOENT;
|
||||
};
|
||||
@ -552,6 +567,7 @@ namespace Driver
|
||||
|
||||
dev->Device = fs->RegisterFileSystem(fsi, dev);
|
||||
dev->SetDevice(0, MinorID++);
|
||||
MinorID++; /* 1 = /proc/self */
|
||||
|
||||
devNode = fs->Mount(fs->GetRoot(0), dev, "/dev");
|
||||
_dev->Parent = devNode->Parent;
|
||||
@ -613,6 +629,13 @@ namespace Driver
|
||||
S_IFCHR;
|
||||
createDevice(_dev, devNode, "mem", 0, MinorID++, mode);
|
||||
|
||||
/* c rw- r-- --- */
|
||||
mode = S_IRUSR | S_IWUSR |
|
||||
S_IRGRP |
|
||||
|
||||
S_IFCHR;
|
||||
createDevice(_dev, devNode, "kcon", 0, MinorID++, mode);
|
||||
|
||||
/* ------------------------------------------------------ */
|
||||
|
||||
MinorID = 0;
|
||||
|
@ -89,7 +89,7 @@ namespace Driver
|
||||
{
|
||||
if (Drivers.empty())
|
||||
{
|
||||
KPrint("\eE85230No drivers to load");
|
||||
KPrint("\x1b[1;31;41mNo drivers to load");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -41,7 +41,6 @@
|
||||
#include "keyboard.hpp"
|
||||
|
||||
extern void ExPrint(const char *Format, ...);
|
||||
extern Video::Font *CrashFont;
|
||||
extern void DisplayTopOverlay();
|
||||
extern CPU::ExceptionFrame *ExFrame;
|
||||
|
||||
@ -75,7 +74,7 @@ nsa bool WriteDiagDataToNode(FileNode *node)
|
||||
uint8_t *buf = (uint8_t *)KernelAllocator.RequestPages(TO_PAGES(fileSize));
|
||||
if (!buf)
|
||||
{
|
||||
ExPrint("\eFF0000Failed to allocate memory for diagnostic data\n");
|
||||
ExPrint("\x1b[0;30;41mFailed to allocate memory for diagnostic data\x1b[0m\n");
|
||||
Display->UpdateBuffer();
|
||||
return false;
|
||||
}
|
||||
@ -89,12 +88,12 @@ nsa bool WriteDiagDataToNode(FileNode *node)
|
||||
file->Data.KernelMemoryLength = uint32_t(kSize);
|
||||
memcpy(file->Data.KernelMemory, (void *)KStart, kSize);
|
||||
|
||||
ExPrint("\eFAFAFAWriting to %s\n", node->Path.c_str());
|
||||
ExPrint("Writing to %s\n", node->Path.c_str());
|
||||
size_t w = node->Write(buf, fileSize, 0);
|
||||
if (w != fileSize)
|
||||
{
|
||||
debug("%d out of %d bytes written", w, fileSize);
|
||||
ExPrint("\eFF0000Failed to write diagnostic data to file: %s\n",
|
||||
ExPrint("\x1b[0;30;41mFailed to write diagnostic data to file: %s\x1b[0m\n",
|
||||
strerror((int)w));
|
||||
Display->UpdateBuffer();
|
||||
return false;
|
||||
@ -108,7 +107,7 @@ nsa void DiagnosticDataCollection()
|
||||
Display->ClearBuffer();
|
||||
DisplayTopOverlay();
|
||||
|
||||
ExPrint("\n\eFAFAFAPlease wait while we collect some diagnostic information...\n");
|
||||
ExPrint("\nPlease wait while we collect some diagnostic information...\n");
|
||||
ExPrint("This may take a while...\n");
|
||||
|
||||
mode_t mode = S_IRWXU |
|
||||
@ -119,7 +118,7 @@ nsa void DiagnosticDataCollection()
|
||||
FileNode *panicDir = fs->ForceCreate(nullptr, "/var/panic", mode);
|
||||
if (!panicDir)
|
||||
{
|
||||
ExPrint("\eFF0000Failed to create /var/panic\n");
|
||||
ExPrint("\x1b[0;30;41mFailed to create /var/panic\x1b[0m\n");
|
||||
Display->UpdateBuffer();
|
||||
return;
|
||||
}
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include <lock.hpp>
|
||||
#include <rand.hpp>
|
||||
#include <uart.hpp>
|
||||
#include <kcon.hpp>
|
||||
#include <debug.h>
|
||||
#include <smp.hpp>
|
||||
#include <cpu.hpp>
|
||||
@ -38,6 +39,8 @@
|
||||
|
||||
#include "../../kernel.h"
|
||||
|
||||
using namespace KernelConsole;
|
||||
|
||||
extern const char *x86ExceptionMnemonics[];
|
||||
extern void DisplayCrashScreen(CPU::ExceptionFrame *);
|
||||
extern bool UserModeExceptionHandler(CPU::ExceptionFrame *);
|
||||
@ -45,13 +48,43 @@ extern void DisplayStackSmashing();
|
||||
extern void DisplayBufferOverflow();
|
||||
extern void DisplayAssertionFailed(const char *, int, const char *);
|
||||
|
||||
Video::Font *CrashFont = nullptr;
|
||||
void *FbBeforePanic = nullptr;
|
||||
size_t FbPagesBeforePanic = 0;
|
||||
FontRenderer CrashFontRenderer;
|
||||
|
||||
int ExTermColors[] = {
|
||||
[TerminalColor::BLACK] = 0x000000,
|
||||
[TerminalColor::RED] = 0xAA0000,
|
||||
[TerminalColor::GREEN] = 0x00AA00,
|
||||
[TerminalColor::YELLOW] = 0xAA5500,
|
||||
[TerminalColor::BLUE] = 0x0000AA,
|
||||
[TerminalColor::MAGENTA] = 0xAA00AA,
|
||||
[TerminalColor::CYAN] = 0x00AAAA,
|
||||
[TerminalColor::GREY] = 0xAAAAAA,
|
||||
};
|
||||
|
||||
int ExTermBrightColors[] = {
|
||||
[TerminalColor::BLACK] = 0x858585,
|
||||
[TerminalColor::RED] = 0xFF5555,
|
||||
[TerminalColor::GREEN] = 0x55FF55,
|
||||
[TerminalColor::YELLOW] = 0xFFFF55,
|
||||
[TerminalColor::BLUE] = 0x5555FF,
|
||||
[TerminalColor::MAGENTA] = 0xFF55FF,
|
||||
[TerminalColor::CYAN] = 0x55FFFF,
|
||||
[TerminalColor::GREY] = 0xFFFFFF,
|
||||
};
|
||||
|
||||
void paint_callback(TerminalCell *cell, long x, long y)
|
||||
{
|
||||
if (cell->attr.Bright)
|
||||
CrashFontRenderer.Paint(x, y, cell->c, ExTermBrightColors[cell->attr.Foreground], ExTermColors[cell->attr.Background]);
|
||||
else
|
||||
CrashFontRenderer.Paint(x, y, cell->c, ExTermColors[cell->attr.Foreground], ExTermColors[cell->attr.Background]);
|
||||
}
|
||||
|
||||
nsa void __printfWrapper(char c, void *)
|
||||
{
|
||||
Display->Print(c, CrashFont, true);
|
||||
KernelConsole::Terminals[15]->Process(c);
|
||||
}
|
||||
|
||||
nsa void ExPrint(const char *Format, ...)
|
||||
@ -120,11 +153,17 @@ nsa void InitFont()
|
||||
}
|
||||
memcpy(FbBeforePanic, Display->GetBuffer, Display->GetSize);
|
||||
|
||||
if (CrashFont)
|
||||
return;
|
||||
CrashFont = new Video::Font(&_binary_files_tamsyn_font_1_11_Tamsyn8x16b_psf_start,
|
||||
&_binary_files_tamsyn_font_1_11_Tamsyn8x16b_psf_end,
|
||||
Video::FontType::PCScreenFont2);
|
||||
if (CrashFontRenderer.CurrentFont == nullptr)
|
||||
CrashFontRenderer.CurrentFont = new Video::Font(&_binary_files_tamsyn_font_1_11_Tamsyn8x16b_psf_start,
|
||||
&_binary_files_tamsyn_font_1_11_Tamsyn8x16b_psf_end,
|
||||
Video::FontType::PCScreenFont2);
|
||||
|
||||
if (Terminals[15] == nullptr)
|
||||
{
|
||||
size_t Cols = Display->GetWidth / CrashFontRenderer.CurrentFont->GetInfo().Width;
|
||||
size_t Rows = Display->GetHeight / CrashFontRenderer.CurrentFont->GetInfo().Height;
|
||||
Terminals[15] = new VirtualTerminal(Cols, Rows, Display->GetWidth, Display->GetHeight, paint_callback, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
std::atomic<bool> UnrecoverableLock = false;
|
||||
@ -137,7 +176,7 @@ nsa __noreturn void HandleUnrecoverableException(CPU::ExceptionFrame *Frame)
|
||||
for (uint32_t y = 0; y < Display->GetHeight; y++)
|
||||
Display->SetPixel(x, y, 0xFF250500);
|
||||
|
||||
Display->SetBufferCursor(0, 0);
|
||||
ExPrint("\x1b[H");
|
||||
}
|
||||
|
||||
CPUData *core = GetCurrentCPU();
|
||||
@ -145,8 +184,8 @@ nsa __noreturn void HandleUnrecoverableException(CPU::ExceptionFrame *Frame)
|
||||
while (UnrecoverableLock.exchange(true, std::memory_order_acquire))
|
||||
CPU::Pause();
|
||||
|
||||
ExPrint("\eFFFFFF-----------------------------------------------\n");
|
||||
ExPrint("Unrecoverable exception %#lx on CPU %d\n",
|
||||
ExPrint("\x1b[0m-----------------------------------------------\n");
|
||||
ExPrint("\x1b[30;41mUnrecoverable exception %#lx on CPU %d\n",
|
||||
Frame->InterruptNumber, core->ID);
|
||||
#if defined(a86)
|
||||
ExPrint("CR0=%#lx CR2=%#lx CR3=%#lx CR4=%#lx CR8=%#lx\n",
|
||||
@ -191,7 +230,7 @@ nsa __noreturn void HandleUnrecoverableException(CPU::ExceptionFrame *Frame)
|
||||
|
||||
nsa __noreturn void HandleExceptionInsideException(CPU::ExceptionFrame *Frame)
|
||||
{
|
||||
ExPrint("\eFFFFFF-----------------------------------------------\n");
|
||||
ExPrint("\x1b[0m-----------------------------------------------\n");
|
||||
ExPrint("Exception inside exception: %#lx at %#lx\n",
|
||||
Frame->InterruptNumber,
|
||||
#if defined(a64)
|
||||
@ -282,14 +321,13 @@ nsa void HandleException(CPU::ExceptionFrame *Frame)
|
||||
{
|
||||
const char msg[] = "Entering in panic mode...";
|
||||
size_t msgLen = strlen(msg);
|
||||
size_t msgPixels = msgLen * CrashFont->GetInfo().Width;
|
||||
size_t msgPixels = msgLen * CrashFontRenderer.CurrentFont->GetInfo().Width;
|
||||
uint32_t x = uint32_t((Display->GetWidth - msgPixels) / 2);
|
||||
uint32_t y = uint32_t((Display->GetHeight - CrashFont->GetInfo().Height) / 2);
|
||||
Display->SetBufferCursor(x, y);
|
||||
Display->PrintString("\eFF2525");
|
||||
Display->PrintString(msg, CrashFont);
|
||||
Display->SetBufferCursor(0, 0);
|
||||
Display->UpdateBuffer();
|
||||
uint32_t y = uint32_t((Display->GetHeight - CrashFontRenderer.CurrentFont->GetInfo().Height) / 2);
|
||||
x /= CrashFontRenderer.CurrentFont->GetInfo().Width;
|
||||
y /= CrashFontRenderer.CurrentFont->GetInfo().Height;
|
||||
printf("\x1b[2J\x1b[%d;%dH", y, x);
|
||||
printf("\x1b[30;41m%s\x1b[0m\x1b[H", msg);
|
||||
}
|
||||
|
||||
if (DriverManager)
|
||||
@ -314,12 +352,16 @@ nsa void BaseBufferStackError(bool Stack)
|
||||
do it for us if we return. */
|
||||
CPU::PageTable(KernelPageTable);
|
||||
|
||||
if (CrashFont == nullptr)
|
||||
if (CrashFontRenderer.CurrentFont == nullptr)
|
||||
CrashFontRenderer.CurrentFont = new Video::Font(&_binary_files_tamsyn_font_1_11_Tamsyn8x16b_psf_start,
|
||||
&_binary_files_tamsyn_font_1_11_Tamsyn8x16b_psf_end,
|
||||
Video::FontType::PCScreenFont2);
|
||||
|
||||
if (Terminals[15] == nullptr)
|
||||
{
|
||||
/* Hope we won't crash here */
|
||||
CrashFont = new Video::Font(&_binary_files_tamsyn_font_1_11_Tamsyn8x16b_psf_start,
|
||||
&_binary_files_tamsyn_font_1_11_Tamsyn8x16b_psf_end,
|
||||
Video::FontType::PCScreenFont2);
|
||||
size_t Cols = Display->GetWidth / CrashFontRenderer.CurrentFont->GetInfo().Width;
|
||||
size_t Rows = Display->GetHeight / CrashFontRenderer.CurrentFont->GetInfo().Height;
|
||||
Terminals[15] = new VirtualTerminal(Cols, Rows, Display->GetWidth, Display->GetHeight, paint_callback, nullptr);
|
||||
}
|
||||
|
||||
ExceptionLock.store(true, std::memory_order_release);
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include <display.hpp>
|
||||
#include <convert.h>
|
||||
#include <printf.h>
|
||||
#include <kcon.hpp>
|
||||
#include <debug.h>
|
||||
#include <smp.hpp>
|
||||
#include <cpu.hpp>
|
||||
@ -33,13 +34,16 @@
|
||||
|
||||
#include "../../kernel.h"
|
||||
|
||||
#define ERROR_COLOR "\eFF0000"
|
||||
#define WARN_COLOR "\eFFAA00"
|
||||
#define DEFAULT_COLOR "\e00FF00"
|
||||
using namespace KernelConsole;
|
||||
|
||||
#define ERROR_COLOR "\x1b[31m"
|
||||
#define WARN_COLOR "\x1b[33m"
|
||||
#define DEFAULT_COLOR "\x1b[0m"
|
||||
|
||||
extern void ExPrint(const char *Format, ...);
|
||||
extern void ArrowInput(uint8_t key);
|
||||
extern void UserInput(char *Input);
|
||||
extern FontRenderer CrashFontRenderer;
|
||||
|
||||
const char sc_ascii_low[] = {'?', '?', '1', '2', '3', '4', '5', '6',
|
||||
'7', '8', '9', '0', '-', '=', '?', '?', 'q', 'w', 'e', 'r', 't', 'y',
|
||||
@ -142,16 +146,13 @@ CrashKeyboardDriver::CrashKeyboardDriver() : Interrupts::Handler(1) /* IRQ1 */
|
||||
{
|
||||
#define WaitRead PS2Wait(true)
|
||||
#define WaitWrite PS2Wait(false)
|
||||
#define SetMessageLocation \
|
||||
Display->SetBufferCursor(8, \
|
||||
Display->GetHeight - \
|
||||
Display->GetCurrentFont()->GetInfo().Height - 24)
|
||||
#define SetMessageLocation \
|
||||
ExPrint("\x1b[%d;%dH", (Display->GetWidth / CrashFontRenderer.CurrentFont->GetInfo().Width) - 1, 0);
|
||||
|
||||
CPU::Interrupts(CPU::Disable);
|
||||
|
||||
/* Dots will be printed at the bottom of the screen as a progress bar. */
|
||||
Display->SetBufferCursor(8,
|
||||
Display->GetHeight -
|
||||
Display->GetCurrentFont()->GetInfo().Height - 8);
|
||||
ExPrint("\x1b[%d;%dH", (Display->GetWidth / CrashFontRenderer.CurrentFont->GetInfo().Width) - 2, 0);
|
||||
#if defined(a86)
|
||||
|
||||
/* Disable port 1 & 2 */
|
||||
@ -164,7 +165,7 @@ CrashKeyboardDriver::CrashKeyboardDriver() : Interrupts::Handler(1) /* IRQ1 */
|
||||
WaitWrite;
|
||||
outb(0x64, 0xA7);
|
||||
}
|
||||
Display->Print('.');
|
||||
ExPrint(".");
|
||||
|
||||
/* Flush */
|
||||
{
|
||||
@ -181,7 +182,7 @@ CrashKeyboardDriver::CrashKeyboardDriver() : Interrupts::Handler(1) /* IRQ1 */
|
||||
}
|
||||
}
|
||||
|
||||
Display->Print('.');
|
||||
ExPrint(".");
|
||||
/* Test controller */
|
||||
{
|
||||
/* Save config */
|
||||
@ -221,7 +222,7 @@ CrashKeyboardDriver::CrashKeyboardDriver() : Interrupts::Handler(1) /* IRQ1 */
|
||||
WaitWrite;
|
||||
outb(0x60, cfg);
|
||||
}
|
||||
Display->Print('.');
|
||||
ExPrint(".");
|
||||
|
||||
/* Disable scanning; Enable port 1; Set default settings */
|
||||
{
|
||||
@ -235,7 +236,7 @@ CrashKeyboardDriver::CrashKeyboardDriver() : Interrupts::Handler(1) /* IRQ1 */
|
||||
/* Set default settings */
|
||||
outb(0x60, 0xF6);
|
||||
}
|
||||
Display->Print('.');
|
||||
ExPrint(".");
|
||||
|
||||
/* Test port 1 */
|
||||
{
|
||||
@ -264,7 +265,7 @@ CrashKeyboardDriver::CrashKeyboardDriver() : Interrupts::Handler(1) /* IRQ1 */
|
||||
}
|
||||
}
|
||||
}
|
||||
Display->Print('.');
|
||||
ExPrint(".");
|
||||
|
||||
/* Configure the controller */
|
||||
{
|
||||
@ -283,7 +284,7 @@ CrashKeyboardDriver::CrashKeyboardDriver() : Interrupts::Handler(1) /* IRQ1 */
|
||||
WaitWrite;
|
||||
outb(0x60, cfg);
|
||||
}
|
||||
Display->Print('.');
|
||||
ExPrint(".");
|
||||
|
||||
/* Enable port 1; Set scan code; Enable scanning */
|
||||
{
|
||||
@ -327,7 +328,7 @@ CrashKeyboardDriver::CrashKeyboardDriver() : Interrupts::Handler(1) /* IRQ1 */
|
||||
/* Enable scanning */
|
||||
outb(0x60, 0xF4);
|
||||
}
|
||||
Display->Print('.');
|
||||
ExPrint(".");
|
||||
|
||||
#endif // defined(a86)
|
||||
|
||||
@ -365,7 +366,8 @@ nsa void CrashKeyboardDriver::OnInterruptReceived(CPU::TrapFrame *Frame)
|
||||
{
|
||||
if (BackSpaceLimit > 0)
|
||||
{
|
||||
Display->Print('\b');
|
||||
char keyBuf[5] = {'\b', '\x1b', '[', 'K', '\0'};
|
||||
ExPrint(keyBuf);
|
||||
backspace(UserInputBuffer);
|
||||
BackSpaceLimit--;
|
||||
}
|
||||
@ -379,7 +381,8 @@ nsa void CrashKeyboardDriver::OnInterruptReceived(CPU::TrapFrame *Frame)
|
||||
else
|
||||
{
|
||||
append(UserInputBuffer, s_cst(char, key));
|
||||
Display->Print((char)key);
|
||||
char keyBuf[2] = {(char)key, '\0'};
|
||||
ExPrint(keyBuf);
|
||||
BackSpaceLimit++;
|
||||
}
|
||||
Display->UpdateBuffer(); /* Update as we type. */
|
||||
|
@ -42,8 +42,8 @@
|
||||
extern void ExPrint(const char *Format, ...);
|
||||
extern void DiagnosticDataCollection();
|
||||
extern void InitFont();
|
||||
extern KernelConsole::FontRenderer CrashFontRenderer;
|
||||
|
||||
extern Video::Font *CrashFont;
|
||||
extern void *FbBeforePanic;
|
||||
|
||||
struct StackFrame
|
||||
@ -168,8 +168,7 @@ nsa char *TrimWhiteSpace(char *str)
|
||||
|
||||
nsa void ExDumpData(void *Address, unsigned long Length)
|
||||
{
|
||||
ExPrint("\eAAAAAA-------------------------------------------------------------------------\n");
|
||||
Display->UpdateBuffer();
|
||||
ExPrint("-------------------------------------------------------------------------\n");
|
||||
unsigned char *AddressChar = (unsigned char *)Address;
|
||||
unsigned char Buffer[17];
|
||||
unsigned long Iterate;
|
||||
@ -178,11 +177,10 @@ nsa void ExDumpData(void *Address, unsigned long Length)
|
||||
if ((Iterate % 16) == 0)
|
||||
{
|
||||
if (Iterate != 0)
|
||||
ExPrint(" \e8A78FF%s\eAABBCC\n", Buffer);
|
||||
ExPrint(" \e9E9E9E%04x\eAABBCC ", Iterate);
|
||||
Display->UpdateBuffer();
|
||||
ExPrint(" %s\n", Buffer);
|
||||
ExPrint(" %04x ", Iterate);
|
||||
}
|
||||
ExPrint(" \e4287f5%02x\eAABBCC", AddressChar[Iterate]);
|
||||
ExPrint(" %02x", AddressChar[Iterate]);
|
||||
if ((AddressChar[Iterate] < 0x20) || (AddressChar[Iterate] > 0x7E))
|
||||
Buffer[Iterate % 16] = '.';
|
||||
else
|
||||
@ -193,65 +191,38 @@ nsa void ExDumpData(void *Address, unsigned long Length)
|
||||
while ((Iterate % 16) != 0)
|
||||
{
|
||||
ExPrint(" ");
|
||||
Display->UpdateBuffer();
|
||||
Iterate++;
|
||||
}
|
||||
|
||||
ExPrint(" \e8A78FF%s\eAAAAAA\n", Buffer);
|
||||
ExPrint(" %s\n", Buffer);
|
||||
ExPrint("-------------------------------------------------------------------------\n\n.");
|
||||
Display->UpdateBuffer();
|
||||
}
|
||||
|
||||
nsa void DisplayTopOverlay()
|
||||
{
|
||||
Video::Font *f = Display->GetCurrentFont();
|
||||
Video::FontInfo fi = f->GetInfo();
|
||||
|
||||
for (uint32_t i = 0; i < Display->GetWidth; i++)
|
||||
{
|
||||
for (uint32_t j = 0; j < fi.Height + 8; j++)
|
||||
{
|
||||
// uint32_t grayValue = 0x505050 - (j * 0x020202);
|
||||
// Display->SetPixel(i, j, grayValue);
|
||||
Display->SetPixel(i, j, 0x202020);
|
||||
}
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < Display->GetWidth; i++)
|
||||
Display->SetPixel(i, fi.Height + 8, 0x404040);
|
||||
|
||||
Display->SetBufferCursor(8, (fi.Height + 8) / 6);
|
||||
|
||||
/* This wouldn't have enough space for a 640x480 screen */
|
||||
// ExPrint("%sMAIN %sDETAILS %sSTACK %sPROCESS \eAAAAAA| ",
|
||||
// ActiveScreen == 0 ? "\e00AAFF" : "\eAAAAAA",
|
||||
// ActiveScreen == 1 ? "\e00AAFF" : "\eAAAAAA",
|
||||
// ActiveScreen == 2 ? "\e00AAFF" : "\eAAAAAA",
|
||||
// ActiveScreen == 3 ? "\e00AAFF" : "\eAAAAAA");
|
||||
|
||||
ExPrint("%s %s %s %s \eAAAAAA| ",
|
||||
ActiveScreen == 0 ? "\eAAAAAA"
|
||||
ExPrint("\x1b[H%s %s %s %s \x1b[0m| ",
|
||||
ActiveScreen == 0 ? "\x1b[1;37m"
|
||||
"MAIN "
|
||||
: "\e5A5A5A"
|
||||
: "\x1b[0m"
|
||||
"M",
|
||||
ActiveScreen == 1 ? "\eAAAAAA"
|
||||
ActiveScreen == 1 ? "\x1b[1;37m"
|
||||
"DETAIL "
|
||||
: "\e5A5A5A"
|
||||
: "\x1b[0m"
|
||||
"D",
|
||||
ActiveScreen == 2 ? "\eAAAAAA"
|
||||
ActiveScreen == 2 ? "\x1b[1;37m"
|
||||
"STACK "
|
||||
: "\e5A5A5A"
|
||||
: "\x1b[0m"
|
||||
"S",
|
||||
ActiveScreen == 3 ? "\eAAAAAA"
|
||||
ActiveScreen == 3 ? "\x1b[1;37m"
|
||||
"PROCESS"
|
||||
: "\e5A5A5A"
|
||||
: "\x1b[0m"
|
||||
"P");
|
||||
|
||||
ExPrint("%s %s %s | ", KERNEL_NAME, KERNEL_ARCH, KERNEL_VERSION);
|
||||
ExPrint("%ld | ", TO_MiB(KernelAllocator.GetFreeMemory()));
|
||||
ExPrint("%s %s", CPU::Hypervisor(), CPU::Vendor());
|
||||
|
||||
Display->SetBufferCursor(0, fi.Height + 10);
|
||||
ExPrint("\x1b[3;1H");
|
||||
|
||||
/* https://imgflip.com/i/77slbl */
|
||||
if ((Random::rand32() % 100) >= 98)
|
||||
@ -320,23 +291,12 @@ nsa void DisplayTopOverlay()
|
||||
|
||||
nsa void DisplayBottomOverlay()
|
||||
{
|
||||
Video::Font *f = Display->GetCurrentFont();
|
||||
Video::FontInfo fi = f->GetInfo();
|
||||
|
||||
for (uint32_t i = 0; i < Display->GetWidth; i++)
|
||||
for (uint32_t j = Display->GetHeight - fi.Height - 8; j < Display->GetHeight; j++)
|
||||
Display->SetPixel(i, j, 0x202020);
|
||||
|
||||
for (uint32_t i = 0; i < Display->GetWidth; i++)
|
||||
Display->SetPixel(i, Display->GetHeight - fi.Height - 8, 0x404040);
|
||||
|
||||
Display->SetBufferCursor(8, Display->GetHeight - fi.Height - 4);
|
||||
ExPrint("\eAAAAAA> \eFAFAFA");
|
||||
ExPrint("\x1b[%d;%dH> \x1b[1;37m", (Display->GetWidth / CrashFontRenderer.CurrentFont->GetInfo().Width) - 1, 1);
|
||||
}
|
||||
|
||||
nsa void DisplayMainScreen(CPU::ExceptionFrame *Frame)
|
||||
{
|
||||
ExPrint("\n\eFAFAFAWe're sorry, but the system has encountered a critical error and needs to restart.\n");
|
||||
ExPrint("\nWe're sorry, but the system has encountered a critical error and needs to restart.\n");
|
||||
|
||||
ExPrint("\nError: %s (%s 0x%x)\n",
|
||||
#if defined(a86)
|
||||
@ -373,15 +333,15 @@ nsa void DisplayMainScreen(CPU::ExceptionFrame *Frame)
|
||||
ExPrint(" 2. Remove any newly installed hardware.\n");
|
||||
ExPrint(" 3. Check for any available updates for your operating system.\n");
|
||||
ExPrint(" 4. Uninstall any recently installed drivers or software.\n");
|
||||
ExPrint(" If none of the above steps resolve the issue, create a new issue on \e00AAFFhttps://github.com/Fennix-Project/Fennix\eFAFAFA for further assistance.\n");
|
||||
ExPrint(" If none of the above steps resolve the issue, create a new issue on https://github.com/Fennix-Project/Fennix for further assistance.\n");
|
||||
|
||||
ExPrint("\nUse command 'diag' to create a diagnostic report.\n");
|
||||
}
|
||||
|
||||
nsa void DisplayDetailsScreen(CPU::ExceptionFrame *Frame)
|
||||
{
|
||||
ExPrint("\n\eFAFAFAException Frame:\n");
|
||||
ExPrint(" General Purpose Registers:\n\eAAAAAA");
|
||||
ExPrint("\nException Frame:\n");
|
||||
ExPrint(" General Purpose Registers:\n");
|
||||
ExPrint(" RAX: %#lx RBX: %#lx RCX: %#lx RDX: %#lx\n",
|
||||
Frame->rax, Frame->rbx, Frame->rcx, Frame->rdx);
|
||||
ExPrint(" RSI: %#lx RDI: %#lx R8: %#lx R9: %#lx\n",
|
||||
@ -390,28 +350,28 @@ nsa void DisplayDetailsScreen(CPU::ExceptionFrame *Frame)
|
||||
Frame->r10, Frame->r11, Frame->r12, Frame->r13);
|
||||
ExPrint(" R14: %#lx R15: %#lx\n", Frame->r14, Frame->r15);
|
||||
|
||||
ExPrint("\eFAFAFA Control Registers:\n\eAAAAAA");
|
||||
ExPrint(" Control Registers:\n");
|
||||
ExPrint(" CR0: %#lx CR2: %#lx CR3: %#lx CR4: %#lx\n",
|
||||
Frame->cr0, Frame->cr2, Frame->cr3, Frame->cr4);
|
||||
ExPrint(" CR8: %#lx\n", Frame->cr8);
|
||||
|
||||
ExPrint("\eFAFAFA Segment Registers:\n\eAAAAAA");
|
||||
ExPrint(" Segment Registers:\n");
|
||||
ExPrint(" CS: %#lx SS: %#lx DS: %#lx ES: %#lx FS: %#lx GS: %#lx\n",
|
||||
Frame->cs, Frame->ss, Frame->ds, Frame->es, Frame->fs, Frame->gs);
|
||||
|
||||
ExPrint("\eFAFAFA Debug Registers:\n\eAAAAAA");
|
||||
ExPrint(" Debug Registers:\n");
|
||||
ExPrint(" DR0: %#lx DR1: %#lx DR2: %#lx DR3: %#lx\n",
|
||||
Frame->dr0, Frame->dr1, Frame->dr2, Frame->dr3);
|
||||
ExPrint(" DR6: %#lx DR7: %#lx\n", Frame->dr6, Frame->dr7);
|
||||
|
||||
ExPrint("\eFAFAFA Other:\n\eAAAAAA");
|
||||
ExPrint(" Other:\n");
|
||||
ExPrint(" INT: %#lx ERR: %#lx RIP: %#lx RFLAGS: %#lx\n",
|
||||
Frame->InterruptNumber, Frame->ErrorCode,
|
||||
Frame->rip, Frame->rflags.raw);
|
||||
ExPrint(" RSP: %#lx RBP: %#lx\n",
|
||||
Frame->rsp, Frame->rbp);
|
||||
|
||||
ExPrint("\eFAFAFAException Details:\n");
|
||||
ExPrint("Exception Details:\n");
|
||||
switch (Frame->InterruptNumber)
|
||||
{
|
||||
case CPU::x86::PageFault:
|
||||
@ -477,7 +437,7 @@ nsa void DisplayStackScreen(CPU::ExceptionFrame *Frame)
|
||||
sf = (struct StackFrame *)Frame->ebp;
|
||||
#endif
|
||||
|
||||
ExPrint("\n\eFAFAFAStack trace (%#lx):\n", sf);
|
||||
ExPrint("\nStack trace (%#lx):\n", sf);
|
||||
|
||||
if (!vmm.Check(sf))
|
||||
{
|
||||
@ -487,7 +447,7 @@ nsa void DisplayStackScreen(CPU::ExceptionFrame *Frame)
|
||||
sf = (struct StackFrame *)ptr;
|
||||
else
|
||||
{
|
||||
ExPrint("\eFF0000< No stack trace available. >\n");
|
||||
ExPrint("\x1b[31m< No stack trace available. >\x1b[0m\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -503,8 +463,8 @@ nsa void DisplayStackScreen(CPU::ExceptionFrame *Frame)
|
||||
fIP = Frame->pc;
|
||||
#endif
|
||||
|
||||
ExPrint("\eAAAAAA%p", (void *)fIP);
|
||||
ExPrint("\e5A5A5A in ");
|
||||
ExPrint("%p", (void *)fIP);
|
||||
ExPrint(" in ");
|
||||
if ((fIP >= (uintptr_t)&_kernel_start &&
|
||||
fIP <= (uintptr_t)&_kernel_end))
|
||||
{
|
||||
@ -513,15 +473,15 @@ nsa void DisplayStackScreen(CPU::ExceptionFrame *Frame)
|
||||
if (offset < 0)
|
||||
offset = -offset;
|
||||
|
||||
ExPrint("\eFAFAFA%s\e5A5A5A+%#lx \eFFAAAA<- Exception\n",
|
||||
ExPrint("%s+%#lx \x1b[31m<- Exception\x1b[0m\n",
|
||||
sym, offset);
|
||||
}
|
||||
else
|
||||
ExPrint("\eFF5555??? \eFFAAAA<- Exception\n");
|
||||
ExPrint("??? \x1b[31m<- Exception\x1b[0m\n");
|
||||
|
||||
if (!sf || !sf->ip || !sf->bp)
|
||||
{
|
||||
ExPrint("\n\eFF0000< No stack trace available. >\n");
|
||||
ExPrint("\n\x1b[31m< No stack trace available. >\x1b[0m\n");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -530,8 +490,8 @@ nsa void DisplayStackScreen(CPU::ExceptionFrame *Frame)
|
||||
if (!sf->ip)
|
||||
break;
|
||||
|
||||
ExPrint("\eAAAAAA%p", (void *)sf->ip);
|
||||
ExPrint("\e5A5A5A in ");
|
||||
ExPrint("%p", (void *)sf->ip);
|
||||
ExPrint(" in ");
|
||||
if ((sf->ip >= (uintptr_t)&_kernel_start &&
|
||||
sf->ip <= (uintptr_t)&_kernel_end))
|
||||
{
|
||||
@ -540,10 +500,10 @@ nsa void DisplayStackScreen(CPU::ExceptionFrame *Frame)
|
||||
if (offset < 0)
|
||||
offset = -offset;
|
||||
|
||||
ExPrint("\eFAFAFA%s\e5A5A5A+%#lx\n", sym, offset);
|
||||
ExPrint("%s+%#lx\n", sym, offset);
|
||||
}
|
||||
else
|
||||
ExPrint("\eFF5555???\n");
|
||||
ExPrint("???\n");
|
||||
|
||||
if (!vmm.Check(sf->bp))
|
||||
return;
|
||||
@ -554,17 +514,17 @@ nsa void DisplayStackScreen(CPU::ExceptionFrame *Frame)
|
||||
nsa void DisplayProcessScreen(CPU::ExceptionFrame *Frame, bool IgnoreReady = true)
|
||||
{
|
||||
const char *StatusColor[] = {
|
||||
"FF0000", // Unknown
|
||||
"AAFF00", // Ready
|
||||
"00AA00", // Running
|
||||
"FFAA00", // Sleeping
|
||||
"FFAA00", // Blocked
|
||||
"FFAA00", // Stopped
|
||||
"FFAA00", // Waiting
|
||||
"31m", // Unknown
|
||||
"1;33m", // Ready
|
||||
"32m", // Running
|
||||
"1;33m", // Sleeping
|
||||
"1;33m", // Blocked
|
||||
"1;33m", // Stopped
|
||||
"1;33m", // Waiting
|
||||
|
||||
"FF00FF", // Core dump
|
||||
"FF0088", // Zombie
|
||||
"FF0000", // Terminated
|
||||
"35m", // Core dump
|
||||
"1;31m", // Zombie
|
||||
"31m", // Terminated
|
||||
};
|
||||
|
||||
const char *StatusString[] = {
|
||||
@ -583,7 +543,7 @@ nsa void DisplayProcessScreen(CPU::ExceptionFrame *Frame, bool IgnoreReady = tru
|
||||
|
||||
if (!TaskManager)
|
||||
{
|
||||
ExPrint("\eFF5555Tasking is not initialized\n");
|
||||
ExPrint("Tasking is not initialized\n");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -593,7 +553,7 @@ nsa void DisplayProcessScreen(CPU::ExceptionFrame *Frame, bool IgnoreReady = tru
|
||||
|
||||
std::vector<Tasking::PCB *> Plist = TaskManager->GetProcessList();
|
||||
|
||||
ExPrint("\n\eFAFAFAProcess list (%ld):\n", Plist.size());
|
||||
ExPrint("\nProcess list (%ld):\n", Plist.size());
|
||||
bool pRdy = false;
|
||||
bool showNote = false;
|
||||
/* FIXME: This is slow */
|
||||
@ -620,9 +580,9 @@ nsa void DisplayProcessScreen(CPU::ExceptionFrame *Frame, bool IgnoreReady = tru
|
||||
}
|
||||
}
|
||||
|
||||
ExPrint("\eAAAAAA-> \eFAFAFA%.*s%s\e8A8A8A(%ld) \e%s%s \e8A8A8A[exe: %s]\n",
|
||||
ExPrint("-> %.*s%s(%ld) \x1b[%s%s\x1b[0m [exe: %s]\n",
|
||||
textLimit, Process->Name,
|
||||
strlen(Process->Name) > textLimit ? "\e8A8A8A..." : "",
|
||||
strlen(Process->Name) > textLimit ? "..." : "",
|
||||
Process->ID, StatusColor[Process->State.load()],
|
||||
StatusString[Process->State.load()],
|
||||
Process->Executable
|
||||
@ -641,22 +601,24 @@ nsa void DisplayProcessScreen(CPU::ExceptionFrame *Frame, bool IgnoreReady = tru
|
||||
continue;
|
||||
}
|
||||
|
||||
ExPrint("\eAAAAAA -> \eFAFAFA%.*s%s\e8A8A8A(%ld) \e%s%s\n",
|
||||
ExPrint(" -> %.*s%s(%ld) \x1b[%s%s\x1b[0m\n",
|
||||
textLimit, Thread->Name,
|
||||
strlen(Thread->Name) > textLimit ? "\e8A8A8A..." : "",
|
||||
strlen(Thread->Name) > textLimit ? "..." : "",
|
||||
Thread->ID, StatusColor[Thread->State.load()],
|
||||
StatusString[Thread->State.load()]);
|
||||
}
|
||||
if (tRdy)
|
||||
ExPrint("\eAAAAAA%s -> \e8A8A8A...\n");
|
||||
ExPrint(" -> ...\n");
|
||||
}
|
||||
if (pRdy)
|
||||
ExPrint("\eAAAAAA-> \e8A8A8A...\n");
|
||||
ExPrint("-> ...\n");
|
||||
|
||||
if (showNote)
|
||||
ExPrint("\e5A5A5ANote: Some processes may not be displayed.\n");
|
||||
ExPrint("Note: Some processes may not be displayed.\n");
|
||||
}
|
||||
|
||||
void UserInput(char *Input);
|
||||
void ArrowInput(uint8_t key);
|
||||
CPU::ExceptionFrame *ExFrame;
|
||||
nsa void DisplayCrashScreen(CPU::ExceptionFrame *Frame)
|
||||
{
|
||||
@ -668,11 +630,10 @@ nsa void DisplayCrashScreen(CPU::ExceptionFrame *Frame)
|
||||
// memcpy(BufferBeforeUpdate, Display->GetBuffer, Display->GetSize);
|
||||
|
||||
Display->ClearBuffer();
|
||||
ExPrint("\x1b[2J\x1b[H");
|
||||
if (Config.InterruptsOnCrash == false)
|
||||
{
|
||||
Display->SetBufferCursor(0, 0);
|
||||
DisplayMainScreen(Frame);
|
||||
Display->UpdateBuffer();
|
||||
CPU::Stop();
|
||||
}
|
||||
|
||||
@ -680,21 +641,122 @@ nsa void DisplayCrashScreen(CPU::ExceptionFrame *Frame)
|
||||
|
||||
DisplayMainScreen(Frame);
|
||||
|
||||
Display->UpdateBuffer();
|
||||
new CrashKeyboardDriver;
|
||||
|
||||
DisplayBottomOverlay();
|
||||
Display->UpdateBuffer();
|
||||
CPU::Halt(true);
|
||||
// CPU::Halt(true);
|
||||
|
||||
#ifdef DEBUG
|
||||
static int once = 0;
|
||||
static uint8_t com4 = 0xFF;
|
||||
if (!once++)
|
||||
com4 = inb(0x2E8);
|
||||
if (com4 == 0xFF)
|
||||
CPU::Halt(true);
|
||||
|
||||
char UserInputBuffer[256]{'\0'};
|
||||
int BackSpaceLimit = 0;
|
||||
|
||||
while (true)
|
||||
{
|
||||
while ((inb(0x2E8 + 5) & 1) == 0)
|
||||
CPU::Pause();
|
||||
char key = inb(0x2E8);
|
||||
// debug("key: %d", key);
|
||||
|
||||
if (key == '\x7f') /* Backspace (DEL) */
|
||||
{
|
||||
if (BackSpaceLimit <= 0)
|
||||
continue;
|
||||
|
||||
char keyBuf[5] = {'\b', '\x1b', '[', 'K', '\0'};
|
||||
ExPrint(keyBuf);
|
||||
backspace(UserInputBuffer);
|
||||
BackSpaceLimit--;
|
||||
continue;
|
||||
}
|
||||
else if (key == '\x0d') /* Enter (CR) */
|
||||
{
|
||||
UserInput(UserInputBuffer);
|
||||
BackSpaceLimit = 0;
|
||||
UserInputBuffer[0] = '\0';
|
||||
continue;
|
||||
}
|
||||
else if (key == '\x1b') /* Escape */
|
||||
{
|
||||
char tmp[16]{'\0'};
|
||||
append(tmp, key);
|
||||
|
||||
while ((inb(0x2E8 + 5) & 1) == 0)
|
||||
CPU::Pause();
|
||||
char key = inb(0x2E8);
|
||||
append(tmp, key);
|
||||
|
||||
if (key == '[')
|
||||
{
|
||||
// 27 91
|
||||
// < 68
|
||||
// > 67
|
||||
// down 66
|
||||
// up 65
|
||||
while ((inb(0x2E8 + 5) & 1) == 0)
|
||||
CPU::Pause();
|
||||
key = inb(0x2E8);
|
||||
append(tmp, key);
|
||||
switch (key)
|
||||
{
|
||||
case 'A':
|
||||
key = KEY_D_UP;
|
||||
break;
|
||||
case 'B':
|
||||
key = KEY_D_DOWN;
|
||||
break;
|
||||
case 'C':
|
||||
key = KEY_D_RIGHT;
|
||||
break;
|
||||
case 'D':
|
||||
key = KEY_D_LEFT;
|
||||
break;
|
||||
default:
|
||||
{
|
||||
for (size_t i = 0; i < strlen(tmp); i++)
|
||||
{
|
||||
if ((int)sizeof(UserInputBuffer) <= BackSpaceLimit)
|
||||
continue;
|
||||
|
||||
append(UserInputBuffer, tmp[i]);
|
||||
BackSpaceLimit++;
|
||||
char keyBuf[2] = {(char)tmp[i], '\0'};
|
||||
ExPrint(keyBuf);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
ArrowInput(key);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if ((int)sizeof(UserInputBuffer) <= BackSpaceLimit)
|
||||
continue;
|
||||
|
||||
append(UserInputBuffer, key);
|
||||
BackSpaceLimit++;
|
||||
char keyBuf[2] = {(char)key, '\0'};
|
||||
ExPrint(keyBuf);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
nsa void DisplayStackSmashing()
|
||||
{
|
||||
InitFont();
|
||||
ExPrint("\x1b[2J\x1b[H");
|
||||
Display->ClearBuffer();
|
||||
DisplayTopOverlay();
|
||||
|
||||
ExPrint("\n\eFAFAFAWe're sorry, but the system has encountered a critical error and needs to restart.\n");
|
||||
ExPrint("\nWe're sorry, but the system has encountered a critical error and needs to restart.\n");
|
||||
ExPrint("\nError: Stack Smashing In Kernel Mode\n");
|
||||
|
||||
CPUData *core = GetCurrentCPU();
|
||||
@ -708,9 +770,7 @@ nsa void DisplayStackSmashing()
|
||||
|
||||
ExPrint("\nWhat to do:\n");
|
||||
ExPrint(" This is a kernel bug.\n");
|
||||
ExPrint(" Please create a new issue on \e00AAFFhttps://github.com/Fennix-Project/Fennix\eFAFAFA for further assistance.\n");
|
||||
|
||||
Display->UpdateBuffer();
|
||||
ExPrint(" Please create a new issue on https://github.com/Fennix-Project/Fennix for further assistance.\n");
|
||||
|
||||
/* TODO: Add additional info */
|
||||
}
|
||||
@ -718,10 +778,11 @@ nsa void DisplayStackSmashing()
|
||||
nsa void DisplayBufferOverflow()
|
||||
{
|
||||
InitFont();
|
||||
ExPrint("\x1b[2J\x1b[H");
|
||||
Display->ClearBuffer();
|
||||
DisplayTopOverlay();
|
||||
|
||||
ExPrint("\n\eFAFAFAWe're sorry, but the system has encountered a critical error and needs to restart.\n");
|
||||
ExPrint("\nWe're sorry, but the system has encountered a critical error and needs to restart.\n");
|
||||
ExPrint("\nError: Buffer Overflow In Kernel Mode\n");
|
||||
|
||||
CPUData *core = GetCurrentCPU();
|
||||
@ -735,9 +796,7 @@ nsa void DisplayBufferOverflow()
|
||||
|
||||
ExPrint("\nWhat to do:\n");
|
||||
ExPrint(" This is a kernel bug.\n");
|
||||
ExPrint(" Please create a new issue on \e00AAFFhttps://github.com/Fennix-Project/Fennix\eFAFAFA for further assistance.\n");
|
||||
|
||||
Display->UpdateBuffer();
|
||||
ExPrint(" Please create a new issue on https://github.com/Fennix-Project/Fennix for further assistance.\n");
|
||||
|
||||
/* TODO: Add additional info */
|
||||
}
|
||||
@ -745,10 +804,11 @@ nsa void DisplayBufferOverflow()
|
||||
nsa void DisplayAssertionFailed(const char *File, int Line, const char *Expression)
|
||||
{
|
||||
InitFont();
|
||||
ExPrint("\x1b[2J\x1b[H");
|
||||
Display->ClearBuffer();
|
||||
DisplayTopOverlay();
|
||||
|
||||
ExPrint("\n\eFAFAFAWe're sorry, but the system has encountered a critical error and needs to restart.\n");
|
||||
ExPrint("\nWe're sorry, but the system has encountered a critical error and needs to restart.\n");
|
||||
ExPrint("\nError: Assertion Failed\n");
|
||||
ExPrint("In file \"%s\" at line %d, \"%s\" failed\n",
|
||||
File, Line, Expression);
|
||||
@ -764,7 +824,7 @@ nsa void DisplayAssertionFailed(const char *File, int Line, const char *Expressi
|
||||
|
||||
ExPrint("\nWhat to do:\n");
|
||||
ExPrint(" This is a kernel bug.\n");
|
||||
ExPrint(" Please create a new issue on \e00AAFFhttps://github.com/Fennix-Project/Fennix\eFAFAFA for further assistance.\n");
|
||||
ExPrint(" Please create a new issue on https://github.com/Fennix-Project/Fennix for further assistance.\n");
|
||||
|
||||
CPU::ExceptionFrame ef;
|
||||
// Fill only the necessary fields
|
||||
@ -789,7 +849,6 @@ nsa void DisplayAssertionFailed(const char *File, int Line, const char *Expressi
|
||||
ef.ebp = ef.esp = (uint32_t)stk;
|
||||
#endif
|
||||
DisplayStackScreen(&ef);
|
||||
Display->UpdateBuffer();
|
||||
|
||||
/* TODO: Add additional info */
|
||||
}
|
||||
@ -817,6 +876,7 @@ nsa void ArrowInput(uint8_t key)
|
||||
}
|
||||
|
||||
Display->ClearBuffer();
|
||||
ExPrint("\x1b[2J");
|
||||
DisplayTopOverlay();
|
||||
|
||||
switch (ActiveScreen)
|
||||
@ -838,31 +898,31 @@ nsa void ArrowInput(uint8_t key)
|
||||
}
|
||||
|
||||
DisplayBottomOverlay();
|
||||
Display->UpdateBuffer();
|
||||
}
|
||||
|
||||
nsa void UserInput(char *Input)
|
||||
{
|
||||
debug("User input: %s", Input);
|
||||
Display->ClearBuffer();
|
||||
ExPrint("\x1b[2J");
|
||||
DisplayTopOverlay();
|
||||
|
||||
if (strcmp(Input, "help") == 0)
|
||||
{
|
||||
ExPrint("Commands:\n");
|
||||
ExPrint("\eAAAAAA help - Display this help message.\n");
|
||||
ExPrint("\eCACACA clear - Clear the screen.\n");
|
||||
ExPrint("\eAAAAAA exit - Shutdown the device.\n");
|
||||
ExPrint("\eCACACA reboot - Reboot the device.\n");
|
||||
ExPrint("\eAAAAAA bitmap - Display the kernel's bitmap.\n");
|
||||
ExPrint("\eCACACA mem - Display memory information.\n");
|
||||
ExPrint("\eAAAAAA dump [addr] [len] - Dump [len] bytes from [addr].\n");
|
||||
ExPrint("\eCACACA diag - Collect diagnostic information.\n");
|
||||
ExPrint("\eAAAAAA screen - Display the final output prior to system panic.\n");
|
||||
ExPrint("\x1b[1;37m help - Display this help message.\n");
|
||||
ExPrint("\x1b[0m clear - Clear the screen.\n");
|
||||
ExPrint("\x1b[1;37m exit - Shutdown the device.\n");
|
||||
ExPrint("\x1b[0m reboot - Reboot the device.\n");
|
||||
ExPrint("\x1b[1;37m bitmap - Display the kernel's bitmap.\n");
|
||||
ExPrint("\x1b[0m mem - Display memory information.\n");
|
||||
ExPrint("\x1b[1;37m dump [addr] [len] - Dump [len] bytes from [addr].\n");
|
||||
ExPrint("\x1b[0m diag - Collect diagnostic information.\n");
|
||||
ExPrint("\x1b[1;37m screen - Display the final output prior to system panic.\n");
|
||||
}
|
||||
else if (strcmp(Input, "clear") == 0)
|
||||
{
|
||||
Display->ClearBuffer();
|
||||
ExPrint("\x1b[2J");
|
||||
DisplayTopOverlay();
|
||||
}
|
||||
else if (strcmp(Input, "exit") == 0)
|
||||
@ -871,14 +931,15 @@ nsa void UserInput(char *Input)
|
||||
|
||||
const char msg[] = "Shutting down...";
|
||||
size_t msgLen = strlen(msg);
|
||||
size_t msgPixels = msgLen * CrashFont->GetInfo().Width;
|
||||
size_t msgPixels = msgLen * CrashFontRenderer.CurrentFont->GetInfo().Width;
|
||||
uint32_t x = uint32_t((Display->GetWidth - msgPixels) / 2);
|
||||
uint32_t y = uint32_t((Display->GetHeight - CrashFont->GetInfo().Height) / 2);
|
||||
Display->SetBufferCursor(x, y);
|
||||
Display->PrintString("\eAAAAAA");
|
||||
Display->PrintString(msg, CrashFont);
|
||||
uint32_t y = uint32_t((Display->GetHeight - CrashFontRenderer.CurrentFont->GetInfo().Height) / 2);
|
||||
x /= CrashFontRenderer.CurrentFont->GetInfo().Width;
|
||||
y /= CrashFontRenderer.CurrentFont->GetInfo().Height;
|
||||
ExPrint("\x1b[2J");
|
||||
ExPrint("\x1b[%d;%dH", y, x);
|
||||
ExPrint("\x1b[30;41m%s\x1b[0m\x1b[H", msg);
|
||||
|
||||
Display->UpdateBuffer();
|
||||
PowerManager->Shutdown();
|
||||
CPU::Stop();
|
||||
}
|
||||
@ -888,42 +949,37 @@ nsa void UserInput(char *Input)
|
||||
|
||||
const char msg[] = "Rebooting...";
|
||||
size_t msgLen = strlen(msg);
|
||||
size_t msgPixels = msgLen * CrashFont->GetInfo().Width;
|
||||
size_t msgPixels = msgLen * CrashFontRenderer.CurrentFont->GetInfo().Width;
|
||||
uint32_t x = uint32_t((Display->GetWidth - msgPixels) / 2);
|
||||
uint32_t y = uint32_t((Display->GetHeight - CrashFont->GetInfo().Height) / 2);
|
||||
Display->SetBufferCursor(x, y);
|
||||
Display->PrintString("\eAAAAAA");
|
||||
Display->PrintString(msg, CrashFont);
|
||||
uint32_t y = uint32_t((Display->GetHeight - CrashFontRenderer.CurrentFont->GetInfo().Height) / 2);
|
||||
x /= CrashFontRenderer.CurrentFont->GetInfo().Width;
|
||||
y /= CrashFontRenderer.CurrentFont->GetInfo().Height;
|
||||
ExPrint("\x1b[2J");
|
||||
ExPrint("\x1b[%d;%dH", y, x);
|
||||
ExPrint("\x1b[30;41m%s\x1b[0m\x1b[H", msg);
|
||||
|
||||
Display->UpdateBuffer();
|
||||
PowerManager->Reboot();
|
||||
CPU::Stop();
|
||||
}
|
||||
else if (strncmp(Input, "bitmap", 6) == 0)
|
||||
{
|
||||
Bitmap bm = KernelAllocator.GetPageBitmap();
|
||||
Video::Font *oldFont = CrashFont;
|
||||
CrashFont = Display->GetDefaultFont();
|
||||
|
||||
ExPrint("\n\eAAAAAA[0%%] %08ld: ", 0);
|
||||
ExPrint("\n[0%%] %08ld: ", 0);
|
||||
for (size_t i = 0; i < bm.Size; i++)
|
||||
{
|
||||
if (bm.Get(i))
|
||||
Display->PrintString("\eFF0000");
|
||||
ExPrint("\x1b[31m1\x1b[0m");
|
||||
else
|
||||
Display->PrintString("\e00FF00");
|
||||
Display->Print('0');
|
||||
ExPrint("\x1b[32m0\x1b[0m");
|
||||
if (i % 128 == 127)
|
||||
{
|
||||
short Percentage = s_cst(short, (i * 100) / bm.Size);
|
||||
ExPrint("\n\eAAAAAA[%03ld%%] %08ld: ", Percentage, i);
|
||||
Display->UpdateBuffer();
|
||||
ExPrint("\n[%03ld%%] %08ld: ", Percentage, i);
|
||||
}
|
||||
}
|
||||
ExPrint("\n\eAAAAAA--- END OF BITMAP ---\nBitmap size: %ld\n\n.", bm.Size);
|
||||
ExPrint("\n--- END OF BITMAP ---\nBitmap size: %ld\n\n.", bm.Size);
|
||||
DisplayTopOverlay();
|
||||
Display->UpdateBuffer();
|
||||
CrashFont = oldFont;
|
||||
}
|
||||
else if (strcmp(Input, "mem") == 0)
|
||||
{
|
||||
@ -932,17 +988,17 @@ nsa void UserInput(char *Input)
|
||||
uint64_t Free = KernelAllocator.GetFreeMemory();
|
||||
uint64_t Reserved = KernelAllocator.GetReservedMemory();
|
||||
|
||||
ExPrint("\e22AA44Total: %ld bytes\n\eFF0000Used: %ld bytes\n\e00FF00Free: %ld bytes\n\eFF00FFReserved: %ld bytes\n", Total, Used, Free, Reserved);
|
||||
ExPrint("\x1b[1;32mTotal: %ld bytes\n\x1b[1;31mUsed: %ld bytes\n\x1b[1;32mFree: %ld bytes\n\x1b[1;35mReserved: %ld bytes\n", Total, Used, Free, Reserved);
|
||||
int Progress = s_cst(int, (Used * 100) / Total);
|
||||
int ReservedProgress = s_cst(int, (Reserved * 100) / Total);
|
||||
ExPrint("\e22AA44%3d%% \eCCCCCC[", Progress);
|
||||
ExPrint("\x1b[1;32m%3d%% \x1b[0m[", Progress);
|
||||
for (int i = 0; i < Progress; i++)
|
||||
ExPrint("\eFF0000|");
|
||||
ExPrint("\x1b[1;31m|");
|
||||
for (int i = 0; i < 100 - Progress; i++)
|
||||
ExPrint("\e00FF00|");
|
||||
ExPrint("\x1b[1;32m|");
|
||||
for (int i = 0; i < ReservedProgress; i++)
|
||||
ExPrint("\eFF00FF|");
|
||||
ExPrint("\eCCCCCC]\eAAAAAA\n");
|
||||
ExPrint("\x1b[1;35m|");
|
||||
ExPrint("\x1b[0m]\n");
|
||||
}
|
||||
else if (strncmp(Input, "dump", 4) == 0)
|
||||
{
|
||||
@ -951,7 +1007,7 @@ nsa void UserInput(char *Input)
|
||||
char *len = strtok(NULL, " ");
|
||||
if (addr == NULL || len == NULL)
|
||||
{
|
||||
ExPrint("\eFF0000Invalid arguments\n");
|
||||
ExPrint("\x1b[31mInvalid arguments\n");
|
||||
goto End;
|
||||
}
|
||||
|
||||
@ -968,7 +1024,7 @@ nsa void UserInput(char *Input)
|
||||
{
|
||||
if (!vmm.Check((void *)adr))
|
||||
{
|
||||
ExPrint("\eFFA500Address %#lx is not mapped\n", adr);
|
||||
ExPrint("\x1b[31mAddress %#lx is not mapped\n", adr);
|
||||
IsRangeValid = false;
|
||||
}
|
||||
}
|
||||
@ -977,11 +1033,7 @@ nsa void UserInput(char *Input)
|
||||
if (IsRangeValid)
|
||||
{
|
||||
debug("Dumping %ld bytes from %#lx\n", Length, Address);
|
||||
|
||||
Video::Font *oldFont = CrashFont;
|
||||
CrashFont = Display->GetDefaultFont();
|
||||
ExDumpData((void *)Address, (unsigned long)Length);
|
||||
CrashFont = oldFont;
|
||||
}
|
||||
}
|
||||
else if (strcmp(Input, "diag") == 0)
|
||||
@ -992,11 +1044,10 @@ nsa void UserInput(char *Input)
|
||||
{
|
||||
if (unlikely(FbBeforePanic == nullptr))
|
||||
{
|
||||
ExPrint("\eFF0000No screen data available\n");
|
||||
ExPrint("No screen data available\n");
|
||||
goto End;
|
||||
}
|
||||
memcpy(Display->GetBuffer, FbBeforePanic, Display->GetSize);
|
||||
Display->UpdateBuffer();
|
||||
return;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
@ -1018,5 +1069,4 @@ nsa void UserInput(char *Input)
|
||||
|
||||
End:
|
||||
DisplayBottomOverlay();
|
||||
Display->UpdateBuffer();
|
||||
}
|
||||
|
@ -156,11 +156,11 @@ namespace Time
|
||||
hpet = new HighPrecisionEventTimer(((ACPI::ACPI *)acpi)->HPET);
|
||||
ActiveTimer = HPET;
|
||||
SupportedTimers |= HPET;
|
||||
KPrint("\e11FF11HPET found");
|
||||
KPrint("HPET found");
|
||||
}
|
||||
else
|
||||
{
|
||||
KPrint("\eFF2200HPET not found");
|
||||
KPrint("\x1b[33mHPET not found");
|
||||
}
|
||||
|
||||
/* TODO: ACPI check */
|
||||
@ -168,7 +168,7 @@ namespace Time
|
||||
}
|
||||
else
|
||||
{
|
||||
KPrint("\eFF2200ACPI not found");
|
||||
KPrint("\x1b[33mACPI not found");
|
||||
}
|
||||
|
||||
bool TSCInvariant = false;
|
||||
@ -191,10 +191,10 @@ namespace Time
|
||||
tsc = new TimeStampCounter;
|
||||
// FIXME: ActiveTimer = TSC;
|
||||
SupportedTimers |= TSC;
|
||||
KPrint("\e11FF11Invariant TSC found");
|
||||
KPrint("Invariant TSC found");
|
||||
}
|
||||
else
|
||||
KPrint("\eFF2200TSC is not invariant");
|
||||
KPrint("\x1b[33mTSC is not invariant");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -24,8 +24,6 @@ NewLock(PrintLock);
|
||||
|
||||
namespace Video
|
||||
{
|
||||
Font *Display::GetCurrentFont() { return CurrentFont; }
|
||||
void Display::SetCurrentFont(Font *Font) { CurrentFont = Font; }
|
||||
uint16_t Display::GetBitsPerPixel() { return this->framebuffer.BitsPerPixel; }
|
||||
size_t Display::GetPitch() { return this->framebuffer.Pitch; }
|
||||
|
||||
@ -83,223 +81,6 @@ namespace Video
|
||||
}
|
||||
}
|
||||
|
||||
void Display::Scroll(int Lines)
|
||||
{
|
||||
if (this->DoNotScroll)
|
||||
return;
|
||||
|
||||
if (Lines == 0)
|
||||
return;
|
||||
|
||||
if (Lines > 0)
|
||||
{
|
||||
uint32_t LineSize = this->Width * (this->framebuffer.BitsPerPixel / 8);
|
||||
uint32_t BytesToMove = LineSize * Lines * this->CurrentFont->GetInfo().Height;
|
||||
size_t BytesToClear = this->Size - BytesToMove;
|
||||
memmove(this->Buffer, (uint8_t *)this->Buffer + BytesToMove, BytesToClear);
|
||||
memset((uint8_t *)this->Buffer + BytesToClear, 0, BytesToMove);
|
||||
|
||||
// memset(this->DirtyMap.data(), true, this->DirtyMap.size());
|
||||
}
|
||||
}
|
||||
|
||||
__no_sanitize("undefined") char Display::Print(char Char,
|
||||
Video::Font *_Font,
|
||||
bool WriteToUART,
|
||||
bool IgnoreSpecialChars)
|
||||
{
|
||||
// SmartLock(PrintLock);
|
||||
|
||||
if (this->ColorIteration)
|
||||
{
|
||||
// RRGGBB
|
||||
if (Char >= '0' && Char <= '9')
|
||||
this->Color = (this->Color << 4) | (Char - '0');
|
||||
else if (Char >= 'a' && Char <= 'f')
|
||||
this->Color = (this->Color << 4) | (Char - 'a' + 10);
|
||||
else if (Char >= 'A' && Char <= 'F')
|
||||
this->Color = (this->Color << 4) | (Char - 'A' + 10);
|
||||
else
|
||||
this->Color = 0xFFFFFF;
|
||||
this->ColorPickerIteration++;
|
||||
if (this->ColorPickerIteration == 6)
|
||||
{
|
||||
this->ColorPickerIteration = 0;
|
||||
this->ColorIteration = false;
|
||||
}
|
||||
return Char;
|
||||
}
|
||||
|
||||
if (WriteToUART && Char != '\e')
|
||||
UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM1).Write(Char);
|
||||
|
||||
if (_Font == nullptr)
|
||||
_Font = this->DefaultFont;
|
||||
this->CurrentFont = _Font;
|
||||
uint32_t FontHeight;
|
||||
|
||||
if (IgnoreSpecialChars)
|
||||
goto IgnoreSpecialChars;
|
||||
|
||||
switch (Char)
|
||||
{
|
||||
case '\e':
|
||||
{
|
||||
this->ColorIteration = true;
|
||||
return Char;
|
||||
}
|
||||
case '\b':
|
||||
{
|
||||
switch (_Font->GetInfo().Type)
|
||||
{
|
||||
case FontType::PCScreenFont1:
|
||||
{
|
||||
fixme("PCScreenFont1");
|
||||
break;
|
||||
}
|
||||
case FontType::PCScreenFont2:
|
||||
{
|
||||
uint32_t fonthdrWidth = _Font->GetInfo().PSF2Font->Header->width;
|
||||
uint32_t fonthdrHeight = _Font->GetInfo().PSF2Font->Header->height;
|
||||
|
||||
for (unsigned long Y = this->CursorY; Y < this->CursorY + fonthdrHeight; Y++)
|
||||
for (unsigned long X = this->CursorX - fonthdrWidth; X < this->CursorX; X++)
|
||||
*(uint32_t *)((uintptr_t)this->Buffer +
|
||||
(Y * this->Width + X) * (this->framebuffer.BitsPerPixel / 8)) = 0;
|
||||
|
||||
// for (size_t i = 0; i < 9; ++i)
|
||||
// {
|
||||
// size_t row = (CursorY / RegionHeight) + (i / 3) - 1;
|
||||
// size_t col = (CursorX / RegionWidth) + (i % 3) - 1;
|
||||
// if (row < Height / RegionHeight && col < Width / RegionWidth)
|
||||
// MarkRegionDirty(row, col);
|
||||
// }
|
||||
break;
|
||||
}
|
||||
default:
|
||||
warn("Unsupported font type");
|
||||
break;
|
||||
}
|
||||
|
||||
if (this->CursorX > 0)
|
||||
this->CursorX -= this->GetCurrentFont()->GetInfo().Width;
|
||||
|
||||
return Char;
|
||||
}
|
||||
case '\t':
|
||||
{
|
||||
this->CursorX = (this->CursorX + 8) & ~(8 - 1);
|
||||
return Char;
|
||||
}
|
||||
case '\r':
|
||||
{
|
||||
this->CursorX = 0;
|
||||
return Char;
|
||||
}
|
||||
case '\n':
|
||||
{
|
||||
this->CursorX = 0;
|
||||
this->CursorY += this->GetCurrentFont()->GetInfo().Height;
|
||||
return Char;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
IgnoreSpecialChars:
|
||||
FontHeight = this->GetCurrentFont()->GetInfo().Height;
|
||||
|
||||
if (this->CursorX + this->GetCurrentFont()->GetInfo().Width >= this->Width)
|
||||
{
|
||||
this->CursorX = 0;
|
||||
this->CursorY += FontHeight;
|
||||
}
|
||||
|
||||
if (this->CursorY + FontHeight >= this->Height)
|
||||
{
|
||||
if (!this->DoNotScroll)
|
||||
{
|
||||
this->CursorY -= FontHeight;
|
||||
this->Scroll(1);
|
||||
}
|
||||
}
|
||||
|
||||
switch (_Font->GetInfo().Type)
|
||||
{
|
||||
case FontType::PCScreenFont1:
|
||||
{
|
||||
uint32_t *PixelPtr = (uint32_t *)this->Buffer;
|
||||
char *FontPtr = (char *)_Font->GetInfo().PSF1Font->GlyphBuffer + (Char * _Font->GetInfo().PSF1Font->Header->charsize);
|
||||
for (uint64_t Y = this->CursorY; Y < this->CursorY + 16; Y++)
|
||||
{
|
||||
for (uint64_t X = this->CursorX; X < this->CursorX + 8; X++)
|
||||
if ((*FontPtr & (0b10000000 >> (X - this->CursorX))) > 0)
|
||||
*(unsigned int *)(PixelPtr + X + (Y * this->Width)) = this->Color;
|
||||
FontPtr++;
|
||||
}
|
||||
this->CursorX += 8;
|
||||
|
||||
break;
|
||||
}
|
||||
case FontType::PCScreenFont2:
|
||||
{
|
||||
// if (_Font->PSF2Font->GlyphBuffer == (uint16_t *)0x01) // HAS UNICODE TABLE
|
||||
// Char = _Font->PSF2Font->GlyphBuffer[Char];
|
||||
|
||||
FontInfo fInfo = _Font->GetInfo();
|
||||
|
||||
int BytesPerLine = (fInfo.PSF2Font->Header->width + 7) / 8;
|
||||
char *FontAddress = (char *)fInfo.StartAddress;
|
||||
uint32_t FontHeaderSize = fInfo.PSF2Font->Header->headersize;
|
||||
uint32_t FontCharSize = fInfo.PSF2Font->Header->charsize;
|
||||
uint32_t FontLength = fInfo.PSF2Font->Header->length;
|
||||
char *FontPtr = FontAddress + FontHeaderSize + (Char > 0 && (uint32_t)Char < FontLength ? Char : 0) * FontCharSize;
|
||||
|
||||
uint32_t FontHdrWidth = fInfo.PSF2Font->Header->width;
|
||||
uint32_t FontHdrHeight = fInfo.PSF2Font->Header->height;
|
||||
|
||||
for (size_t Y = this->CursorY; Y < this->CursorY + FontHdrHeight; Y++)
|
||||
{
|
||||
for (size_t X = this->CursorX; X < this->CursorX + FontHdrWidth; X++)
|
||||
{
|
||||
if ((*FontPtr & (0b10000000 >> (X - this->CursorX))) > 0)
|
||||
{
|
||||
void *FramebufferAddress = (void *)((uintptr_t)this->Buffer +
|
||||
(Y * this->Width + X) *
|
||||
(this->framebuffer.BitsPerPixel / 8));
|
||||
*(uint32_t *)FramebufferAddress = this->Color;
|
||||
}
|
||||
}
|
||||
FontPtr += BytesPerLine;
|
||||
}
|
||||
this->CursorX += FontHdrWidth;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
warn("Unsupported font type");
|
||||
break;
|
||||
}
|
||||
|
||||
// // MarkRegionDirty(CursorY / RegionHeight, CursorX / RegionWidth);
|
||||
// for (size_t i = 0; i < 9; ++i)
|
||||
// {
|
||||
// size_t row = (CursorY / RegionHeight) + (i / 3) - 1;
|
||||
// size_t col = (CursorX / RegionWidth) + (i % 3) - 1;
|
||||
// if (row < Height / RegionHeight && col < Width / RegionWidth)
|
||||
// MarkRegionDirty(row, col);
|
||||
// }
|
||||
return Char;
|
||||
}
|
||||
|
||||
void Display::PrintString(const char *String,
|
||||
Video::Font *Font,
|
||||
bool WriteToUART,
|
||||
bool IgnoreSpecialChars)
|
||||
{
|
||||
for (size_t i = 0; String[i] != '\0'; ++i)
|
||||
Print(String[i], Font, WriteToUART, IgnoreSpecialChars);
|
||||
}
|
||||
|
||||
void Display::UpdateBuffer()
|
||||
{
|
||||
if (!DirectWrite)
|
||||
@ -367,7 +148,6 @@ namespace Video
|
||||
}
|
||||
|
||||
Display::Display(BootInfo::FramebufferInfo Info,
|
||||
bool LoadDefaultFont,
|
||||
bool _DirectWrite)
|
||||
: framebuffer(Info), DirectWrite(_DirectWrite)
|
||||
{
|
||||
@ -380,16 +160,6 @@ namespace Video
|
||||
Buffer = KernelAllocator.RequestPages(TO_PAGES(Size));
|
||||
|
||||
// DirtyMap.resize((Width / RegionWidth) * (Height / RegionHeight), false);
|
||||
|
||||
if (!LoadDefaultFont)
|
||||
return;
|
||||
this->DefaultFont = new Font(&_binary_files_tamsyn_font_1_11_Tamsyn7x14r_psf_start, &_binary_files_tamsyn_font_1_11_Tamsyn7x14r_psf_end, FontType::PCScreenFont2);
|
||||
#ifdef DEBUG
|
||||
FontInfo fInfo = this->DefaultFont->GetInfo();
|
||||
debug("Font loaded: %dx%d %s",
|
||||
fInfo.Width, fInfo.Height,
|
||||
fInfo.Type == FontType::PCScreenFont1 ? "PSF1" : "PSF2");
|
||||
#endif
|
||||
}
|
||||
|
||||
Display::~Display() {}
|
||||
|
499
core/vt.cpp
Normal file
499
core/vt.cpp
Normal file
@ -0,0 +1,499 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <kcon.hpp>
|
||||
|
||||
#include <memory.hpp>
|
||||
#include <stropts.h>
|
||||
#include <string.h>
|
||||
#include <uart.hpp>
|
||||
|
||||
#include "../kernel.h"
|
||||
|
||||
namespace KernelConsole
|
||||
{
|
||||
void VirtualTerminal::Clear(unsigned short StartX, unsigned short StartY, unsigned short EndX, unsigned short EndY)
|
||||
{
|
||||
assert(this->PaintCB != nullptr);
|
||||
for (long i = StartX + StartY * this->termSize.ws_row; i < EndX + EndY * this->termSize.ws_row; i++)
|
||||
{
|
||||
TerminalCell *cell = &this->Cells[i];
|
||||
cell->c = ' ';
|
||||
cell->attr = {};
|
||||
|
||||
this->PaintCB(cell, i % this->termSize.ws_row, i / this->termSize.ws_row);
|
||||
}
|
||||
}
|
||||
|
||||
void VirtualTerminal::Scroll(unsigned short Lines)
|
||||
{
|
||||
assert(this->PaintCB != nullptr);
|
||||
if (Lines == 0)
|
||||
return;
|
||||
|
||||
Lines = Lines > this->termSize.ws_col ? this->termSize.ws_col : Lines;
|
||||
|
||||
for (int i = 0; i < ((this->termSize.ws_row * this->termSize.ws_col) - (this->termSize.ws_row * Lines)); i++)
|
||||
{
|
||||
this->Cells[i] = this->Cells[i + (this->termSize.ws_row * Lines)];
|
||||
this->PaintCB(&this->Cells[i], i % this->termSize.ws_row, i / this->termSize.ws_row);
|
||||
}
|
||||
|
||||
for (int i = ((this->termSize.ws_row * this->termSize.ws_col) - (this->termSize.ws_row * Lines)); i < this->termSize.ws_row * this->termSize.ws_col; i++)
|
||||
{
|
||||
TerminalCell *cell = &this->Cells[i];
|
||||
cell->attr = {};
|
||||
cell->c = ' ';
|
||||
|
||||
this->PaintCB(cell, i % this->termSize.ws_row, i / this->termSize.ws_row);
|
||||
}
|
||||
|
||||
// Move the cursor up $lines
|
||||
if (this->Cursor.Y > 0)
|
||||
{
|
||||
this->Cursor.Y -= Lines;
|
||||
|
||||
if (this->Cursor.Y < 0)
|
||||
this->Cursor.Y = 0;
|
||||
|
||||
if (this->CursorCB != nullptr)
|
||||
this->CursorCB(&this->Cursor);
|
||||
}
|
||||
}
|
||||
|
||||
void VirtualTerminal::NewLine()
|
||||
{
|
||||
this->Cursor.X = 0;
|
||||
this->Cursor.Y++;
|
||||
|
||||
if (this->Cursor.Y >= this->termSize.ws_col)
|
||||
this->Scroll(1);
|
||||
|
||||
if (this->CursorCB != nullptr)
|
||||
this->CursorCB(&this->Cursor);
|
||||
}
|
||||
|
||||
void VirtualTerminal::Append(char c)
|
||||
{
|
||||
if (c == '\n')
|
||||
this->NewLine();
|
||||
else if (c == '\r')
|
||||
{
|
||||
this->Cursor.X = 0;
|
||||
if (this->CursorCB != nullptr)
|
||||
this->CursorCB(&this->Cursor);
|
||||
}
|
||||
else if (c == '\t')
|
||||
{
|
||||
int n = 8 - (this->Cursor.X % 8);
|
||||
|
||||
for (int i = 0; i < n; i++)
|
||||
this->Append(' ');
|
||||
}
|
||||
else if (c == '\b')
|
||||
{
|
||||
if (this->Cursor.X > 0)
|
||||
{
|
||||
this->Cursor.X--;
|
||||
}
|
||||
else
|
||||
{
|
||||
this->Cursor.Y--;
|
||||
this->Cursor.X = this->termSize.ws_row - 1;
|
||||
}
|
||||
|
||||
if (this->CursorCB != nullptr)
|
||||
this->CursorCB(&this->Cursor);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (this->Cursor.X >= this->termSize.ws_row)
|
||||
this->NewLine();
|
||||
|
||||
TerminalCell *cell = &this->Cells[this->Cursor.X + this->Cursor.Y * this->termSize.ws_row];
|
||||
cell->c = c;
|
||||
cell->attr = this->Attribute;
|
||||
|
||||
assert(this->PaintCB != nullptr);
|
||||
this->PaintCB(cell, this->Cursor.X, this->Cursor.Y);
|
||||
|
||||
this->Cursor.X++;
|
||||
|
||||
if (this->CursorCB != nullptr)
|
||||
this->CursorCB(&this->Cursor);
|
||||
}
|
||||
}
|
||||
|
||||
void VirtualTerminal::csi_cup(ANSIArgument *Args, int ArgsCount)
|
||||
{
|
||||
if (ArgsCount == 1 && Args[0].Empty)
|
||||
{
|
||||
this->Cursor.X = 0;
|
||||
this->Cursor.Y = 0;
|
||||
}
|
||||
else if (ArgsCount == 2)
|
||||
{
|
||||
if (Args[0].Empty)
|
||||
this->Cursor.Y = 0;
|
||||
else
|
||||
this->Cursor.Y = MIN(Args[0].Value - 1, this->termSize.ws_col - 1);
|
||||
|
||||
if (Args[1].Empty)
|
||||
this->Cursor.Y = 0;
|
||||
else
|
||||
this->Cursor.X = MIN(Args[1].Value - 1, this->termSize.ws_row - 1);
|
||||
}
|
||||
|
||||
if (this->CursorCB != nullptr)
|
||||
this->CursorCB(&this->Cursor);
|
||||
}
|
||||
|
||||
void VirtualTerminal::csi_ed(ANSIArgument *Args, int ArgsCount)
|
||||
{
|
||||
TerminalCursor cursor = this->Cursor;
|
||||
|
||||
if (Args[0].Empty)
|
||||
this->Clear(cursor.X, cursor.Y, this->termSize.ws_row, this->termSize.ws_col - 1);
|
||||
else
|
||||
{
|
||||
int attr = Args[0].Value;
|
||||
|
||||
if (attr == 0)
|
||||
this->Clear(cursor.X, cursor.Y, this->termSize.ws_row, this->termSize.ws_col - 1);
|
||||
else if (attr == 1)
|
||||
this->Clear(0, 0, cursor.X, cursor.Y);
|
||||
else if (attr == 2)
|
||||
this->Clear(0, 0, this->termSize.ws_row, this->termSize.ws_col - 1);
|
||||
}
|
||||
}
|
||||
|
||||
void VirtualTerminal::csi_el(ANSIArgument *Args, int ArgsCount)
|
||||
{
|
||||
TerminalCursor cursor = this->Cursor;
|
||||
|
||||
if (Args[0].Empty)
|
||||
this->Clear(cursor.X, cursor.Y, this->termSize.ws_row, cursor.Y);
|
||||
else
|
||||
{
|
||||
int attr = Args[0].Value;
|
||||
|
||||
if (attr == 0)
|
||||
this->Clear(cursor.X, cursor.Y, this->termSize.ws_row, cursor.Y);
|
||||
else if (attr == 1)
|
||||
this->Clear(0, cursor.Y, cursor.X, cursor.Y);
|
||||
else if (attr == 2)
|
||||
this->Clear(0, cursor.Y, this->termSize.ws_row, cursor.Y);
|
||||
}
|
||||
}
|
||||
|
||||
void VirtualTerminal::csi_sgr(ANSIArgument *Args, int ArgsCount)
|
||||
{
|
||||
for (int i = 0; i < ArgsCount; i++)
|
||||
{
|
||||
if (Args[i].Empty || Args[i].Value == 0)
|
||||
this->Attribute = {};
|
||||
else
|
||||
{
|
||||
int attr = Args[i].Value;
|
||||
|
||||
if (attr == 1)
|
||||
this->Attribute.Bright = true;
|
||||
else if (attr >= 30 && attr <= 37)
|
||||
this->Attribute.Foreground = (TerminalColor)(attr - 30);
|
||||
else if (attr >= 40 && attr <= 47)
|
||||
this->Attribute.Background = (TerminalColor)(attr - 40);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VirtualTerminal::csi_cuu(ANSIArgument *Args, int ArgsCount)
|
||||
{
|
||||
int P1 = (ArgsCount > 0 && !Args[0].Empty) ? Args[0].Value : 1;
|
||||
Cursor.Y -= P1;
|
||||
if (Cursor.Y < 0)
|
||||
Cursor.Y = 0;
|
||||
if (CursorCB)
|
||||
CursorCB(&Cursor);
|
||||
}
|
||||
|
||||
void VirtualTerminal::csi_cud(ANSIArgument *Args, int ArgsCount)
|
||||
{
|
||||
int P1 = (ArgsCount > 0 && !Args[0].Empty) ? Args[0].Value : 1;
|
||||
Cursor.Y += P1;
|
||||
if (Cursor.Y >= this->termSize.ws_col)
|
||||
Cursor.Y = this->termSize.ws_col - 1;
|
||||
if (CursorCB)
|
||||
CursorCB(&Cursor);
|
||||
}
|
||||
|
||||
void VirtualTerminal::csi_cuf(ANSIArgument *Args, int ArgsCount)
|
||||
{
|
||||
int P1 = (ArgsCount > 0 && !Args[0].Empty) ? Args[0].Value : 1;
|
||||
Cursor.X += P1;
|
||||
if (Cursor.X >= this->termSize.ws_row)
|
||||
Cursor.X = this->termSize.ws_row - 1;
|
||||
if (CursorCB)
|
||||
CursorCB(&Cursor);
|
||||
}
|
||||
|
||||
void VirtualTerminal::csi_cub(ANSIArgument *Args, int ArgsCount)
|
||||
{
|
||||
int P1 = (ArgsCount > 0 && !Args[0].Empty) ? Args[0].Value : 1;
|
||||
Cursor.X -= P1;
|
||||
if (Cursor.X < 0)
|
||||
Cursor.X = 0;
|
||||
if (CursorCB)
|
||||
CursorCB(&Cursor);
|
||||
}
|
||||
|
||||
void VirtualTerminal::csi_cnl(ANSIArgument *Args, int ArgsCount)
|
||||
{
|
||||
int P1 = (ArgsCount > 0 && !Args[0].Empty) ? Args[0].Value : 1;
|
||||
Cursor.Y += P1;
|
||||
if (Cursor.Y >= this->termSize.ws_col)
|
||||
Cursor.Y = this->termSize.ws_col - 1;
|
||||
Cursor.X = 0;
|
||||
if (CursorCB)
|
||||
CursorCB(&Cursor);
|
||||
}
|
||||
|
||||
void VirtualTerminal::csi_cpl(ANSIArgument *Args, int ArgsCount)
|
||||
{
|
||||
int P1 = (ArgsCount > 0 && !Args[0].Empty) ? Args[0].Value : 1;
|
||||
Cursor.Y -= P1;
|
||||
if (Cursor.Y < 0)
|
||||
Cursor.Y = 0;
|
||||
Cursor.X = 0;
|
||||
if (CursorCB)
|
||||
CursorCB(&Cursor);
|
||||
}
|
||||
|
||||
void VirtualTerminal::csi_cha(ANSIArgument *Args, int ArgsCount)
|
||||
{
|
||||
int P1 = (ArgsCount > 0 && !Args[0].Empty) ? Args[0].Value : 1;
|
||||
Cursor.X = P1 - 1;
|
||||
if (Cursor.X >= this->termSize.ws_row)
|
||||
Cursor.X = this->termSize.ws_row - 1;
|
||||
if (CursorCB)
|
||||
CursorCB(&Cursor);
|
||||
}
|
||||
|
||||
void VirtualTerminal::Process(char c)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
static int once = 0;
|
||||
static uint8_t com4 = 0xFF;
|
||||
if (!once++)
|
||||
{
|
||||
com4 = inb(0x2E8);
|
||||
debug("COM4 is available");
|
||||
outb(s_cst(uint16_t, 0x2E8 + 1), 0x00);
|
||||
outb(s_cst(uint16_t, 0x2E8 + 3), 0x80);
|
||||
outb(s_cst(uint16_t, 0x2E8 + 0), 0x01);
|
||||
outb(s_cst(uint16_t, 0x2E8 + 1), 0x00);
|
||||
outb(s_cst(uint16_t, 0x2E8 + 3), 0x03);
|
||||
outb(s_cst(uint16_t, 0x2E8 + 2), 0xC7);
|
||||
outb(s_cst(uint16_t, 0x2E8 + 4), 0x0B);
|
||||
outb(s_cst(uint16_t, 0x2E8 + 4), 0x0F);
|
||||
}
|
||||
if (com4 != 0xFF)
|
||||
{
|
||||
while ((inb(s_cst(uint16_t, 0x2E8 + 5)) & 0x20) == 0)
|
||||
;
|
||||
outb(0x2E8, c);
|
||||
}
|
||||
|
||||
// while (true)
|
||||
// {
|
||||
// while ((inb(0x2E8 + 5) & 1) == 0)
|
||||
// ;
|
||||
// outb(0x2E8, inb(0x2E8));
|
||||
// }
|
||||
#endif
|
||||
|
||||
ANSIParser *parser = &this->Parser;
|
||||
|
||||
switch (parser->State)
|
||||
{
|
||||
case ANSIParser::ParserState::Escape:
|
||||
{
|
||||
if (c == '\x1b')
|
||||
{
|
||||
parser->State = ANSIParser::ParserState::Bracket;
|
||||
parser->Index = 0;
|
||||
parser->Stack[parser->Index].Value = 0;
|
||||
parser->Stack[parser->Index].Empty = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
parser->State = ANSIParser::ParserState::Escape;
|
||||
this->Append(c);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ANSIParser::ParserState::Bracket:
|
||||
{
|
||||
if (c == '[')
|
||||
parser->State = ANSIParser::ParserState::Attribute;
|
||||
else
|
||||
{
|
||||
parser->State = ANSIParser::ParserState::Escape;
|
||||
this->Append(c);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ANSIParser::ParserState::Attribute:
|
||||
{
|
||||
if (isdigit(c))
|
||||
{
|
||||
parser->Stack[parser->Index].Value *= 10;
|
||||
parser->Stack[parser->Index].Value += c - '0';
|
||||
parser->Stack[parser->Index].Empty = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (parser->Index < 8)
|
||||
parser->Index++;
|
||||
|
||||
parser->Stack[parser->Index].Value = 0;
|
||||
parser->Stack[parser->Index].Empty = true;
|
||||
parser->State = ANSIParser::ParserState::EndValue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ANSIParser::ParserState::EndValue:
|
||||
break;
|
||||
default:
|
||||
assert(!"Invalid parser state");
|
||||
}
|
||||
|
||||
if (parser->State == ANSIParser::ParserState::EndValue)
|
||||
{
|
||||
if (c == ';')
|
||||
parser->State = ANSIParser::ParserState::Attribute;
|
||||
else
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case 'A':
|
||||
this->csi_cuu(parser->Stack, parser->Index);
|
||||
break;
|
||||
case 'B':
|
||||
this->csi_cud(parser->Stack, parser->Index);
|
||||
break;
|
||||
|
||||
case 'C':
|
||||
this->csi_cuf(parser->Stack, parser->Index);
|
||||
break;
|
||||
case 'D':
|
||||
this->csi_cub(parser->Stack, parser->Index);
|
||||
break;
|
||||
|
||||
case 'E':
|
||||
this->csi_cnl(parser->Stack, parser->Index);
|
||||
break;
|
||||
case 'F':
|
||||
this->csi_cpl(parser->Stack, parser->Index);
|
||||
break;
|
||||
|
||||
case 'G':
|
||||
this->csi_cha(parser->Stack, parser->Index);
|
||||
break;
|
||||
case 'd':
|
||||
fixme("move cursor left P1 columns");
|
||||
break;
|
||||
|
||||
case 'H':
|
||||
this->csi_cup(parser->Stack, parser->Index);
|
||||
break;
|
||||
case 'J':
|
||||
this->csi_ed(parser->Stack, parser->Index);
|
||||
break;
|
||||
case 'K':
|
||||
this->csi_el(parser->Stack, parser->Index);
|
||||
break;
|
||||
case 'm':
|
||||
this->csi_sgr(parser->Stack, parser->Index);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
parser->State = ANSIParser::ParserState::Escape;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VirtualTerminal::VirtualTerminal(unsigned short Rows, unsigned short Columns,
|
||||
unsigned short XPixels, unsigned short YPixels,
|
||||
PaintCallback _Paint, CursorCallback _Print)
|
||||
: PaintCB(_Paint), CursorCB(_Print)
|
||||
{
|
||||
this->termSize = {
|
||||
.ws_row = Rows,
|
||||
.ws_col = Columns,
|
||||
.ws_xpixel = XPixels,
|
||||
.ws_ypixel = YPixels,
|
||||
};
|
||||
|
||||
/*
|
||||
- ICRNL - Map Carriage Return to New Line
|
||||
- IXON - Enable XON/XOFF flow control
|
||||
|
||||
- OPOST - Enable output processing
|
||||
- ONLCR - Map New Line to Carriage Return - New Line
|
||||
|
||||
- CS8 - 8-bit characters
|
||||
- CREAD - Enable receiver
|
||||
- HUPCL - Hang up on last close
|
||||
|
||||
- ECHO - Echo input characters
|
||||
- ICANON - Enable canonical input (enable line editing)
|
||||
*/
|
||||
this->term.c_iflag = /*ICRNL |*/ IXON;
|
||||
this->term.c_oflag = OPOST | ONLCR;
|
||||
this->term.c_cflag = CS8 | CREAD | HUPCL;
|
||||
this->term.c_lflag = ECHO | ICANON;
|
||||
|
||||
this->term.c_cc[VINTR] = 0x03; /* ^C */
|
||||
this->term.c_cc[VQUIT] = 0x1C; /* ^\ */
|
||||
this->term.c_cc[VERASE] = 0x7F; /* DEL */
|
||||
this->term.c_cc[VKILL] = 0x15; /* ^U */
|
||||
this->term.c_cc[VEOF] = 0x04; /* ^D */
|
||||
this->term.c_cc[VTIME] = 0; /* Timeout for non-canonical read */
|
||||
this->term.c_cc[VMIN] = 1; /* Minimum number of characters for non-canonical read */
|
||||
this->term.c_cc[VSWTC] = 0; /* ^O */
|
||||
this->term.c_cc[VSTART] = 0x11; /* ^Q */
|
||||
this->term.c_cc[VSTOP] = 0x13; /* ^S */
|
||||
this->term.c_cc[VSUSP] = 0x1A; /* ^Z */
|
||||
this->term.c_cc[VEOL] = 0x00; /* NUL */
|
||||
this->term.c_cc[VREPRINT] = 0x12; /* ^R */
|
||||
this->term.c_cc[VDISCARD] = 0x14; /* ^T */
|
||||
this->term.c_cc[VWERASE] = 0x17; /* ^W */
|
||||
this->term.c_cc[VLNEXT] = 0x19; /* ^Y */
|
||||
this->term.c_cc[VEOL2] = 0x7F; /* DEL (or sometimes EOF) */
|
||||
|
||||
this->Cells = new TerminalCell[Rows * Columns];
|
||||
|
||||
debug("Allocated %d bytes for terminal cells",
|
||||
(Rows * Columns) * sizeof(TerminalCell));
|
||||
}
|
||||
|
||||
VirtualTerminal::~VirtualTerminal()
|
||||
{
|
||||
delete[] this->Cells;
|
||||
}
|
||||
}
|
@ -350,7 +350,7 @@ namespace Execute
|
||||
}
|
||||
}
|
||||
|
||||
Elf64_Ehdr ELFHeader;
|
||||
Elf64_Ehdr ELFHeader{};
|
||||
fd->Read(&ELFHeader, sizeof(Elf64_Ehdr), 0);
|
||||
uintptr_t EntryPoint = ELFHeader.e_entry;
|
||||
debug("Entry point is %#lx", EntryPoint);
|
||||
@ -808,7 +808,7 @@ namespace Execute
|
||||
while (envp[envc] != nullptr)
|
||||
envc++;
|
||||
|
||||
Elf32_Ehdr ELFHeader;
|
||||
Elf32_Ehdr ELFHeader{};
|
||||
fd->Read(&ELFHeader, sizeof(Elf32_Ehdr), 0);
|
||||
|
||||
std::vector<Elf64_Phdr> PhdrINTERP = ELFGetSymbolType_x86_64(fd, PT_INTERP);
|
||||
|
@ -184,17 +184,10 @@ namespace Video
|
||||
{
|
||||
private:
|
||||
BootInfo::FramebufferInfo framebuffer;
|
||||
Font *DefaultFont = nullptr;
|
||||
Font *CurrentFont = nullptr;
|
||||
bool ColorIteration = false;
|
||||
int ColorPickerIteration = 0;
|
||||
|
||||
void *Buffer;
|
||||
size_t Size;
|
||||
uint32_t Width, Height;
|
||||
uint32_t Color;
|
||||
uint32_t CursorX, CursorY;
|
||||
bool DoNotScroll;
|
||||
bool DirectWrite;
|
||||
|
||||
uint32_t RegionWidth = 64, RegionHeight = 64;
|
||||
@ -207,9 +200,6 @@ namespace Video
|
||||
decltype(Height) &GetHeight = Height;
|
||||
|
||||
BootInfo::FramebufferInfo GetFramebufferStruct() { return framebuffer; }
|
||||
Font *GetDefaultFont() { return DefaultFont; }
|
||||
Font *GetCurrentFont();
|
||||
void SetCurrentFont(Font *Font);
|
||||
uint16_t GetBitsPerPixel();
|
||||
size_t GetPitch();
|
||||
|
||||
@ -219,41 +209,12 @@ namespace Video
|
||||
void DrawRectangle(uint32_t X, uint32_t Y,
|
||||
uint32_t Width, uint32_t Height,
|
||||
uint32_t Color);
|
||||
void Scroll(int Lines);
|
||||
|
||||
void SetDoNotScroll(bool Value)
|
||||
{
|
||||
this->DoNotScroll = Value;
|
||||
}
|
||||
|
||||
void SetBufferCursor(uint32_t X, uint32_t Y)
|
||||
{
|
||||
this->CursorX = X;
|
||||
this->CursorY = Y;
|
||||
}
|
||||
|
||||
void GetBufferCursor(uint32_t *X, uint32_t *Y)
|
||||
{
|
||||
*X = this->CursorX;
|
||||
*Y = this->CursorY;
|
||||
}
|
||||
|
||||
void UpdateRegion(size_t RegionRow, size_t RegionColumn);
|
||||
void MarkRegionDirty(size_t RegionRow, size_t RegionCol);
|
||||
void UpdateBuffer();
|
||||
|
||||
char Print(char Char,
|
||||
Video::Font *Font = nullptr,
|
||||
bool WriteToUART = false,
|
||||
bool IgnoreSpecialChars = false);
|
||||
|
||||
void PrintString(const char *String,
|
||||
Video::Font *Font = nullptr,
|
||||
bool WriteToUART = false,
|
||||
bool IgnoreSpecialChars = false);
|
||||
|
||||
Display(BootInfo::FramebufferInfo Info,
|
||||
bool LoadDefaultFont = true,
|
||||
bool DirectWrite = true);
|
||||
~Display();
|
||||
};
|
||||
|
119
include/kcon.hpp
119
include/kcon.hpp
@ -18,11 +18,130 @@
|
||||
#ifndef __FENNIX_KERNEL_KERNEL_CONSOLE_H__
|
||||
#define __FENNIX_KERNEL_KERNEL_CONSOLE_H__
|
||||
|
||||
#include <display.hpp>
|
||||
#include <termios.h>
|
||||
#include <atomic>
|
||||
|
||||
namespace KernelConsole
|
||||
{
|
||||
enum TerminalColor
|
||||
{
|
||||
BLACK,
|
||||
RED,
|
||||
GREEN,
|
||||
YELLOW,
|
||||
BLUE,
|
||||
MAGENTA,
|
||||
CYAN,
|
||||
GREY
|
||||
};
|
||||
|
||||
struct ANSIArgument
|
||||
{
|
||||
int Value = 0;
|
||||
bool Empty = true;
|
||||
};
|
||||
|
||||
struct ANSIParser
|
||||
{
|
||||
enum ParserState
|
||||
{
|
||||
Escape,
|
||||
Bracket,
|
||||
Attribute,
|
||||
EndValue
|
||||
} State = Escape;
|
||||
|
||||
ANSIArgument Stack[8] = {};
|
||||
int Index = 0;
|
||||
};
|
||||
|
||||
struct TerminalAttribute
|
||||
{
|
||||
bool Bright = false;
|
||||
TerminalColor Background = BLACK;
|
||||
TerminalColor Foreground = GREY;
|
||||
};
|
||||
|
||||
struct TerminalCell
|
||||
{
|
||||
char c = '\0';
|
||||
TerminalAttribute attr{};
|
||||
};
|
||||
|
||||
struct TerminalCursor
|
||||
{
|
||||
long X = 0;
|
||||
long Y = 0;
|
||||
};
|
||||
|
||||
typedef void (*PaintCallback)(TerminalCell *Cell, long X, long Y);
|
||||
typedef void (*CursorCallback)(TerminalCursor *Cursor);
|
||||
|
||||
class FontRenderer
|
||||
{
|
||||
public:
|
||||
Video::Font *CurrentFont = nullptr;
|
||||
TerminalCursor Cursor = {0, 0};
|
||||
char Paint(long CellX, long CellY, char Char, uint32_t Foreground, uint32_t Background);
|
||||
};
|
||||
|
||||
class VirtualTerminal
|
||||
{
|
||||
private:
|
||||
ANSIParser Parser{};
|
||||
TerminalAttribute Attribute{};
|
||||
|
||||
TerminalCell *Cells = nullptr;
|
||||
TerminalCursor Cursor{};
|
||||
|
||||
PaintCallback PaintCB = nullptr;
|
||||
CursorCallback CursorCB = nullptr;
|
||||
|
||||
public:
|
||||
termios term;
|
||||
winsize termSize;
|
||||
|
||||
void Clear(unsigned short StartX, unsigned short StartY, unsigned short EndX, unsigned short EndY);
|
||||
void Scroll(unsigned short Lines);
|
||||
void NewLine();
|
||||
void Append(char c);
|
||||
void csi_cup(ANSIArgument *Args, int ArgsCount);
|
||||
void csi_ed(ANSIArgument *Args, int ArgsCount);
|
||||
void csi_el(ANSIArgument *Args, int ArgsCount);
|
||||
void csi_sgr(ANSIArgument *Args, int ArgsCount);
|
||||
void csi_cuu(ANSIArgument *Args, int ArgsCount);
|
||||
void csi_cud(ANSIArgument *Args, int ArgsCount);
|
||||
void csi_cuf(ANSIArgument *Args, int ArgsCount);
|
||||
void csi_cub(ANSIArgument *Args, int ArgsCount);
|
||||
void csi_cnl(ANSIArgument *Args, int ArgsCount);
|
||||
void csi_cpl(ANSIArgument *Args, int ArgsCount);
|
||||
void csi_cha(ANSIArgument *Args, int ArgsCount);
|
||||
void Process(char c);
|
||||
|
||||
VirtualTerminal(unsigned short Rows, unsigned short Columns,
|
||||
unsigned short XPixels, unsigned short YPixels,
|
||||
PaintCallback Paint, CursorCallback Print);
|
||||
~VirtualTerminal();
|
||||
};
|
||||
|
||||
/**
|
||||
* 0 - Default
|
||||
* 1...11 - User
|
||||
* ...
|
||||
* 15 - Panic
|
||||
*/
|
||||
extern VirtualTerminal *Terminals[16];
|
||||
extern std::atomic<VirtualTerminal *> CurrentTerminal;
|
||||
extern int TermColors[];
|
||||
extern int TermBrightColors[];
|
||||
|
||||
bool SetTheme(std::string Theme);
|
||||
|
||||
/* Limited in functionality */
|
||||
void EarlyInit();
|
||||
|
||||
/* Full working terminal */
|
||||
void LateInit();
|
||||
}
|
||||
|
||||
|
@ -75,6 +75,8 @@ typedef __builtin_va_list va_list;
|
||||
|
||||
#define offsetof(type, member) __builtin_offsetof(type, member)
|
||||
|
||||
#define RGB_TO_HEX(r, g, b) ((r << 16) | (g << 8) | (b))
|
||||
|
||||
#define MAX(a, b) \
|
||||
({ \
|
||||
__typeof__(a) _a = (a); \
|
||||
|
@ -170,10 +170,7 @@ struct termios
|
||||
tcflag_t c_oflag;
|
||||
tcflag_t c_cflag;
|
||||
tcflag_t c_lflag;
|
||||
cc_t c_line;
|
||||
cc_t c_cc[NCCS];
|
||||
speed_t c_ispeed;
|
||||
speed_t c_ospeed;
|
||||
};
|
||||
|
||||
struct winsize
|
||||
@ -184,4 +181,10 @@ struct winsize
|
||||
unsigned short ws_ypixel;
|
||||
};
|
||||
|
||||
struct ttysize
|
||||
{
|
||||
int ts_lines;
|
||||
int ts_cols;
|
||||
};
|
||||
|
||||
#endif // !__FENNIX_KERNEL_TERMIOS_H__
|
||||
|
32
kernel.cpp
32
kernel.cpp
@ -25,6 +25,7 @@
|
||||
#include <printf.h>
|
||||
#include <lock.hpp>
|
||||
#include <uart.hpp>
|
||||
#include <kcon.hpp>
|
||||
#include <debug.h>
|
||||
#include <smp.hpp>
|
||||
#include <cargs.h>
|
||||
@ -63,8 +64,9 @@ Driver::Manager *DriverManager = nullptr;
|
||||
|
||||
EXTERNC void putchar(char c)
|
||||
{
|
||||
if (Display)
|
||||
Display->Print(c);
|
||||
KernelConsole::VirtualTerminal *vt = KernelConsole::CurrentTerminal.load(std::memory_order_acquire);
|
||||
if (vt != nullptr)
|
||||
vt->Process(c);
|
||||
else
|
||||
UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM1).Write(c);
|
||||
}
|
||||
@ -79,20 +81,20 @@ EXTERNC void _KPrint(const char *Format, va_list Args)
|
||||
if (Nanoseconds != 0)
|
||||
{
|
||||
#if defined(a64)
|
||||
printf("\eCCCCCC[\e00AEFF%lu.%07lu\eCCCCCC] ",
|
||||
printf("\x1b[1;30m[\x1b[1;34m%lu.%07lu\x1b[1;30m]\x1b[0m ",
|
||||
Nanoseconds / 10000000, Nanoseconds % 10000000);
|
||||
#elif defined(a32)
|
||||
printf("\eCCCCCC[\e00AEFF%llu.%07llu\eCCCCCC] ",
|
||||
printf("\x1b[1;30m[\x1b[1;34m%llu.%07llu\x1b[1;30m]\x1b[0m ",
|
||||
Nanoseconds / 10000000, Nanoseconds % 10000000);
|
||||
#elif defined(aa64)
|
||||
printf("\eCCCCCC[\e00AEFF%lu.%07lu\eCCCCCC] ",
|
||||
printf("\x1b[1;30m[\x1b[1;34m%lu.%07lu\x1b[1;30m]\x1b[0m ",
|
||||
Nanoseconds / 10000000, Nanoseconds % 10000000);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
vprintf(Format, Args);
|
||||
printf("\eCCCCCC\n");
|
||||
printf("\x1b[0m\n");
|
||||
if (!Config.Quiet && Display)
|
||||
Display->UpdateBuffer();
|
||||
}
|
||||
@ -119,26 +121,28 @@ EXTERNC void KPrint(const char *Format, ...)
|
||||
EXTERNC NIF void Main()
|
||||
{
|
||||
Display = new Video::Display(bInfo.Framebuffer[0]);
|
||||
KernelConsole::EarlyInit();
|
||||
|
||||
KPrint("%s - %s [\e058C19%s\eFFFFFF]",
|
||||
printf("\x1b[H\x1b[2J");
|
||||
KPrint("%s - %s [\x1b[32m%s\x1b[0m]",
|
||||
KERNEL_NAME, KERNEL_VERSION, GIT_COMMIT_SHORT);
|
||||
KPrint("CPU: \e058C19%s \e8822AA%s \e8888FF%s",
|
||||
KPrint("CPU: \x1b[32m%s \x1b[31m%s \x1b[37m%s",
|
||||
CPU::Hypervisor(), CPU::Vendor(), CPU::Name());
|
||||
|
||||
if (Display->GetFramebufferStruct().BitsPerPixel != 32)
|
||||
KPrint("\eFF5500Framebuffer is not 32 bpp. This may cause issues.");
|
||||
KPrint("\x1b[1;31mFramebuffer is not 32 bpp. This may cause issues.");
|
||||
|
||||
if (Display->GetWidth < 640 || Display->GetHeight < 480)
|
||||
{
|
||||
KPrint("\eFF5500Minimum supported resolution is 640x480!");
|
||||
KPrint("\eFF5500Some elements may not be displayed correctly.");
|
||||
KPrint("\x1b[1;31mMinimum supported resolution is 640x480!");
|
||||
KPrint("\x1b[1;31mSome elements may not be displayed correctly.");
|
||||
}
|
||||
|
||||
debug("CPU: %s %s %s",
|
||||
CPU::Hypervisor(), CPU::Vendor(), CPU::Name());
|
||||
|
||||
if (DebuggerIsAttached)
|
||||
KPrint("\eFFA500Kernel debugger detected.");
|
||||
KPrint("Kernel debugger detected.");
|
||||
|
||||
#if defined(a86) && defined(DEBUG)
|
||||
uint8_t lpt1 = inb(0x378);
|
||||
@ -171,7 +175,7 @@ EXTERNC NIF void Main()
|
||||
if (com4 != 0xFF)
|
||||
KPrint("COM4 is present.");
|
||||
|
||||
KPrint("Display: %dx%d %d bpp \eFF0000R:%d %d \e00FF00G: %d %d \e0000FFB: %d %d",
|
||||
KPrint("Display: %dx%d %d bpp R:%d %d G:%d %d B:%d %d",
|
||||
Display->GetFramebufferStruct().Width,
|
||||
Display->GetFramebufferStruct().Height,
|
||||
Display->GetFramebufferStruct().BitsPerPixel,
|
||||
@ -236,7 +240,7 @@ EXTERNC NIF void Main()
|
||||
KPrint("Initializing Filesystem");
|
||||
KernelVFS();
|
||||
|
||||
KPrint("\e058C19################################");
|
||||
KPrint("\x1b[1;32m################################");
|
||||
TaskManager = new Tasking::Task(Tasking::IP(KernelMainThread));
|
||||
TaskManager->StartScheduler();
|
||||
CPU::Halt(true);
|
||||
|
1
kernel.h
1
kernel.h
@ -33,6 +33,7 @@
|
||||
#include <task.hpp>
|
||||
#include <time.hpp>
|
||||
#include <disk.hpp>
|
||||
#include <kcon.hpp>
|
||||
#include <pci.hpp>
|
||||
#include <smp.hpp>
|
||||
#endif
|
||||
|
@ -143,22 +143,22 @@ void ParseConfig(char *ConfigString, KernelConfig *ModConfig)
|
||||
value = cag_option_get_value(&context);
|
||||
if (strcmp(value, "xallocv1") == 0)
|
||||
{
|
||||
KPrint("\eAAFFAAUsing XallocV1 as memory allocator");
|
||||
KPrint("Using XallocV1 as memory allocator");
|
||||
ModConfig->AllocatorType = Memory::XallocV1;
|
||||
}
|
||||
else if (strcmp(value, "xallocv2") == 0)
|
||||
{
|
||||
KPrint("\eAAFFAAUsing XallocV2 as memory allocator");
|
||||
KPrint("Using XallocV2 as memory allocator");
|
||||
ModConfig->AllocatorType = Memory::XallocV2;
|
||||
}
|
||||
else if (strcmp(value, "liballoc11") == 0)
|
||||
{
|
||||
KPrint("\eAAFFAAUsing Liballoc11 as memory allocator");
|
||||
KPrint("Using Liballoc11 as memory allocator");
|
||||
ModConfig->AllocatorType = Memory::liballoc11;
|
||||
}
|
||||
else if (strcmp(value, "pages") == 0)
|
||||
{
|
||||
KPrint("\eAAFFAAUsing Pages as memory allocator");
|
||||
KPrint("Using Pages as memory allocator");
|
||||
ModConfig->AllocatorType = Memory::Pages;
|
||||
}
|
||||
break;
|
||||
@ -166,14 +166,14 @@ void ParseConfig(char *ConfigString, KernelConfig *ModConfig)
|
||||
case 'c':
|
||||
{
|
||||
value = cag_option_get_value(&context);
|
||||
KPrint("\eAAFFAAUsing %s cores", atoi(value) ? value : "all");
|
||||
KPrint("Using %s cores", atoi(value) ? value : "all");
|
||||
ModConfig->Cores = atoi(value);
|
||||
break;
|
||||
}
|
||||
case 'p':
|
||||
{
|
||||
value = cag_option_get_value(&context);
|
||||
KPrint("\eAAFFAARedirecting I/O APIC interrupts to %s%s",
|
||||
KPrint("Redirecting I/O APIC interrupts to %s%s",
|
||||
atoi(value) ? "core " : "", atoi(value) ? value : "BSP");
|
||||
ModConfig->IOAPICInterruptCore = atoi(value);
|
||||
break;
|
||||
@ -183,17 +183,17 @@ void ParseConfig(char *ConfigString, KernelConfig *ModConfig)
|
||||
value = cag_option_get_value(&context);
|
||||
if (strcmp(value, "multi") == 0)
|
||||
{
|
||||
KPrint("\eAAFFAAUsing Multi-Tasking Scheduler");
|
||||
KPrint("Using Multi-Tasking Scheduler");
|
||||
ModConfig->SchedulerType = Multi;
|
||||
}
|
||||
else if (strcmp(value, "single") == 0)
|
||||
{
|
||||
KPrint("\eAAFFAAUsing Single-Tasking Scheduler");
|
||||
KPrint("Using Single-Tasking Scheduler");
|
||||
ModConfig->SchedulerType = Mono;
|
||||
}
|
||||
else
|
||||
{
|
||||
KPrint("\eAAFFAAUnknown scheduler: %s", value);
|
||||
KPrint("Unknown scheduler: %s", value);
|
||||
ModConfig->SchedulerType = Multi;
|
||||
}
|
||||
break;
|
||||
@ -202,14 +202,14 @@ void ParseConfig(char *ConfigString, KernelConfig *ModConfig)
|
||||
{
|
||||
value = cag_option_get_value(&context);
|
||||
strncpy(ModConfig->DriverDirectory, value, strlen(value));
|
||||
KPrint("\eAAFFAAUsing %s as module directory", value);
|
||||
KPrint("Using %s as module directory", value);
|
||||
break;
|
||||
}
|
||||
case 'i':
|
||||
{
|
||||
value = cag_option_get_value(&context);
|
||||
strncpy(ModConfig->InitPath, value, strlen(value));
|
||||
KPrint("\eAAFFAAUsing %s as init program", value);
|
||||
KPrint("Using %s as init program", value);
|
||||
break;
|
||||
}
|
||||
case 'y':
|
||||
@ -218,7 +218,7 @@ void ParseConfig(char *ConfigString, KernelConfig *ModConfig)
|
||||
strcmp(value, "true") == 0
|
||||
? ModConfig->UseLinuxSyscalls = true
|
||||
: ModConfig->UseLinuxSyscalls = false;
|
||||
KPrint("\eAAFFAAUse Linux syscalls by default: %s", value);
|
||||
KPrint("Use Linux syscalls by default: %s", value);
|
||||
break;
|
||||
}
|
||||
case 'o':
|
||||
@ -227,7 +227,7 @@ void ParseConfig(char *ConfigString, KernelConfig *ModConfig)
|
||||
strcmp(value, "true") == 0
|
||||
? ModConfig->InterruptsOnCrash = true
|
||||
: ModConfig->InterruptsOnCrash = false;
|
||||
KPrint("\eAAFFAAInterrupts on crash: %s", value);
|
||||
KPrint("Interrupts on crash: %s", value);
|
||||
break;
|
||||
}
|
||||
case 'l':
|
||||
@ -236,7 +236,7 @@ void ParseConfig(char *ConfigString, KernelConfig *ModConfig)
|
||||
strcmp(value, "true") == 0
|
||||
? ModConfig->UnlockDeadLock = true
|
||||
: ModConfig->UnlockDeadLock = false;
|
||||
KPrint("\eAAFFAAUnlocking the deadlock after 10 retries");
|
||||
KPrint("Unlocking the deadlock after 10 retries");
|
||||
break;
|
||||
}
|
||||
case 's':
|
||||
@ -244,7 +244,7 @@ void ParseConfig(char *ConfigString, KernelConfig *ModConfig)
|
||||
value = cag_option_get_value(&context);
|
||||
strcmp(value, "true") == 0 ? ModConfig->SIMD = true
|
||||
: ModConfig->SIMD = false;
|
||||
KPrint("\eAAFFAASingle Instruction, Multiple Data (SIMD): %s", value);
|
||||
KPrint("Single Instruction, Multiple Data (SIMD): %s", value);
|
||||
break;
|
||||
}
|
||||
case 'b':
|
||||
@ -252,7 +252,7 @@ void ParseConfig(char *ConfigString, KernelConfig *ModConfig)
|
||||
value = cag_option_get_value(&context);
|
||||
strcmp(value, "true") == 0 ? ModConfig->Quiet = true
|
||||
: ModConfig->Quiet = false;
|
||||
KPrint("\eAAFFAAQuiet boot: %s", value);
|
||||
KPrint("Quiet boot: %s", value);
|
||||
break;
|
||||
}
|
||||
case 'h':
|
||||
@ -260,12 +260,12 @@ void ParseConfig(char *ConfigString, KernelConfig *ModConfig)
|
||||
KPrint("\n---------------------------------------------------------------------------\nUsage: fennix.elf [OPTION]...\nKernel configuration.");
|
||||
cag_option_print(ConfigOptions, CAG_ARRAY_SIZE(ConfigOptions),
|
||||
nullptr);
|
||||
KPrint("\eFF2200System Halted.");
|
||||
KPrint("\x1b[1;31;41mSystem Halted.");
|
||||
CPU::Stop();
|
||||
}
|
||||
default:
|
||||
{
|
||||
KPrint("\eFF2200Unknown option: %c", identifier);
|
||||
KPrint("\x1b[31mUnknown option: %c", identifier);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include <lock.hpp>
|
||||
#include <printf.h>
|
||||
#include <exec.hpp>
|
||||
#include <kcon.hpp>
|
||||
#include <cwalk.h>
|
||||
#include <vm.hpp>
|
||||
#include <vector>
|
||||
@ -83,6 +84,7 @@ void KernelMainThread()
|
||||
DriverManager->PreloadDrivers();
|
||||
DriverManager->LoadAllDrivers();
|
||||
|
||||
KernelConsole::LateInit();
|
||||
#ifdef DEBUG
|
||||
// TaskManager->CreateThread(thisProcess,
|
||||
// Tasking::IP(KShellThread))
|
||||
@ -96,12 +98,12 @@ void KernelMainThread()
|
||||
int tid = SpawnInit();
|
||||
if (tid < 0)
|
||||
{
|
||||
KPrint("\eE85230Failed to start %s! Error: %s (%d)",
|
||||
KPrint("\x1b[1;37;41mFailed to start %s! Error: %s (%d)",
|
||||
Config.InitPath, strerror(tid), tid);
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
KPrint("Waiting for \e22AAFF%s\eCCCCCC to start...",
|
||||
KPrint("Waiting for \x1b[32m%s\x1b[0m to start...",
|
||||
Config.InitPath);
|
||||
thisThread->SetPriority(Tasking::Idle);
|
||||
|
||||
@ -110,7 +112,7 @@ void KernelMainThread()
|
||||
TaskManager->WaitForThread(initThread);
|
||||
ExitCode = initThread->GetExitCode();
|
||||
Exit:
|
||||
KPrint("\eE85230Userspace process exited with code %d (%#x)",
|
||||
KPrint("\x1b[31mUserspace process exited with code %d (%#x)",
|
||||
ExitCode, ExitCode < 0 ? -ExitCode : ExitCode);
|
||||
|
||||
KPrint("Dropping to kernel shell");
|
||||
|
@ -43,6 +43,7 @@ void cmd_lsmod(const char *args);
|
||||
void cmd_modinfo(const char *args);
|
||||
void cmd_panic(const char *args);
|
||||
void cmd_dump(const char *args);
|
||||
void cmd_theme(const char *args);
|
||||
|
||||
#define IF_ARG(x) strcmp(args, x) == 0
|
||||
|
||||
|
@ -21,6 +21,5 @@
|
||||
|
||||
void cmd_clear(const char *)
|
||||
{
|
||||
Display->SetBufferCursor(0, 0);
|
||||
Display->ClearBuffer();
|
||||
printf("\x1b[2J");
|
||||
}
|
||||
|
@ -26,19 +26,19 @@ using namespace vfs;
|
||||
const char *ColorNodeType(FileNode *node)
|
||||
{
|
||||
if (node->IsRegularFile())
|
||||
return "\eCCCCCC";
|
||||
return "\x1b[32m";
|
||||
else if (node->IsDirectory())
|
||||
return "\e3871F5";
|
||||
return "\x1b[34m";
|
||||
else if (node->IsBlockDevice())
|
||||
return "\eE8CD1E";
|
||||
return "\x1b[33m";
|
||||
else if (node->IsCharacterDevice())
|
||||
return "\e86E01F";
|
||||
return "\x1b[33m";
|
||||
else if (node->IsFIFO())
|
||||
return "\eE0991F";
|
||||
return "\x1b[33m";
|
||||
else if (node->IsSymbolicLink())
|
||||
return "\e1FB9E0";
|
||||
return "\x1b[35m";
|
||||
else
|
||||
return "\eF72020";
|
||||
return "\x1b[0m";
|
||||
}
|
||||
|
||||
__no_sanitize("alignment") size_t MaxNameLength(FileNode *nodes)
|
||||
@ -100,7 +100,7 @@ __no_sanitize("alignment") void PrintLS(FileNode *node)
|
||||
offset += read / sizeof(kdirent);
|
||||
}
|
||||
|
||||
printf("\eCCCCCC\n");
|
||||
printf("\x1b[0m\n");
|
||||
delete[] dirBuffer;
|
||||
}
|
||||
|
||||
|
25
kshell/commands/theme.cpp
Normal file
25
kshell/commands/theme.cpp
Normal file
@ -0,0 +1,25 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "../cmds.hpp"
|
||||
|
||||
#include "../../kernel.h"
|
||||
|
||||
void cmd_theme(const char *args)
|
||||
{
|
||||
KernelConsole::SetTheme(args);
|
||||
}
|
@ -41,16 +41,16 @@ const char *TaskStateStrings[] = {
|
||||
|
||||
void cmd_top(const char *)
|
||||
{
|
||||
printf("\e9400A1PID \e9CA100Name \e00A15BState \eCCCCCCPriority Memory Usage CPU Usage\n");
|
||||
printf("PID Name State Priority Memory Usage CPU Usage\n");
|
||||
foreach (auto Proc in TaskManager->GetProcessList())
|
||||
{
|
||||
#if defined(a64)
|
||||
printf("\e9400A1%-4d \e9CA100%-20s \e00A15B%s \eCCCCCC%d %ld KiB %ld\n",
|
||||
printf("%-4d %-20s %s %d %ld KiB %ld\n",
|
||||
Proc->ID, Proc->Name, TaskStateStrings[Proc->State.load()],
|
||||
Proc->Info.Priority, TO_KiB(Proc->GetSize()),
|
||||
Proc->Info.UserTime + Proc->Info.KernelTime);
|
||||
#elif defined(a32)
|
||||
printf("\e9400A1%-4d \e9CA100%-20s \e00A15B%s \eCCCCCC%d %lld KiB %lld\n",
|
||||
printf("%-4d %-20s %s %d %lld KiB %lld\n",
|
||||
Proc->ID, Proc->Name, TaskStateStrings[Proc->State.load()],
|
||||
Proc->Info.Priority, TO_KiB(Proc->GetSize()),
|
||||
Proc->Info.UserTime + Proc->Info.KernelTime);
|
||||
@ -59,12 +59,12 @@ void cmd_top(const char *)
|
||||
foreach (auto Thrd in Proc->Threads)
|
||||
{
|
||||
#if defined(a64)
|
||||
printf(" \eA80011%-4d \e9CA100%-20s \e00A15B%s \eCCCCCC%d %ld KiB %ld\n",
|
||||
printf(" %-4d %-20s %s %d %ld KiB %ld\n",
|
||||
Thrd->ID, Thrd->Name, TaskStateStrings[Thrd->State.load()],
|
||||
Thrd->Info.Priority, TO_KiB(Thrd->GetSize()),
|
||||
Thrd->Info.UserTime + Thrd->Info.KernelTime);
|
||||
#elif defined(a32)
|
||||
printf(" \eA80011%-4d \e9CA100%-20s \e00A15B%s \eCCCCCC%d %lld KiB %lld\n",
|
||||
printf(" %-4d %-20s %s %d %lld KiB %lld\n",
|
||||
Thrd->ID, Thrd->Name, TaskStateStrings[Thrd->State.load()],
|
||||
Thrd->Info.Priority, TO_KiB(Thrd->GetSize()),
|
||||
Thrd->Info.UserTime + Thrd->Info.KernelTime);
|
||||
|
272
kshell/shell.cpp
272
kshell/shell.cpp
@ -77,89 +77,17 @@ static Command commands[] = {
|
||||
{"depmod", nullptr},
|
||||
{"panic", cmd_panic},
|
||||
{"dump", cmd_dump},
|
||||
{"theme", cmd_theme},
|
||||
{"builtin", __cmd_builtin},
|
||||
};
|
||||
|
||||
std::atomic_uint32_t CurX = 0x10, CurY = 0x10;
|
||||
std::atomic_bool CurBlinking = false;
|
||||
std::atomic_bool CurHalt = true;
|
||||
std::atomic_uint64_t BlinkerSleep = 0;
|
||||
|
||||
NewLock(BlinkerLock);
|
||||
|
||||
void PrintBlinker(uint32_t fx, uint32_t fy)
|
||||
void KShellThread()
|
||||
{
|
||||
for (uint32_t i = 0; i < fx; i++)
|
||||
{
|
||||
for (uint32_t j = 0; j < fy; j++)
|
||||
{
|
||||
uint32_t px = CurX.load() + i;
|
||||
uint32_t py = CurY.load() + j;
|
||||
uint32_t color = Display->GetPixel(px, py);
|
||||
Display->SetPixel(px, py, ~color);
|
||||
}
|
||||
}
|
||||
}
|
||||
assert(!ShellLock.Locked());
|
||||
ShellLock.Lock(__FUNCTION__);
|
||||
|
||||
void UpdateBlinker(bool force = false)
|
||||
{
|
||||
SmartLock(BlinkerLock);
|
||||
if (CurBlinking.load() || force)
|
||||
{
|
||||
uint32_t fx = 0, fy = 0;
|
||||
if (unlikely(fx == 0 || fy == 0))
|
||||
{
|
||||
fx = Display->GetCurrentFont()->GetInfo().Width;
|
||||
fy = Display->GetCurrentFont()->GetInfo().Height;
|
||||
}
|
||||
|
||||
PrintBlinker(fx, fy);
|
||||
CurBlinking.store(force);
|
||||
Display->UpdateBuffer();
|
||||
}
|
||||
}
|
||||
|
||||
void CursorBlink()
|
||||
{
|
||||
uint32_t fx, fy;
|
||||
fx = Display->GetCurrentFont()->GetInfo().Width;
|
||||
fy = Display->GetCurrentFont()->GetInfo().Height;
|
||||
while (true)
|
||||
{
|
||||
if (CurHalt.load() ||
|
||||
BlinkerSleep.load() > TimeManager->GetCounter())
|
||||
{
|
||||
TaskManager->Sleep(250);
|
||||
continue;
|
||||
}
|
||||
|
||||
{
|
||||
SmartLock(BlinkerLock);
|
||||
PrintBlinker(fx, fy);
|
||||
CurBlinking.store(!CurBlinking.load());
|
||||
Display->UpdateBuffer();
|
||||
}
|
||||
TaskManager->Sleep(500);
|
||||
|
||||
{
|
||||
SmartLock(BlinkerLock);
|
||||
PrintBlinker(fx, fy);
|
||||
CurBlinking.store(!CurBlinking.load());
|
||||
Display->UpdateBuffer();
|
||||
}
|
||||
TaskManager->Sleep(500);
|
||||
}
|
||||
}
|
||||
|
||||
void StartKernelShell()
|
||||
{
|
||||
if (ShellLock.Locked())
|
||||
return;
|
||||
SmartLock(ShellLock);
|
||||
|
||||
debug("Starting kernel shell...");
|
||||
KPrint("Starting kernel shell...");
|
||||
thisThread->SetPriority(Tasking::TaskPriority::High);
|
||||
thisThread->SetPriority(Tasking::TaskPriority::Normal);
|
||||
|
||||
std::string strBuf = "";
|
||||
std::vector<std::string *> history;
|
||||
@ -168,7 +96,8 @@ void StartKernelShell()
|
||||
bool upperCase = false;
|
||||
bool tabDblPress = false;
|
||||
|
||||
FileNode *kfd = fs->GetByPath("/dev/input/keyboard", fs->GetRoot(0));
|
||||
const char *keyDevPath = "/dev/input/keyboard";
|
||||
FileNode *kfd = fs->GetByPath(keyDevPath, fs->GetRoot(0));
|
||||
if (kfd == nullptr)
|
||||
{
|
||||
KPrint("Failed to open keyboard device!");
|
||||
@ -179,12 +108,14 @@ void StartKernelShell()
|
||||
auto strBufBck = [&]()
|
||||
{
|
||||
for (size_t i = 0; i < strBuf.size(); i++)
|
||||
Display->Print('\b');
|
||||
{
|
||||
putchar('\b');
|
||||
putchar(' ');
|
||||
putchar('\b');
|
||||
}
|
||||
};
|
||||
|
||||
std::thread thd(CursorBlink);
|
||||
|
||||
printf("Using \eCA21F6/dev/key\eCCCCCC for keyboard input.\n");
|
||||
printf("Using \x1b[1;34m%s\x1b[0m for keyboard input.\n", keyDevPath);
|
||||
while (true)
|
||||
{
|
||||
size_t bsCount = 0;
|
||||
@ -198,26 +129,20 @@ void StartKernelShell()
|
||||
cwd = fs->GetRoot(0);
|
||||
std::string cwdStr = fs->GetByNode(cwd);
|
||||
|
||||
printf("\e34C6EB%s@%s:%s$ \eCCCCCC",
|
||||
printf("\x1b[1;34m%s@%s:%s$ \x1b[0m",
|
||||
"kernel", "fennix",
|
||||
cwdStr.c_str());
|
||||
Display->UpdateBuffer();
|
||||
|
||||
Display->GetBufferCursor(&homeX, &homeY);
|
||||
|
||||
KeyboardReport scBuf{};
|
||||
ssize_t nBytes;
|
||||
while (true)
|
||||
{
|
||||
uint32_t __cx, __cy;
|
||||
Display->GetBufferCursor(&__cx, &__cy);
|
||||
CurX.store(__cx);
|
||||
CurY.store(__cy);
|
||||
CurHalt.store(false);
|
||||
|
||||
nBytes = kfd->Read(&scBuf, sizeof(KeyboardReport), 0);
|
||||
if (nBytes == 0)
|
||||
{
|
||||
debug("Empty read from keyboard device!");
|
||||
continue;
|
||||
}
|
||||
if (nBytes < (ssize_t)sizeof(KeyboardReport))
|
||||
{
|
||||
KPrint("Failed to read from keyboard device: %s",
|
||||
@ -225,10 +150,6 @@ void StartKernelShell()
|
||||
return;
|
||||
}
|
||||
|
||||
BlinkerSleep.store(TimeManager->CalculateTarget(250, Time::Units::Milliseconds));
|
||||
CurHalt.store(true);
|
||||
UpdateBlinker();
|
||||
|
||||
const KeyScanCodes &sc = scBuf.Key;
|
||||
switch (sc & ~KEY_PRESSED)
|
||||
{
|
||||
@ -263,28 +184,14 @@ void StartKernelShell()
|
||||
tabDblPress = false;
|
||||
if (strBuf.size() == 0)
|
||||
{
|
||||
if (unseekX != 0 || unseekY != 0)
|
||||
{
|
||||
Display->SetBufferCursor(unseekX, unseekY);
|
||||
unseekX = unseekY = 0;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < sizeof(commands) / sizeof(commands[0]); i++)
|
||||
printf("%s ", commands[i].Name);
|
||||
|
||||
Display->Print('\n');
|
||||
Display->UpdateBuffer();
|
||||
putchar('\n');
|
||||
goto SecLoopEnd;
|
||||
}
|
||||
|
||||
if (unseekX != 0 || unseekY != 0)
|
||||
{
|
||||
Display->SetBufferCursor(unseekX, unseekY);
|
||||
unseekX = unseekY = 0;
|
||||
}
|
||||
|
||||
strBufBck();
|
||||
Display->UpdateBuffer();
|
||||
|
||||
for (size_t i = 0; i < sizeof(commands) / sizeof(commands[0]); i++)
|
||||
{
|
||||
@ -293,9 +200,8 @@ void StartKernelShell()
|
||||
|
||||
strBuf = commands[i].Name;
|
||||
for (size_t i = 0; i < strlen(strBuf.c_str()); i++)
|
||||
Display->Print(strBuf[i]);
|
||||
putchar(strBuf[i]);
|
||||
seekCount = bsCount = strBuf.size();
|
||||
Display->UpdateBuffer();
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
@ -312,31 +218,24 @@ void StartKernelShell()
|
||||
{
|
||||
debug("seekCount == bsCount (%d == %d)",
|
||||
seekCount, bsCount);
|
||||
Display->Print('\b');
|
||||
putchar('\b');
|
||||
putchar(' ');
|
||||
putchar('\b');
|
||||
strBuf.pop_back();
|
||||
seekCount = --bsCount;
|
||||
Display->UpdateBuffer();
|
||||
continue;
|
||||
}
|
||||
|
||||
uint32_t tmpX, tmpY;
|
||||
Display->GetBufferCursor(&tmpX, &tmpY);
|
||||
|
||||
Display->SetBufferCursor(unseekX, unseekY);
|
||||
strBufBck();
|
||||
size_t strSeek = seekCount ? seekCount - 1 : 0;
|
||||
seekCount = strSeek;
|
||||
debug("strSeek: %d: %s", strSeek, strBuf.c_str());
|
||||
strBuf.erase(strSeek);
|
||||
Display->PrintString(strBuf.c_str());
|
||||
printf("%s", strBuf.c_str());
|
||||
debug("after strBuf: %s", strBuf.c_str());
|
||||
|
||||
uint32_t fx = Display->GetCurrentFont()->GetInfo().Width;
|
||||
Display->SetBufferCursor(tmpX - fx, tmpY);
|
||||
unseekX -= fx;
|
||||
|
||||
bsCount--;
|
||||
Display->UpdateBuffer();
|
||||
continue;
|
||||
}
|
||||
case KEY_DELETE:
|
||||
@ -354,20 +253,13 @@ void StartKernelShell()
|
||||
continue;
|
||||
}
|
||||
|
||||
uint32_t tmpX, tmpY;
|
||||
Display->GetBufferCursor(&tmpX, &tmpY);
|
||||
|
||||
Display->SetBufferCursor(unseekX, unseekY);
|
||||
strBufBck();
|
||||
debug("seekCount: %d: %s", seekCount, strBuf.c_str());
|
||||
strBuf.erase(seekCount);
|
||||
Display->PrintString(strBuf.c_str());
|
||||
printf("%s", strBuf.c_str());
|
||||
debug("after strBuf: %s", strBuf.c_str());
|
||||
|
||||
Display->SetBufferCursor(tmpX, tmpY);
|
||||
unseekX -= Display->GetCurrentFont()->GetInfo().Width;
|
||||
bsCount--;
|
||||
Display->UpdateBuffer();
|
||||
continue;
|
||||
}
|
||||
case KEY_UP_ARROW:
|
||||
@ -383,19 +275,16 @@ void StartKernelShell()
|
||||
|
||||
if (unseekX != 0 || unseekY != 0)
|
||||
{
|
||||
Display->SetBufferCursor(unseekX, unseekY);
|
||||
unseekX = unseekY = 0;
|
||||
}
|
||||
|
||||
strBufBck();
|
||||
Display->UpdateBuffer();
|
||||
|
||||
strBuf = history[hIdx]->c_str();
|
||||
|
||||
for (size_t i = 0; i < strlen(strBuf.c_str()); i++)
|
||||
Display->Print(strBuf[i]);
|
||||
putchar(strBuf[i]);
|
||||
seekCount = bsCount = strBuf.size();
|
||||
Display->UpdateBuffer();
|
||||
continue;
|
||||
}
|
||||
case KEY_DOWN_ARROW:
|
||||
@ -410,35 +299,26 @@ void StartKernelShell()
|
||||
if (hIdx == history.size() - 1)
|
||||
{
|
||||
if (unseekX != 0 || unseekY != 0)
|
||||
{
|
||||
Display->SetBufferCursor(unseekX, unseekY);
|
||||
unseekX = unseekY = 0;
|
||||
}
|
||||
|
||||
hIdx++;
|
||||
strBufBck();
|
||||
seekCount = bsCount = strBuf.size();
|
||||
Display->UpdateBuffer();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (unseekX != 0 || unseekY != 0)
|
||||
{
|
||||
Display->SetBufferCursor(unseekX, unseekY);
|
||||
unseekX = unseekY = 0;
|
||||
}
|
||||
|
||||
strBufBck();
|
||||
Display->UpdateBuffer();
|
||||
|
||||
hIdx++;
|
||||
strBuf = history[hIdx]->c_str();
|
||||
|
||||
for (size_t i = 0; i < strlen(strBuf.c_str()); i++)
|
||||
Display->Print(strBuf[i]);
|
||||
putchar(strBuf[i]);
|
||||
|
||||
seekCount = bsCount = strBuf.size();
|
||||
Display->UpdateBuffer();
|
||||
continue;
|
||||
}
|
||||
case KEY_LEFT_ARROW:
|
||||
@ -446,7 +326,6 @@ void StartKernelShell()
|
||||
if (!(sc & KEY_PRESSED))
|
||||
continue;
|
||||
|
||||
UpdateBlinker();
|
||||
if (seekCount == 0)
|
||||
continue;
|
||||
|
||||
@ -454,9 +333,6 @@ void StartKernelShell()
|
||||
|
||||
seekCount--;
|
||||
|
||||
if (unseekX == 0 && unseekY == 0)
|
||||
Display->GetBufferCursor(&unseekX, &unseekY);
|
||||
|
||||
if (ctrlDown)
|
||||
{
|
||||
uint32_t offset = 0;
|
||||
@ -474,27 +350,9 @@ void StartKernelShell()
|
||||
}
|
||||
seekCount++;
|
||||
debug("offset: %d; seekCount: %d", offset, seekCount);
|
||||
|
||||
uint32_t fx = Display->GetCurrentFont()->GetInfo().Width;
|
||||
uint32_t cx, cy;
|
||||
Display->GetBufferCursor(&cx, &cy);
|
||||
Display->SetBufferCursor(cx - (fx * offset), cy);
|
||||
CurX.store(cx - (fx * offset));
|
||||
CurY.store(cy);
|
||||
UpdateBlinker(true);
|
||||
Display->UpdateBuffer();
|
||||
continue;
|
||||
}
|
||||
|
||||
uint32_t cx, cy;
|
||||
Display->GetBufferCursor(&cx, &cy);
|
||||
uint32_t fx = Display->GetCurrentFont()->GetInfo().Width;
|
||||
Display->SetBufferCursor(cx - fx, cy);
|
||||
|
||||
CurX.store(cx - fx);
|
||||
CurY.store(cy);
|
||||
UpdateBlinker(true);
|
||||
Display->UpdateBuffer();
|
||||
continue;
|
||||
}
|
||||
case KEY_RIGHT_ARROW:
|
||||
@ -502,16 +360,12 @@ void StartKernelShell()
|
||||
if (!(sc & KEY_PRESSED))
|
||||
continue;
|
||||
|
||||
UpdateBlinker();
|
||||
if (seekCount == bsCount)
|
||||
continue;
|
||||
seekCount++;
|
||||
|
||||
debug("orig seekCount: %d", seekCount);
|
||||
|
||||
if (unseekX == 0 && unseekY == 0)
|
||||
Display->GetBufferCursor(&unseekX, &unseekY);
|
||||
|
||||
if (ctrlDown)
|
||||
{
|
||||
uint32_t offset = 0;
|
||||
@ -528,28 +382,9 @@ void StartKernelShell()
|
||||
seekCount--;
|
||||
|
||||
debug("offset: %d; seekCount: %d", offset, seekCount);
|
||||
|
||||
uint32_t fx = Display->GetCurrentFont()->GetInfo().Width;
|
||||
uint32_t cx, cy;
|
||||
Display->GetBufferCursor(&cx, &cy);
|
||||
Display->SetBufferCursor(cx + (fx * offset), cy);
|
||||
|
||||
CurX.store(cx + (fx * offset));
|
||||
CurY.store(cy);
|
||||
UpdateBlinker(true);
|
||||
Display->UpdateBuffer();
|
||||
continue;
|
||||
}
|
||||
|
||||
uint32_t cx, cy;
|
||||
Display->GetBufferCursor(&cx, &cy);
|
||||
uint32_t fx = Display->GetCurrentFont()->GetInfo().Width;
|
||||
Display->SetBufferCursor(cx + fx, cy);
|
||||
|
||||
CurX.store(cx + fx);
|
||||
CurY.store(cy);
|
||||
Display->UpdateBuffer();
|
||||
UpdateBlinker(true);
|
||||
continue;
|
||||
}
|
||||
case KEY_HOME:
|
||||
@ -560,20 +395,9 @@ void StartKernelShell()
|
||||
if (homeX == 0 || homeY == 0)
|
||||
continue;
|
||||
|
||||
UpdateBlinker();
|
||||
if (unseekX == 0 || unseekY == 0)
|
||||
Display->GetBufferCursor(&unseekX, &unseekY);
|
||||
|
||||
Display->SetBufferCursor(homeX, homeY);
|
||||
|
||||
seekCount = 0;
|
||||
|
||||
debug("seekCount set to 0");
|
||||
|
||||
CurX.store(homeX);
|
||||
CurY.store(homeY);
|
||||
Display->UpdateBuffer();
|
||||
UpdateBlinker(true);
|
||||
continue;
|
||||
}
|
||||
case KEY_END:
|
||||
@ -584,16 +408,8 @@ void StartKernelShell()
|
||||
if (unseekX == 0 || unseekY == 0)
|
||||
continue;
|
||||
|
||||
UpdateBlinker();
|
||||
Display->SetBufferCursor(unseekX, unseekY);
|
||||
seekCount = bsCount;
|
||||
|
||||
debug("seekCount set to bsCount (%d)", bsCount);
|
||||
|
||||
CurX.store(unseekX);
|
||||
CurY.store(unseekY);
|
||||
Display->UpdateBuffer();
|
||||
UpdateBlinker(true);
|
||||
continue;
|
||||
}
|
||||
default:
|
||||
@ -614,20 +430,18 @@ void StartKernelShell()
|
||||
{
|
||||
case 'C':
|
||||
{
|
||||
Display->Print('^');
|
||||
Display->Print('C');
|
||||
Display->Print('\n');
|
||||
putchar('^');
|
||||
putchar('C');
|
||||
putchar('\n');
|
||||
fixme("No SIGINT handler yet.");
|
||||
Display->UpdateBuffer();
|
||||
goto SecLoopEnd;
|
||||
}
|
||||
case 'D':
|
||||
{
|
||||
Display->Print('^');
|
||||
Display->Print('D');
|
||||
Display->Print('\n');
|
||||
putchar('^');
|
||||
putchar('D');
|
||||
putchar('\n');
|
||||
fixme("No SIGKILL handler yet.");
|
||||
Display->UpdateBuffer();
|
||||
goto SecLoopEnd;
|
||||
}
|
||||
default:
|
||||
@ -637,7 +451,7 @@ void StartKernelShell()
|
||||
|
||||
if (c == '\n')
|
||||
{
|
||||
Display->Print(c);
|
||||
putchar(c);
|
||||
if (strBuf.length() > 0)
|
||||
{
|
||||
std::string *hBuff = new std::string(strBuf.c_str());
|
||||
@ -648,34 +462,23 @@ void StartKernelShell()
|
||||
}
|
||||
else if (seekCount >= bsCount)
|
||||
{
|
||||
Display->Print(c);
|
||||
putchar(c);
|
||||
strBuf += c;
|
||||
seekCount = ++bsCount;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t tmpX, tmpY;
|
||||
Display->GetBufferCursor(&tmpX, &tmpY);
|
||||
|
||||
if (unseekX != 0 && unseekY != 0)
|
||||
Display->SetBufferCursor(unseekX, unseekY);
|
||||
strBufBck();
|
||||
|
||||
// size_t strSeek = seekCount ? seekCount - 1 : 0;
|
||||
debug("seekCount: %d; \"%s\"", seekCount, strBuf.c_str());
|
||||
strBuf.insert(seekCount, (size_t)1, c);
|
||||
Display->PrintString(strBuf.c_str());
|
||||
printf("%s", strBuf.c_str());
|
||||
debug("after strBuf: %s (seek and bs is +1 [seek: %d; bs: %d])",
|
||||
strBuf.c_str(), seekCount + 1, bsCount + 1);
|
||||
|
||||
uint32_t fx = Display->GetCurrentFont()->GetInfo().Width;
|
||||
Display->SetBufferCursor(tmpX + fx, tmpY);
|
||||
unseekX += fx;
|
||||
seekCount++;
|
||||
bsCount++;
|
||||
}
|
||||
|
||||
Display->UpdateBuffer();
|
||||
}
|
||||
SecLoopEnd:
|
||||
|
||||
@ -817,10 +620,5 @@ void StartKernelShell()
|
||||
printf("%s: command not found\n",
|
||||
cmd_only.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void KShellThread()
|
||||
{
|
||||
StartKernelShell();
|
||||
inf_loop;
|
||||
}
|
||||
|
@ -59,7 +59,7 @@ namespace vfs
|
||||
|
||||
PTMXDevice::PTMXDevice()
|
||||
{
|
||||
|
||||
fixme("PTMXDevice");
|
||||
// /* c rw- rw- rw- */
|
||||
// mode_t mode = S_IRUSR | S_IWUSR |
|
||||
// S_IRGRP | S_IWGRP |
|
||||
|
@ -209,6 +209,7 @@ namespace vfs
|
||||
|
||||
std::string Virtual::GetByNode(FileNode *Node)
|
||||
{
|
||||
assert(Node != nullptr);
|
||||
if (Node->Parent == nullptr)
|
||||
{
|
||||
if (Node->Node->Flags & I_FLAG_ROOT)
|
||||
|
@ -29,10 +29,7 @@ namespace vfs
|
||||
min:
|
||||
0 - <ROOT>
|
||||
1 - /proc/self
|
||||
2 - /dev/null
|
||||
3 - /dev/zero
|
||||
4 - /dev/random
|
||||
5 - /dev/mem
|
||||
...
|
||||
*/
|
||||
|
||||
int __vfs_Lookup(struct Inode *_Parent, const char *Name, struct Inode **Result)
|
||||
@ -176,8 +173,6 @@ namespace vfs
|
||||
self->Node->Device = FileSystemRoots->Node.Device;
|
||||
self->Node->SetDevice(0, 1);
|
||||
self->Node->Flags = iFlags;
|
||||
|
||||
new vfs::PTMXDevice();
|
||||
}
|
||||
|
||||
dev_t Virtual::EarlyReserveDevice()
|
||||
|
@ -78,14 +78,14 @@ void StressKernel()
|
||||
Tasking::PCB *pcb = nullptr;
|
||||
if (TO_MiB(KernelAllocator.GetFreeMemory()) < 20)
|
||||
{
|
||||
KPrint("\eE85230Not enough memory left!");
|
||||
KPrint("\x1b[1;31;41mNot enough memory left!");
|
||||
goto End;
|
||||
}
|
||||
|
||||
ptr = KernelAllocator.RequestPages(TO_PAGES(chunk));
|
||||
if (ptr == nullptr)
|
||||
{
|
||||
KPrint("\eE85230Failed to allocate memory!");
|
||||
KPrint("\x1b[1;31;41mFailed to allocate memory!");
|
||||
KPrint("Score is: %d MiB (current is %d MiB)",
|
||||
TO_MiB(highestScore.load()), TO_MiB(totalAllocated.load()));
|
||||
continue;
|
||||
|
@ -123,8 +123,9 @@ void TaskMgr()
|
||||
}
|
||||
|
||||
uint32_t tmpX, tmpY;
|
||||
Display->GetBufferCursor(&tmpX, &tmpY);
|
||||
Display->SetBufferCursor(0, 0);
|
||||
fixme("cursor 127-128; 179");
|
||||
// Display->GetBufferCursor(&tmpX, &tmpY);
|
||||
// Display->SetBufferCursor(0, 0);
|
||||
printf("\eF02C21Task Manager\n");
|
||||
static uint64_t OldSystemTime = 0;
|
||||
foreach (auto Proc in TaskManager->GetProcessList())
|
||||
@ -175,7 +176,7 @@ void TaskMgr()
|
||||
#endif
|
||||
if (sanity > 1000)
|
||||
sanity = 0;
|
||||
Display->SetBufferCursor(tmpX, tmpY);
|
||||
// Display->SetBufferCursor(tmpX, tmpY);
|
||||
if (!Config.Quiet)
|
||||
Display->UpdateBuffer();
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user