mirror of
https://github.com/Fennix-Project/Kernel.git
synced 2025-07-03 19:39:18 +00:00
Refactor filesystem & stl code
This commit is contained in:
172
core/console.cpp
Normal file
172
core/console.cpp
Normal file
@ -0,0 +1,172 @@
|
||||
/*
|
||||
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 <filesystem/ioctl.hpp>
|
||||
#include <memory.hpp>
|
||||
#include <stropts.h>
|
||||
#include <string.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)
|
||||
{
|
||||
switch (Request)
|
||||
{
|
||||
case TCGETS:
|
||||
{
|
||||
struct termios *t = (struct termios *)Argp;
|
||||
memcpy(t, &term, sizeof(struct termios));
|
||||
return 0;
|
||||
}
|
||||
case TCSETS:
|
||||
{
|
||||
debug("TCSETS not supported");
|
||||
return -EINVAL;
|
||||
|
||||
struct termios *t = (struct termios *)Argp;
|
||||
memcpy(&term, t, sizeof(struct termios));
|
||||
return 0;
|
||||
}
|
||||
case TIOCGPGRP:
|
||||
{
|
||||
*((pid_t *)Argp) = 0;
|
||||
return 0;
|
||||
}
|
||||
case TIOCSPGRP:
|
||||
{
|
||||
*((pid_t *)Argp) = 0;
|
||||
return 0;
|
||||
}
|
||||
case TIOCGWINSZ:
|
||||
{
|
||||
struct winsize *ws = (struct winsize *)Argp;
|
||||
memcpy(ws, &termSize, sizeof(struct winsize));
|
||||
return 0;
|
||||
}
|
||||
case TIOCSWINSZ:
|
||||
{
|
||||
debug("TIOCSWINSZ not supported");
|
||||
return -EINVAL;
|
||||
|
||||
struct winsize *ws = (struct winsize *)Argp;
|
||||
memcpy(&termSize, ws, sizeof(struct winsize));
|
||||
return 0;
|
||||
}
|
||||
case TCSETSW:
|
||||
case TCSETSF:
|
||||
case TCGETA:
|
||||
case TCSETA:
|
||||
case TCSETAW:
|
||||
case TCSETAF:
|
||||
case TCSBRK:
|
||||
case TCXONC:
|
||||
case TCFLSH:
|
||||
case TIOCEXCL:
|
||||
case TIOCNXCL:
|
||||
case TIOCSCTTY:
|
||||
case TIOCOUTQ:
|
||||
case TIOCSTI:
|
||||
case TIOCMGET:
|
||||
case TIOCMBIS:
|
||||
case TIOCMBIC:
|
||||
case TIOCMSET:
|
||||
{
|
||||
fixme("ioctl %#lx not implemented", Request);
|
||||
return -ENOSYS;
|
||||
}
|
||||
case TIOCGPTN:
|
||||
case 0xffffffff80045430: /* FIXME: ???? */
|
||||
{
|
||||
fixme("stub ioctl %#lx", Request);
|
||||
|
||||
int *n = (int *)Argp;
|
||||
*n = -1;
|
||||
break;
|
||||
}
|
||||
case TIOCSPTLCK:
|
||||
{
|
||||
fixme("stub ioctl %#lx", Request);
|
||||
|
||||
int *n = (int *)Argp;
|
||||
*n = 0;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
debug("Unknown ioctl %#lx", Request);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void EarlyInit()
|
||||
{
|
||||
/*
|
||||
- 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)
|
||||
*/
|
||||
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 */
|
||||
}
|
||||
|
||||
void LateInit()
|
||||
{
|
||||
}
|
||||
}
|
@ -16,14 +16,16 @@
|
||||
*/
|
||||
|
||||
#include <driver.hpp>
|
||||
#include <interface/driver.h>
|
||||
#include <interface/fs.h>
|
||||
#include <type_traits>
|
||||
|
||||
#include "../../kernel.h"
|
||||
#include "../../driver.h"
|
||||
|
||||
// #define DEBUG_API
|
||||
|
||||
#ifdef DEBUG_API
|
||||
#define dbg_api(Format, ...) function(Format, ##__VA_ARGS__)
|
||||
#define dbg_api(Format, ...) func(Format, ##__VA_ARGS__)
|
||||
#else
|
||||
#define dbg_api(Format, ...)
|
||||
#endif
|
||||
@ -53,19 +55,19 @@ namespace Driver
|
||||
{
|
||||
case _drf_Entry:
|
||||
drv->Entry = (int (*)())Function;
|
||||
debug("Entry %#lx for %s", (uintptr_t)Function, drv->Path);
|
||||
debug("Entry %#lx for %s", (uintptr_t)Function, drv->Path.c_str());
|
||||
break;
|
||||
case _drf_Final:
|
||||
drv->Final = (int (*)())Function;
|
||||
debug("Finalize %#lx for %s", (uintptr_t)Function, drv->Path);
|
||||
debug("Finalize %#lx for %s", (uintptr_t)Function, drv->Path.c_str());
|
||||
break;
|
||||
case _drf_Panic:
|
||||
drv->Panic = (int (*)())Function;
|
||||
debug("Panic %#lx for %s", (uintptr_t)Function, drv->Path);
|
||||
debug("Panic %#lx for %s", (uintptr_t)Function, drv->Path.c_str());
|
||||
break;
|
||||
case _drf_Probe:
|
||||
drv->Probe = (int (*)())Function;
|
||||
debug("Probe %#lx for %s", (uintptr_t)Function, drv->Path);
|
||||
debug("Probe %#lx for %s", (uintptr_t)Function, drv->Path.c_str());
|
||||
break;
|
||||
default:
|
||||
assert(!"Invalid driver function type");
|
||||
@ -134,7 +136,7 @@ namespace Driver
|
||||
{
|
||||
if (ih.first == IRQ)
|
||||
{
|
||||
debug("Removing IRQ %d: %#lx for %s", IRQ, (uintptr_t)ih.second, drv->Path);
|
||||
debug("Removing IRQ %d: %#lx for %s", IRQ, (uintptr_t)ih.second, drv->Path.c_str());
|
||||
Interrupts::RemoveHandler((void (*)(CPU::TrapFrame *))ih.second, IRQ);
|
||||
drv->InterruptHandlers->erase(IRQ);
|
||||
break;
|
||||
@ -177,7 +179,7 @@ namespace Driver
|
||||
foreach (auto &i in * drv->InterruptHandlers)
|
||||
{
|
||||
Interrupts::RemoveHandler((void (*)(CPU::TrapFrame *))Handler, i.first);
|
||||
debug("Removed IRQ %d: %#lx for %s", i.first, (uintptr_t)Handler, drv->Path);
|
||||
debug("Removed IRQ %d: %#lx for %s", i.first, (uintptr_t)Handler, drv->Path.c_str());
|
||||
}
|
||||
drv->InterruptHandlers->clear();
|
||||
return 0;
|
||||
@ -185,217 +187,6 @@ namespace Driver
|
||||
|
||||
/* --------- */
|
||||
|
||||
dev_t RegisterInputDevice(dev_t MajorID, DeviceDriverType Type)
|
||||
{
|
||||
dbg_api("%d, %d", MajorID, Type);
|
||||
|
||||
switch (Type)
|
||||
{
|
||||
case ddt_Keyboard:
|
||||
return DriverManager->InputKeyboardDev->Register(MajorID);
|
||||
case ddt_Mouse:
|
||||
return DriverManager->InputMouseDev->Register(MajorID);
|
||||
/* ... */
|
||||
default:
|
||||
assert(!"Invalid input device type");
|
||||
}
|
||||
}
|
||||
|
||||
int UnregisterInputDevice(dev_t MajorID, dev_t MinorID, DeviceDriverType Type)
|
||||
{
|
||||
dbg_api("%d, %d, %d", MajorID, MinorID, Type);
|
||||
|
||||
switch (Type)
|
||||
{
|
||||
case ddt_Keyboard:
|
||||
return DriverManager->InputKeyboardDev->Unregister(MajorID, MinorID);
|
||||
case ddt_Mouse:
|
||||
return DriverManager->InputMouseDev->Unregister(MajorID, MinorID);
|
||||
/* ... */
|
||||
default:
|
||||
assert(!"Invalid input device type");
|
||||
}
|
||||
}
|
||||
|
||||
int ReportKeyboardEvent(dev_t MajorID, dev_t MinorID, uint8_t ScanCode)
|
||||
{
|
||||
dbg_api("%d, %d, %d", MajorID, MinorID, ScanCode);
|
||||
|
||||
return DriverManager->InputKeyboardDev->ReportKeyEvent(MajorID, MinorID, ScanCode);
|
||||
}
|
||||
|
||||
int ReportRelativeMouseEvent(dev_t MajorID, dev_t MinorID, __MouseButtons Button, int X, int Y, int8_t Z)
|
||||
{
|
||||
dbg_api("%d, %d, %d, %d, %d, %d", MajorID, MinorID, Button, X, Y, Z);
|
||||
|
||||
return DriverManager->InputMouseDev->ReportMouseEvent(MajorID, MinorID,
|
||||
Button.LeftButton, Button.RightButton, Button.MiddleButton,
|
||||
Button.Button4, Button.Button5, Button.Button6, Button.Button7, Button.Button8,
|
||||
X, Y, Z, true);
|
||||
}
|
||||
|
||||
int ReportAbsoluteMouseEvent(dev_t MajorID, dev_t MinorID, __MouseButtons Button, uintptr_t X, uintptr_t Y, int8_t Z)
|
||||
{
|
||||
dbg_api("%d, %d, %d, %d, %d, %d", MajorID, MinorID, Button, X, Y, Z);
|
||||
|
||||
return DriverManager->InputMouseDev->ReportMouseEvent(MajorID, MinorID,
|
||||
Button.LeftButton, Button.RightButton, Button.MiddleButton,
|
||||
Button.Button4, Button.Button5, Button.Button6, Button.Button7, Button.Button8,
|
||||
X, Y, Z, false);
|
||||
}
|
||||
|
||||
/* --------- */
|
||||
|
||||
dev_t RegisterBlockDevice(dev_t MajorID, DeviceDriverType Type, void *Open, void *Close, void *Read, void *Write, void *Ioctl)
|
||||
{
|
||||
dbg_api("%d, %d, %#lx, %#lx, %#lx, %#lx, %#lx", MajorID, Type, Open, Close, Read, Write, Ioctl);
|
||||
|
||||
switch (Type)
|
||||
{
|
||||
case ddt_SATA:
|
||||
{
|
||||
dev_t ret = DriverManager->BlockSATADev->Register(MajorID);
|
||||
DriverManager->BlockSATADev->NewBlock(MajorID, ret,
|
||||
(SlaveDeviceFile::drvOpen_t)Open,
|
||||
(SlaveDeviceFile::drvClose_t)Close,
|
||||
(SlaveDeviceFile::drvRead_t)Read,
|
||||
(SlaveDeviceFile::drvWrite_t)Write,
|
||||
(SlaveDeviceFile::drvIoctl_t)Ioctl);
|
||||
return ret;
|
||||
}
|
||||
case ddt_ATA:
|
||||
{
|
||||
dev_t ret = DriverManager->BlockHDDev->Register(MajorID);
|
||||
DriverManager->BlockHDDev->NewBlock(MajorID, ret,
|
||||
(SlaveDeviceFile::drvOpen_t)Open,
|
||||
(SlaveDeviceFile::drvClose_t)Close,
|
||||
(SlaveDeviceFile::drvRead_t)Read,
|
||||
(SlaveDeviceFile::drvWrite_t)Write,
|
||||
(SlaveDeviceFile::drvIoctl_t)Ioctl);
|
||||
return ret;
|
||||
}
|
||||
case ddt_NVMe:
|
||||
{
|
||||
dev_t ret = DriverManager->BlockNVMeDev->Register(MajorID);
|
||||
DriverManager->BlockNVMeDev->NewBlock(MajorID, ret,
|
||||
(SlaveDeviceFile::drvOpen_t)Open,
|
||||
(SlaveDeviceFile::drvClose_t)Close,
|
||||
(SlaveDeviceFile::drvRead_t)Read,
|
||||
(SlaveDeviceFile::drvWrite_t)Write,
|
||||
(SlaveDeviceFile::drvIoctl_t)Ioctl);
|
||||
return ret;
|
||||
}
|
||||
/* ... */
|
||||
default:
|
||||
assert(!"Invalid storage device type");
|
||||
}
|
||||
}
|
||||
|
||||
int UnregisterBlockDevice(dev_t MajorID, dev_t MinorID, DeviceDriverType Type)
|
||||
{
|
||||
dbg_api("%d, %d, %d", MajorID, MinorID, Type);
|
||||
|
||||
switch (Type)
|
||||
{
|
||||
case ddt_SATA:
|
||||
return DriverManager->BlockSATADev->Unregister(MajorID, MinorID);
|
||||
case ddt_ATA:
|
||||
return DriverManager->BlockHDDev->Unregister(MajorID, MinorID);
|
||||
case ddt_NVMe:
|
||||
return DriverManager->BlockNVMeDev->Unregister(MajorID, MinorID);
|
||||
/* ... */
|
||||
default:
|
||||
assert(!"Invalid storage device type");
|
||||
}
|
||||
}
|
||||
|
||||
/* --------- */
|
||||
|
||||
dev_t RegisterAudioDevice(dev_t MajorID, DeviceDriverType Type, void *Open, void *Close, void *Read, void *Write, void *Ioctl)
|
||||
{
|
||||
dbg_api("%d, %d, %#lx, %#lx, %#lx, %#lx, %#lx", MajorID, Type, Open, Close, Read, Write, Ioctl);
|
||||
|
||||
switch (Type)
|
||||
{
|
||||
case ddt_Audio:
|
||||
{
|
||||
dev_t ret = DriverManager->AudioDev->Register(MajorID);
|
||||
DriverManager->AudioDev->NewAudio(MajorID, ret,
|
||||
(SlaveDeviceFile::drvOpen_t)Open,
|
||||
(SlaveDeviceFile::drvClose_t)Close,
|
||||
(SlaveDeviceFile::drvRead_t)Read,
|
||||
(SlaveDeviceFile::drvWrite_t)Write,
|
||||
(SlaveDeviceFile::drvIoctl_t)Ioctl);
|
||||
return ret;
|
||||
}
|
||||
/* ... */
|
||||
default:
|
||||
assert(!"Invalid audio device type");
|
||||
}
|
||||
}
|
||||
|
||||
int UnregisterAudioDevice(dev_t MajorID, dev_t MinorID, DeviceDriverType Type)
|
||||
{
|
||||
dbg_api("%d, %d, %d", MajorID, MinorID, Type);
|
||||
|
||||
switch (Type)
|
||||
{
|
||||
case ddt_Audio:
|
||||
return DriverManager->AudioDev->Unregister(MajorID, MinorID);
|
||||
/* ... */
|
||||
default:
|
||||
assert(!"Invalid audio device type");
|
||||
}
|
||||
}
|
||||
|
||||
/* --------- */
|
||||
|
||||
dev_t RegisterNetDevice(dev_t MajorID, DeviceDriverType Type, void *Open, void *Close, void *Read, void *Write, void *Ioctl)
|
||||
{
|
||||
dbg_api("%d, %d, %#lx, %#lx, %#lx, %#lx, %#lx", MajorID, Type, Open, Close, Read, Write, Ioctl);
|
||||
|
||||
switch (Type)
|
||||
{
|
||||
case ddt_Network:
|
||||
{
|
||||
dev_t ret = DriverManager->NetDev->Register(MajorID);
|
||||
DriverManager->NetDev->NewNet(MajorID, ret,
|
||||
(SlaveDeviceFile::drvOpen_t)Open,
|
||||
(SlaveDeviceFile::drvClose_t)Close,
|
||||
(SlaveDeviceFile::drvRead_t)Read,
|
||||
(SlaveDeviceFile::drvWrite_t)Write,
|
||||
(SlaveDeviceFile::drvIoctl_t)Ioctl);
|
||||
return ret;
|
||||
}
|
||||
/* ... */
|
||||
default:
|
||||
assert(!"Invalid audio device type");
|
||||
}
|
||||
}
|
||||
|
||||
int UnregisterNetDevice(dev_t MajorID, dev_t MinorID, DeviceDriverType Type)
|
||||
{
|
||||
dbg_api("%d, %d, %d", MajorID, MinorID, Type);
|
||||
|
||||
switch (Type)
|
||||
{
|
||||
case ddt_Network:
|
||||
return DriverManager->NetDev->Unregister(MajorID, MinorID);
|
||||
/* ... */
|
||||
default:
|
||||
assert(!"Invalid audio device type");
|
||||
}
|
||||
}
|
||||
|
||||
int ReportNetworkPacket(dev_t MajorID, dev_t MinorID, void *Buffer, size_t Size)
|
||||
{
|
||||
dbg_api("%d, %d, %#lx, %d", MajorID, MinorID, Buffer, Size);
|
||||
|
||||
return DriverManager->NetDev->ReportNetworkPacket(MajorID, MinorID, Buffer, Size);
|
||||
}
|
||||
|
||||
/* --------- */
|
||||
|
||||
void d_KPrint(dev_t MajorID, const char *Format, va_list args)
|
||||
{
|
||||
dbg_api("%d %s, %#lx", MajorID, Format, args);
|
||||
@ -891,22 +682,6 @@ namespace Driver
|
||||
api->UnregisterInterruptHandler = UnregisterInterruptHandler;
|
||||
api->UnregisterAllInterruptHandlers = UnregisterAllInterruptHandlers;
|
||||
|
||||
api->RegisterInputDevice = RegisterInputDevice;
|
||||
api->UnregisterInputDevice = UnregisterInputDevice;
|
||||
api->ReportKeyboardEvent = ReportKeyboardEvent;
|
||||
api->ReportRelativeMouseEvent = ReportRelativeMouseEvent;
|
||||
api->ReportAbsoluteMouseEvent = ReportAbsoluteMouseEvent;
|
||||
|
||||
api->RegisterBlockDevice = RegisterBlockDevice;
|
||||
api->UnregisterBlockDevice = UnregisterBlockDevice;
|
||||
|
||||
api->RegisterAudioDevice = RegisterAudioDevice;
|
||||
api->UnregisterAudioDevice = UnregisterAudioDevice;
|
||||
|
||||
api->RegisterNetDevice = RegisterNetDevice;
|
||||
api->UnregisterNetDevice = UnregisterNetDevice;
|
||||
api->ReportNetworkPacket = ReportNetworkPacket;
|
||||
|
||||
api->KPrint = d_KPrint;
|
||||
api->KernelLog = KernelLog;
|
||||
|
||||
@ -944,3 +719,28 @@ namespace Driver
|
||||
api->strstr = api__strstr;
|
||||
}
|
||||
}
|
||||
|
||||
dev_t __api_RegisterFileSystem(FileSystemInfo *Info, struct Inode *Root)
|
||||
{
|
||||
return fs->RegisterFileSystem(Info, Root);
|
||||
}
|
||||
|
||||
int __api_UnregisterFileSystem(dev_t Device)
|
||||
{
|
||||
return fs->UnregisterFileSystem(Device);
|
||||
}
|
||||
|
||||
struct APISymbols
|
||||
{
|
||||
const char *Name;
|
||||
void *Function;
|
||||
};
|
||||
|
||||
static struct APISymbols APISymbols[] = {
|
||||
{"RegisterFileSystem", (void *)__api_RegisterFileSystem},
|
||||
{"UnregisterFileSystem", (void *)__api_UnregisterFileSystem},
|
||||
};
|
||||
|
||||
/* Checking functions signatures */
|
||||
static_assert(std::is_same_v<decltype(__api_RegisterFileSystem), decltype(RegisterFileSystem)>);
|
||||
static_assert(std::is_same_v<decltype(__api_UnregisterFileSystem), decltype(UnregisterFileSystem)>);
|
||||
|
@ -1,327 +0,0 @@
|
||||
/*
|
||||
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 <driver.hpp>
|
||||
|
||||
#include <memory.hpp>
|
||||
#include <ints.hpp>
|
||||
#include <task.hpp>
|
||||
#include <printf.h>
|
||||
#include <exec.hpp>
|
||||
#include <cwalk.h>
|
||||
#include <md5.h>
|
||||
|
||||
#include "../../../kernel.h"
|
||||
#include "../../../driver.h"
|
||||
|
||||
using namespace vfs;
|
||||
|
||||
namespace Driver
|
||||
{
|
||||
int MasterDeviceFile::open(int Flags, mode_t Mode)
|
||||
{
|
||||
switch (this->DeviceType)
|
||||
{
|
||||
default:
|
||||
if (this->SlavesMap.empty())
|
||||
return -ENOSYS;
|
||||
Slaves slave = this->SlavesMap.begin()->second;
|
||||
return slave->begin()->second->open(Flags, Mode);
|
||||
}
|
||||
}
|
||||
|
||||
int MasterDeviceFile::close()
|
||||
{
|
||||
switch (this->DeviceType)
|
||||
{
|
||||
default:
|
||||
if (this->SlavesMap.empty())
|
||||
return -ENOSYS;
|
||||
Slaves slave = this->SlavesMap.begin()->second;
|
||||
return slave->begin()->second->close();
|
||||
}
|
||||
}
|
||||
|
||||
size_t MasterDeviceFile::read(uint8_t *Buffer,
|
||||
size_t Size,
|
||||
off_t Offset)
|
||||
{
|
||||
switch (this->DeviceType)
|
||||
{
|
||||
case ddt_Keyboard:
|
||||
{
|
||||
while (KeyQueue.empty())
|
||||
TaskManager->Yield();
|
||||
|
||||
/* Request scancode */
|
||||
if (Size == 2 && Buffer[1] == 0x00)
|
||||
{
|
||||
while (RawKeyQueue.empty())
|
||||
TaskManager->Yield();
|
||||
|
||||
Buffer[0] = RawKeyQueue.front();
|
||||
RawKeyQueue.pop_front();
|
||||
return 1;
|
||||
}
|
||||
|
||||
Buffer[0] = KeyQueue.front();
|
||||
KeyQueue.pop_front();
|
||||
return 1;
|
||||
}
|
||||
default:
|
||||
if (this->SlavesMap.empty())
|
||||
return 0;
|
||||
Slaves slave = this->SlavesMap.begin()->second;
|
||||
return slave->begin()->second->read(Buffer, Size, Offset);
|
||||
}
|
||||
}
|
||||
|
||||
size_t MasterDeviceFile::write(uint8_t *Buffer,
|
||||
size_t Size,
|
||||
off_t Offset)
|
||||
{
|
||||
switch (this->DeviceType)
|
||||
{
|
||||
default:
|
||||
if (this->SlavesMap.empty())
|
||||
return 0;
|
||||
Slaves slave = this->SlavesMap.begin()->second;
|
||||
return slave->begin()->second->write(Buffer, Size, Offset);
|
||||
}
|
||||
}
|
||||
|
||||
int MasterDeviceFile::ioctl(unsigned long Request,
|
||||
void *Argp)
|
||||
{
|
||||
switch (this->DeviceType)
|
||||
{
|
||||
default:
|
||||
if (this->SlavesMap.empty())
|
||||
return -ENOSYS;
|
||||
Slaves slave = this->SlavesMap.begin()->second;
|
||||
return slave->begin()->second->ioctl(Request, Argp);
|
||||
}
|
||||
}
|
||||
|
||||
void MasterDeviceFile::ClearBuffers()
|
||||
{
|
||||
this->RawKeyQueue.clear();
|
||||
this->KeyQueue.clear();
|
||||
/* ... */
|
||||
|
||||
foreach (auto &sm in this->SlavesMap)
|
||||
{
|
||||
Slaves slave = sm.second;
|
||||
foreach (auto &sdf in *slave)
|
||||
sdf.second->ClearBuffers();
|
||||
}
|
||||
}
|
||||
|
||||
int MasterDeviceFile::ReportKeyEvent(maj_t ID, min_t MinorID, uint8_t ScanCode)
|
||||
{
|
||||
debug("New key event: %02x", ScanCode);
|
||||
if (this->SlavesMap.find(ID) == this->SlavesMap.end())
|
||||
return -EINVAL;
|
||||
|
||||
std::unordered_map<min_t, SlaveDeviceFile *> *slave = this->SlavesMap[ID];
|
||||
if ((*slave).find(MinorID) == (*slave).end())
|
||||
return -EINVAL;
|
||||
|
||||
/* We are master, keep a copy of the scancode and
|
||||
converted key */
|
||||
|
||||
if (RawKeyQueue.size() > 16)
|
||||
RawKeyQueue.pop_front();
|
||||
RawKeyQueue.push_back(ScanCode);
|
||||
|
||||
if (KeyQueue.size() > 16)
|
||||
KeyQueue.pop_front();
|
||||
|
||||
switch (ScanCode & ~KEY_PRESSED)
|
||||
{
|
||||
case KEY_LEFT_SHIFT:
|
||||
case KEY_RIGHT_SHIFT:
|
||||
{
|
||||
if (ScanCode & KEY_PRESSED)
|
||||
UpperCase = true;
|
||||
else
|
||||
UpperCase = false;
|
||||
break;
|
||||
}
|
||||
case KEY_CAPS_LOCK:
|
||||
{
|
||||
if (ScanCode & KEY_PRESSED)
|
||||
CapsLock = !CapsLock;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (ScanCode & KEY_PRESSED)
|
||||
KeyQueue.push_back(GetScanCode(ScanCode, UpperCase || CapsLock));
|
||||
|
||||
SlaveDeviceFile *sdf = (*slave)[MinorID];
|
||||
return sdf->ReportKeyEvent(ScanCode);
|
||||
}
|
||||
|
||||
int MasterDeviceFile::ReportMouseEvent(maj_t ID, min_t MinorID,
|
||||
bool LeftButton, bool RightButton, bool MiddleButton,
|
||||
bool Button4, bool Button5, bool Button6, bool Button7, bool Button8,
|
||||
uintptr_t X, uintptr_t Y, int8_t Z, bool Relative)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
int MasterDeviceFile::ReportNetworkPacket(maj_t ID, min_t MinorID, void *Buffer, size_t Size)
|
||||
{
|
||||
/* TODO: Buffer must be allocated by the kernel */
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
int MasterDeviceFile::NewBlock(maj_t ID, min_t MinorID, drvOpen_t Open, drvClose_t Close,
|
||||
drvRead_t Read, drvWrite_t Write, drvIoctl_t Ioctl)
|
||||
{
|
||||
assert(this->SlavesMap.find(ID) != this->SlavesMap.end());
|
||||
Slaves slave = this->SlavesMap[ID];
|
||||
assert((*slave).find(MinorID) != (*slave).end());
|
||||
SlaveDeviceFile *sdf = (*slave)[MinorID];
|
||||
sdf->Open = Open;
|
||||
sdf->Close = Close;
|
||||
sdf->Read = Read;
|
||||
sdf->Write = Write;
|
||||
sdf->Ioctl = Ioctl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int MasterDeviceFile::NewAudio(maj_t ID, min_t MinorID, drvOpen_t Open, drvClose_t Close,
|
||||
drvRead_t Read, drvWrite_t Write, drvIoctl_t Ioctl)
|
||||
{
|
||||
assert(this->SlavesMap.find(ID) != this->SlavesMap.end());
|
||||
Slaves slave = this->SlavesMap[ID];
|
||||
assert((*slave).find(MinorID) != (*slave).end());
|
||||
SlaveDeviceFile *sdf = (*slave)[MinorID];
|
||||
sdf->Open = Open;
|
||||
sdf->Close = Close;
|
||||
sdf->Read = Read;
|
||||
sdf->Write = Write;
|
||||
sdf->Ioctl = Ioctl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int MasterDeviceFile::NewNet(maj_t ID, min_t MinorID, drvOpen_t Open, drvClose_t Close,
|
||||
drvRead_t Read, drvWrite_t Write, drvIoctl_t Ioctl)
|
||||
{
|
||||
assert(this->SlavesMap.find(ID) != this->SlavesMap.end());
|
||||
Slaves slave = this->SlavesMap[ID];
|
||||
assert((*slave).find(MinorID) != (*slave).end());
|
||||
SlaveDeviceFile *sdf = (*slave)[MinorID];
|
||||
sdf->Open = Open;
|
||||
sdf->Close = Close;
|
||||
sdf->Read = Read;
|
||||
sdf->Write = Write;
|
||||
sdf->Ioctl = Ioctl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
dev_t MasterDeviceFile::Register(maj_t ID)
|
||||
{
|
||||
debug("Registering slave device %d", ID);
|
||||
Slaves slave;
|
||||
if (this->SlavesMap.find(ID) != this->SlavesMap.end())
|
||||
slave = this->SlavesMap[ID];
|
||||
else
|
||||
slave = new std::unordered_map<min_t, SlaveDeviceFile *>();
|
||||
|
||||
char name[24];
|
||||
sprintf(name, "%s%ld", this->SlaveName, this->SlaveIDCounter);
|
||||
SlaveDeviceFile *sdf = new SlaveDeviceFile(name,
|
||||
this->SlaveParent,
|
||||
this->DeviceType,
|
||||
this->Type);
|
||||
|
||||
sdf->DeviceMajor = ID;
|
||||
sdf->DeviceMinor = this->SlaveIDCounter;
|
||||
|
||||
(*slave)[this->SlaveIDCounter] = sdf;
|
||||
this->SlavesMap[ID] = slave;
|
||||
return this->SlaveIDCounter++;
|
||||
}
|
||||
|
||||
int MasterDeviceFile::Unregister(maj_t ID, min_t MinorID)
|
||||
{
|
||||
debug("Unregistering slave device %d:%d", ID, MinorID);
|
||||
if (this->SlavesMap.find(ID) == this->SlavesMap.end())
|
||||
return -EINVAL;
|
||||
|
||||
std::unordered_map<min_t, SlaveDeviceFile *> *slave = this->SlavesMap[ID];
|
||||
if ((*slave).find(MinorID) == (*slave).end())
|
||||
return -EINVAL;
|
||||
|
||||
SlaveDeviceFile *sdf = (*slave)[MinorID];
|
||||
delete sdf;
|
||||
slave->erase(MinorID);
|
||||
if (slave->empty())
|
||||
{
|
||||
delete slave;
|
||||
this->SlavesMap.erase(ID);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
MasterDeviceFile::MasterDeviceFile(const char *MasterName,
|
||||
const char *_SlaveName,
|
||||
Node *Parent,
|
||||
int Type)
|
||||
: Node(Parent, MasterName, NodeType::FILE)
|
||||
{
|
||||
strncpy(this->SlaveName, _SlaveName, sizeof(this->Name));
|
||||
this->DeviceType = Type;
|
||||
this->SlaveParent = Parent;
|
||||
|
||||
switch (Type)
|
||||
{
|
||||
case ddt_Keyboard:
|
||||
case ddt_Mouse:
|
||||
case ddt_Joystick:
|
||||
case ddt_Gamepad:
|
||||
case ddt_Touchpad:
|
||||
case ddt_Touchscreen:
|
||||
this->Type = NodeType::CHARDEVICE;
|
||||
break;
|
||||
case ddt_SATA:
|
||||
case ddt_ATA:
|
||||
case ddt_NVMe:
|
||||
this->Type = NodeType::BLOCKDEVICE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
MasterDeviceFile::~MasterDeviceFile()
|
||||
{
|
||||
foreach (auto &sm in this->SlavesMap)
|
||||
{
|
||||
Slaves slave = sm.second;
|
||||
foreach (auto &sdf in *slave)
|
||||
delete sdf.second;
|
||||
delete slave;
|
||||
}
|
||||
this->SlavesMap.clear();
|
||||
}
|
||||
}
|
@ -1,131 +0,0 @@
|
||||
/*
|
||||
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 <driver.hpp>
|
||||
|
||||
#include <memory.hpp>
|
||||
#include <ints.hpp>
|
||||
#include <task.hpp>
|
||||
#include <printf.h>
|
||||
#include <exec.hpp>
|
||||
#include <cwalk.h>
|
||||
#include <md5.h>
|
||||
|
||||
#include "../../../kernel.h"
|
||||
#include "../../../driver.h"
|
||||
|
||||
using namespace vfs;
|
||||
|
||||
namespace Driver
|
||||
{
|
||||
int SlaveDeviceFile::open(int Flags, mode_t Mode)
|
||||
{
|
||||
switch (this->DeviceType)
|
||||
{
|
||||
default:
|
||||
if (this->Open)
|
||||
return this->Open(this->DeviceMajor, this->DeviceMinor,
|
||||
Flags, Mode);
|
||||
return -ENOSYS;
|
||||
}
|
||||
}
|
||||
|
||||
int SlaveDeviceFile::close()
|
||||
{
|
||||
switch (this->DeviceType)
|
||||
{
|
||||
default:
|
||||
if (this->Close)
|
||||
return this->Close(this->DeviceMajor, this->DeviceMinor);
|
||||
return -ENOSYS;
|
||||
}
|
||||
}
|
||||
|
||||
size_t SlaveDeviceFile::read(uint8_t *Buffer,
|
||||
size_t Size,
|
||||
off_t Offset)
|
||||
{
|
||||
switch (this->DeviceType)
|
||||
{
|
||||
case ddt_Keyboard:
|
||||
{
|
||||
while (KeyQueue.empty())
|
||||
TaskManager->Yield();
|
||||
|
||||
Buffer[0] = KeyQueue.front();
|
||||
KeyQueue.pop_front();
|
||||
return 1;
|
||||
}
|
||||
default:
|
||||
if (this->Read)
|
||||
return this->Read(this->DeviceMajor, this->DeviceMinor,
|
||||
Buffer, Size, Offset);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
size_t SlaveDeviceFile::write(uint8_t *Buffer,
|
||||
size_t Size,
|
||||
off_t Offset)
|
||||
{
|
||||
switch (this->DeviceType)
|
||||
{
|
||||
default:
|
||||
if (this->Write)
|
||||
return this->Write(this->DeviceMajor, this->DeviceMinor,
|
||||
Buffer, Size, Offset);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int SlaveDeviceFile::ioctl(unsigned long Request,
|
||||
void *Argp)
|
||||
{
|
||||
switch (this->DeviceType)
|
||||
{
|
||||
default:
|
||||
if (this->Ioctl)
|
||||
return this->Ioctl(this->DeviceMajor, this->DeviceMinor,
|
||||
Request, Argp);
|
||||
return -ENOSYS;
|
||||
}
|
||||
}
|
||||
|
||||
void SlaveDeviceFile::ClearBuffers()
|
||||
{
|
||||
KeyQueue.clear();
|
||||
/* ... */
|
||||
}
|
||||
|
||||
int SlaveDeviceFile::ReportKeyEvent(uint8_t ScanCode)
|
||||
{
|
||||
if (KeyQueue.size() > 16)
|
||||
KeyQueue.pop_front();
|
||||
KeyQueue.push_back(ScanCode);
|
||||
return 0;
|
||||
}
|
||||
|
||||
SlaveDeviceFile::SlaveDeviceFile(const char *Name, vfs::Node *Parent, int Type, vfs::NodeType NType)
|
||||
: Node(Parent, Name, NType)
|
||||
{
|
||||
this->DeviceType = Type;
|
||||
}
|
||||
|
||||
SlaveDeviceFile::~SlaveDeviceFile()
|
||||
{
|
||||
}
|
||||
}
|
@ -17,6 +17,7 @@
|
||||
|
||||
#include <driver.hpp>
|
||||
|
||||
#include <interface/driver.h>
|
||||
#include <memory.hpp>
|
||||
#include <ints.hpp>
|
||||
#include <task.hpp>
|
||||
@ -26,12 +27,64 @@
|
||||
#include <md5.h>
|
||||
|
||||
#include "../../kernel.h"
|
||||
#include "../../driver.h"
|
||||
|
||||
using namespace vfs;
|
||||
|
||||
namespace Driver
|
||||
{
|
||||
void Manager::PreloadDrivers()
|
||||
{
|
||||
debug("Initializing driver manager");
|
||||
const char *DriverDirectory = Config.DriverDirectory;
|
||||
FileNode *drvDirNode = fs->GetByPath(DriverDirectory, nullptr);
|
||||
if (!drvDirNode)
|
||||
{
|
||||
error("Failed to open driver directory %s", DriverDirectory);
|
||||
KPrint("Failed to open driver directory %s", DriverDirectory);
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (const auto &drvNode in drvDirNode->Children)
|
||||
{
|
||||
debug("Checking driver %s", drvNode->Path.c_str());
|
||||
if (!drvNode->IsRegularFile())
|
||||
continue;
|
||||
|
||||
if (Execute::GetBinaryType(drvNode->Path) != Execute::BinTypeELF)
|
||||
{
|
||||
error("Driver %s is not an ELF binary", drvNode->Path.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
Memory::VirtualMemoryArea *dVma = new Memory::VirtualMemoryArea(thisProcess->PageTable);
|
||||
|
||||
uintptr_t EntryPoint, BaseAddress;
|
||||
int err = this->LoadDriverFile(EntryPoint, BaseAddress, dVma, drvNode);
|
||||
debug("err = %d (%s)", err, strerror(err));
|
||||
if (err != 0)
|
||||
{
|
||||
error("Failed to load driver %s: %s",
|
||||
drvNode->Path.c_str(), strerror(err));
|
||||
|
||||
delete dVma;
|
||||
continue;
|
||||
}
|
||||
|
||||
Drivers[DriverIDCounter++] = {
|
||||
.BaseAddress = BaseAddress,
|
||||
.EntryPoint = EntryPoint,
|
||||
.vma = dVma,
|
||||
.Path = drvNode->Path,
|
||||
.InterruptHandlers = new std::unordered_map<uint8_t, void *>};
|
||||
|
||||
dev_t countr = DriverIDCounter - 1;
|
||||
const char *drvName;
|
||||
size_t drvNameLen;
|
||||
cwk_path_get_basename(drvNode->Path.c_str(), &drvName, &drvNameLen);
|
||||
strncpy(Drivers[countr].Name, drvName, sizeof(Drivers[countr].Name));
|
||||
}
|
||||
}
|
||||
|
||||
void Manager::LoadAllDrivers()
|
||||
{
|
||||
if (Drivers.empty())
|
||||
@ -56,7 +109,7 @@ namespace Driver
|
||||
dApi->Base = Drv->BaseAddress;
|
||||
PopulateDriverAPI(dApi);
|
||||
|
||||
debug("Calling driver %s at %#lx", Drv->Path, Drv->EntryPoint);
|
||||
debug("Calling driver %s at %#lx", Drv->Path.c_str(), Drv->EntryPoint);
|
||||
int (*DrvInit)(__driverAPI *) = (int (*)(__driverAPI *))Drv->EntryPoint;
|
||||
Drv->ErrorCode = DrvInit(dApi);
|
||||
if (Drv->ErrorCode < 0)
|
||||
@ -64,7 +117,7 @@ namespace Driver
|
||||
KPrint("FATAL: _start() failed for %s: %s",
|
||||
Drv->Name, strerror(Drv->ErrorCode));
|
||||
error("Failed to load driver %s: %s",
|
||||
Drv->Path, strerror(Drv->ErrorCode));
|
||||
Drv->Path.c_str(), strerror(Drv->ErrorCode));
|
||||
|
||||
Drv->vma->FreeAllPages();
|
||||
continue;
|
||||
@ -73,48 +126,36 @@ namespace Driver
|
||||
KPrint("Loading driver %s", Drv->Name);
|
||||
|
||||
debug("Calling Probe()=%#lx on driver %s",
|
||||
Drv->Probe, Drv->Path);
|
||||
Drv->Probe, Drv->Path.c_str());
|
||||
Drv->ErrorCode = Drv->Probe();
|
||||
if (Drv->ErrorCode < 0)
|
||||
{
|
||||
KPrint("Probe() failed for %s: %s",
|
||||
Drv->Name, strerror(Drv->ErrorCode));
|
||||
error("Failed to probe driver %s: %s",
|
||||
Drv->Path, strerror(Drv->ErrorCode));
|
||||
Drv->Path.c_str(), strerror(Drv->ErrorCode));
|
||||
|
||||
Drv->vma->FreeAllPages();
|
||||
continue;
|
||||
}
|
||||
|
||||
debug("Calling driver Entry()=%#lx function on driver %s",
|
||||
Drv->Entry, Drv->Path);
|
||||
Drv->Entry, Drv->Path.c_str());
|
||||
Drv->ErrorCode = Drv->Entry();
|
||||
if (Drv->ErrorCode < 0)
|
||||
{
|
||||
KPrint("Entry() failed for %s: %s",
|
||||
Drv->Name, strerror(Drv->ErrorCode));
|
||||
error("Failed to initialize driver %s: %s",
|
||||
Drv->Path, strerror(Drv->ErrorCode));
|
||||
Drv->Path.c_str(), strerror(Drv->ErrorCode));
|
||||
|
||||
Drv->vma->FreeAllPages();
|
||||
continue;
|
||||
}
|
||||
|
||||
debug("Loaded driver %s", Drv->Path);
|
||||
debug("Loaded driver %s", Drv->Path.c_str());
|
||||
Drv->Initialized = true;
|
||||
}
|
||||
|
||||
InputMouseDev->ClearBuffers();
|
||||
InputKeyboardDev->ClearBuffers();
|
||||
|
||||
BlockSATADev->ClearBuffers();
|
||||
BlockHDDev->ClearBuffers();
|
||||
BlockNVMeDev->ClearBuffers();
|
||||
|
||||
AudioDev->ClearBuffers();
|
||||
|
||||
NetDev->ClearBuffers();
|
||||
/* ... */
|
||||
}
|
||||
|
||||
void Manager::UnloadAllDrivers()
|
||||
@ -151,6 +192,9 @@ namespace Driver
|
||||
void Manager::Panic()
|
||||
{
|
||||
Memory::Virtual vmm;
|
||||
if (Drivers.size() == 0)
|
||||
return;
|
||||
|
||||
foreach (auto Driver in Drivers)
|
||||
{
|
||||
if (!Driver.second.Initialized)
|
||||
@ -168,21 +212,18 @@ namespace Driver
|
||||
}
|
||||
}
|
||||
|
||||
int Manager::LoadDriverFile(uintptr_t &EntryPoint,
|
||||
uintptr_t &BaseAddress,
|
||||
Memory::VirtualMemoryArea *dVma,
|
||||
RefNode *rDrv)
|
||||
int Manager::LoadDriverFile(uintptr_t &EntryPoint, uintptr_t &BaseAddress,
|
||||
Memory::VirtualMemoryArea *dVma, FileNode *rDrv)
|
||||
{
|
||||
Elf64_Ehdr ELFHeader;
|
||||
rDrv->seek(0, SEEK_SET);
|
||||
rDrv->read((uint8_t *)&ELFHeader, sizeof(Elf64_Ehdr));
|
||||
rDrv->Read(&ELFHeader, sizeof(Elf64_Ehdr), 0);
|
||||
if (ELFHeader.e_type != ET_DYN)
|
||||
{
|
||||
error("Driver %s is not a shared object", rDrv->node->FullPath);
|
||||
error("Driver %s is not a shared object", rDrv->Path.c_str());
|
||||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
trace("Loading driver %s in memory", rDrv->node->Name);
|
||||
trace("Loading driver %s in memory", rDrv->Name.c_str());
|
||||
|
||||
BaseAddress = 0;
|
||||
{
|
||||
@ -192,8 +233,7 @@ namespace Driver
|
||||
size_t SegmentsSize = 0;
|
||||
for (Elf64_Half i = 0; i < ELFHeader.e_phnum; i++)
|
||||
{
|
||||
rDrv->seek(ELFHeader.e_phoff + (i * sizeof(Elf64_Phdr)), SEEK_SET);
|
||||
rDrv->read((uint8_t *)&ProgramHeader, sizeof(Elf64_Phdr));
|
||||
rDrv->Read(&ProgramHeader, sizeof(Elf64_Phdr), ELFHeader.e_phoff + (i * sizeof(Elf64_Phdr)));
|
||||
|
||||
if (ProgramHeader.p_type == PT_LOAD ||
|
||||
ProgramHeader.p_type == PT_DYNAMIC)
|
||||
@ -217,8 +257,7 @@ namespace Driver
|
||||
|
||||
for (Elf64_Half i = 0; i < ELFHeader.e_phnum; i++)
|
||||
{
|
||||
rDrv->seek(ELFHeader.e_phoff + (i * sizeof(Elf64_Phdr)), SEEK_SET);
|
||||
rDrv->read((uint8_t *)&ProgramHeader, sizeof(Elf64_Phdr));
|
||||
rDrv->Read(&ProgramHeader, sizeof(Elf64_Phdr), ELFHeader.e_phoff + (i * sizeof(Elf64_Phdr)));
|
||||
|
||||
switch (ProgramHeader.p_type)
|
||||
{
|
||||
@ -237,8 +276,7 @@ namespace Driver
|
||||
|
||||
if (ProgramHeader.p_filesz > 0)
|
||||
{
|
||||
rDrv->seek(ProgramHeader.p_offset, SEEK_SET);
|
||||
rDrv->read((uint8_t *)SegmentDestination, ProgramHeader.p_filesz);
|
||||
rDrv->Read(SegmentDestination, ProgramHeader.p_filesz, ProgramHeader.p_offset);
|
||||
}
|
||||
|
||||
if (ProgramHeader.p_memsz - ProgramHeader.p_filesz > 0)
|
||||
@ -264,8 +302,7 @@ namespace Driver
|
||||
|
||||
if (ProgramHeader.p_filesz > 0)
|
||||
{
|
||||
rDrv->seek(ProgramHeader.p_offset, SEEK_SET);
|
||||
rDrv->read((uint8_t *)DynamicSegmentDestination, ProgramHeader.p_filesz);
|
||||
rDrv->Read(DynamicSegmentDestination, ProgramHeader.p_filesz, ProgramHeader.p_offset);
|
||||
}
|
||||
|
||||
if (ProgramHeader.p_memsz - ProgramHeader.p_filesz > 0)
|
||||
@ -288,8 +325,7 @@ namespace Driver
|
||||
Elf64_Phdr ProgramHeader;
|
||||
for (Elf64_Half i = 0; i < ELFHeader.e_phnum; i++)
|
||||
{
|
||||
rDrv->seek(ELFHeader.e_phoff + (i * sizeof(Elf64_Phdr)), SEEK_SET);
|
||||
rDrv->read((uint8_t *)&ProgramHeader, sizeof(Elf64_Phdr));
|
||||
rDrv->Read(&ProgramHeader, sizeof(Elf64_Phdr), ELFHeader.e_phoff + (i * sizeof(Elf64_Phdr)));
|
||||
|
||||
if (ProgramHeader.p_type == PT_DYNAMIC)
|
||||
{
|
||||
@ -381,14 +417,11 @@ namespace Driver
|
||||
break;
|
||||
}
|
||||
|
||||
vfs::RefNode *fd = fs->Open(rDrv->node->FullPath);
|
||||
|
||||
std::vector<Elf64_Dyn> SymTab = Execute::ELFGetDynamicTag_x86_64(fd, DT_SYMTAB);
|
||||
std::vector<Elf64_Dyn> StrTab = Execute::ELFGetDynamicTag_x86_64(fd, DT_STRTAB);
|
||||
std::vector<Elf64_Dyn> SymTab = Execute::ELFGetDynamicTag_x86_64(rDrv, DT_SYMTAB);
|
||||
std::vector<Elf64_Dyn> StrTab = Execute::ELFGetDynamicTag_x86_64(rDrv, DT_STRTAB);
|
||||
Elf64_Sym *_SymTab = (Elf64_Sym *)((uintptr_t)BaseAddress + SymTab[0].d_un.d_ptr);
|
||||
char *DynStr = (char *)((uintptr_t)BaseAddress + StrTab[0].d_un.d_ptr);
|
||||
UNUSED(DynStr);
|
||||
delete fd;
|
||||
|
||||
Elf64_Rela *Rela = (Elf64_Rela *)(BaseAddress + Dynamic->d_un.d_ptr);
|
||||
for (size_t i = 0; i < (PltRelSize->d_un.d_val / sizeof(Elf64_Rela)); i++)
|
||||
@ -431,14 +464,12 @@ namespace Driver
|
||||
{
|
||||
fixme("DT_SYMTAB");
|
||||
break;
|
||||
vfs::RefNode *fd = fs->Open(rDrv->node->FullPath);
|
||||
|
||||
std::vector<Elf64_Dyn> SymTab = Execute::ELFGetDynamicTag_x86_64(fd, DT_SYMTAB);
|
||||
std::vector<Elf64_Dyn> StrTab = Execute::ELFGetDynamicTag_x86_64(fd, DT_STRTAB);
|
||||
std::vector<Elf64_Dyn> SymTab = Execute::ELFGetDynamicTag_x86_64(rDrv, DT_SYMTAB);
|
||||
std::vector<Elf64_Dyn> StrTab = Execute::ELFGetDynamicTag_x86_64(rDrv, DT_STRTAB);
|
||||
Elf64_Sym *_SymTab = (Elf64_Sym *)((uintptr_t)BaseAddress + SymTab[0].d_un.d_ptr);
|
||||
char *DynStr = (char *)((uintptr_t)BaseAddress + StrTab[0].d_un.d_ptr);
|
||||
UNUSED(DynStr);
|
||||
delete fd;
|
||||
|
||||
size_t symtabEntrySize = 0;
|
||||
Elf64_Dyn *entrySizeDyn = Dynamic;
|
||||
@ -476,8 +507,8 @@ namespace Driver
|
||||
* this will create more issues :/ */
|
||||
// if (strcmp(SymbolName, "DriverProbe") == 0)
|
||||
// {
|
||||
// Drivers[MajorIDCounter].Probe = (int (*)())(BaseAddress + s->st_value);
|
||||
// debug("Found probe function at %#lx", Drivers[MajorIDCounter].Probe);
|
||||
// Drivers[DriverIDCounter].Probe = (int (*)())(BaseAddress + s->st_value);
|
||||
// debug("Found probe function at %#lx", Drivers[DriverIDCounter].Probe);
|
||||
// }
|
||||
}
|
||||
break;
|
||||
@ -498,7 +529,7 @@ namespace Driver
|
||||
EntryPoint += BaseAddress;
|
||||
|
||||
debug("Driver %s has entry point %#lx and base %#lx",
|
||||
rDrv->node->FullPath, EntryPoint, BaseAddress);
|
||||
rDrv->Path.c_str(), EntryPoint, BaseAddress);
|
||||
|
||||
/* FIXME: Do not add to the KernelSymbolTable! */
|
||||
// Memory::SmartHeap sh(rDrv->Size);
|
||||
@ -510,79 +541,11 @@ namespace Driver
|
||||
|
||||
Manager::Manager()
|
||||
{
|
||||
debug("Initializing driver manager");
|
||||
const char *DriverDirectory = Config.DriverDirectory;
|
||||
RefNode *drvDirNode = fs->Open(DriverDirectory);
|
||||
if (!drvDirNode)
|
||||
{
|
||||
error("Failed to open driver directory %s", DriverDirectory);
|
||||
KPrint("Failed to open driver directory %s", DriverDirectory);
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (auto drvNode in drvDirNode->node->Children)
|
||||
{
|
||||
if (drvNode->Type != vfs::FILE)
|
||||
continue;
|
||||
|
||||
if (Execute::GetBinaryType(drvNode->FullPath) != Execute::BinTypeELF)
|
||||
{
|
||||
error("Driver %s is not an ELF binary", drvNode->FullPath);
|
||||
continue;
|
||||
}
|
||||
|
||||
RefNode *rDrv = drvNode->CreateReference();
|
||||
|
||||
Memory::VirtualMemoryArea *dVma =
|
||||
new Memory::VirtualMemoryArea(thisProcess->PageTable);
|
||||
|
||||
uintptr_t EntryPoint, BaseAddress;
|
||||
int err = this->LoadDriverFile(EntryPoint, BaseAddress, dVma, rDrv);
|
||||
debug("err = %d (%s)", err, strerror(err));
|
||||
if (err != 0)
|
||||
{
|
||||
error("Failed to load driver %s: %s",
|
||||
drvNode->FullPath, strerror(err));
|
||||
|
||||
delete rDrv;
|
||||
delete dVma;
|
||||
continue;
|
||||
}
|
||||
delete rDrv;
|
||||
|
||||
Drivers[MajorIDCounter++] = {
|
||||
.BaseAddress = BaseAddress,
|
||||
.EntryPoint = EntryPoint,
|
||||
.vma = dVma,
|
||||
.Path = drvNode->FullPath,
|
||||
.InterruptHandlers = new std::unordered_map<uint8_t, void *>};
|
||||
|
||||
dev_t countr = MajorIDCounter - 1;
|
||||
const char *drvName;
|
||||
size_t drvNameLen;
|
||||
cwk_path_get_basename(drvNode->FullPath, &drvName, &drvNameLen);
|
||||
strncpy(Drivers[countr].Name, drvName, sizeof(Drivers[countr].Name));
|
||||
}
|
||||
|
||||
delete drvDirNode;
|
||||
|
||||
InputMouseDev = new MasterDeviceFile("mice", "mouse", DevFS, ddt_Mouse);
|
||||
InputKeyboardDev = new MasterDeviceFile("key", "kbd", DevFS, ddt_Keyboard);
|
||||
|
||||
BlockSATADev = new MasterDeviceFile("sd", "sd", DevFS, ddt_SATA);
|
||||
BlockHDDev = new MasterDeviceFile("hd", "hd", DevFS, ddt_ATA);
|
||||
BlockNVMeDev = new MasterDeviceFile("nvme", "nvme", DevFS, ddt_NVMe);
|
||||
|
||||
AudioDev = new MasterDeviceFile("audio", "snd", DevFS, ddt_Audio);
|
||||
|
||||
NetDev = new MasterDeviceFile("network", "net", DevFS, ddt_Network);
|
||||
}
|
||||
|
||||
Manager::~Manager()
|
||||
{
|
||||
debug("Unloading drivers");
|
||||
UnloadAllDrivers();
|
||||
delete InputMouseDev;
|
||||
delete InputKeyboardDev;
|
||||
}
|
||||
}
|
||||
|
@ -15,10 +15,9 @@
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <interface/driver.h>
|
||||
#include <driver.hpp>
|
||||
|
||||
#include "../../driver.h"
|
||||
|
||||
static char ScanCodeConversionTableLower[] = {
|
||||
[KEY_1] = '1',
|
||||
[KEY_2] = '2',
|
||||
|
@ -345,15 +345,15 @@ namespace Interrupts
|
||||
#ifdef DEBUG
|
||||
foreach (auto ev in RegisteredEvents)
|
||||
{
|
||||
void *func = ev.IsHandler
|
||||
? ev.Data
|
||||
: (void *)ev.Callback;
|
||||
void *fct = ev.IsHandler
|
||||
? ev.Data
|
||||
: (void *)ev.Callback;
|
||||
const char *symbol = ev.IsHandler
|
||||
? "class"
|
||||
: KernelSymbolTable->GetSymbol((uintptr_t)func);
|
||||
: KernelSymbolTable->GetSymbol((uintptr_t)fct);
|
||||
|
||||
debug("Event IRQ%d [%#lx %s] has priority %ld",
|
||||
ev.IRQ, func, symbol, ev.Priority);
|
||||
ev.IRQ, fct, symbol, ev.Priority);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -173,7 +173,7 @@ typedef volatile _Atomic(int64_t) atomic64_t;
|
||||
typedef volatile _Atomic(void *) atomicptr_t;
|
||||
|
||||
/* Intellisense errors */
|
||||
#ifndef __debug_vscode__
|
||||
#ifndef __vscode__
|
||||
|
||||
static FORCEINLINE int32_t atomic_load32(atomic32_t *src) { return atomic_load_explicit(src, memory_order_relaxed); }
|
||||
static FORCEINLINE void atomic_store32(atomic32_t *dst, int32_t val) { atomic_store_explicit(dst, val, memory_order_relaxed); }
|
||||
|
@ -86,6 +86,6 @@ EXTERNC int __rpmalloc_munmap(void *addr, size_t length)
|
||||
|
||||
EXTERNC int __rpmalloc_posix_madvise(void *addr, size_t length, int advice)
|
||||
{
|
||||
function("%#lx %d %d", addr, length, advice);
|
||||
func("%#lx %d %d", addr, length, advice);
|
||||
return 0;
|
||||
}
|
||||
|
@ -427,7 +427,11 @@ NIF void InitializeMemoryManagement()
|
||||
|
||||
void *malloc(size_t Size)
|
||||
{
|
||||
assert(Size > 0);
|
||||
if (Size == 0)
|
||||
{
|
||||
warn("Attempt to allocate 0 bytes");
|
||||
Size = 16;
|
||||
}
|
||||
|
||||
memdbg("malloc(%d)->[%s]", Size,
|
||||
KernelSymbolTable ? KernelSymbolTable->GetSymbol((uintptr_t)__builtin_return_address(0))
|
||||
@ -474,7 +478,11 @@ void *malloc(size_t Size)
|
||||
|
||||
void *calloc(size_t n, size_t Size)
|
||||
{
|
||||
assert(Size > 0);
|
||||
if (Size == 0)
|
||||
{
|
||||
warn("Attempt to allocate 0 bytes");
|
||||
Size = 16;
|
||||
}
|
||||
|
||||
memdbg("calloc(%d, %d)->[%s]", n, Size,
|
||||
KernelSymbolTable ? KernelSymbolTable->GetSymbol((uintptr_t)__builtin_return_address(0))
|
||||
@ -521,7 +529,11 @@ void *calloc(size_t n, size_t Size)
|
||||
|
||||
void *realloc(void *Address, size_t Size)
|
||||
{
|
||||
assert(Size > 0);
|
||||
if (Size == 0)
|
||||
{
|
||||
warn("Attempt to allocate 0 bytes");
|
||||
Size = 16;
|
||||
}
|
||||
|
||||
memdbg("realloc(%#lx, %d)->[%s]", Address, Size,
|
||||
KernelSymbolTable ? KernelSymbolTable->GetSymbol((uintptr_t)__builtin_return_address(0))
|
||||
@ -568,7 +580,11 @@ void *realloc(void *Address, size_t Size)
|
||||
|
||||
void free(void *Address)
|
||||
{
|
||||
assert(Address != nullptr);
|
||||
if (Address == nullptr)
|
||||
{
|
||||
warn("Attempt to free a null pointer");
|
||||
return;
|
||||
}
|
||||
|
||||
memdbg("free(%#lx)->[%s]", Address,
|
||||
KernelSymbolTable ? KernelSymbolTable->GetSymbol((uintptr_t)__builtin_return_address(0))
|
||||
@ -609,105 +625,3 @@ void free(void *Address)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void *operator new(std::size_t Size)
|
||||
{
|
||||
assert(Size > 0);
|
||||
|
||||
memdbg("new(%d)->[%s]", Size,
|
||||
KernelSymbolTable ? KernelSymbolTable->GetSymbol((uintptr_t)__builtin_return_address(0))
|
||||
: "Unknown");
|
||||
|
||||
void *ret = malloc(Size);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void *operator new[](std::size_t Size)
|
||||
{
|
||||
assert(Size > 0);
|
||||
|
||||
memdbg("new[](%d)->[%s]", Size,
|
||||
KernelSymbolTable ? KernelSymbolTable->GetSymbol((uintptr_t)__builtin_return_address(0))
|
||||
: "Unknown");
|
||||
|
||||
void *ret = malloc(Size);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void *operator new(std::size_t Size, std::align_val_t Alignment)
|
||||
{
|
||||
assert(Size > 0);
|
||||
|
||||
memdbg("new(%d, %d)->[%s]", Size, Alignment,
|
||||
KernelSymbolTable ? KernelSymbolTable->GetSymbol((uintptr_t)__builtin_return_address(0))
|
||||
: "Unknown");
|
||||
|
||||
fixme("operator new with alignment(%#lx) is not implemented",
|
||||
Alignment);
|
||||
|
||||
void *ret = malloc(Size);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void operator delete(void *Pointer)
|
||||
{
|
||||
assert(Pointer != nullptr);
|
||||
|
||||
memdbg("delete(%#lx)->[%s]", Pointer,
|
||||
KernelSymbolTable ? KernelSymbolTable->GetSymbol((uintptr_t)__builtin_return_address(0))
|
||||
: "Unknown");
|
||||
|
||||
free(Pointer);
|
||||
}
|
||||
|
||||
void operator delete[](void *Pointer)
|
||||
{
|
||||
assert(Pointer != nullptr);
|
||||
|
||||
memdbg("delete[](%#lx)->[%s]", Pointer,
|
||||
KernelSymbolTable ? KernelSymbolTable->GetSymbol((uintptr_t)__builtin_return_address(0))
|
||||
: "Unknown");
|
||||
|
||||
free(Pointer);
|
||||
}
|
||||
|
||||
void operator delete(void *Pointer, long unsigned int Size)
|
||||
{
|
||||
assert(Pointer != nullptr);
|
||||
assert(Size > 0);
|
||||
|
||||
memdbg("delete(%#lx, %d)->[%s]",
|
||||
Pointer, Size,
|
||||
KernelSymbolTable ? KernelSymbolTable->GetSymbol((uintptr_t)__builtin_return_address(0))
|
||||
: "Unknown");
|
||||
|
||||
free(Pointer);
|
||||
}
|
||||
|
||||
void operator delete[](void *Pointer, long unsigned int Size)
|
||||
{
|
||||
assert(Pointer != nullptr);
|
||||
assert(Size > 0);
|
||||
|
||||
memdbg("delete[](%#lx, %d)->[%s]",
|
||||
Pointer, Size,
|
||||
KernelSymbolTable ? KernelSymbolTable->GetSymbol((uintptr_t)__builtin_return_address(0))
|
||||
: "Unknown");
|
||||
|
||||
free(Pointer);
|
||||
}
|
||||
|
||||
void operator delete(void *Pointer, unsigned long Size, std::align_val_t Alignment)
|
||||
{
|
||||
assert(Pointer != nullptr);
|
||||
assert(Size > 0);
|
||||
|
||||
memdbg("delete(%#lx, %d, %d)->[%s]",
|
||||
Pointer, Size, Alignment,
|
||||
KernelSymbolTable ? KernelSymbolTable->GetSymbol((uintptr_t)__builtin_return_address(0))
|
||||
: "Unknown");
|
||||
|
||||
fixme("operator delete with alignment is not implemented");
|
||||
|
||||
free(Pointer);
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ namespace Memory
|
||||
{
|
||||
VirtualAllocation::AllocatedPages VirtualAllocation::RequestPages(size_t Count)
|
||||
{
|
||||
function("%lld", Count);
|
||||
func("%lld", Count);
|
||||
|
||||
void *pAddress = KernelAllocator.RequestPages(Count);
|
||||
memset(pAddress, 0, FROM_PAGES(Count));
|
||||
@ -79,7 +79,7 @@ namespace Memory
|
||||
|
||||
void VirtualAllocation::FreePages(void *Address, size_t Count)
|
||||
{
|
||||
function("%#lx, %lld", Address, Count);
|
||||
func("%#lx, %lld", Address, Count);
|
||||
|
||||
SmartLock(MgrLock);
|
||||
foreach (auto &apl in AllocatedPagesList)
|
||||
@ -110,7 +110,7 @@ namespace Memory
|
||||
|
||||
void VirtualAllocation::MapTo(AllocatedPages ap, PageTable *TargetTable)
|
||||
{
|
||||
function("%#lx, %#lx", ap.VirtualAddress, TargetTable);
|
||||
func("%#lx, %#lx", ap.VirtualAddress, TargetTable);
|
||||
|
||||
Virtual vmm(TargetTable);
|
||||
vmm.Map(ap.VirtualAddress, ap.PhysicalAddress, FROM_PAGES(ap.PageCount), RW | KRsv | G);
|
||||
@ -120,7 +120,7 @@ namespace Memory
|
||||
: BaseAddress(Base), CurrentBase(Base),
|
||||
Table((PageTable *)CPU::PageTable())
|
||||
{
|
||||
function("%#lx", Base);
|
||||
func("%#lx", Base);
|
||||
}
|
||||
|
||||
VirtualAllocation::~VirtualAllocation()
|
||||
|
@ -36,9 +36,9 @@ namespace Memory
|
||||
|
||||
void *VirtualMemoryArea::RequestPages(size_t Count, bool User, bool Protect)
|
||||
{
|
||||
function("%lld, %s, %s", Count,
|
||||
User ? "true" : "false",
|
||||
Protect ? "true" : "false");
|
||||
func("%lld, %s, %s", Count,
|
||||
User ? "true" : "false",
|
||||
Protect ? "true" : "false");
|
||||
|
||||
void *Address = KernelAllocator.RequestPages(Count);
|
||||
memset(Address, 0, Count * PAGE_SIZE);
|
||||
@ -61,7 +61,7 @@ namespace Memory
|
||||
|
||||
void VirtualMemoryArea::FreePages(void *Address, size_t Count)
|
||||
{
|
||||
function("%#lx, %lld", Address, Count);
|
||||
func("%#lx, %lld", Address, Count);
|
||||
|
||||
SmartLock(MgrLock);
|
||||
forItr(itr, AllocatedPagesList)
|
||||
@ -104,7 +104,7 @@ namespace Memory
|
||||
|
||||
void VirtualMemoryArea::DetachAddress(void *Address)
|
||||
{
|
||||
function("%#lx", Address);
|
||||
func("%#lx", Address);
|
||||
|
||||
SmartLock(MgrLock);
|
||||
forItr(itr, AllocatedPagesList)
|
||||
@ -128,12 +128,12 @@ namespace Memory
|
||||
bool Read, bool Write, bool Exec,
|
||||
bool Fixed, bool Shared)
|
||||
{
|
||||
function("%#lx, %lld, %s, %s, %s, %s, %s", Address, Length,
|
||||
Read ? "true" : "false",
|
||||
Write ? "true" : "false",
|
||||
Exec ? "true" : "false",
|
||||
Fixed ? "true" : "false",
|
||||
Shared ? "true" : "false");
|
||||
func("%#lx, %lld, %s, %s, %s, %s, %s", Address, Length,
|
||||
Read ? "true" : "false",
|
||||
Write ? "true" : "false",
|
||||
Exec ? "true" : "false",
|
||||
Fixed ? "true" : "false",
|
||||
Shared ? "true" : "false");
|
||||
|
||||
Virtual vmm(this->Table);
|
||||
|
||||
@ -191,7 +191,7 @@ namespace Memory
|
||||
|
||||
bool VirtualMemoryArea::HandleCoW(uintptr_t PFA)
|
||||
{
|
||||
function("%#lx", PFA);
|
||||
func("%#lx", PFA);
|
||||
Virtual vmm(this->Table);
|
||||
PageTableEntry *pte = vmm.GetPTE((void *)PFA);
|
||||
|
||||
@ -269,7 +269,7 @@ namespace Memory
|
||||
|
||||
void VirtualMemoryArea::Fork(VirtualMemoryArea *Parent)
|
||||
{
|
||||
function("%#lx", Parent);
|
||||
func("%#lx", Parent);
|
||||
assert(Parent);
|
||||
|
||||
debug("parent apl:%d sr:%d [P:%#lx C:%#lx]",
|
||||
|
@ -65,7 +65,7 @@ struct DiagnosticFile
|
||||
} Data;
|
||||
};
|
||||
|
||||
nsa bool WriteDiagDataToNode(vfs::RefNode *refFile)
|
||||
nsa bool WriteDiagDataToNode(FileNode *node)
|
||||
{
|
||||
uintptr_t KStart = (uintptr_t)&_kernel_start;
|
||||
uintptr_t kEnd = (uintptr_t)&_kernel_end;
|
||||
@ -89,8 +89,8 @@ nsa bool WriteDiagDataToNode(vfs::RefNode *refFile)
|
||||
file->Data.KernelMemoryLength = uint32_t(kSize);
|
||||
memcpy(file->Data.KernelMemory, (void *)KStart, kSize);
|
||||
|
||||
ExPrint("\eFAFAFAWriting to %s\n", refFile->node->FullPath);
|
||||
size_t w = refFile->write(buf, fileSize);
|
||||
ExPrint("\eFAFAFAWriting 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);
|
||||
@ -111,7 +111,12 @@ nsa void DiagnosticDataCollection()
|
||||
ExPrint("\n\eFAFAFAPlease wait while we collect some diagnostic information...\n");
|
||||
ExPrint("This may take a while...\n");
|
||||
|
||||
vfs::Node *panicDir = fs->CreateIfNotExists("/var/panic", vfs::DIRECTORY);
|
||||
mode_t mode = S_IRWXU |
|
||||
S_IRWXG |
|
||||
S_IROTH |
|
||||
S_IFDIR;
|
||||
|
||||
FileNode *panicDir = fs->ForceCreate(nullptr, "/var/panic", mode);
|
||||
if (!panicDir)
|
||||
{
|
||||
ExPrint("\eFF0000Failed to create /var/panic\n");
|
||||
@ -119,6 +124,7 @@ nsa void DiagnosticDataCollection()
|
||||
return;
|
||||
}
|
||||
|
||||
FileNode *dumpFile;
|
||||
Time::Clock clock = Time::ReadClock();
|
||||
char filename[64];
|
||||
for (int i = 0; i < INT32_MAX; i++)
|
||||
@ -128,18 +134,18 @@ nsa void DiagnosticDataCollection()
|
||||
if (fs->PathExists(filename, panicDir))
|
||||
continue;
|
||||
|
||||
fs->Create(filename, vfs::FILE, panicDir);
|
||||
mode = S_IRWXU |
|
||||
S_IRWXG |
|
||||
S_IROTH |
|
||||
S_IFREG;
|
||||
|
||||
dumpFile = fs->Create(panicDir, filename, mode);
|
||||
break;
|
||||
}
|
||||
|
||||
vfs::RefNode *refFile = fs->Open(filename, panicDir);
|
||||
if (!WriteDiagDataToNode(refFile))
|
||||
{
|
||||
delete refFile;
|
||||
if (!WriteDiagDataToNode(dumpFile))
|
||||
return;
|
||||
}
|
||||
|
||||
ExPrint("You can find the diagnostic file in /var/panic/%s\n", filename);
|
||||
Display->UpdateBuffer();
|
||||
delete refFile;
|
||||
}
|
||||
|
@ -517,7 +517,7 @@ nsa void DisplayStackScreen(CPU::ExceptionFrame *Frame)
|
||||
sym, offset);
|
||||
}
|
||||
else
|
||||
ExPrint("\eFF5555???\n");
|
||||
ExPrint("\eFF5555??? \eFFAAAA<- Exception\n");
|
||||
|
||||
if (!sf || !sf->ip || !sf->bp)
|
||||
{
|
||||
@ -591,7 +591,7 @@ nsa void DisplayProcessScreen(CPU::ExceptionFrame *Frame, bool IgnoreReady = tru
|
||||
if (Display->GetWidth > 800 && Display->GetHeight > 600)
|
||||
textLimit = 128;
|
||||
|
||||
std::list<Tasking::PCB *> Plist = TaskManager->GetProcessList();
|
||||
std::vector<Tasking::PCB *> Plist = TaskManager->GetProcessList();
|
||||
|
||||
ExPrint("\n\eFAFAFAProcess list (%ld):\n", Plist.size());
|
||||
bool pRdy = false;
|
||||
@ -626,7 +626,7 @@ nsa void DisplayProcessScreen(CPU::ExceptionFrame *Frame, bool IgnoreReady = tru
|
||||
Process->ID, StatusColor[Process->State.load()],
|
||||
StatusString[Process->State.load()],
|
||||
Process->Executable
|
||||
? Process->Executable->Name
|
||||
? Process->Executable->Name.c_str()
|
||||
: "none");
|
||||
|
||||
bool tRdy = false;
|
||||
@ -766,6 +766,29 @@ nsa void DisplayAssertionFailed(const char *File, int Line, const char *Expressi
|
||||
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");
|
||||
|
||||
CPU::ExceptionFrame ef;
|
||||
// Fill only the necessary fields
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wframe-address"
|
||||
|
||||
/* Jump over HandleAssertionFailed, and ip will be the function where it failed */
|
||||
void *fun = __builtin_return_address(1);
|
||||
/* Jump over this, HandleAssertionFailed & ip */
|
||||
void *stk = __builtin_frame_address(2);
|
||||
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
#ifdef __x86_64__
|
||||
asmv("movq %%cr3, %0" : "=r"(ef.cr3));
|
||||
ef.rip = (uint64_t)fun;
|
||||
ef.rbp = ef.rsp = (uint64_t)stk;
|
||||
#elif defined(__i386__)
|
||||
asmv("movl %%cr3, %0" : "=r"(ef.cr3));
|
||||
ef.eip = (uint32_t)fun;
|
||||
ef.ebp = ef.esp = (uint32_t)stk;
|
||||
#endif
|
||||
DisplayStackScreen(&ef);
|
||||
Display->UpdateBuffer();
|
||||
|
||||
/* TODO: Add additional info */
|
||||
|
@ -40,15 +40,11 @@ namespace SymbolResolver
|
||||
return Result.FunctionName;
|
||||
}
|
||||
|
||||
std::vector<SymbolTable> rSymTable = this->SymTable;
|
||||
rSymTable.reverse();
|
||||
|
||||
foreach (auto st in rSymTable)
|
||||
for (auto it = this->SymTable.rbegin(); it != this->SymTable.rend(); ++it)
|
||||
{
|
||||
if (unlikely(st.Address <= Address &&
|
||||
st.Address > Result.Address))
|
||||
if (unlikely(it->Address <= Address && it->Address > Result.Address))
|
||||
{
|
||||
Result = st;
|
||||
Result = *it;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -72,14 +68,11 @@ namespace SymbolResolver
|
||||
return Result.Address;
|
||||
}
|
||||
|
||||
std::vector<SymbolTable> rSymTable = this->SymTable;
|
||||
rSymTable.reverse();
|
||||
|
||||
foreach (auto st in rSymTable)
|
||||
for (auto it = this->SymTable.rbegin(); it != this->SymTable.rend(); ++it)
|
||||
{
|
||||
if (unlikely(strcmp(st.FunctionName, Name) == 0))
|
||||
if (unlikely(strcmp(it->FunctionName, Name) == 0))
|
||||
{
|
||||
Result = st;
|
||||
Result = *it;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user