mirror of
https://github.com/EnderIce2/Fennix.git
synced 2025-07-02 10:59:15 +00:00
Merge remote-tracking branch 'Kernel/master'
This commit is contained in:
150
Kernel/core/panic/diag.cpp
Normal file
150
Kernel/core/panic/diag.cpp
Normal file
@ -0,0 +1,150 @@
|
||||
/*
|
||||
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 <display.hpp>
|
||||
#include <bitmap.hpp>
|
||||
#include <convert.h>
|
||||
#include <printf.h>
|
||||
#include <lock.hpp>
|
||||
#include <rand.hpp>
|
||||
#include <uart.hpp>
|
||||
#include <time.hpp>
|
||||
#include <debug.h>
|
||||
#include <smp.hpp>
|
||||
#include <cpu.hpp>
|
||||
#include <io.h>
|
||||
|
||||
#if defined(a64)
|
||||
#include "../../arch/amd64/cpu/gdt.hpp"
|
||||
#include "../arch/amd64/cpu/apic.hpp"
|
||||
#elif defined(a32)
|
||||
#include "../../arch/i386/cpu/gdt.hpp"
|
||||
#include "../arch/i386/cpu/apic.hpp"
|
||||
#elif defined(aa64)
|
||||
#endif
|
||||
|
||||
#include "../../kernel.h"
|
||||
#include "kbd/keyboard.hpp"
|
||||
|
||||
extern void ExPrint(const char *Format, ...);
|
||||
extern void DisplayTopOverlay();
|
||||
extern CPU::ExceptionFrame *ExFrame;
|
||||
|
||||
/* TODO: Add more info */
|
||||
struct DiagnosticFile
|
||||
{
|
||||
__packed __aligned(16) struct
|
||||
{
|
||||
uint8_t Signature[5] = {'D', 'I', 'A', 'G', '\0'};
|
||||
uint32_t Version = 1;
|
||||
char Is64Bit = 0;
|
||||
uint32_t Length = 0;
|
||||
} Header;
|
||||
|
||||
__packed __aligned(16) struct
|
||||
{
|
||||
CPU::ExceptionFrame Frame;
|
||||
|
||||
uint32_t KernelMemoryLength;
|
||||
uint8_t KernelMemory[];
|
||||
} Data;
|
||||
};
|
||||
|
||||
nsa bool WriteDiagDataToNode(FileNode *node)
|
||||
{
|
||||
uintptr_t KStart = (uintptr_t)&_kernel_start;
|
||||
uintptr_t kEnd = (uintptr_t)&_kernel_end;
|
||||
size_t kSize = kEnd - KStart;
|
||||
|
||||
size_t fileSize = sizeof(DiagnosticFile) + kSize;
|
||||
uint8_t *buf = (uint8_t *)KernelAllocator.RequestPages(TO_PAGES(fileSize));
|
||||
if (!buf)
|
||||
{
|
||||
ExPrint("\x1b[0;30;41mFailed to allocate memory for diagnostic data\x1b[0m\n");
|
||||
Display->UpdateBuffer();
|
||||
return false;
|
||||
}
|
||||
|
||||
DiagnosticFile *file = (DiagnosticFile *)buf;
|
||||
file->Header = {};
|
||||
file->Header.Length = uint32_t(fileSize);
|
||||
file->Header.Is64Bit = sizeof(void *) == 8;
|
||||
|
||||
file->Data.Frame = *ExFrame;
|
||||
file->Data.KernelMemoryLength = uint32_t(kSize);
|
||||
memcpy(file->Data.KernelMemory, (void *)KStart, kSize);
|
||||
|
||||
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("\x1b[0;30;41mFailed to write diagnostic data to file: %s\x1b[0m\n",
|
||||
strerror((int)w));
|
||||
Display->UpdateBuffer();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
nsa void DiagnosticDataCollection()
|
||||
{
|
||||
Display->ClearBuffer();
|
||||
DisplayTopOverlay();
|
||||
|
||||
ExPrint("\nPlease wait while we collect some diagnostic information...\n");
|
||||
ExPrint("This may take a while...\n");
|
||||
|
||||
mode_t mode = S_IRWXU |
|
||||
S_IRWXG |
|
||||
S_IROTH |
|
||||
S_IFDIR;
|
||||
|
||||
FileNode *panicDir = fs->ForceCreate(nullptr, "/var/panic", mode);
|
||||
if (!panicDir)
|
||||
{
|
||||
ExPrint("\x1b[0;30;41mFailed to create /var/panic\x1b[0m\n");
|
||||
Display->UpdateBuffer();
|
||||
return;
|
||||
}
|
||||
|
||||
FileNode *dumpFile;
|
||||
Time::Clock clock = Time::ReadClock();
|
||||
char filename[64];
|
||||
for (int i = 0; i < INT32_MAX; i++)
|
||||
{
|
||||
sprintf(filename, "dump-%d-%d-%d-%d.dmp",
|
||||
clock.Year, clock.Month, clock.Day, i);
|
||||
if (fs->PathExists(filename, panicDir))
|
||||
continue;
|
||||
|
||||
mode = S_IRWXU |
|
||||
S_IRWXG |
|
||||
S_IROTH |
|
||||
S_IFREG;
|
||||
|
||||
dumpFile = fs->Create(panicDir, filename, mode);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!WriteDiagDataToNode(dumpFile))
|
||||
return;
|
||||
|
||||
ExPrint("You can find the diagnostic file in /var/panic/%s\n", filename);
|
||||
Display->UpdateBuffer();
|
||||
}
|
403
Kernel/core/panic/handler.cpp
Normal file
403
Kernel/core/panic/handler.cpp
Normal file
@ -0,0 +1,403 @@
|
||||
/*
|
||||
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 <display.hpp>
|
||||
#include <bitmap.hpp>
|
||||
#include <convert.h>
|
||||
#include <printf.h>
|
||||
#include <lock.hpp>
|
||||
#include <rand.hpp>
|
||||
#include <uart.hpp>
|
||||
#include <kcon.hpp>
|
||||
#include <debug.h>
|
||||
#include <smp.hpp>
|
||||
#include <cpu.hpp>
|
||||
#include <io.h>
|
||||
|
||||
#if defined(a64)
|
||||
#include "../../arch/amd64/cpu/gdt.hpp"
|
||||
#include "../arch/amd64/cpu/apic.hpp"
|
||||
#elif defined(a32)
|
||||
#include "../../arch/i386/cpu/gdt.hpp"
|
||||
#include "../arch/i386/cpu/apic.hpp"
|
||||
#elif defined(aa64)
|
||||
#endif
|
||||
|
||||
#include "../../kernel.h"
|
||||
|
||||
using namespace KernelConsole;
|
||||
|
||||
extern const char *x86ExceptionMnemonics[];
|
||||
extern void DisplayCrashScreen(CPU::ExceptionFrame *);
|
||||
extern bool UserModeExceptionHandler(CPU::ExceptionFrame *);
|
||||
extern void DisplayStackSmashing();
|
||||
extern void DisplayBufferOverflow();
|
||||
extern void DisplayAssertionFailed(const char *, int, const char *);
|
||||
|
||||
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 *)
|
||||
{
|
||||
KernelConsole::Terminals[15]->Process(c);
|
||||
}
|
||||
|
||||
nsa void ExPrint(const char *Format, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, Format);
|
||||
vfctprintf(__printfWrapper, NULL, Format, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
nsa void HaltAllCores()
|
||||
{
|
||||
if (SMP::CPUCores <= 1)
|
||||
return;
|
||||
|
||||
#if defined(a86)
|
||||
if (Interrupts::apic[0] == nullptr)
|
||||
return;
|
||||
|
||||
APIC::InterruptCommandRegister icr{};
|
||||
|
||||
bool x2APIC = ((APIC::APIC *)Interrupts::apic[0])->x2APIC;
|
||||
if (likely(x2APIC))
|
||||
{
|
||||
icr.x2.VEC = s_cst(uint8_t, CPU::x86::IRQ31);
|
||||
icr.x2.MT = APIC::Fixed;
|
||||
icr.x2.L = APIC::Assert;
|
||||
|
||||
for (int i = 1; i < SMP::CPUCores; i++)
|
||||
{
|
||||
icr.x2.DES = uint8_t(i);
|
||||
((APIC::APIC *)Interrupts::apic[i])->ICR(icr);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
icr.VEC = s_cst(uint8_t, CPU::x86::IRQ31);
|
||||
icr.MT = APIC::Fixed;
|
||||
icr.L = APIC::Assert;
|
||||
|
||||
for (int i = 1; i < SMP::CPUCores; i++)
|
||||
{
|
||||
icr.DES = uint8_t(i);
|
||||
((APIC::APIC *)Interrupts::apic[i])->ICR(icr);
|
||||
}
|
||||
}
|
||||
#elif defined(aa64)
|
||||
#endif
|
||||
}
|
||||
|
||||
nsa void InitFont()
|
||||
{
|
||||
/* Hope we won't crash here */
|
||||
|
||||
if (Display == nullptr)
|
||||
{
|
||||
error("Can't initialize font without display initalized");
|
||||
CPU::Stop();
|
||||
}
|
||||
|
||||
if (FbBeforePanic == nullptr)
|
||||
{
|
||||
FbPagesBeforePanic = TO_PAGES(Display->GetSize);
|
||||
FbBeforePanic = KernelAllocator.RequestPages(FbPagesBeforePanic);
|
||||
debug("Created before panic framebuffer at %#lx", FbBeforePanic);
|
||||
}
|
||||
memcpy(FbBeforePanic, Display->GetBuffer, Display->GetSize);
|
||||
|
||||
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;
|
||||
nsa __noreturn void HandleUnrecoverableException(CPU::ExceptionFrame *Frame)
|
||||
{
|
||||
static int setOnce = 0;
|
||||
if (!setOnce++) /* FIXME: SMP */
|
||||
{
|
||||
for (uint32_t x = 0; x < Display->GetWidth; x++)
|
||||
for (uint32_t y = 0; y < Display->GetHeight; y++)
|
||||
Display->SetPixel(x, y, 0xFF250500);
|
||||
|
||||
ExPrint("\x1b[H");
|
||||
}
|
||||
|
||||
CPUData *core = GetCurrentCPU();
|
||||
|
||||
while (UnrecoverableLock.exchange(true, std::memory_order_acquire))
|
||||
CPU::Pause();
|
||||
|
||||
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",
|
||||
Frame->cr0, Frame->cr2, Frame->cr3, Frame->cr4, Frame->cr8);
|
||||
ExPrint("DR0=%#lx DR1=%#lx DR2=%#lx DR3=%#lx DR6=%#lx DR7=%#lx\n",
|
||||
Frame->dr0, Frame->dr1, Frame->dr2, Frame->dr3, Frame->dr6, Frame->dr7);
|
||||
ExPrint("GS=%#lx FS=%#lx ES=%#lx DS=%#lx SS=%#lx CS=%#lx\n",
|
||||
Frame->gs, Frame->fs, Frame->es, Frame->ds, Frame->ss, Frame->cs);
|
||||
#endif
|
||||
#if defined(a64)
|
||||
ExPrint("R8=%#lx R9=%#lx R10=%#lx R11=%#lx R12=%#lx R13=%#lx R14=%#lx R15=%#lx\n",
|
||||
Frame->r8, Frame->r9, Frame->r10, Frame->r11, Frame->r12, Frame->r13,
|
||||
Frame->r14, Frame->r15);
|
||||
#endif
|
||||
#if defined(a86)
|
||||
ExPrint("AX=%#lx BX=%#lx CX=%#lx DX=%#lx SI=%#lx DI=%#lx BP=%#lx SP=%#lx\n",
|
||||
|
||||
#ifdef a64
|
||||
Frame->rax, Frame->rbx, Frame->rcx, Frame->rdx, Frame->rsi, Frame->rdi,
|
||||
Frame->rbp, Frame->rsp);
|
||||
#else
|
||||
Frame->eax, Frame->ebx, Frame->ecx, Frame->edx, Frame->esi, Frame->edi,
|
||||
Frame->ebp, Frame->esp);
|
||||
#endif /* a64 */
|
||||
|
||||
ExPrint("IP=%#lx FL=%#lx INT=%#lx ERR=%#lx\n",
|
||||
|
||||
#ifdef a64
|
||||
Frame->rip, Frame->rflags.raw,
|
||||
#else
|
||||
Frame->eip, Frame->eflags.raw,
|
||||
#endif /* a64 */
|
||||
Frame->InterruptNumber, Frame->ErrorCode);
|
||||
#endif /* a86 */
|
||||
|
||||
Display->UpdateBuffer();
|
||||
error("Unrecoverable Exception: %#lx", Frame->InterruptNumber);
|
||||
|
||||
UnrecoverableLock.store(false, std::memory_order_release);
|
||||
CPU::Stop();
|
||||
}
|
||||
|
||||
nsa __noreturn void HandleExceptionInsideException(CPU::ExceptionFrame *Frame)
|
||||
{
|
||||
ExPrint("\x1b[0m-----------------------------------------------\n");
|
||||
ExPrint("Exception inside exception: %#lx at %#lx\n",
|
||||
Frame->InterruptNumber,
|
||||
#if defined(a64)
|
||||
Frame->rip);
|
||||
#elif defined(a32)
|
||||
Frame->eip);
|
||||
#elif defined(aa64)
|
||||
Frame->pc);
|
||||
#endif
|
||||
#if defined(a86)
|
||||
ExPrint("CR0=%#lx CR2=%#lx CR3=%#lx CR4=%#lx CR8=%#lx\n",
|
||||
Frame->cr0, Frame->cr2, Frame->cr3, Frame->cr4, Frame->cr8);
|
||||
ExPrint("DR0=%#lx DR1=%#lx DR2=%#lx DR3=%#lx DR6=%#lx DR7=%#lx\n",
|
||||
Frame->dr0, Frame->dr1, Frame->dr2, Frame->dr3, Frame->dr6, Frame->dr7);
|
||||
ExPrint("GS=%#lx FS=%#lx ES=%#lx DS=%#lx SS=%#lx CS=%#lx\n",
|
||||
Frame->gs, Frame->fs, Frame->es, Frame->ds, Frame->ss, Frame->cs);
|
||||
#endif
|
||||
#if defined(a64)
|
||||
ExPrint("R8=%#lx R9=%#lx R10=%#lx R11=%#lx R12=%#lx R13=%#lx R14=%#lx R15=%#lx\n",
|
||||
Frame->r8, Frame->r9, Frame->r10, Frame->r11, Frame->r12, Frame->r13,
|
||||
Frame->r14, Frame->r15);
|
||||
#endif
|
||||
#if defined(a86)
|
||||
ExPrint("AX=%#lx BX=%#lx CX=%#lx DX=%#lx SI=%#lx DI=%#lx BP=%#lx SP=%#lx\n",
|
||||
|
||||
#ifdef a64
|
||||
Frame->rax, Frame->rbx, Frame->rcx, Frame->rdx, Frame->rsi, Frame->rdi,
|
||||
Frame->rbp, Frame->rsp);
|
||||
#else
|
||||
Frame->eax, Frame->ebx, Frame->ecx, Frame->edx, Frame->esi, Frame->edi,
|
||||
Frame->ebp, Frame->esp);
|
||||
#endif /* a64 */
|
||||
|
||||
ExPrint("IP=%#lx FL=%#lx INT=%#lx ERR=%#lx\n",
|
||||
|
||||
#ifdef a64
|
||||
Frame->rip, Frame->rflags.raw,
|
||||
#else
|
||||
Frame->eip, Frame->eflags.raw,
|
||||
#endif /* a64 */
|
||||
Frame->InterruptNumber, Frame->ErrorCode);
|
||||
#endif /* a86 */
|
||||
Display->UpdateBuffer();
|
||||
CPU::Stop();
|
||||
}
|
||||
|
||||
std::atomic<bool> ExceptionLock = false;
|
||||
nsa void HandleException(CPU::ExceptionFrame *Frame)
|
||||
{
|
||||
/* We don't need to restore the page table
|
||||
because the ExceptionHandlerStub will
|
||||
do it for us if we return. */
|
||||
CPU::PageTable(KernelPageTable);
|
||||
InitFont();
|
||||
|
||||
/* First check the exception */
|
||||
if (unlikely(Frame->InterruptNumber == CPU::x86::DoubleFault))
|
||||
{
|
||||
ExceptionLock.store(true, std::memory_order_release);
|
||||
HandleUnrecoverableException(Frame);
|
||||
}
|
||||
|
||||
if (Frame->cs == GDT_USER_CODE && Frame->ss == GDT_USER_DATA)
|
||||
{
|
||||
if (UserModeExceptionHandler(Frame))
|
||||
goto ExceptionExit;
|
||||
|
||||
CPUData *core = GetCurrentCPU();
|
||||
if (likely(core->CurrentThread->Security.IsCritical == false))
|
||||
TaskManager->Yield();
|
||||
|
||||
error("Critical thread \"%s\"(%d) died",
|
||||
core->CurrentThread->Name,
|
||||
core->CurrentThread->ID);
|
||||
}
|
||||
|
||||
debug("-----------------------------------------------------------------------------------");
|
||||
error("Exception: %#x", Frame->InterruptNumber);
|
||||
debug("%ld MiB / %ld MiB (%ld MiB Reserved)",
|
||||
TO_MiB(KernelAllocator.GetUsedMemory()),
|
||||
TO_MiB(KernelAllocator.GetTotalMemory()),
|
||||
TO_MiB(KernelAllocator.GetReservedMemory()));
|
||||
|
||||
if (ExceptionLock.load(std::memory_order_acquire))
|
||||
HandleExceptionInsideException(Frame);
|
||||
ExceptionLock.store(true, std::memory_order_release);
|
||||
|
||||
{
|
||||
const char msg[] = "Entering in panic mode...";
|
||||
size_t msgLen = strlen(msg);
|
||||
size_t msgPixels = msgLen * CrashFontRenderer.CurrentFont->GetInfo().Width;
|
||||
uint32_t x = uint32_t((Display->GetWidth - msgPixels) / 2);
|
||||
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)
|
||||
DriverManager->Panic();
|
||||
if (TaskManager)
|
||||
TaskManager->Panic();
|
||||
Interrupts::RemoveAll();
|
||||
HaltAllCores();
|
||||
ForceUnlock = true;
|
||||
|
||||
DisplayCrashScreen(Frame);
|
||||
CPU::Stop();
|
||||
|
||||
ExceptionExit:
|
||||
ExceptionLock.store(false, std::memory_order_release);
|
||||
}
|
||||
|
||||
nsa void BaseBufferStackError(bool Stack)
|
||||
{
|
||||
/* We don't need to restore the page table
|
||||
because the ExceptionHandlerStub will
|
||||
do it for us if we return. */
|
||||
CPU::PageTable(KernelPageTable);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
ExceptionLock.store(true, std::memory_order_release);
|
||||
|
||||
if (DriverManager)
|
||||
DriverManager->Panic();
|
||||
if (TaskManager)
|
||||
TaskManager->Panic();
|
||||
HaltAllCores();
|
||||
ForceUnlock = true;
|
||||
|
||||
debug("-----------------------------------------------------------------------------------");
|
||||
error("%s", Stack ? "Stack smashing detected" : "Buffer overflow detected");
|
||||
debug("%ld MiB / %ld MiB (%ld MiB Reserved)",
|
||||
TO_MiB(KernelAllocator.GetUsedMemory()),
|
||||
TO_MiB(KernelAllocator.GetTotalMemory()),
|
||||
TO_MiB(KernelAllocator.GetReservedMemory()));
|
||||
}
|
||||
|
||||
nsa __noreturn void HandleStackSmashing()
|
||||
{
|
||||
BaseBufferStackError(true);
|
||||
DisplayStackSmashing();
|
||||
CPU::Stop();
|
||||
}
|
||||
|
||||
nsa __noreturn void HandleBufferOverflow()
|
||||
{
|
||||
BaseBufferStackError(false);
|
||||
DisplayBufferOverflow();
|
||||
CPU::Stop();
|
||||
}
|
||||
|
||||
EXTERNC nsa __noreturn void HandleAssertionFailed(const char *File, int Line,
|
||||
const char *Expression)
|
||||
{
|
||||
DisplayAssertionFailed(File, Line, Expression);
|
||||
CPU::Stop();
|
||||
}
|
94
Kernel/core/panic/kbd/ehci.cpp
Normal file
94
Kernel/core/panic/kbd/ehci.cpp
Normal file
@ -0,0 +1,94 @@
|
||||
/*
|
||||
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 "ehci.hpp"
|
||||
|
||||
#include <interface/aip.h>
|
||||
#include <display.hpp>
|
||||
#include <convert.h>
|
||||
#include <printf.h>
|
||||
#include <kcon.hpp>
|
||||
#include <debug.h>
|
||||
#include <smp.hpp>
|
||||
#include <cpu.hpp>
|
||||
#include <io.h>
|
||||
|
||||
#if defined(a64)
|
||||
#include "../../../arch/amd64/cpu/gdt.hpp"
|
||||
#elif defined(a32)
|
||||
#elif defined(aa64)
|
||||
#endif
|
||||
|
||||
#include "../../../kernel.h"
|
||||
|
||||
using namespace KernelConsole;
|
||||
using namespace PCI;
|
||||
|
||||
#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;
|
||||
|
||||
nsa void CrashEHCIKeyboardDriver::OnInterruptReceived(CPU::TrapFrame *Frame)
|
||||
{
|
||||
}
|
||||
|
||||
nsa bool CrashEHCIKeyboardDriver::Initialize()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
nsa CrashEHCIKeyboardDriver::CrashEHCIKeyboardDriver(PCI::PCIDevice dev)
|
||||
: Interrupts::Handler(dev)
|
||||
{
|
||||
Header = (PCIDeviceHeader *)dev.Header;
|
||||
|
||||
switch (Header->HeaderType)
|
||||
{
|
||||
case 128:
|
||||
{
|
||||
ExPrint(ERROR_COLOR "Unknown header type %d! Guessing PCI Header 0\n" DEFAULT_COLOR,
|
||||
Header->HeaderType);
|
||||
[[fallthrough]];
|
||||
}
|
||||
case 0: /* PCI Header 0 */
|
||||
{
|
||||
PCI::PCIHeader0 *hdr = (PCI::PCIHeader0 *)Header;
|
||||
UNUSED(hdr);
|
||||
break;
|
||||
}
|
||||
case 1: /* PCI Header 1 (PCI-to-PCI Bridge) */
|
||||
{
|
||||
ExPrint(ERROR_COLOR "PCI-to-PCI Bridge not supported\n" DEFAULT_COLOR);
|
||||
break;
|
||||
}
|
||||
case 2: /* PCI Header 2 (PCI-to-CardBus Bridge) */
|
||||
{
|
||||
ExPrint(ERROR_COLOR "PCI-to-CardBus Bridge not supported\n" DEFAULT_COLOR);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
ExPrint(ERROR_COLOR "Invalid PCI header type\n" DEFAULT_COLOR);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
31
Kernel/core/panic/kbd/ehci.hpp
Normal file
31
Kernel/core/panic/kbd/ehci.hpp
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
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/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ints.hpp>
|
||||
|
||||
class CrashEHCIKeyboardDriver : public Interrupts::Handler
|
||||
{
|
||||
public:
|
||||
PCI::PCIDeviceHeader *Header = nullptr;
|
||||
|
||||
void OnInterruptReceived(CPU::TrapFrame *Frame);
|
||||
bool Initialize();
|
||||
CrashEHCIKeyboardDriver(PCI::PCIDevice dev);
|
||||
~CrashEHCIKeyboardDriver() = default;
|
||||
};
|
101
Kernel/core/panic/kbd/keyboard.cpp
Normal file
101
Kernel/core/panic/kbd/keyboard.cpp
Normal file
@ -0,0 +1,101 @@
|
||||
/*
|
||||
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 "keyboard.hpp"
|
||||
#include "ps2.hpp"
|
||||
#include "uhci.hpp"
|
||||
#include "ehci.hpp"
|
||||
#include "xhci.hpp"
|
||||
|
||||
#include <interface/aip.h>
|
||||
#include <display.hpp>
|
||||
#include <convert.h>
|
||||
#include <printf.h>
|
||||
#include <kcon.hpp>
|
||||
#include <debug.h>
|
||||
#include <smp.hpp>
|
||||
#include <cpu.hpp>
|
||||
#include <io.h>
|
||||
|
||||
#if defined(a64)
|
||||
#include "../../../arch/amd64/cpu/gdt.hpp"
|
||||
#elif defined(a32)
|
||||
#elif defined(aa64)
|
||||
#endif
|
||||
|
||||
#include "../../../kernel.h"
|
||||
|
||||
using namespace KernelConsole;
|
||||
using namespace PCI;
|
||||
|
||||
nsa bool DetectUSBKeyboard()
|
||||
{
|
||||
if (!PCIManager)
|
||||
return false;
|
||||
std::list<PCIDevice> uhci = PCIManager->FindPCIDevice(0xC, 0x3, 0x00); /* UHCI */
|
||||
debug("There are %lu UHCI devices", uhci.size());
|
||||
|
||||
std::list<PCIDevice> ohci = PCIManager->FindPCIDevice(0xC, 0x3, 0x10); /* OHCI */
|
||||
debug("There are %lu OHCI devices", ohci.size());
|
||||
|
||||
std::list<PCIDevice> ehci = PCIManager->FindPCIDevice(0xC, 0x3, 0x20); /* EHCI */
|
||||
debug("There are %lu EHCI devices", uhci.size());
|
||||
|
||||
std::list<PCIDevice> xhci = PCIManager->FindPCIDevice(0xC, 0x3, 0x30); /* XHCI */
|
||||
debug("There are %lu XHCI devices", xhci.size());
|
||||
|
||||
debug("Initializing UHCI devices");
|
||||
for (const auto &dev : uhci)
|
||||
{
|
||||
CrashUHCIKeyboardDriver *usb = new CrashUHCIKeyboardDriver(dev);
|
||||
if (!usb->Initialize())
|
||||
{
|
||||
error("Failed to initialize UHCI keyboard driver");
|
||||
uhci.pop_front();
|
||||
}
|
||||
}
|
||||
|
||||
debug("Initializing EHCI devices");
|
||||
for (const auto &dev : ehci)
|
||||
{
|
||||
CrashEHCIKeyboardDriver *usb = new CrashEHCIKeyboardDriver(dev);
|
||||
if (!usb->Initialize())
|
||||
{
|
||||
error("Failed to initialize UHCI keyboard driver");
|
||||
ehci.pop_front();
|
||||
}
|
||||
}
|
||||
|
||||
debug("Initializing XHCI devices");
|
||||
for (const auto &dev : xhci)
|
||||
{
|
||||
CrashXHCIKeyboardDriver *usb = new CrashXHCIKeyboardDriver(dev);
|
||||
if (!usb->Initialize())
|
||||
{
|
||||
error("Failed to initialize XHCI keyboard driver");
|
||||
xhci.pop_front();
|
||||
}
|
||||
}
|
||||
|
||||
return xhci.size() > 0 || uhci.size() > 0 || ohci.size() > 0;
|
||||
}
|
||||
|
||||
nsa void InitializeKeyboards()
|
||||
{
|
||||
if (DetectUSBKeyboard() == false)
|
||||
new CrashPS2KeyboardDriver;
|
||||
}
|
206
Kernel/core/panic/kbd/keyboard.hpp
Normal file
206
Kernel/core/panic/kbd/keyboard.hpp
Normal file
@ -0,0 +1,206 @@
|
||||
/*
|
||||
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 <ints.hpp>
|
||||
|
||||
#pragma once
|
||||
|
||||
enum Keys
|
||||
{
|
||||
KEY_INVALID = 0x0,
|
||||
KEY_D_ESCAPE = 0x1,
|
||||
KEY_D_1 = 0x2,
|
||||
KEY_D_2 = 0x3,
|
||||
KEY_D_3 = 0x4,
|
||||
KEY_D_4 = 0x5,
|
||||
KEY_D_5 = 0x6,
|
||||
KEY_D_6 = 0x7,
|
||||
KEY_D_7 = 0x8,
|
||||
KEY_D_8 = 0x9,
|
||||
KEY_D_9 = 0xa,
|
||||
KEY_D_0 = 0xb,
|
||||
KEY_D_MINUS = 0xc,
|
||||
KEY_D_EQUALS = 0xd,
|
||||
KEY_D_BACKSPACE = 0xe,
|
||||
KEY_D_TAB = 0xf,
|
||||
KEY_D_Q = 0x10,
|
||||
KEY_D_W = 0x11,
|
||||
KEY_D_E = 0x12,
|
||||
KEY_D_R = 0x13,
|
||||
KEY_D_T = 0x14,
|
||||
KEY_D_Y = 0x15,
|
||||
KEY_D_U = 0x16,
|
||||
KEY_D_I = 0x17,
|
||||
KEY_D_O = 0x18,
|
||||
KEY_D_P = 0x19,
|
||||
KEY_D_LBRACKET = 0x1a,
|
||||
KEY_D_RBRACKET = 0x1b,
|
||||
KEY_D_RETURN = 0x1c,
|
||||
KEY_D_LCTRL = 0x1d,
|
||||
KEY_D_A = 0x1e,
|
||||
KEY_D_S = 0x1f,
|
||||
KEY_D_D = 0x20,
|
||||
KEY_D_F = 0x21,
|
||||
KEY_D_G = 0x22,
|
||||
KEY_D_H = 0x23,
|
||||
KEY_D_J = 0x24,
|
||||
KEY_D_K = 0x25,
|
||||
KEY_D_L = 0x26,
|
||||
KEY_D_SEMICOLON = 0x27,
|
||||
KEY_D_APOSTROPHE = 0x28,
|
||||
KEY_D_GRAVE = 0x29,
|
||||
KEY_D_LSHIFT = 0x2a,
|
||||
KEY_D_BACKSLASH = 0x2b,
|
||||
KEY_D_Z = 0x2c,
|
||||
KEY_D_X = 0x2d,
|
||||
KEY_D_C = 0x2e,
|
||||
KEY_D_V = 0x2f,
|
||||
KEY_D_B = 0x30,
|
||||
KEY_D_N = 0x31,
|
||||
KEY_D_M = 0x32,
|
||||
KEY_D_COMMA = 0x33,
|
||||
KEY_D_PERIOD = 0x34,
|
||||
KEY_D_SLASH = 0x35,
|
||||
KEY_D_RSHIFT = 0x36,
|
||||
KEY_D_PRTSC = 0x37,
|
||||
KEY_D_LALT = 0x38,
|
||||
KEY_D_SPACE = 0x39,
|
||||
KEY_D_CAPSLOCK = 0x3a,
|
||||
KEY_D_NUMLOCK = 0x45,
|
||||
KEY_D_SCROLLLOCK = 0x46,
|
||||
|
||||
KEY_D_KP_MULTIPLY = 0x37,
|
||||
KEY_D_KP_7 = 0x47,
|
||||
KEY_D_KP_8 = 0x48,
|
||||
KEY_D_KP_9 = 0x49,
|
||||
KEY_D_KP_MINUS = 0x4a,
|
||||
KEY_D_KP_4 = 0x4b,
|
||||
KEY_D_KP_5 = 0x4c,
|
||||
KEY_D_KP_6 = 0x4d,
|
||||
KEY_D_KP_PLUS = 0x4e,
|
||||
KEY_D_KP_1 = 0x4f,
|
||||
KEY_D_KP_2 = 0x50,
|
||||
KEY_D_KP_3 = 0x51,
|
||||
KEY_D_KP_0 = 0x52,
|
||||
KEY_D_KP_PERIOD = 0x53,
|
||||
|
||||
KEY_D_F1 = 0x3b,
|
||||
KEY_D_F2 = 0x3c,
|
||||
KEY_D_F3 = 0x3d,
|
||||
KEY_D_F4 = 0x3e,
|
||||
KEY_D_F5 = 0x3f,
|
||||
KEY_D_F6 = 0x40,
|
||||
KEY_D_F7 = 0x41,
|
||||
KEY_D_F8 = 0x42,
|
||||
KEY_D_F9 = 0x43,
|
||||
KEY_D_F10 = 0x44,
|
||||
KEY_D_F11 = 0x57,
|
||||
KEY_D_F12 = 0x58,
|
||||
|
||||
KEY_D_UP = 0x48,
|
||||
KEY_D_LEFT = 0x4b,
|
||||
KEY_D_RIGHT = 0x4d,
|
||||
KEY_D_DOWN = 0x50,
|
||||
|
||||
KEY_U_ESCAPE = 0x81,
|
||||
KEY_U_1 = 0x82,
|
||||
KEY_U_2 = 0x83,
|
||||
KEY_U_3 = 0x84,
|
||||
KEY_U_4 = 0x85,
|
||||
KEY_U_5 = 0x86,
|
||||
KEY_U_6 = 0x87,
|
||||
KEY_U_7 = 0x88,
|
||||
KEY_U_8 = 0x89,
|
||||
KEY_U_9 = 0x8a,
|
||||
KEY_U_0 = 0x8b,
|
||||
KEY_U_MINUS = 0x8c,
|
||||
KEY_U_EQUALS = 0x8d,
|
||||
KEY_U_BACKSPACE = 0x8e,
|
||||
KEY_U_TAB = 0x8f,
|
||||
KEY_U_Q = 0x90,
|
||||
KEY_U_W = 0x91,
|
||||
KEY_U_E = 0x92,
|
||||
KEY_U_R = 0x93,
|
||||
KEY_U_T = 0x94,
|
||||
KEY_U_Y = 0x95,
|
||||
KEY_U_U = 0x96,
|
||||
KEY_U_I = 0x97,
|
||||
KEY_U_O = 0x98,
|
||||
KEY_U_P = 0x99,
|
||||
KEY_U_LBRACKET = 0x9a,
|
||||
KEY_U_RBRACKET = 0x9b,
|
||||
KEY_U_RETURN = 0x9c,
|
||||
KEY_U_LCTRL = 0x9d,
|
||||
KEY_U_A = 0x9e,
|
||||
KEY_U_S = 0x9f,
|
||||
KEY_U_D = 0xa0,
|
||||
KEY_U_F = 0xa1,
|
||||
KEY_U_G = 0xa2,
|
||||
KEY_U_H = 0xa3,
|
||||
KEY_U_J = 0xa4,
|
||||
KEY_U_K = 0xa5,
|
||||
KEY_U_L = 0xa6,
|
||||
KEY_U_SEMICOLON = 0xa7,
|
||||
KEY_U_APOSTROPHE = 0xa8,
|
||||
KEY_U_GRAVE = 0xa9,
|
||||
KEY_U_LSHIFT = 0xaa,
|
||||
KEY_U_BACKSLASH = 0xab,
|
||||
KEY_U_Z = 0xac,
|
||||
KEY_U_X = 0xad,
|
||||
KEY_U_C = 0xae,
|
||||
KEY_U_V = 0xaf,
|
||||
KEY_U_B = 0xb0,
|
||||
KEY_U_N = 0xb1,
|
||||
KEY_U_M = 0xb2,
|
||||
KEY_U_COMMA = 0xb3,
|
||||
KEY_U_PERIOD = 0xb4,
|
||||
KEY_U_SLASH = 0xb5,
|
||||
KEY_U_RSHIFT = 0xb6,
|
||||
KEY_U_KP_MULTIPLY = 0xb7,
|
||||
KEY_U_LALT = 0xb8,
|
||||
KEY_U_SPACE = 0xb9,
|
||||
KEY_U_CAPSLOCK = 0xba,
|
||||
KEY_U_F1 = 0xbb,
|
||||
KEY_U_F2 = 0xbc,
|
||||
KEY_U_F3 = 0xbd,
|
||||
KEY_U_F4 = 0xbe,
|
||||
KEY_U_F5 = 0xbf,
|
||||
KEY_U_F6 = 0xc0,
|
||||
KEY_U_F7 = 0xc1,
|
||||
KEY_U_F8 = 0xc2,
|
||||
KEY_U_F9 = 0xc3,
|
||||
KEY_U_F10 = 0xc4,
|
||||
KEY_U_NUMLOCK = 0xc5,
|
||||
KEY_U_SCROLLLOCK = 0xc6,
|
||||
KEY_U_KP_7 = 0xc7,
|
||||
KEY_U_KP_8 = 0xc8,
|
||||
KEY_U_KP_9 = 0xc9,
|
||||
KEY_U_KP_MINUS = 0xca,
|
||||
KEY_U_KP_4 = 0xcb,
|
||||
KEY_U_KP_5 = 0xcc,
|
||||
KEY_U_KP_6 = 0xcd,
|
||||
KEY_U_KP_PLUS = 0xce,
|
||||
KEY_U_KP_1 = 0xcf,
|
||||
KEY_U_KP_2 = 0xd0,
|
||||
KEY_U_KP_3 = 0xd1,
|
||||
KEY_U_KP_0 = 0xd2,
|
||||
KEY_U_KP_PERIOD = 0xd3,
|
||||
KEY_U_F11 = 0xd7,
|
||||
KEY_U_F12 = 0xd8,
|
||||
};
|
||||
|
||||
void InitializeKeyboards();
|
416
Kernel/core/panic/kbd/ps2.cpp
Normal file
416
Kernel/core/panic/kbd/ps2.cpp
Normal file
@ -0,0 +1,416 @@
|
||||
/*
|
||||
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 "ps2.hpp"
|
||||
#include "keyboard.hpp"
|
||||
|
||||
#include <interface/aip.h>
|
||||
#include <display.hpp>
|
||||
#include <convert.h>
|
||||
#include <printf.h>
|
||||
#include <kcon.hpp>
|
||||
#include <debug.h>
|
||||
#include <smp.hpp>
|
||||
#include <cpu.hpp>
|
||||
#include <io.h>
|
||||
|
||||
#if defined(a64)
|
||||
#include "../../../arch/amd64/cpu/gdt.hpp"
|
||||
#elif defined(a32)
|
||||
#elif defined(aa64)
|
||||
#endif
|
||||
|
||||
#include "../../../kernel.h"
|
||||
|
||||
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',
|
||||
'u', 'i', 'o', 'p', '[', ']', '?', '?', 'a', 's', 'd', 'f', 'g',
|
||||
'h', 'j', 'k', 'l', ';', '\'', '`', '?', '\\', 'z', 'x', 'c', 'v',
|
||||
'b', 'n', 'm', ',', '.', '/', '?', '?', '?', ' '};
|
||||
|
||||
const char sc_ascii_high[] = {'?', '?', '!', '@', '#', '$', '%', '^',
|
||||
'&', '*', '(', ')', '_', '+', '?', '?', 'Q', 'W', 'E', 'R', 'T', 'Y',
|
||||
'U', 'I', 'O', 'P', '{', '}', '?', '?', 'A', 'S', 'D', 'F', 'G',
|
||||
'H', 'J', 'K', 'L', ';', '\"', '~', '?', '|', 'Z', 'X', 'C', 'V',
|
||||
'B', 'N', 'M', '<', '>', '?', '?', '?', '?', ' '};
|
||||
|
||||
static int LowerCase = true;
|
||||
|
||||
nsa static inline int GetLetterFromScanCode(uint8_t ScanCode)
|
||||
{
|
||||
if (ScanCode & 0x80)
|
||||
{
|
||||
switch (ScanCode)
|
||||
{
|
||||
case KEY_U_LSHIFT:
|
||||
LowerCase = true;
|
||||
return KEY_INVALID;
|
||||
case KEY_U_RSHIFT:
|
||||
LowerCase = true;
|
||||
return KEY_INVALID;
|
||||
default:
|
||||
return KEY_INVALID;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (ScanCode)
|
||||
{
|
||||
case KEY_D_RETURN:
|
||||
return '\n';
|
||||
case KEY_D_LSHIFT:
|
||||
LowerCase = false;
|
||||
return KEY_INVALID;
|
||||
case KEY_D_RSHIFT:
|
||||
LowerCase = false;
|
||||
return KEY_INVALID;
|
||||
case KEY_D_BACKSPACE:
|
||||
return ScanCode;
|
||||
default:
|
||||
{
|
||||
if (ScanCode > 0x39)
|
||||
break;
|
||||
if (LowerCase)
|
||||
return sc_ascii_low[ScanCode];
|
||||
else
|
||||
return sc_ascii_high[ScanCode];
|
||||
}
|
||||
}
|
||||
}
|
||||
return KEY_INVALID;
|
||||
}
|
||||
|
||||
nsa void CrashPS2KeyboardDriver::PS2Wait(bool Output)
|
||||
{
|
||||
#if defined(a86)
|
||||
TimeoutCallNumber++;
|
||||
int timeout = 100000;
|
||||
PS2_STATUSES status = {.Raw = inb(PS2_STATUS)};
|
||||
while (timeout--)
|
||||
{
|
||||
if (!Output)
|
||||
{
|
||||
if (status.OutputBufferFull == 0)
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (status.InputBufferFull == 0)
|
||||
return;
|
||||
}
|
||||
status.Raw = inb(PS2_STATUS);
|
||||
}
|
||||
ExPrint(WARN_COLOR "PS/2 controller timeout (%s;%d)\n" DEFAULT_COLOR,
|
||||
Output ? "output" : "input", TimeoutCallNumber);
|
||||
#endif // a86
|
||||
}
|
||||
|
||||
/*
|
||||
This simple driver relies on the PS/2 controller to handle the keyboard.
|
||||
|
||||
Maybe is not the most efficient way but most x86 devices out there
|
||||
still has PS/2 support (emulated or not).
|
||||
|
||||
We even have to make sure IRQ1 is enabled in the PIC but on x64 we use
|
||||
the I/O APIC... "outb(0x21, 0b11111101);" can be used but the EOI is
|
||||
automatically sent to I/O APIC if enabled/supported which is bad.
|
||||
|
||||
FIXME: On some real devices, the PS/2 keyboard doesn't send interrupts.
|
||||
*/
|
||||
nsa CrashPS2KeyboardDriver::CrashPS2KeyboardDriver() : Interrupts::Handler(1) /* IRQ1 */
|
||||
{
|
||||
#define WaitRead PS2Wait(true)
|
||||
#define WaitWrite PS2Wait(false)
|
||||
#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. */
|
||||
ExPrint("\x1b[%d;%dH", (Display->GetWidth / CrashFontRenderer.CurrentFont->GetInfo().Width) - 2, 0);
|
||||
#if defined(a86)
|
||||
|
||||
/* Disable port 1 & 2 */
|
||||
{
|
||||
/* Disable Port 1 */
|
||||
WaitWrite;
|
||||
outb(PS2_CMD, PS2_CMD_DISABLE_PORT_1);
|
||||
|
||||
/* Disable Port 2 */
|
||||
WaitWrite;
|
||||
outb(PS2_CMD, PS2_CMD_DISABLE_PORT_2);
|
||||
}
|
||||
ExPrint(".");
|
||||
|
||||
/* Flush */
|
||||
{
|
||||
PS2_STATUSES status;
|
||||
int timeout = 0x500;
|
||||
while (timeout--)
|
||||
{
|
||||
status.Raw = inb(PS2_STATUS);
|
||||
if (status.OutputBufferFull == 0)
|
||||
break;
|
||||
inb(PS2_DATA);
|
||||
}
|
||||
|
||||
if (timeout <= 0)
|
||||
{
|
||||
SetMessageLocation;
|
||||
ExPrint(ERROR_COLOR
|
||||
"PS/2 controller timeout (flush;0)\n" DEFAULT_COLOR);
|
||||
CPU::Stop();
|
||||
}
|
||||
}
|
||||
ExPrint(".");
|
||||
|
||||
/* Test controller */
|
||||
{
|
||||
/* Save config */
|
||||
WaitWrite;
|
||||
outb(PS2_CMD, PS2_CMD_READ_CONFIG);
|
||||
WaitRead;
|
||||
PS2_CONFIGURATION cfg = {.Raw = inb(PS2_DATA)};
|
||||
cfg.Port1Interrupt = 1;
|
||||
cfg.Port2Interrupt = 1;
|
||||
cfg.Port1Translation = 1;
|
||||
|
||||
/* Update config */
|
||||
WaitWrite;
|
||||
outb(PS2_CMD, PS2_DATA);
|
||||
WaitWrite;
|
||||
outb(PS2_DATA, cfg.Raw);
|
||||
|
||||
/* Test PS/2 controller */
|
||||
WaitWrite;
|
||||
outb(PS2_CMD, PS2_CMD_TEST_CONTROLLER);
|
||||
WaitRead;
|
||||
uint8_t test = inb(PS2_DATA);
|
||||
if (test != PS2_TEST_PASSED)
|
||||
{
|
||||
if (test == PS2_ACK)
|
||||
{
|
||||
trace("PS/2 controller sent ACK to test request.");
|
||||
|
||||
WaitRead;
|
||||
test = inb(PS2_DATA);
|
||||
}
|
||||
|
||||
if (test != PS2_TEST_PASSED)
|
||||
{
|
||||
SetMessageLocation;
|
||||
ExPrint(ERROR_COLOR
|
||||
"PS/2 controller self test failed (%#x)\n" DEFAULT_COLOR,
|
||||
test);
|
||||
CPU::Stop();
|
||||
}
|
||||
}
|
||||
|
||||
/* Restore config */
|
||||
WaitWrite;
|
||||
outb(PS2_CMD, PS2_DATA);
|
||||
WaitWrite;
|
||||
outb(PS2_DATA, cfg.Raw);
|
||||
}
|
||||
ExPrint(".");
|
||||
|
||||
/* Disable scanning; Enable port 1; Set default settings */
|
||||
{
|
||||
/* Disable scanning */
|
||||
outb(PS2_DATA, PS2_KBD_CMD_DISABLE_SCANNING);
|
||||
|
||||
/* Enable Port 1 */
|
||||
WaitWrite;
|
||||
outb(PS2_CMD, PS2_CMD_ENABLE_PORT_1);
|
||||
|
||||
/* Set default settings */
|
||||
outb(PS2_DATA, PS2_KBD_CMD_DEFAULTS);
|
||||
}
|
||||
ExPrint(".");
|
||||
|
||||
/* Test port 1 */
|
||||
{
|
||||
WaitWrite;
|
||||
outb(PS2_CMD, PS2_CMD_TEST_PORT_1);
|
||||
WaitRead;
|
||||
uint8_t test = inb(PS2_DATA);
|
||||
|
||||
if (test != 0x00)
|
||||
{
|
||||
if (test == PS2_KBD_RESP_ACK)
|
||||
{
|
||||
trace("PS/2 keyboard sent ACK to test request.");
|
||||
|
||||
WaitRead;
|
||||
test = inb(PS2_DATA);
|
||||
}
|
||||
|
||||
if (test != 0x00)
|
||||
{
|
||||
SetMessageLocation;
|
||||
ExPrint(ERROR_COLOR
|
||||
"PS/2 keyboard self test failed (%#x)\n" DEFAULT_COLOR,
|
||||
test);
|
||||
CPU::Stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
ExPrint(".");
|
||||
|
||||
/* Configure the controller */
|
||||
{
|
||||
// /* Read Controller Configuration */
|
||||
// WaitWrite;
|
||||
// outb(PS2_CMD, PS2_CMD_READ_CONFIG);
|
||||
// WaitRead;
|
||||
// uint8_t cfg = inb(PS2_DATA);
|
||||
|
||||
// /* Enable Port 1 & Port 1 translation */
|
||||
// cfg |= 0b01000001;
|
||||
|
||||
// /* Write Controller Configuration */
|
||||
// WaitWrite;
|
||||
// outb(PS2_CMD, PS2_CMD_WRITE_CONFIG);
|
||||
// WaitWrite;
|
||||
// outb(PS2_DATA, cfg);
|
||||
}
|
||||
ExPrint(".");
|
||||
|
||||
/* Enable port 1; Set scan code; Enable scanning */
|
||||
{
|
||||
/* Enable Port 1 */
|
||||
outb(PS2_CMD, PS2_CMD_ENABLE_PORT_1);
|
||||
|
||||
/* Set scan code set 1 */
|
||||
WaitWrite;
|
||||
outb(PS2_DATA, PS2_KBD_CMD_SCAN_CODE_SET);
|
||||
WaitWrite;
|
||||
outb(PS2_DATA, PS2_KBD_SCAN_CODE_SET_2);
|
||||
|
||||
/* Check if we have scan code set 1 */
|
||||
WaitWrite;
|
||||
outb(PS2_DATA, PS2_KBD_CMD_SCAN_CODE_SET);
|
||||
WaitWrite;
|
||||
outb(PS2_DATA, PS2_KBD_SCAN_CODE_GET_CURRENT);
|
||||
|
||||
/* Read scan code set */
|
||||
WaitRead;
|
||||
uint8_t scs = inb(PS2_DATA);
|
||||
if (scs == PS2_KBD_RESP_ACK || scs == PS2_KBD_RESP_RESEND)
|
||||
{
|
||||
if (scs == PS2_KBD_RESP_ACK)
|
||||
trace("PS/2 keyboard sent ACK to scan code set request.");
|
||||
if (scs == PS2_KBD_RESP_RESEND)
|
||||
trace("PS/2 keyboard sent RESEND to scan code set request.");
|
||||
|
||||
WaitRead;
|
||||
scs = inb(PS2_DATA);
|
||||
}
|
||||
|
||||
if (scs != PS2_KBD_SC_SET_2)
|
||||
{
|
||||
SetMessageLocation;
|
||||
ExPrint(WARN_COLOR
|
||||
"PS/2 keyboard scan code set 1 not supported (%#x)\n" DEFAULT_COLOR,
|
||||
scs);
|
||||
}
|
||||
|
||||
/* Enable scanning */
|
||||
outb(PS2_DATA, PS2_KBD_CMD_ENABLE_SCANNING);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
WaitWrite;
|
||||
outb(PS2_CMD, PS2_CMD_READ_CONFIG);
|
||||
WaitRead;
|
||||
PS2_CONFIGURATION cfg = {.Raw = inb(PS2_DATA)};
|
||||
debug("PS2 CONFIG:\nPort1int: %d\nPort2int: %d\nSysFlg: %d\nZ: %d\nP1clk: %d\nP2clk: %d\nP1trans: %d\nz: %d",
|
||||
cfg.Port1Interrupt, cfg.Port2Interrupt, cfg.SystemFlag, cfg.Zero0, cfg.Port1Clock, cfg.Port2Clock, cfg.Port1Translation, cfg.Zero1);
|
||||
#endif
|
||||
|
||||
ExPrint(".");
|
||||
|
||||
#endif // defined(a86)
|
||||
|
||||
CPU::Interrupts(CPU::Enable);
|
||||
}
|
||||
|
||||
nsa void CrashPS2KeyboardDriver::OnInterruptReceived(CPU::TrapFrame *)
|
||||
{
|
||||
#if defined(a86)
|
||||
uint8_t scanCode = inb(PS2_DATA);
|
||||
|
||||
if (scanCode == KEY_D_TAB ||
|
||||
scanCode == KEY_D_LCTRL ||
|
||||
scanCode == KEY_D_LALT ||
|
||||
scanCode == KEY_U_LCTRL ||
|
||||
scanCode == KEY_U_LALT)
|
||||
return;
|
||||
|
||||
switch (scanCode)
|
||||
{
|
||||
case KEY_D_UP:
|
||||
case KEY_D_LEFT:
|
||||
case KEY_D_RIGHT:
|
||||
case KEY_D_DOWN:
|
||||
ArrowInput(scanCode);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
int key = GetLetterFromScanCode(scanCode);
|
||||
if (key != KEY_INVALID)
|
||||
{
|
||||
if (key == KEY_D_BACKSPACE)
|
||||
{
|
||||
if (BackSpaceLimit > 0)
|
||||
{
|
||||
char keyBuf[5] = {'\b', '\x1b', '[', 'K', '\0'};
|
||||
ExPrint(keyBuf);
|
||||
backspace(UserInputBuffer);
|
||||
BackSpaceLimit--;
|
||||
}
|
||||
}
|
||||
else if (key == '\n')
|
||||
{
|
||||
UserInput(UserInputBuffer);
|
||||
BackSpaceLimit = 0;
|
||||
UserInputBuffer[0] = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
append(UserInputBuffer, s_cst(char, key));
|
||||
char keyBuf[2] = {(char)key, '\0'};
|
||||
ExPrint(keyBuf);
|
||||
BackSpaceLimit++;
|
||||
}
|
||||
Display->UpdateBuffer(); /* Update as we type. */
|
||||
}
|
||||
#endif // a64 || a32
|
||||
}
|
35
Kernel/core/panic/kbd/ps2.hpp
Normal file
35
Kernel/core/panic/kbd/ps2.hpp
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
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/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ints.hpp>
|
||||
|
||||
class CrashPS2KeyboardDriver : public Interrupts::Handler
|
||||
{
|
||||
private:
|
||||
void PS2Wait(bool Read);
|
||||
void OnInterruptReceived(CPU::TrapFrame *Frame);
|
||||
|
||||
int BackSpaceLimit = 0;
|
||||
char UserInputBuffer[256];
|
||||
int TimeoutCallNumber = 0;
|
||||
|
||||
public:
|
||||
CrashPS2KeyboardDriver();
|
||||
~CrashPS2KeyboardDriver() = default;
|
||||
};
|
178
Kernel/core/panic/kbd/uhci.cpp
Normal file
178
Kernel/core/panic/kbd/uhci.cpp
Normal file
@ -0,0 +1,178 @@
|
||||
/*
|
||||
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 "uhci.hpp"
|
||||
|
||||
#include <interface/aip.h>
|
||||
#include <display.hpp>
|
||||
#include <convert.h>
|
||||
#include <printf.h>
|
||||
#include <kcon.hpp>
|
||||
#include <debug.h>
|
||||
#include <smp.hpp>
|
||||
#include <cpu.hpp>
|
||||
#include <io.h>
|
||||
|
||||
#if defined(a64)
|
||||
#include "../../../arch/amd64/cpu/gdt.hpp"
|
||||
#elif defined(a32)
|
||||
#elif defined(aa64)
|
||||
#endif
|
||||
|
||||
#include "../../../kernel.h"
|
||||
|
||||
using namespace KernelConsole;
|
||||
using namespace PCI;
|
||||
|
||||
#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;
|
||||
|
||||
nsa void CrashUHCIKeyboardDriver::OnInterruptReceived(CPU::TrapFrame *Frame)
|
||||
{
|
||||
}
|
||||
|
||||
__no_sanitize("undefined") nsa bool CrashUHCIKeyboardDriver::Initialize()
|
||||
{
|
||||
return false; /* FIXME: stub */
|
||||
|
||||
debug("Allocating resources");
|
||||
this->FrameList = (uint32_t *)(uintptr_t)KernelAllocator.RequestPages(TO_PAGES(1024 * sizeof(FrameList[0])));
|
||||
this->td = (TD *)KernelAllocator.RequestPages(TO_PAGES(sizeof(TD) * 32));
|
||||
memset(td, 0, sizeof(TD) * 32);
|
||||
this->qh = (QH *)KernelAllocator.RequestPages(TO_PAGES(sizeof(QH) * 8));
|
||||
memset(qh, 0, sizeof(QH) * 8);
|
||||
|
||||
/* FIXME: stub */
|
||||
|
||||
debug("Initializing controller");
|
||||
outw((uint16_t)((uintptr_t)io + 0xC0), 0x8F00); /* Disable Legacy Mode Support */
|
||||
|
||||
/* Disable All Interrupts */
|
||||
io->USBINTR.TOCRC = 0;
|
||||
io->USBINTR.RIE = 0;
|
||||
io->USBINTR.IOCE = 0;
|
||||
io->USBINTR.SPIE = 0;
|
||||
|
||||
/* Configure Frame List */
|
||||
io->FRNUM.FN = 0;
|
||||
io->FRBASEADD.BA = (uint32_t)(uintptr_t)FrameList;
|
||||
io->SOFMOD.SOFTVAL = 0b1000000;
|
||||
|
||||
io->USBSTS.raw = 0xFFFF; /* Clear USBSTS */
|
||||
|
||||
if (io->USBSTS.HCH)
|
||||
io->USBCMD.RS = 1;
|
||||
else
|
||||
{
|
||||
debug("Controller not halted, what to do?");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
nsa CrashUHCIKeyboardDriver::CrashUHCIKeyboardDriver(PCI::PCIDevice dev)
|
||||
: Interrupts::Handler(dev)
|
||||
{
|
||||
Header = (PCIDeviceHeader *)dev.Header;
|
||||
|
||||
switch (Header->HeaderType)
|
||||
{
|
||||
case 128:
|
||||
{
|
||||
ExPrint(ERROR_COLOR "Unknown header type %d! Guessing PCI Header 0\n" DEFAULT_COLOR,
|
||||
Header->HeaderType);
|
||||
[[fallthrough]];
|
||||
}
|
||||
case 0: /* PCI Header 0 */
|
||||
{
|
||||
PCI::PCIHeader0 *hdr = (PCI::PCIHeader0 *)Header;
|
||||
|
||||
uint32_t BAR[6];
|
||||
size_t BARsSize[6];
|
||||
|
||||
BAR[0] = hdr->BAR0;
|
||||
BAR[1] = hdr->BAR1;
|
||||
BAR[2] = hdr->BAR2;
|
||||
BAR[3] = hdr->BAR3;
|
||||
BAR[4] = hdr->BAR4;
|
||||
BAR[5] = hdr->BAR5;
|
||||
|
||||
/* BARs Size */
|
||||
for (short i = 0; i < 6; i++)
|
||||
{
|
||||
if (BAR[i] == 0)
|
||||
continue;
|
||||
|
||||
size_t size;
|
||||
if ((BAR[i] & 1) == 0) /* Memory Base */
|
||||
{
|
||||
hdr->BAR0 = 0xFFFFFFFF;
|
||||
size = hdr->BAR0;
|
||||
hdr->BAR0 = BAR[i];
|
||||
BARsSize[i] = size & (~15);
|
||||
BARsSize[i] = ~BARsSize[i] + 1;
|
||||
BARsSize[i] = BARsSize[i] & 0xFFFFFFFF;
|
||||
debug("MEM BAR%d %#lx size: %d",
|
||||
i, BAR[i], BARsSize[i]);
|
||||
}
|
||||
else if ((BAR[i] & 1) == 1) /* I/O Base */
|
||||
{
|
||||
hdr->BAR1 = 0xFFFFFFFF;
|
||||
size = hdr->BAR1;
|
||||
hdr->BAR1 = BAR[i];
|
||||
BARsSize[i] = size & (~3);
|
||||
BARsSize[i] = ~BARsSize[i] + 1;
|
||||
BARsSize[i] = BARsSize[i] & 0xFFFF;
|
||||
debug("I/O BAR%d %#lx size: %d",
|
||||
i, BAR[i], BARsSize[i]);
|
||||
}
|
||||
}
|
||||
|
||||
uintptr_t baseAddress = BAR[4];
|
||||
|
||||
assert(baseAddress & 0x1); /* must be I/O */
|
||||
|
||||
debug("baseAddress: %#lx size %#lx", baseAddress, BARsSize[4]);
|
||||
Memory::Virtual vmm;
|
||||
vmm.Map((void *)baseAddress, (void *)baseAddress, BARsSize[4], Memory::RW);
|
||||
io = (IORegisters *)baseAddress;
|
||||
|
||||
break;
|
||||
}
|
||||
case 1: /* PCI Header 1 (PCI-to-PCI Bridge) */
|
||||
{
|
||||
ExPrint(ERROR_COLOR "PCI-to-PCI Bridge not supported\n" DEFAULT_COLOR);
|
||||
break;
|
||||
}
|
||||
case 2: /* PCI Header 2 (PCI-to-CardBus Bridge) */
|
||||
{
|
||||
ExPrint(ERROR_COLOR "PCI-to-CardBus Bridge not supported\n" DEFAULT_COLOR);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
ExPrint(ERROR_COLOR "Invalid PCI header type\n" DEFAULT_COLOR);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
215
Kernel/core/panic/kbd/uhci.hpp
Normal file
215
Kernel/core/panic/kbd/uhci.hpp
Normal file
@ -0,0 +1,215 @@
|
||||
/*
|
||||
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/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ints.hpp>
|
||||
|
||||
class CrashUHCIKeyboardDriver : public Interrupts::Handler
|
||||
{
|
||||
public:
|
||||
struct IORegisters
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint16_t RS : 1;
|
||||
uint16_t HCRESET : 1;
|
||||
uint16_t GRESET : 1;
|
||||
uint16_t EGSM : 1;
|
||||
uint16_t FGR : 1;
|
||||
uint16_t SWDBG : 1;
|
||||
uint16_t CF : 1;
|
||||
uint16_t MAXP : 1;
|
||||
uint16_t __reserved0 : 8;
|
||||
} __packed;
|
||||
uint16_t raw;
|
||||
} USBCMD;
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint16_t USBINT : 1;
|
||||
uint16_t USBERRINT : 1;
|
||||
uint16_t RD : 1;
|
||||
uint16_t HSE : 1;
|
||||
uint16_t HCPE : 1;
|
||||
uint16_t HCH : 1;
|
||||
uint16_t __reserved0 : 10;
|
||||
} __packed;
|
||||
uint16_t raw;
|
||||
} USBSTS;
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint16_t TOCRC : 1;
|
||||
uint16_t RIE : 1;
|
||||
uint16_t IOCE : 1;
|
||||
uint16_t SPIE : 1;
|
||||
uint16_t __reserved0 : 12;
|
||||
} __packed;
|
||||
uint16_t raw;
|
||||
} USBINTR;
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint16_t FN : 9;
|
||||
uint16_t __reserved0 : 7;
|
||||
} __packed;
|
||||
uint16_t raw;
|
||||
} FRNUM;
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint32_t __reserved0 : 12;
|
||||
uint32_t BA : 20;
|
||||
} __packed;
|
||||
uint32_t raw;
|
||||
} FRBASEADD;
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint8_t SOFTVAL : 7;
|
||||
uint8_t __reserved0 : 1;
|
||||
} __packed;
|
||||
uint8_t raw;
|
||||
} SOFMOD;
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint16_t CCS : 1;
|
||||
uint16_t CSC : 1;
|
||||
uint16_t PE : 1;
|
||||
uint16_t PEC : 1;
|
||||
uint16_t LS : 1;
|
||||
uint16_t RD : 1;
|
||||
uint16_t __reserved0 : 1; // always 1
|
||||
uint16_t LSDA : 1;
|
||||
uint16_t PR : 1;
|
||||
uint16_t __reserved1 : 2;
|
||||
uint16_t SUS : 1;
|
||||
uint16_t __reserved2 : 4;
|
||||
} __packed;
|
||||
uint16_t raw;
|
||||
} PORTSC[2];
|
||||
} __packed;
|
||||
|
||||
struct TD
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint32_t T : 1;
|
||||
uint32_t Q : 1;
|
||||
uint32_t Vf : 1;
|
||||
uint32_t __reserved0 : 1;
|
||||
uint32_t LP : 28;
|
||||
} __packed;
|
||||
uint32_t raw;
|
||||
} LINK;
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint32_t ActLen : 11;
|
||||
uint32_t __reserved0 : 5;
|
||||
uint32_t STATUS : 8;
|
||||
uint32_t IOC : 1;
|
||||
uint32_t IOS : 1;
|
||||
uint32_t LS : 1;
|
||||
uint32_t unknown_0 : 2; /* missing in the spec @ 3.2.2 */
|
||||
uint32_t SPD : 1;
|
||||
uint32_t __reserved1 : 2;
|
||||
} __packed;
|
||||
uint32_t raw;
|
||||
} CS;
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint32_t PID : 8;
|
||||
uint32_t DeviceAddress : 6;
|
||||
uint32_t EndPt : 4;
|
||||
uint32_t D : 1;
|
||||
uint32_t __reserved0 : 1;
|
||||
uint32_t MaxLen : 11;
|
||||
} __packed;
|
||||
uint32_t raw;
|
||||
} TOKEN;
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint32_t Addr : 32;
|
||||
} __packed;
|
||||
uint32_t raw;
|
||||
} BUFFER;
|
||||
|
||||
/* The last 4 DWords of the
|
||||
Transfer Descriptor are
|
||||
reserved for use by software.
|
||||
- UHCI Design Guide 1.1 @ 3.2.5
|
||||
*/
|
||||
|
||||
uint32_t __padding[4];
|
||||
} *td __aligned(16) __packed;
|
||||
|
||||
struct QH
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint32_t T : 1;
|
||||
uint32_t Q : 1;
|
||||
uint32_t __reserved0 : 2; /* must be 0 */
|
||||
uint32_t QHLP : 28;
|
||||
} __packed;
|
||||
uint32_t raw;
|
||||
} HEAD;
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint32_t T : 1;
|
||||
uint32_t Q : 1;
|
||||
uint32_t __reserved0 : 1;
|
||||
uint32_t __reserved1 : 1; /* must be 0 */
|
||||
uint32_t QELP : 28;
|
||||
} __packed;
|
||||
uint32_t raw;
|
||||
} ELEMENT;
|
||||
|
||||
/* FIXME: It is the same with TD? */
|
||||
} *qh __aligned(16) __packed;
|
||||
|
||||
PCI::PCIDeviceHeader *Header = nullptr;
|
||||
IORegisters *io = nullptr;
|
||||
uint32_t *FrameList = nullptr;
|
||||
|
||||
void OnInterruptReceived(CPU::TrapFrame *Frame);
|
||||
bool Initialize();
|
||||
CrashUHCIKeyboardDriver(PCI::PCIDevice dev);
|
||||
~CrashUHCIKeyboardDriver() = default;
|
||||
};
|
204
Kernel/core/panic/kbd/xhci.cpp
Normal file
204
Kernel/core/panic/kbd/xhci.cpp
Normal file
@ -0,0 +1,204 @@
|
||||
/*
|
||||
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 "xhci.hpp"
|
||||
|
||||
#include <interface/aip.h>
|
||||
#include <display.hpp>
|
||||
#include <convert.h>
|
||||
#include <printf.h>
|
||||
#include <kcon.hpp>
|
||||
#include <debug.h>
|
||||
#include <smp.hpp>
|
||||
#include <cpu.hpp>
|
||||
#include <io.h>
|
||||
|
||||
#if defined(a64)
|
||||
#include "../../../arch/amd64/cpu/gdt.hpp"
|
||||
#elif defined(a32)
|
||||
#elif defined(aa64)
|
||||
#endif
|
||||
|
||||
#include "../../../kernel.h"
|
||||
|
||||
using namespace KernelConsole;
|
||||
using namespace PCI;
|
||||
|
||||
#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;
|
||||
|
||||
nsa bool CrashXHCIKeyboardDriver::TakeOwnership()
|
||||
{
|
||||
HCExtCap *exCap = (HCExtCap *)(uintptr_t)this->ExtendedCaps;
|
||||
|
||||
if (exCap->USBLEGSUP.CapID != 1)
|
||||
return true;
|
||||
|
||||
if (exCap->USBLEGSUP.BIOSOwnsHC == 0)
|
||||
return true;
|
||||
|
||||
exCap->USBLEGSUP.OSOwnsHC = 1;
|
||||
TimeManager->Sleep(200, Time::Milliseconds);
|
||||
if (exCap->USBLEGSUP.BIOSOwnsHC == 0)
|
||||
return true;
|
||||
|
||||
ExPrint(ERROR_COLOR "BIOS owns the USB controller\n" DEFAULT_COLOR);
|
||||
return false;
|
||||
}
|
||||
|
||||
nsa bool CrashXHCIKeyboardDriver::Initialize()
|
||||
{
|
||||
int timeout = 10;
|
||||
|
||||
if (!TakeOwnership())
|
||||
{
|
||||
ExPrint(ERROR_COLOR "Failed to take ownership\n" DEFAULT_COLOR);
|
||||
return false;
|
||||
}
|
||||
|
||||
stub;
|
||||
return false; /* FIXME: stub */
|
||||
}
|
||||
|
||||
nsa CrashXHCIKeyboardDriver::CrashXHCIKeyboardDriver(PCIDevice xhci)
|
||||
: Interrupts::Handler(xhci)
|
||||
{
|
||||
Header = (PCIDeviceHeader *)xhci.Header;
|
||||
|
||||
switch (Header->HeaderType)
|
||||
{
|
||||
case 128:
|
||||
{
|
||||
ExPrint(ERROR_COLOR "Unknown header type %d! Guessing PCI Header 0\n" DEFAULT_COLOR,
|
||||
Header->HeaderType);
|
||||
[[fallthrough]];
|
||||
}
|
||||
case 0: /* PCI Header 0 */
|
||||
{
|
||||
PCI::PCIHeader0 *hdr = (PCI::PCIHeader0 *)Header;
|
||||
|
||||
uint32_t BAR[6];
|
||||
size_t BARsSize[6];
|
||||
|
||||
BAR[0] = hdr->BAR0;
|
||||
BAR[1] = hdr->BAR1;
|
||||
BAR[2] = hdr->BAR2;
|
||||
BAR[3] = hdr->BAR3;
|
||||
BAR[4] = hdr->BAR4;
|
||||
BAR[5] = hdr->BAR5;
|
||||
|
||||
/* BARs Size */
|
||||
for (short i = 0; i < 6; i++)
|
||||
{
|
||||
if (BAR[i] == 0)
|
||||
continue;
|
||||
|
||||
size_t size;
|
||||
if ((BAR[i] & 1) == 0) /* Memory Base */
|
||||
{
|
||||
hdr->BAR0 = 0xFFFFFFFF;
|
||||
size = hdr->BAR0;
|
||||
hdr->BAR0 = BAR[i];
|
||||
BARsSize[i] = size & (~15);
|
||||
BARsSize[i] = ~BARsSize[i] + 1;
|
||||
BARsSize[i] = BARsSize[i] & 0xFFFFFFFF;
|
||||
debug("MEM BAR%d %#lx size: %d",
|
||||
i, BAR[i], BARsSize[i]);
|
||||
}
|
||||
else if ((BAR[i] & 1) == 1) /* I/O Base */
|
||||
{
|
||||
hdr->BAR1 = 0xFFFFFFFF;
|
||||
size = hdr->BAR1;
|
||||
hdr->BAR1 = BAR[i];
|
||||
BARsSize[i] = size & (~3);
|
||||
BARsSize[i] = ~BARsSize[i] + 1;
|
||||
BARsSize[i] = BARsSize[i] & 0xFFFF;
|
||||
debug("IO BAR%d %#lx size: %d",
|
||||
i, BAR[i], BARsSize[i]);
|
||||
}
|
||||
}
|
||||
|
||||
debug("IO %d 64-BIT %d", BAR[0] & 0x1, BAR[0] & 0x4);
|
||||
|
||||
uintptr_t baseAddress = BAR[0];
|
||||
if (BAR[0] & 0x4)
|
||||
baseAddress |= (uintptr_t)BAR[1] << 32;
|
||||
|
||||
if (baseAddress & 0x1)
|
||||
baseAddress &= 0xFFFFFFFFFFFFFFFC;
|
||||
else
|
||||
baseAddress &= 0xFFFFFFFFFFFFFFF0;
|
||||
|
||||
debug("baseAddress: %#lx", baseAddress);
|
||||
Memory::Virtual vmm;
|
||||
vmm.Map((void *)baseAddress, (void *)baseAddress, BARsSize[0], Memory::RW);
|
||||
caps = (XHCIcap *)baseAddress;
|
||||
ops = (XHCIop *)(baseAddress + caps->CAPLENGTH);
|
||||
port = (XHCIport *)(baseAddress + caps->CAPLENGTH + 0x400);
|
||||
runtime = (XHCIruntime *)(baseAddress + (caps->RTSOFF & ~0x1F));
|
||||
doorbell = (XHCIdoorbell *)(baseAddress + (caps->DBOFF & ~0x3));
|
||||
uint16_t exCapOffset = caps->HCCPARAMS1.xHCIExtendedCapacitiesPointer << 2;
|
||||
ExtendedCaps = (uintptr_t)caps + exCapOffset;
|
||||
debug("ExtendedCaps: %#lx (%#lx + %#lx)", ExtendedCaps, caps, exCapOffset);
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Waddress-of-packed-member"
|
||||
Interrupter = &runtime->Interrupter[0];
|
||||
#pragma GCC diagnostic pop
|
||||
break;
|
||||
}
|
||||
case 1: /* PCI Header 1 (PCI-to-PCI Bridge) */
|
||||
{
|
||||
ExPrint(ERROR_COLOR "PCI-to-PCI Bridge not supported\n" DEFAULT_COLOR);
|
||||
break;
|
||||
}
|
||||
case 2: /* PCI Header 2 (PCI-to-CardBus Bridge) */
|
||||
{
|
||||
ExPrint(ERROR_COLOR "PCI-to-CardBus Bridge not supported\n" DEFAULT_COLOR);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
ExPrint(ERROR_COLOR "Invalid PCI header type\n" DEFAULT_COLOR);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsa void CrashXHCIKeyboardDriver::OnInterruptReceived(CPU::TrapFrame *Frame)
|
||||
{
|
||||
debug("Interrupt received");
|
||||
|
||||
Interrupter->IMAN.IP = 1;
|
||||
|
||||
if (!ops->USBSTS.EINT)
|
||||
debug("!USBSTS.EINT");
|
||||
// return;
|
||||
|
||||
ops->USBSTS.EINT = 1;
|
||||
|
||||
stub;
|
||||
|
||||
Interrupter->IMAN.IP = 0;
|
||||
ops->USBSTS.EINT = 0;
|
||||
}
|
257
Kernel/core/panic/kbd/xhci.hpp
Normal file
257
Kernel/core/panic/kbd/xhci.hpp
Normal file
@ -0,0 +1,257 @@
|
||||
/*
|
||||
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/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ints.hpp>
|
||||
|
||||
class CrashXHCIKeyboardDriver : public Interrupts::Handler
|
||||
{
|
||||
private:
|
||||
struct XHCIcap
|
||||
{
|
||||
uint8_t CAPLENGTH;
|
||||
uint8_t __reserved0;
|
||||
uint16_t HCIVERSION;
|
||||
uint32_t HCSPARAMS1;
|
||||
uint32_t HCSPARAMS2;
|
||||
uint32_t HCSPARAMS3;
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint32_t AC64 : 1;
|
||||
uint32_t BNC : 1;
|
||||
uint32_t CSZ : 1;
|
||||
uint32_t PPC : 1;
|
||||
uint32_t PIND : 1;
|
||||
uint32_t LHRC : 1;
|
||||
uint32_t LTC : 1;
|
||||
uint32_t NSS : 1;
|
||||
uint32_t PAE : 1;
|
||||
uint32_t SPC : 1;
|
||||
uint32_t SEC : 1;
|
||||
uint32_t CFC : 1;
|
||||
uint32_t MaxPSASize : 4;
|
||||
uint32_t xHCIExtendedCapacitiesPointer : 16;
|
||||
|
||||
} __packed;
|
||||
uint32_t raw;
|
||||
} HCCPARAMS1;
|
||||
uint32_t DBOFF;
|
||||
uint32_t RTSOFF;
|
||||
uint32_t HCCPARAMS2;
|
||||
} *caps __packed;
|
||||
|
||||
struct XHCIop
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint32_t RS : 1;
|
||||
uint32_t HCRST : 1;
|
||||
uint32_t INTE : 1;
|
||||
uint32_t HSEE : 1;
|
||||
uint32_t __reserved0 : 3;
|
||||
uint32_t LHCRST : 1;
|
||||
uint32_t CSS : 1;
|
||||
uint32_t CRS : 1;
|
||||
uint32_t EWE : 1;
|
||||
uint32_t EU3S : 1;
|
||||
uint32_t __reserved1 : 1;
|
||||
uint32_t CME : 1;
|
||||
uint32_t ETE : 1;
|
||||
uint32_t TSCEN : 1;
|
||||
uint32_t VTIOEN : 1;
|
||||
uint32_t __reserved2 : 15;
|
||||
} __packed;
|
||||
uint32_t raw;
|
||||
} USBCMD;
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
|
||||
uint32_t HCH : 1;
|
||||
uint32_t __reserved0 : 1;
|
||||
uint32_t HSE : 1;
|
||||
uint32_t EINT : 1;
|
||||
uint32_t PCB : 1;
|
||||
uint32_t __reserved1 : 3;
|
||||
uint32_t SSS : 1;
|
||||
uint32_t RSS : 1;
|
||||
uint32_t SRE : 1;
|
||||
uint32_t CNR : 1;
|
||||
uint32_t HCE : 1;
|
||||
uint32_t __reserved2 : 18;
|
||||
} __packed;
|
||||
uint32_t raw;
|
||||
} USBSTS;
|
||||
uint32_t PAGESIZE;
|
||||
uint8_t __reserved0[8];
|
||||
uint32_t DNCTRL;
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint64_t RCS : 1;
|
||||
uint64_t CS : 1;
|
||||
uint64_t CA : 1;
|
||||
uint64_t CRR : 1;
|
||||
uint64_t __reserved0 : 2;
|
||||
uint64_t CRP : 58;
|
||||
} __packed;
|
||||
uint64_t raw;
|
||||
} CRCR;
|
||||
uint8_t __reserved1[16];
|
||||
uint64_t DCBAAP;
|
||||
uint32_t CONFIG;
|
||||
} *ops __packed;
|
||||
|
||||
struct XHCIport
|
||||
{
|
||||
uint32_t PORTSC;
|
||||
uint32_t PORTMSC;
|
||||
uint32_t PORTLI;
|
||||
uint32_t PORTHLPMC;
|
||||
} *port __packed;
|
||||
|
||||
struct XHCIruntime
|
||||
{
|
||||
uint32_t MFINDEX;
|
||||
uint32_t __reserved0[7];
|
||||
struct XHCIinterrupter
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint32_t IP : 1;
|
||||
uint32_t IE : 1;
|
||||
uint32_t __reserved0 : 30;
|
||||
} __packed;
|
||||
uint32_t raw;
|
||||
} IMAN;
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint32_t IMODI : 16;
|
||||
uint32_t IMODC : 16;
|
||||
} __packed;
|
||||
uint32_t raw;
|
||||
} IMOD;
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint32_t ERSTSZ : 16;
|
||||
uint32_t __reserved0 : 16;
|
||||
} __packed;
|
||||
uint32_t raw;
|
||||
} ERSTSZ;
|
||||
uint32_t __reserved;
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint64_t __reserved0 : 6;
|
||||
uint64_t ERSTBAR : 58;
|
||||
} __packed;
|
||||
uint64_t raw;
|
||||
} ERSTBA;
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint64_t DESI : 3;
|
||||
uint64_t EHB : 1;
|
||||
uint64_t ERDP : 60;
|
||||
} __packed;
|
||||
uint64_t raw;
|
||||
} ERDP;
|
||||
} Interrupter[] __packed;
|
||||
} *runtime __packed;
|
||||
|
||||
union XHCIdoorbell
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint32_t DBTarget : 8;
|
||||
uint32_t __reserved : 8;
|
||||
uint32_t DBTaskID : 16;
|
||||
} __packed;
|
||||
uint32_t raw;
|
||||
} *doorbell;
|
||||
|
||||
struct HCExtCap
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint32_t CapID : 8;
|
||||
uint32_t NextCapPtr : 8;
|
||||
uint32_t BIOSOwnsHC : 1;
|
||||
uint32_t __reserved0 : 7;
|
||||
uint32_t OSOwnsHC : 1;
|
||||
uint32_t __reserved1 : 7;
|
||||
} __packed;
|
||||
uint32_t raw;
|
||||
} USBLEGSUP;
|
||||
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint32_t unknown : 32;
|
||||
} __packed;
|
||||
uint32_t raw;
|
||||
} USBLEGCTLSTS;
|
||||
} __packed;
|
||||
|
||||
struct XHCIprotocol
|
||||
{
|
||||
uint8_t CAPID;
|
||||
uint8_t NextCapPtr;
|
||||
uint8_t RevisionMinor;
|
||||
uint8_t RevisionMajor;
|
||||
uint8_t Name[4];
|
||||
uint8_t CompPortOffset;
|
||||
uint8_t CompPortCount;
|
||||
uint16_t ProtocolDefined : 12;
|
||||
uint8_t PSIC : 4;
|
||||
uint8_t ProtocolSlotType : 4;
|
||||
uint32_t __reserved0 : 28;
|
||||
} __packed;
|
||||
|
||||
PCI::PCIDeviceHeader *Header = nullptr;
|
||||
uintptr_t ExtendedCaps = 0;
|
||||
void *baseAddrArray = nullptr;
|
||||
std::vector<XHCIprotocol *> Protocols = {};
|
||||
XHCIruntime::XHCIinterrupter *Interrupter = nullptr;
|
||||
|
||||
void OnInterruptReceived(CPU::TrapFrame *Frame);
|
||||
bool TakeOwnership();
|
||||
|
||||
public:
|
||||
bool Initialize();
|
||||
|
||||
CrashXHCIKeyboardDriver(PCI::PCIDevice dev);
|
||||
~CrashXHCIKeyboardDriver() {}
|
||||
};
|
1072
Kernel/core/panic/ui.cpp
Normal file
1072
Kernel/core/panic/ui.cpp
Normal file
File diff suppressed because it is too large
Load Diff
166
Kernel/core/panic/user.cpp
Normal file
166
Kernel/core/panic/user.cpp
Normal file
@ -0,0 +1,166 @@
|
||||
/*
|
||||
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 <display.hpp>
|
||||
#include <printf.h>
|
||||
#include <debug.h>
|
||||
#include <smp.hpp>
|
||||
#include <cpu.hpp>
|
||||
|
||||
#if defined(a64)
|
||||
#include "../../arch/amd64/cpu/gdt.hpp"
|
||||
#elif defined(a32)
|
||||
#elif defined(aa64)
|
||||
#endif
|
||||
|
||||
#include "../../kernel.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
nsa void dbgPrint(CPU::ExceptionFrame *Frame)
|
||||
{
|
||||
#if defined(a64)
|
||||
debug("FS=%#lx GS=%#lx SS=%#lx CS=%#lx DS=%#lx", Frame->fs, Frame->gs, Frame->ss, Frame->cs, Frame->ds);
|
||||
debug("R8=%#lx R9=%#lx R10=%#lx R11=%#lx", Frame->r8, Frame->r9, Frame->r10, Frame->r11);
|
||||
debug("R12=%#lx R13=%#lx R14=%#lx R15=%#lx", Frame->r12, Frame->r13, Frame->r14, Frame->r15);
|
||||
debug("RAX=%#lx RBX=%#lx RCX=%#lx RDX=%#lx", Frame->rax, Frame->rbx, Frame->rcx, Frame->rdx);
|
||||
debug("RSI=%#lx RDI=%#lx RBP=%#lx RSP=%#lx", Frame->rsi, Frame->rdi, Frame->rbp, Frame->rsp);
|
||||
debug("RIP=%#lx RFL=%#lx INT=%#lx ERR=%#lx", Frame->rip, Frame->rflags.raw, Frame->InterruptNumber, Frame->ErrorCode);
|
||||
#elif defined(a32)
|
||||
debug("FS=%#x GS=%#x CS=%#x DS=%#x", Frame->fs, Frame->gs, Frame->cs, Frame->ds);
|
||||
debug("EAX=%#x EBX=%#x ECX=%#x EDX=%#x", Frame->eax, Frame->ebx, Frame->ecx, Frame->edx);
|
||||
debug("ESI=%#x EDI=%#x EBP=%#x ESP=%#x", Frame->esi, Frame->edi, Frame->ebp, Frame->esp);
|
||||
debug("EIP=%#x EFL=%#x INT=%#x ERR=%#x", Frame->eip, Frame->eflags.raw, Frame->InterruptNumber, Frame->ErrorCode);
|
||||
#elif defined(aa64)
|
||||
#endif
|
||||
|
||||
#if defined(a86)
|
||||
debug("CR2=%#lx CR3=%#lx", Frame->cr2, Frame->cr3);
|
||||
#endif // defined(a86)
|
||||
|
||||
#if defined(a64)
|
||||
debug("RFL: CF:%s PF:%s AF:%s ZF:%s SF:%s TF:%s IF:%s DF:%s OF:%s IOPL:%s NT:%s RF:%s VM:%s AC:%s VIF:%s VIP:%s ID:%s AlwaysOne:%d R0:%#x R1:%#x R2:%#x R3:%#x",
|
||||
Frame->rflags.CF ? "True " : "False", Frame->rflags.PF ? "True " : "False", Frame->rflags.AF ? "True " : "False", Frame->rflags.ZF ? "True " : "False",
|
||||
Frame->rflags.SF ? "True " : "False", Frame->rflags.TF ? "True " : "False", Frame->rflags.IF ? "True " : "False", Frame->rflags.DF ? "True " : "False",
|
||||
Frame->rflags.OF ? "True " : "False", Frame->rflags.IOPL ? "True " : "False", Frame->rflags.NT ? "True " : "False", Frame->rflags.RF ? "True " : "False",
|
||||
Frame->rflags.VM ? "True " : "False", Frame->rflags.AC ? "True " : "False", Frame->rflags.VIF ? "True " : "False", Frame->rflags.VIP ? "True " : "False",
|
||||
Frame->rflags.ID ? "True " : "False", Frame->rflags.AlwaysOne,
|
||||
Frame->rflags.Reserved0, Frame->rflags.Reserved1, Frame->rflags.Reserved2, Frame->rflags.Reserved3);
|
||||
#elif defined(a32)
|
||||
debug("EFL: CF:%s PF:%s AF:%s ZF:%s SF:%s TF:%s IF:%s DF:%s OF:%s IOPL:%s NT:%s RF:%s VM:%s AC:%s VIF:%s VIP:%s ID:%s AlwaysOne:%d R0:%#x R1:%#x R2:%#x",
|
||||
Frame->eflags.CF ? "True " : "False", Frame->eflags.PF ? "True " : "False", Frame->eflags.AF ? "True " : "False", Frame->eflags.ZF ? "True " : "False",
|
||||
Frame->eflags.SF ? "True " : "False", Frame->eflags.TF ? "True " : "False", Frame->eflags.IF ? "True " : "False", Frame->eflags.DF ? "True " : "False",
|
||||
Frame->eflags.OF ? "True " : "False", Frame->eflags.IOPL ? "True " : "False", Frame->eflags.NT ? "True " : "False", Frame->eflags.RF ? "True " : "False",
|
||||
Frame->eflags.VM ? "True " : "False", Frame->eflags.AC ? "True " : "False", Frame->eflags.VIF ? "True " : "False", Frame->eflags.VIP ? "True " : "False",
|
||||
Frame->eflags.ID ? "True " : "False", Frame->eflags.AlwaysOne,
|
||||
Frame->eflags.Reserved0, Frame->eflags.Reserved1, Frame->eflags.Reserved2);
|
||||
#elif defined(aa64)
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
nsa bool UserModeExceptionHandler(CPU::ExceptionFrame *Frame)
|
||||
{
|
||||
CPUData *core = GetCurrentCPU();
|
||||
Tasking::PCB *proc = core->CurrentProcess;
|
||||
Tasking::TCB *thread = core->CurrentThread;
|
||||
debug("Current process %s(%d) and thread %s(%d)",
|
||||
proc->Name, proc->ID, thread->Name, thread->ID);
|
||||
thread->SetState(Tasking::Waiting);
|
||||
|
||||
#ifdef DEBUG
|
||||
dbgPrint(Frame);
|
||||
#endif
|
||||
|
||||
int sigRet = -1;
|
||||
switch (Frame->InterruptNumber)
|
||||
{
|
||||
case CPU::x86::PageFault:
|
||||
{
|
||||
bool Handled = proc->vma->HandleCoW(Frame->cr2);
|
||||
if (!Handled)
|
||||
Handled = thread->Stack->Expand(Frame->cr2);
|
||||
|
||||
if (likely(Handled))
|
||||
{
|
||||
debug("Page fault handled");
|
||||
Frame->cr2 = 0;
|
||||
thread->SetState(Tasking::Ready);
|
||||
return true;
|
||||
}
|
||||
|
||||
sigRet = proc->Signals.SendSignal(SIGSEGV,
|
||||
{Tasking::KILL_CRASH});
|
||||
break;
|
||||
}
|
||||
case CPU::x86::Debug:
|
||||
case CPU::x86::Breakpoint:
|
||||
{
|
||||
sigRet = proc->Signals.SendSignal(SIGTRAP,
|
||||
{Tasking::KILL_CRASH});
|
||||
break;
|
||||
}
|
||||
case CPU::x86::DivideByZero:
|
||||
case CPU::x86::Overflow:
|
||||
case CPU::x86::BoundRange:
|
||||
case CPU::x86::x87FloatingPoint:
|
||||
case CPU::x86::SIMDFloatingPoint:
|
||||
{
|
||||
sigRet = proc->Signals.SendSignal(SIGFPE,
|
||||
{Tasking::KILL_CRASH});
|
||||
break;
|
||||
}
|
||||
case CPU::x86::InvalidOpcode:
|
||||
case CPU::x86::GeneralProtectionFault:
|
||||
{
|
||||
sigRet = proc->Signals.SendSignal(SIGILL,
|
||||
{Tasking::KILL_CRASH});
|
||||
break;
|
||||
}
|
||||
case CPU::x86::DeviceNotAvailable:
|
||||
{
|
||||
sigRet = proc->Signals.SendSignal(SIGBUS,
|
||||
{Tasking::KILL_CRASH});
|
||||
break;
|
||||
}
|
||||
case CPU::x86::NonMaskableInterrupt:
|
||||
case CPU::x86::DoubleFault:
|
||||
case CPU::x86::CoprocessorSegmentOverrun:
|
||||
case CPU::x86::InvalidTSS:
|
||||
case CPU::x86::SegmentNotPresent:
|
||||
case CPU::x86::StackSegmentFault:
|
||||
case CPU::x86::AlignmentCheck:
|
||||
case CPU::x86::MachineCheck:
|
||||
case CPU::x86::Virtualization:
|
||||
case CPU::x86::Security:
|
||||
default:
|
||||
{
|
||||
error("Unhandled exception %d on CPU %d",
|
||||
Frame->InterruptNumber, core->ID);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (sigRet == 0)
|
||||
{
|
||||
trace("User mode exception handler handled");
|
||||
thread->SetState(Tasking::Ready);
|
||||
return true;
|
||||
}
|
||||
|
||||
error("User mode exception handler failed");
|
||||
return false;
|
||||
}
|
Reference in New Issue
Block a user