Refactor filesystem & stl code

This commit is contained in:
EnderIce2
2024-05-18 07:42:01 +03:00
parent 77a291d08b
commit 6801475243
186 changed files with 15784 additions and 9746 deletions

View File

@ -15,35 +15,31 @@
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef __FENNIX_KERNEL_TERMIOS_H__
#define __FENNIX_KERNEL_TERMIOS_H__
#ifndef __FENNIX_KERNEL_CIRCULAR_BUFFER_H__
#define __FENNIX_KERNEL_CIRCULAR_BUFFER_H__
#include <types.h>
#include <filesystem/termios-bits.hpp>
#include <lock.hpp>
typedef unsigned char cc_t;
typedef unsigned int speed_t;
typedef unsigned int tcflag_t;
#define NCCS 32
struct termios
class CircularBuffer
{
tcflag_t c_iflag;
tcflag_t c_oflag;
tcflag_t c_cflag;
tcflag_t c_lflag;
cc_t c_line;
cc_t c_cc[NCCS];
speed_t c_ispeed;
speed_t c_ospeed;
private:
spin_lock Lock;
uint8_t *Buffer;
size_t BufferSize;
size_t BufferCount;
size_t Head;
size_t Tail;
public:
CircularBuffer(size_t Size);
~CircularBuffer();
size_t Write(const uint8_t *Data, size_t Size);
size_t Read(uint8_t *Data, size_t Size);
size_t Peek(uint8_t *Data, size_t Size);
size_t Count();
size_t Free();
};
struct winsize
{
unsigned short ws_row;
unsigned short ws_col;
unsigned short ws_xpixel;
unsigned short ws_ypixel;
};
#endif // !__FENNIX_KERNEL_TERMIOS_H__
#endif // !__FENNIX_KERNEL_CIRCULAR_BUFFER_H__

View File

@ -17,6 +17,7 @@
#pragma once
#include <types.h>
#include <ctype.h>
#ifdef __cplusplus
extern "C"
@ -31,11 +32,7 @@ extern "C"
#define NAN (__builtin_nanf(""))
int isdigit(int c);
int isspace(int c);
int isempty(char *str);
int isalpha(int c);
int isupper(int c);
unsigned int isdelim(char c, const char *delim);
long abs(long i);
void swap(char *x, char *y);

View File

@ -1,7 +1,7 @@
/*
MIT License
Copyright (c) 2020 Leonard Iklé
Copyright (c) 2024 Leonard Iklé
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@ -27,7 +27,8 @@ SOFTWARE.
#ifndef CWK_LIBRARY_H
#define CWK_LIBRARY_H
#include <types.h>
#include <stdbool.h>
#include <stddef.h>
#if defined(_WIN32) || defined(__CYGWIN__)
#define CWK_EXPORT __declspec(dllexport)
@ -344,9 +345,10 @@ CWK_PUBLIC size_t cwk_path_change_extension(const char *path,
* This function creates a normalized version of the path within the specified
* buffer. This function will not write out more than the specified buffer can
* contain. However, the generated string is always null-terminated - even if
* not the whole path is written out. The function returns the total number of
* characters the complete buffer would have, even if it was not written out
* completely. The path may be the same memory address as the buffer.
* not the whole path is written out. The returned value is the amount of
* characters which the resulting path would take if it was not truncated
* (excluding the null-terminating character). The path may be the same memory
* address as the buffer.
*
* The following will be true for the normalized path:
* 1) "../" will be resolved.
@ -518,4 +520,4 @@ CWK_PUBLIC enum cwk_path_style cwk_path_get_style(void);
} // extern "C"
#endif
#endif
#endif

View File

@ -50,11 +50,11 @@ namespace SysDbg
#ifdef DEBUG
#define debug(Format, ...) SysDbg::WriteLine(DebugLevelDebug, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
#define ubsan(Format, ...) SysDbg::WriteLine(DebugLevelUbsan, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
#define function(Format, ...) SysDbg::WriteLine(DebugLevelFunction, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
#define func(Format, ...) SysDbg::WriteLine(DebugLevelFunction, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
#else
#define debug(Format, ...)
#define ubsan(Format, ...)
#define function(Format, ...)
#define func(Format, ...)
#endif
#define trace(Format, ...) SysDbg::WriteLine(DebugLevelTrace, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
#define fixme(Format, ...) SysDbg::WriteLine(DebugLevelFixme, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
@ -89,11 +89,11 @@ void SysDbgLockedWriteLine(enum DebugLevel Level, const char *File, int Line, co
#ifdef DEBUG
#define debug(Format, ...) SysDbgWriteLine(DebugLevelDebug, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
#define ubsan(Format, ...) SysDbgWriteLine(DebugLevelUbsan, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
#define function(Format, ...) SysDbgWriteLine(DebugLevelFunction, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
#define func(Format, ...) SysDbgWriteLine(DebugLevelFunction, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
#else
#define debug(Format, ...)
#define ubsan(Format, ...)
#define function(Format, ...)
#define func(Format, ...)
#endif
#define trace(Format, ...) SysDbgWriteLine(DebugLevelTrace, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
#define fixme(Format, ...) SysDbgWriteLine(DebugLevelFixme, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)

View File

@ -24,6 +24,7 @@
#include <memory.hpp>
#include <debug.h>
#include <cstring>
#include <vector>
extern uintptr_t _binary_files_tamsyn_font_1_11_Tamsyn10x20b_psf_end;
extern uintptr_t _binary_files_tamsyn_font_1_11_Tamsyn10x20b_psf_size;

View File

@ -38,111 +38,6 @@ namespace Driver
char GetScanCode(uint8_t ScanCode, bool Upper);
bool IsValidChar(uint8_t ScanCode);
class SlaveDeviceFile : public vfs::Node
{
private:
int /* DeviceDriverType */ DeviceType;
std::list<uint8_t> KeyQueue;
public:
typedef int (*drvOpen_t)(dev_t, dev_t, int, mode_t);
typedef int (*drvClose_t)(dev_t, dev_t);
typedef size_t (*drvRead_t)(dev_t, dev_t, uint8_t *, size_t, off_t);
typedef size_t (*drvWrite_t)(dev_t, dev_t, uint8_t *, size_t, off_t);
typedef int (*drvIoctl_t)(dev_t, dev_t, unsigned long, void *);
drvOpen_t Open;
drvClose_t Close;
drvRead_t Read;
drvWrite_t Write;
drvIoctl_t Ioctl;
int open(int Flags, mode_t Mode) final;
int close() final;
size_t read(uint8_t *Buffer,
size_t Size,
off_t Offset) final;
size_t write(uint8_t *Buffer,
size_t Size,
off_t Offset) final;
int ioctl(unsigned long Request,
void *Argp) final;
void ClearBuffers();
int ReportKeyEvent(uint8_t ScanCode);
SlaveDeviceFile(const char *Name, vfs::Node *Parent, int Type, vfs::NodeType NType);
~SlaveDeviceFile();
};
class MasterDeviceFile : private vfs::Node
{
private:
typedef dev_t maj_t;
typedef dev_t min_t;
char SlaveName[16];
vfs::Node *SlaveParent;
int /* DeviceDriverType */ DeviceType;
min_t SlaveIDCounter = 0;
typedef std::unordered_map<min_t, SlaveDeviceFile *> *Slaves;
std::unordered_map<maj_t, Slaves> SlavesMap;
std::list<uint8_t> RawKeyQueue;
std::list<uint8_t> KeyQueue;
bool UpperCase = false;
bool CapsLock = false;
public:
typedef int (*drvOpen_t)(dev_t, dev_t, int, mode_t);
typedef int (*drvClose_t)(dev_t, dev_t);
typedef size_t (*drvRead_t)(dev_t, dev_t, uint8_t *, size_t, off_t);
typedef size_t (*drvWrite_t)(dev_t, dev_t, uint8_t *, size_t, off_t);
typedef int (*drvIoctl_t)(dev_t, dev_t, unsigned long, void *);
int open(int Flags, mode_t Mode) final;
int close() final;
size_t read(uint8_t *Buffer,
size_t Size,
off_t Offset) final;
size_t write(uint8_t *Buffer,
size_t Size,
off_t Offset) final;
int ioctl(unsigned long Request,
void *Argp) final;
void ClearBuffers();
int ReportKeyEvent(maj_t ID, min_t MinorID, uint8_t ScanCode);
int 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);
int ReportNetworkPacket(maj_t ID, min_t MinorID, void *Buffer, size_t Size);
int NewBlock(maj_t ID, min_t MinorID, drvOpen_t Open, drvClose_t Close,
drvRead_t Read, drvWrite_t Write, drvIoctl_t Ioctl);
int NewAudio(maj_t ID, min_t MinorID, drvOpen_t Open, drvClose_t Close,
drvRead_t Read, drvWrite_t Write, drvIoctl_t Ioctl);
int NewNet(maj_t ID, min_t MinorID, drvOpen_t Open, drvClose_t Close,
drvRead_t Read, drvWrite_t Write, drvIoctl_t Ioctl);
dev_t Register(maj_t ID);
int Unregister(maj_t ID, min_t MinorID);
MasterDeviceFile(const char *MasterName,
const char *SlaveName,
vfs::Node *Parent,
int Type);
~MasterDeviceFile();
};
struct DriverObject
{
uintptr_t BaseAddress = 0;
@ -150,7 +45,7 @@ namespace Driver
Memory::VirtualMemoryArea *vma = nullptr;
/* Path has the same pointer as in the Node */
const char *Path = nullptr;
std::string Path;
std::unordered_map<uint8_t, void *> *InterruptHandlers;
char Name[32] = {'\0'};
@ -172,28 +67,18 @@ namespace Driver
private:
NewLock(ModuleInitLock);
std::unordered_map<dev_t, DriverObject> Drivers;
dev_t MajorIDCounter = 0;
dev_t DriverIDCounter = 0;
int LoadDriverFile(uintptr_t &EntryPoint,
uintptr_t &BaseAddress,
Memory::VirtualMemoryArea *dVma,
vfs::RefNode *rDrv);
FileNode *rDrv);
public:
MasterDeviceFile *InputMouseDev = nullptr;
MasterDeviceFile *InputKeyboardDev = nullptr;
MasterDeviceFile *BlockSATADev = nullptr;
MasterDeviceFile *BlockHDDev = nullptr;
MasterDeviceFile *BlockNVMeDev = nullptr;
MasterDeviceFile *AudioDev = nullptr;
MasterDeviceFile *NetDev = nullptr;
std::unordered_map<dev_t, DriverObject> &
GetDrivers() { return Drivers; }
void PreloadDrivers();
void LoadAllDrivers();
void UnloadAllDrivers();
void Panic();

View File

@ -22,7 +22,6 @@
#include <filesystem.hpp>
#include <task.hpp>
#include <std.hpp>
#include <errno.h>
#include <vector>
#include <elf.h>
@ -36,6 +35,7 @@ namespace Execute
BinTypePE,
BinTypeNE,
BinTypeMZ,
BinTypeMachO,
BinTypeUnknown
};
@ -67,20 +67,20 @@ namespace Execute
void *ELFProgramHeaders;
void GenerateAuxiliaryVector_x86_32(Memory::VirtualMemoryArea *vma,
vfs::RefNode *fd, Elf32_Ehdr ELFHeader,
FileNode *fd, Elf32_Ehdr ELFHeader,
uint32_t EntryPoint,
uint32_t BaseAddress);
void GenerateAuxiliaryVector_x86_64(Memory::VirtualMemoryArea *vma,
vfs::RefNode *fd, Elf64_Ehdr ELFHeader,
FileNode *fd, Elf64_Ehdr ELFHeader,
uint64_t EntryPoint,
uint64_t BaseAddress);
void LoadExec_x86_32(vfs::RefNode *fd, Tasking::PCB *TargetProcess);
void LoadExec_x86_64(vfs::RefNode *fd, Tasking::PCB *TargetProcess);
void LoadDyn_x86_32(vfs::RefNode *fd, Tasking::PCB *TargetProcess);
void LoadDyn_x86_64(vfs::RefNode *fd, Tasking::PCB *TargetProcess);
bool LoadInterpreter(vfs::RefNode *fd, Tasking::PCB *TargetProcess);
void LoadExec_x86_32(FileNode *fd, Tasking::PCB *TargetProcess);
void LoadExec_x86_64(FileNode *fd, Tasking::PCB *TargetProcess);
void LoadDyn_x86_32(FileNode *fd, Tasking::PCB *TargetProcess);
void LoadDyn_x86_64(FileNode *fd, Tasking::PCB *TargetProcess);
bool LoadInterpreter(FileNode *fd, Tasking::PCB *TargetProcess);
public:
decltype(IsElfValid) &IsValid = IsElfValid;
@ -89,14 +89,15 @@ namespace Execute
decltype(ELFenvp) &envp = ELFenvp;
decltype(Elfauxv) &auxv = Elfauxv;
ELFObject(char *AbsolutePath,
ELFObject(std::string AbsolutePath,
Tasking::PCB *TargetProcess,
const char **argv,
const char **envp);
~ELFObject();
};
BinaryType GetBinaryType(const char *Path);
BinaryType GetBinaryType(FileNode *Path);
BinaryType GetBinaryType(std::string Path);
int Spawn(char *Path, const char **argv, const char **envp,
Tasking::PCB *Parent = nullptr, bool Fork = false,
@ -108,18 +109,18 @@ namespace Execute
Elf64_Shdr *GetELFSection(Elf64_Ehdr *Header, uint64_t Index);
char *GetELFStringTable(Elf64_Ehdr *Header);
char *ELFLookupString(Elf64_Ehdr *Header, uintptr_t Offset);
Elf64_Sym *ELFLookupSymbol(Elf64_Ehdr *Header, const char *Name);
Elf64_Sym ELFLookupSymbol(vfs::RefNode *fd, const char *Name);
Elf64_Sym *ELFLookupSymbol(Elf64_Ehdr *Header, std::string Name);
Elf64_Sym ELFLookupSymbol(FileNode *fd, std::string Name);
uintptr_t ELFGetSymbolValue(Elf64_Ehdr *Header, uint64_t Table, uint64_t Index);
std::vector<Elf64_Phdr> ELFGetSymbolType_x86_64(vfs::RefNode *fd, SegmentTypes Tag);
std::vector<Elf32_Phdr> ELFGetSymbolType_x86_32(vfs::RefNode *fd, SegmentTypes Tag);
std::vector<Elf64_Phdr> ELFGetSymbolType_x86_64(FileNode *fd, SegmentTypes Tag);
std::vector<Elf32_Phdr> ELFGetSymbolType_x86_32(FileNode *fd, SegmentTypes Tag);
std::vector<Elf64_Shdr> ELFGetSections_x86_64(vfs::RefNode *fd, const char *SectionName);
std::vector<Elf32_Shdr> ELFGetSections_x86_32(vfs::RefNode *fd, const char *SectionName);
std::vector<Elf64_Shdr> ELFGetSections_x86_64(FileNode *fd, std::string SectionName);
std::vector<Elf32_Shdr> ELFGetSections_x86_32(FileNode *fd, std::string SectionName);
std::vector<Elf64_Dyn> ELFGetDynamicTag_x86_64(vfs::RefNode *fd, DynamicArrayTags Tag);
std::vector<Elf32_Dyn> ELFGetDynamicTag_x86_32(vfs::RefNode *fd, DynamicArrayTags Tag);
std::vector<Elf64_Dyn> ELFGetDynamicTag_x86_64(FileNode *fd, DynamicArrayTags Tag);
std::vector<Elf32_Dyn> ELFGetDynamicTag_x86_32(FileNode *fd, DynamicArrayTags Tag);
}
#endif // !__FENNIX_KERNEL_FILE_EXECUTE_H__

View File

@ -20,309 +20,136 @@
#include <types.h>
#include <smart_ptr.hpp>
#include <interface/fs.h>
#include <unordered_map>
#include <lock.hpp>
#include <errno.h>
#include <vector>
#include <atomic>
#include <string>
#include <list>
#define SEEK_SET 0
#define SEEK_CUR 1
#define SEEK_END 2
static_assert(DTTOIF(DT_FIFO) == S_IFIFO);
static_assert(IFTODT(S_IFCHR) == DT_CHR);
/** Other users have execute permission. */
#define S_IXOTH 0001
/** Other users have write permission. */
#define S_IWOTH 0002
/** Other users have read permission. */
#define S_IROTH 0004
/** Other users have read, write, and execute permissions. */
#define S_IRWXO 0007
/** Group members have execute permission. */
#define S_IXGRP 0010
/** Group members have write permission. */
#define S_IWGRP 0020
/** Group members have read permission. */
#define S_IRGRP 0040
/** Group members have read, write, and execute permissions. */
#define S_IRWXG 0070
/** The file owner has execute permission. */
#define S_IXUSR 0100
/** The file owner has write permission. */
#define S_IWUSR 0200
/** The file owner has read permission. */
#define S_IRUSR 0400
/** The file owner has read, write,
* and execute permissions. */
#define S_IRWXU 0700
#define __check_op(op, ...) \
if (fsi->Ops.op == nullptr) \
return -ENOTSUP; \
else \
return fsi->Ops.op(this->Node, ##__VA_ARGS__)
#define O_RDONLY 00
#define O_WRONLY 01
#define O_RDWR 02
#define O_CREAT 0100
#define O_EXCL 0200
#define O_TRUNC 01000
#define O_APPEND 02000
#define O_CLOEXEC 02000000
#define S_IFIFO 0010000
#define S_IFCHR 0020000
#define S_IFDIR 0040000
#define S_IFBLK 0060000
#define S_IFREG 0100000
#define S_IFLNK 0120000
#define S_IFSOCK 0140000
#define S_IFMT 0170000
#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
#define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR)
#define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK)
#define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
#define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO)
#define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK)
#define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK)
struct kstat
class FileNode
{
/** Device ID of the file. */
dev_t st_dev;
/** Inode number. */
ino_t st_ino;
/** File type and mode. */
mode_t st_mode;
/** Number of hard links. */
nlink_t st_nlink;
/** User ID of the file's owner. */
uid_t st_uid;
/** Group ID of the file's owner. */
gid_t st_gid;
/** Device ID for special files. */
dev_t st_rdev;
/** Size of the file in bytes. */
off_t st_size;
/** Time of last access. */
time_t st_atime;
/** Time of last modification. */
time_t st_mtime;
/** Time of last status change. */
time_t st_ctime;
/** Optimal I/O block size. */
blksize_t st_blksize;
/** Number of blocks allocated. */
blkcnt_t st_blocks;
/** Additional file attributes. */
mode_t st_attr;
public:
std::string Name, Path;
FileNode *Parent;
std::vector<FileNode *> Children;
Inode *Node;
FileSystemInfo *fsi;
bool IsDirectory() { return S_ISDIR(Node->Mode); }
bool IsCharacterDevice() { return S_ISCHR(Node->Mode); }
bool IsBlockDevice() { return S_ISBLK(Node->Mode); }
bool IsRegularFile() { return S_ISREG(Node->Mode); }
bool IsFIFO() { return S_ISFIFO(Node->Mode); }
bool IsSymbolicLink() { return S_ISLNK(Node->Mode); }
bool IsSocket() { return S_ISSOCK(Node->Mode); }
int Lookup(const char *Name, Inode **Node) { __check_op(Lookup, Name, Node); }
int Create(const char *Name, mode_t Mode, Inode **Node) { __check_op(Create, Name, Mode, Node); }
int Remove(const char *Name) { __check_op(Remove, Name); }
int Rename(const char *OldName, const char *NewName) { __check_op(Rename, OldName, NewName); }
ssize_t Read(auto Buffer, size_t Size, off_t Offset) { __check_op(Read, (void *)Buffer, Size, Offset); }
ssize_t Write(const auto Buffer, size_t Size, off_t Offset) { __check_op(Write, (const void *)Buffer, Size, Offset); }
int Truncate(off_t Size) { __check_op(Truncate, Size); }
int Open(int Flags, mode_t Mode) { __check_op(Open, Flags, Mode); }
int Close() { __check_op(Close); }
int Ioctl(unsigned long Request, void *Argp) { __check_op(Ioctl, Request, Argp); }
ssize_t ReadDir(struct kdirent *Buffer, size_t Size, off_t Offset, off_t Entries) { __check_op(ReadDir, Buffer, Size, Offset, Entries); }
int MkDir(const char *Name, mode_t Mode, struct Inode **Result) { __check_op(MkDir, Name, Mode, Result); }
int RmDir(const char *Name) { __check_op(RmDir, Name); }
int SymLink(const char *Name, const char *Target, struct Inode **Result) { __check_op(SymLink, Name, Target, Result); }
ssize_t ReadLink(auto Buffer, size_t Size) { __check_op(ReadLink, (char *)Buffer, Size); }
off_t Seek(off_t Offset) { __check_op(Seek, Offset); }
int Stat(struct kstat *Stat) { __check_op(Stat, Stat); }
~FileNode() = delete;
};
static inline int ConvertFileFlags(const char *Mode)
{
int Flags = 0;
if (strchr(Mode, '+'))
Flags |= O_RDWR;
else if (*Mode == 'r')
Flags |= O_RDONLY;
else
Flags |= O_WRONLY;
if (strchr(Mode, 'x'))
Flags |= O_EXCL;
if (strchr(Mode, 'e'))
Flags |= O_CLOEXEC;
if (*Mode != 'r')
Flags |= O_CREAT;
if (*Mode == 'w')
Flags |= O_TRUNC;
if (*Mode == 'a')
Flags |= O_APPEND;
return Flags;
}
#undef __check_op
namespace vfs
{
enum NodeType : mode_t
struct vfsInode
{
NODE_TYPE_NONE = 0x0,
FILE = S_IFREG,
DIRECTORY = S_IFDIR,
CHARDEVICE = S_IFCHR,
BLOCKDEVICE = S_IFBLK,
PIPE = S_IFIFO,
SYMLINK = S_IFLNK,
MOUNTPOINT = S_IFDIR
};
class RefNode;
/**
* Virtual filesystem node
*
* @note https://isocpp.org/wiki/faq/freestore-mgmt#delete-this
*/
class Node
{
private:
NewLock(NodeLock);
public:
virtual int open(int Flags, mode_t Mode);
virtual int close();
virtual size_t read(uint8_t *Buffer, size_t Size, off_t Offset);
virtual size_t write(uint8_t *Buffer, size_t Size, off_t Offset);
virtual int ioctl(unsigned long Request, void *Argp);
// virtual int stat(struct kstat *Stat);
// virtual int lstat(struct kstat *Stat);
// virtual int fstat(struct kstat *Stat);
// virtual int unlink();
// virtual int mkdir(mode_t Mode);
// virtual int rmdir();
// virtual int rename(const char *NewName);
// virtual int chmod(mode_t Mode);
// virtual int chown(uid_t User, gid_t Group);
// virtual int truncate(off_t Size);
// virtual int symlink(const char *Target);
// virtual int readlink(char *Buffer, size_t Size);
// virtual int mount(Node *Target);
// virtual int umount();
typedef int (*open_t)(int, mode_t);
typedef int (*close_t)();
typedef size_t (*read_t)(uint8_t *, size_t, off_t);
typedef size_t (*write_t)(uint8_t *, size_t, off_t);
typedef int (*ioctl_t)(unsigned long, void *);
open_t open_ptr = nullptr;
close_t close_ptr = nullptr;
read_t read_ptr = nullptr;
write_t write_ptr = nullptr;
ioctl_t ioctl_ptr = nullptr;
class Virtual *vFS = nullptr;
Node *Parent = nullptr;
const char *Name;
const char *FullPath;
NodeType Type;
ino_t IndexNode;
const char *Symlink;
Node *SymlinkTarget;
mode_t Mode;
uid_t UserIdentifier;
gid_t GroupIdentifier;
dev_t DeviceMajor;
dev_t DeviceMinor;
time_t AccessTime;
time_t ModifyTime;
time_t ChangeTime;
off_t Size;
std::vector<Node *> Children;
std::vector<RefNode *> References;
RefNode *CreateReference();
void RemoveReference(RefNode *Reference);
/**
* Create a new node
*
* @param Parent The parent node
* @param Name The name of the node
* @param Type The type of the node
* @param NoParent If true, the Parent will
* be used as a hint for the parent node, but it
* won't be set as the parent node.
* @param fs The virtual filesystem (only if
* NoParent is set)
* @param Err If not nullptr, the function will
* write the error code to the given address.
*/
Node(Node *Parent,
const char *Name,
NodeType Type,
bool NoParent = false,
Virtual *fs = nullptr,
int *Err = nullptr);
virtual ~Node();
};
class RefNode
{
private:
std::atomic_int64_t FileOffset = 0;
off_t FileSize = 0;
Node *n;
RefNode *SymlinkTo;
public:
void *SpecialData;
decltype(FileSize) &Size = FileSize;
decltype(n) &node = n;
size_t read(uint8_t *Buffer, size_t Size);
size_t write(uint8_t *Buffer, size_t Size);
off_t seek(off_t Offset, int Whence);
int ioctl(unsigned long Request, void *Argp);
RefNode(Node *node);
~RefNode();
friend class Virtual;
friend class FileDescriptorTable;
Inode Node;
std::string Name;
std::vector<Inode *> Children;
};
class Virtual
{
private:
Node *FileSystemRoot = nullptr;
NewLock(VirtualLock);
Node *GetParent(const char *Path, Node *Parent);
/** @note This function is NOT thread safe */
Node *GetNodeFromPath_Unsafe(const char *Path, Node *Parent = nullptr);
struct FSMountInfo
{
FileSystemInfo *fsi;
Inode *Root;
};
struct CacheNode
{
FileNode *fn;
std::atomic_int References;
};
std::unordered_map<dev_t, FSMountInfo> DeviceMap;
std::atomic_bool RegisterLock = false;
FileNode *__CacheRecursiveSearch(FileNode *, const char *, bool);
FileNode *CacheLookup(const char *Path);
FileNode *CreateCacheNode(FileNode *Parent, Inode *Node, const char *Name, mode_t Mode);
int RemoveCacheNode(FileNode *Node);
public:
Node *nRoot = nullptr;
Node *GetNodeFromPath(const char *Path, Node *Parent = nullptr);
vfsInode *FileSystemRoots = nullptr;
bool PathIsRelative(const char *Path);
Node *GetRootNode() { return FileSystemRoot; }
const char *NormalizePath(const char *Path, Node *Parent = nullptr);
bool PathExists(const char *Path, Node *Parent = nullptr);
Node *Create(const char *Path, NodeType Type, Node *Parent = nullptr);
Node *CreateLink(const char *Path, const char *Target, Node *Parent);
int Delete(const char *Path, bool Recursive = false, Node *Parent = nullptr);
int Delete(Node *Path, bool Recursive = false, Node *Parent = nullptr);
bool PathIsAbsolute(const char *Path) { return !PathIsRelative(Path); }
/**
* Open a file
* @param Path The path to the file, relative or absolute. The buffer shouldn't be modified while the function is running.
* @param Parent Pointer to the parent node, if nullptr, the root node will be used.
* @return A pointer to the vfs::ReferenceNode, or nullptr if the file doesn't exist.
* Reserve a device number for a filesystem
*
* @note After this function is called, the filesystem must
* call LateRegisterFileSystem to release the lock
*/
RefNode *Open(const char *Path, Node *Parent = nullptr);
dev_t EarlyReserveDevice();
Node *CreateIfNotExists(const char *Path, NodeType Type, Node *Parent = nullptr);
/**
* Register a filesystem after the device number has been reserved
*/
int LateRegisterFileSystem(dev_t Device, FileSystemInfo *fsi, Inode *Root);
dev_t RegisterFileSystem(FileSystemInfo *fsi, Inode *Root);
int UnregisterFileSystem(dev_t Device);
void AddRoot(Inode *Root);
FileNode *GetRoot(size_t Index);
FileNode *Create(FileNode *Parent, const char *Name, mode_t Mode);
FileNode *ForceCreate(FileNode *Parent, const char *Name, mode_t Mode);
FileNode *GetByPath(const char *Path, FileNode *Parent);
FileNode *CreateLink(const char *Path, FileNode *Parent, const char *Target);
FileNode *CreateLink(const char *Path, FileNode *Parent, FileNode *Target);
bool PathExists(const char *Path, FileNode *Parent);
int Remove(FileNode *Node);
void Initialize();
Virtual();
~Virtual();
friend class Node;
};
class FileDescriptorTable
@ -330,63 +157,59 @@ namespace vfs
public:
struct Fildes
{
RefNode *Handle = nullptr;
enum FildesType
{
FD_INODE,
FD_PIPE,
FD_SOCKET,
} Type;
mode_t Mode = 0;
int Flags = 0;
int Descriptor = -1;
FileNode *Node = nullptr;
int References = 0;
off_t Offset = 0;
int operator==(const Fildes &other)
{
return this->Handle == other.Handle &&
this->Mode == other.Mode &&
this->Flags == other.Flags &&
this->Descriptor == other.Descriptor;
return Type == other.Type &&
Mode == other.Mode &&
Flags == other.Flags &&
Node == other.Node &&
References == other.References &&
Offset == other.Offset;
}
int operator!=(const Fildes &other)
{
return !(*this == other);
}
} __attribute__((packed)) nullfd;
};
private:
std::vector<Fildes> FileDescriptors;
std::vector<Fildes> FildesDuplicates;
vfs::Node *fdDir = nullptr;
FileNode *fdDir = nullptr;
void *Owner;
Fildes &GetFileDescriptor(int FileDescriptor);
FileDescriptorTable::Fildes &GetDupFildes(int FileDescriptor);
int ProbeMode(mode_t Mode, int Flags);
int AddFileDescriptor(const char *AbsolutePath, mode_t Mode, int Flags);
int RemoveFileDescriptor(int FileDescriptor);
int GetFreeFileDescriptor();
public:
Fildes &GetDescriptor(int FileDescriptor);
const char *GetAbsolutePath(int FileDescriptor);
std::vector<Fildes> &GetFileDescriptors() { return FileDescriptors; }
std::vector<Fildes> &GetFileDescriptorsDuplicates() { return FildesDuplicates; }
RefNode *GetRefNode(int FileDescriptor);
std::unordered_map<int, Fildes> FileMap;
int GetFlags(int FileDescriptor);
int SetFlags(int FileDescriptor, int Flags);
void Fork(FileDescriptorTable *Parent);
int _open(const char *pathname, int flags, mode_t mode);
int _creat(const char *pathname, mode_t mode);
ssize_t _read(int fd, void *buf, size_t count);
ssize_t _write(int fd, const void *buf, size_t count);
int _close(int fd);
off_t _lseek(int fd, off_t offset, int whence);
int _stat(const char *pathname, struct kstat *statbuf);
int _fstat(int fd, struct kstat *statbuf);
int _lstat(const char *pathname, struct kstat *statbuf);
int _dup(int oldfd);
int _dup2(int oldfd, int newfd);
int _ioctl(int fd, unsigned long request, void *argp);
int usr_open(const char *pathname, int flags, mode_t mode);
int usr_creat(const char *pathname, mode_t mode);
ssize_t usr_read(int fd, void *buf, size_t count);
ssize_t usr_write(int fd, const void *buf, size_t count);
int usr_close(int fd);
off_t usr_lseek(int fd, off_t offset, int whence);
int usr_stat(const char *pathname, struct kstat *statbuf);
int usr_fstat(int fd, struct kstat *statbuf);
int usr_lstat(const char *pathname, struct kstat *statbuf);
int usr_dup(int oldfd);
int usr_dup2(int oldfd, int newfd);
int usr_ioctl(int fd, unsigned long request, void *argp);
FileDescriptorTable(void *Owner);
~FileDescriptorTable();
~FileDescriptorTable() = default;
};
}

View File

@ -1,117 +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/>.
*/
#ifndef __FENNIX_KERNEL_FILESYSTEM_FAT_H__
#define __FENNIX_KERNEL_FILESYSTEM_FAT_H__
#include <types.h>
#include <filesystem.hpp>
namespace vfs
{
class FAT
{
public:
enum FatType
{
Unknown,
FAT12,
FAT16,
FAT32
};
/* https://wiki.osdev.org/FAT */
struct BIOSParameterBlock
{
/** The first three bytes EB 3C 90 disassemble to JMP SHORT 3C NOP.
* (The 3C value may be different.) The reason for this is to jump
* over the disk format information (the BPB and EBPB). Since the
* first sector of the disk is loaded into ram at location
* 0x0000:0x7c00 and executed, without this jump, the processor
* would attempt to execute data that isn't code. Even for
* non-bootable volumes, code matching this pattern (or using the
* E9 jump opcode) is required to be present by both Windows and
* OS X. To fulfil this requirement, an infinite loop can be placed
* here with the bytes EB FE 90. */
uint8_t JumpBoot[3];
/** OEM identifier. The first 8 Bytes (3 - 10) is the version of DOS
* being used. The next eight Bytes 29 3A 63 7E 2D 49 48 and 43 read
* out the name of the version. The official FAT Specification from
* Microsoft says that this field is really meaningless and is ignored
* by MS FAT Modules, however it does recommend the value "MSWIN4.1"
* as some 3rd party drivers supposedly check it and expect it to
* have that value. Older versions of dos also report MSDOS5.1,
* linux-formatted floppy will likely to carry "mkdosfs" here, and
* FreeDOS formatted disks have been observed to have "FRDOS5.1" here.
* If the string is less than 8 bytes, it is padded with spaces. */
uint8_t OEM[8];
/** The number of Bytes per sector (remember, all numbers are in the
* little-endian format). */
uint16_t BytesPerSector;
/** Number of sectors per cluster. */
uint8_t SectorsPerCluster;
/** Number of reserved sectors. The boot record sectors are included
* in this value. */
uint16_t ReservedSectors;
/** Number of File Allocation Tables (FAT's) on the storage media.
* Often this value is 2. */
uint8_t NumberOfFATs;
/** Number of root directory entries (must be set so that the root
* directory occupies entire sectors). */
uint16_t RootDirectoryEntries;
/** The total sectors in the logical volume. If this value is 0, it
* means there are more than 65535 sectors in the volume, and the
* actual count is stored in the Large Sector Count entry at 0x20. */
uint16_t Sectors16;
/** This Byte indicates the media descriptor type. */
uint8_t Media;
/** Number of sectors per FAT. FAT12/FAT16 only. */
uint16_t SectorsPerFAT;
/** Number of sectors per track. */
uint16_t SectorsPerTrack;
/** Number of heads or sides on the storage media. */
uint16_t NumberOfHeads;
/** Number of hidden sectors. (i.e. the LBA of the beginning of
* the partition). */
uint32_t HiddenSectors;
/** Large sector count. This field is set if there are more than
* 65535 sectors in the volume, resulting in a value which does not
* fit in the Number of Sectors entry at 0x13. */
uint32_t Sectors32;
} __packed;
FatType GetFATType(BIOSParameterBlock *bpb);
FAT(void *partition);
~FAT();
};
}
#endif // !__FENNIX_KERNEL_FILESYSTEM_FAT_H__

View File

@ -20,7 +20,7 @@
#include <types.h>
#include <stropts.h>
#include <filesystem/termios.hpp>
#include <termios.h>
#define _IOC_NRBITS 8
#define _IOC_TYPEBITS 8

View File

@ -20,184 +20,53 @@
#include <types.h>
#include <filesystem/termios.hpp>
#include <filesystem.hpp>
#include <bitmap.hpp>
#include <task.hpp>
#include <termios.h>
#include <lock.hpp>
#include <vector>
namespace vfs
{
class vfsRoot : public Node
{
public:
vfsRoot(const char *Name, Virtual *vfs_ctx);
~vfsRoot() {}
};
class NullDevice : public Node
{
public:
size_t read(uint8_t *Buffer,
size_t Size,
off_t Offset) final;
size_t write(uint8_t *Buffer,
size_t Size,
off_t Offset) final;
NullDevice();
~NullDevice();
};
class RandomDevice : public Node
{
public:
size_t read(uint8_t *Buffer,
size_t Size,
off_t Offset) final;
size_t write(uint8_t *Buffer,
size_t Size,
off_t Offset) final;
RandomDevice();
~RandomDevice();
};
class ZeroDevice : public Node
{
public:
size_t read(uint8_t *Buffer,
size_t Size,
off_t Offset) final;
size_t write(uint8_t *Buffer,
size_t Size,
off_t Offset) final;
ZeroDevice();
~ZeroDevice();
};
class KConDevice : public Node
{
public:
size_t read(uint8_t *Buffer,
size_t Size,
off_t Offset) final;
size_t write(uint8_t *Buffer,
size_t Size,
off_t Offset) final;
int ioctl(unsigned long Request,
void *Argp) final;
termios term{};
winsize termSize{};
KConDevice();
~KConDevice();
};
class TTYDevice : public Node
{
public:
size_t write(uint8_t *Buffer,
size_t Size,
off_t Offset) final;
int ioctl(unsigned long Request,
void *Argp) final;
TTYDevice();
~TTYDevice();
};
class MasterPTY
{
NewLock(PTYLock);
public:
size_t read(uint8_t *Buffer,
size_t Size,
off_t Offset);
size_t write(uint8_t *Buffer,
size_t Size,
off_t Offset);
MasterPTY();
~MasterPTY();
};
class SlavePTY
{
NewLock(PTYLock);
public:
size_t read(uint8_t *Buffer,
size_t Size,
off_t Offset);
size_t write(uint8_t *Buffer,
size_t Size,
off_t Offset);
SlavePTY();
~SlavePTY();
};
class PTYDevice : public Node
class PTYDevice
{
private:
Node *pts;
Inode *pts;
int id;
int fildes;
bool isMaster;
termios term{};
winsize termSize{};
MasterPTY *MasterDev;
SlavePTY *SlaveDev;
class PTYSlave
{
};
class PTYMaster
{
};
public:
decltype(id) &ptyId = id;
decltype(fildes) &fd = fildes;
int open(int Flags, mode_t Mode) final;
int close() final;
size_t read(uint8_t *Buffer,
size_t Size,
off_t Offset) final;
size_t write(uint8_t *Buffer,
size_t Size,
off_t Offset) final;
int ioctl(unsigned long Request,
void *Argp) final;
ssize_t Read(struct Inode *Node, void *Buffer, size_t Size, off_t Offset);
ssize_t Write(struct Inode *Node, const void *Buffer, size_t Size, off_t Offset);
int Ioctl(struct Inode *Node, unsigned long Request, void *Argp);
int OpenMaster(int Flags, mode_t Mode);
PTYDevice(Node *pts, int id);
PTYDevice(Inode *pts, int id);
~PTYDevice();
};
class PTMXDevice : public Node
class PTMXDevice
{
private:
NewLock(PTMXLock);
Node *pts;
FileNode *ptmx;
FileNode *pts;
Bitmap ptysId;
std::vector<PTYDevice *> ptysList;
std::unordered_map<size_t, PTYDevice *> ptysList;
public:
int open(int Flags, mode_t Mode) final;
/**
* Remove a PTY from the list
*
* @param fd The file descriptor of the PTY
* @param pcb The process that owns the PTY
*
* @note if pcb is nullptr, the current process
* will be used.
*
*/
void RemovePTY(int fd, Tasking::PCB *pcb = nullptr);
int Open(struct Inode *Node, int Flags, mode_t Mode, struct Inode *Result);
int Close(struct Inode *Node);
PTMXDevice();
~PTMXDevice();

View File

@ -1,160 +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/>.
*/
#ifndef __FENNIX_KERNEL_TERMIOS_BITS_H__
#define __FENNIX_KERNEL_TERMIOS_BITS_H__
/* c_cc */
#define VINTR 0
#define VQUIT 1
#define VERASE 2
#define VKILL 3
#define VEOF 4
#define VTIME 5
#define VMIN 6
#define VSWTC 7
#define VSTART 8
#define VSTOP 9
#define VSUSP 10
#define VEOL 11
#define VREPRINT 12
#define VDISCARD 13
#define VWERASE 14
#define VLNEXT 15
#define VEOL2 16
/* c_iflag */
#define IGNBRK 0000001
#define BRKINT 0000002
#define IGNPAR 0000004
#define PARMRK 0000010
#define INPCK 0000020
#define ISTRIP 0000040
#define INLCR 0000100
#define IGNCR 0000200
#define ICRNL 0000400
#define IUCLC 0001000
#define IXON 0002000
#define IXANY 0004000
#define IXOFF 0010000
#define IMAXBEL 0020000
#define IUTF8 0040000
/* c_lflag */
#define ISIG 0000001
#define ICANON 0000002
#define XCASE 0000004
#define ECHO 0000010
#define ECHOE 0000020
#define ECHOK 0000040
#define ECHONL 0000100
#define NOFLSH 0000200
#define TOSTOP 0000400
#define ECHOCTL 0001000
#define ECHOPRT 0002000
#define ECHOKE 0004000
#define FLUSHO 0010000
#define PENDIN 0040000
#define IEXTEN 0100000
#define EXTPROC 0200000
/* c_oflag */
#define OPOST 0000001
#define OLCUC 0000002
#define ONLCR 0000004
#define OCRNL 0000010
#define ONOCR 0000020
#define ONLRET 0000040
#define OFILL 0000100
#define OFDEL 0000200
#define NLDLY 0000400
#define NL0 0000000
#define NL1 0000400
#define CRDLY 0003000
#define _CR0 0000000
#define _CR1 0001000
#define _CR2 0002000
#define _CR3 0003000
#define TABDLY 0014000
#define TAB0 0000000
#define TAB1 0004000
#define TAB2 0010000
#define TAB3 0014000
#define XTABS 0014000
#define BSDLY 0020000
#define BS0 0000000
#define BS1 0020000
#define VTDLY 0040000
#define VT0 0000000
#define VT1 0040000
#define FFDLY 0100000
#define FF0 0000000
#define FF1 0100000
/* c_cflag */
#define CBAUD 0010017
#define _B0 0000000
#define B50 0000001
#define B75 0000002
#define B110 0000003
#define B134 0000004
#define B150 0000005
#define B200 0000006
#define B300 0000007
#define B600 0000010
#define B1200 0000011
#define B1800 0000012
#define B2400 0000013
#define B4800 0000014
#define B9600 0000015
#define B19200 0000016
#define B38400 0000017
#define EXTA B19200
#define EXTB B38400
#define CSIZE 0000060
#define CS5 0000000
#define CS6 0000020
#define CS7 0000040
#define CS8 0000060
#define CSTOPB 0000100
#define CREAD 0000200
#define PARENB 0000400
#define PARODD 0001000
#define HUPCL 0002000
#define CLOCAL 0004000
#define CBAUDEX 0010000
#define BOTHER 0010000
#define B57600 0010001
#define B115200 0010002
#define B230400 0010003
#define B460800 0010004
#define B500000 0010005
#define B576000 0010006
#define B921600 0010007
#define B1000000 0010010
#define B1152000 0010011
#define B1500000 0010012
#define B2000000 0010013
#define B2500000 0010014
#define B3000000 0010015
#define B3500000 0010016
#define B4000000 0010017
#define CIBAUD 002003600000
#define CMSPAR 010000000000
#define CRTSCTS 020000000000
#endif // !__FENNIX_KERNEL_TERMIOS_BITS_H__

View File

@ -18,38 +18,40 @@
#ifndef __FENNIX_KERNEL_FILESYSTEM_USTAR_H__
#define __FENNIX_KERNEL_FILESYSTEM_USTAR_H__
#include <types.h>
#include <filesystem.hpp>
namespace vfs
{
class USTARNode : public Node
{
private:
uintptr_t Address;
public:
size_t read(uint8_t *Buffer, size_t Size, off_t Offset) final;
USTARNode(uintptr_t Address, const char *Name, NodeType Type,
Virtual *vfs_ctx);
~USTARNode();
};
class USTAR
{
enum FileType
public:
enum TypeFlag
{
REGULAR_FILE = '0',
HARDLINK = '1',
SYMLINK = '2',
CHARDEV = '3',
BLOCKDEV = '4',
DIRECTORY = '5',
FIFO = '6'
AREGTYPE = '\0',
REGTYPE = '0',
LNKTYPE = '1',
SYMTYPE = '2',
CHRTYPE = '3',
BLKTYPE = '4',
DIRTYPE = '5',
FIFOTYPE = '6',
CONTTYPE = '7'
};
enum ModeFlag
{
TSUID = 04000,
TSGID = 02000,
TSVTX = 01000,
TUREAD = 00400,
TUWRITE = 00200,
TUEXEC = 00100,
TGREAD = 00040,
TGWRITE = 00020,
TGEXEC = 00010,
TOREAD = 00004,
TOWRITE = 00002,
TOEXEC = 00001,
};
struct FileHeader
@ -73,7 +75,23 @@ namespace vfs
char pad[12];
};
constexpr static int INODE_CHECKSUM = 0x7757A4;
struct USTARInode
{
struct Inode Node;
FileHeader *Header;
USTARInode *Parent;
std::string Name;
std::string Path;
std::vector<USTARInode *> Children;
bool Deleted;
int Checksum;
};
private:
std::unordered_map<ino_t, USTARInode *> Files;
inline uint32_t GetSize(const char *String)
{
uint32_t ret = 0;
@ -95,11 +113,25 @@ namespace vfs
}
public:
dev_t DeviceID = -1;
ino_t NextInode = 0;
int Lookup(struct Inode *Parent, const char *Name, struct Inode **Result);
int Create(struct Inode *Parent, const char *Name, mode_t Mode, struct Inode **Result);
ssize_t Read(struct Inode *Node, void *Buffer, size_t Size, off_t Offset);
ssize_t ReadDir(struct Inode *Node, struct kdirent *Buffer, size_t Size, off_t Offset, off_t Entries);
int SymLink(struct Inode *Node, const char *Name, const char *Target, struct Inode **Result);
ssize_t ReadLink(struct Inode *Node, char *Buffer, size_t Size);
int Stat(struct Inode *Node, struct kstat *Stat);
bool TestArchive(uintptr_t Address);
void ReadArchive(uintptr_t Address, Virtual *vfs_ctx);
USTAR();
~USTAR();
void ReadArchive(uintptr_t Address, size_t Size);
USTAR(){};
~USTAR(){};
};
}
bool TestAndInitializeUSTAR(uintptr_t Address, size_t Size);
#endif // !__FENNIX_KERNEL_FILESYSTEM_USTAR_H__

293
include/interface/driver.h Normal file
View File

@ -0,0 +1,293 @@
/*
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/>.
*/
#ifndef __FENNIX_API_DRIVER_FUNCTIONS_H__
#define __FENNIX_API_DRIVER_FUNCTIONS_H__
#include <types.h>
typedef enum
{
_drf_Entry,
_drf_Final,
_drf_Panic,
_drf_Probe,
} __driverRegFunc;
typedef union
{
struct
{
uint8_t LeftButton : 1;
uint8_t RightButton : 1;
uint8_t MiddleButton : 1;
uint8_t Button4 : 1;
uint8_t Button5 : 1;
uint8_t Button6 : 1;
uint8_t Button7 : 1;
uint8_t Button8 : 1;
};
uint8_t Value;
} __MouseButtons;
typedef struct
{
/* PCIDevice */ void *Device;
/* __PCIArray */ void *Next;
} __PCIArray;
/* ========================================== */
#define PCI_END 0x0000
#define KEY_NULL 0x00
typedef enum
{
KEY_1,
KEY_2,
KEY_3,
KEY_4,
KEY_5,
KEY_6,
KEY_7,
KEY_8,
KEY_9,
KEY_0,
KEY_Q,
KEY_W,
KEY_E,
KEY_R,
KEY_T,
KEY_Y,
KEY_U,
KEY_I,
KEY_O,
KEY_P,
KEY_A,
KEY_S,
KEY_D,
KEY_F,
KEY_G,
KEY_H,
KEY_J,
KEY_K,
KEY_L,
KEY_Z,
KEY_X,
KEY_C,
KEY_V,
KEY_B,
KEY_N,
KEY_M,
KEY_F1,
KEY_F2,
KEY_F3,
KEY_F4,
KEY_F5,
KEY_F6,
KEY_F7,
KEY_F8,
KEY_F9,
KEY_F10,
KEY_F11,
KEY_F12,
KEYPAD_7,
KEYPAD_8,
KEYPAD_9,
KEYPAD_MINUS,
KEYPAD_4,
KEYPAD_5,
KEYPAD_6,
KEYPAD_PLUS,
KEYPAD_1,
KEYPAD_2,
KEYPAD_3,
KEYPAD_0,
KEYPAD_PERIOD,
KEYPAD_RETURN,
KEYPAD_ASTERISK,
KEYPAD_SLASH,
KEY_LEFT_CTRL,
KEY_RIGHT_CTRL,
KEY_LEFT_SHIFT,
KEY_RIGHT_SHIFT,
KEY_LEFT_ALT,
KEY_RIGHT_ALT,
KEY_ESCAPE,
KEY_MINUS,
KEY_EQUAL,
KEY_BACKSPACE,
KEY_TAB,
KEY_LEFT_BRACKET,
KEY_RIGHT_BRACKET,
KEY_RETURN,
KEY_SEMICOLON,
KEY_APOSTROPHE,
KEY_BACK_TICK,
KEY_BACKSLASH,
KEY_COMMA,
KEY_PERIOD,
KEY_SLASH,
KEY_SPACE,
KEY_CAPS_LOCK,
KEY_NUM_LOCK,
KEY_SCROLL_LOCK,
KEY_PRINT_SCREEN,
KEY_HOME,
KEY_UP_ARROW,
KEY_LEFT_ARROW,
KEY_RIGHT_ARROW,
KEY_DOWN_ARROW,
KEY_PAGE_UP,
KEY_PAGE_DOWN,
KEY_END,
KEY_INSERT,
KEY_DELETE,
KEY_LEFT_GUI,
KEY_RIGHT_GUI,
KEY_APPS,
KEY_MULTIMEDIA_PREV_TRACK,
KEY_MULTIMEDIA_NEXT_TRACK,
KEY_MULTIMEDIA_MUTE,
KEY_MULTIMEDIA_CALCULATOR,
KEY_MULTIMEDIA_PLAY,
KEY_MULTIMEDIA_STOP,
KEY_MULTIMEDIA_VOL_DOWN,
KEY_MULTIMEDIA_VOL_UP,
KEY_MULTIMEDIA_WWW_HOME,
KEY_MULTIMEDIA_WWW_SEARCH,
KEY_MULTIMEDIA_WWW_FAVORITES,
KEY_MULTIMEDIA_WWW_REFRESH,
KEY_MULTIMEDIA_WWW_STOP,
KEY_MULTIMEDIA_WWW_FORWARD,
KEY_MULTIMEDIA_WWW_BACK,
KEY_MULTIMEDIA_MY_COMPUTER,
KEY_MULTIMEDIA_EMAIL,
KEY_MULTIMEDIA_MEDIA_SELECT,
KEY_ACPI_POWER,
KEY_ACPI_SLEEP,
KEY_ACPI_WAKE,
KEY_PRESSED = 0x80,
} KeyScanCodes;
typedef enum
{
IOCTL_AUDIO_GET_VOLUME = 0,
IOCTL_AUDIO_SET_VOLUME = 1,
IOCTL_AUDIO_GET_MUTE = 2,
IOCTL_AUDIO_SET_MUTE = 3,
IOCTL_AUDIO_GET_SAMPLE_RATE = 4,
IOCTL_AUDIO_SET_SAMPLE_RATE = 5,
IOCTL_AUDIO_GET_CHANNELS = 6,
IOCTL_AUDIO_SET_CHANNELS = 7,
} AudioIoctl;
typedef enum
{
IOCTL_NET_GET_MAC = 0,
} NetIoctl;
typedef enum
{
MAP_PRESENT = 1 << 0,
MAP_WRITE = 1 << 1,
MAP_USER = 1 << 2,
MAP_WRITE_THROUGH = 1 << 3,
MAP_CACHE_DISABLE = 1 << 4,
} PageMapFlags;
typedef struct
{
struct
{
uint8_t Major;
uint8_t Minor;
uint8_t Patch;
} APIVersion;
dev_t MajorID;
uintptr_t Base;
/* Internal */
int (*RegisterFunction)(dev_t MajorID, void *Function, __driverRegFunc Type);
int (*GetDriverInfo)(dev_t MajorID, const char *Name, const char *Description, const char *Author, const char *Version, const char *License);
/* Interrupts */
int (*RegisterInterruptHandler)(dev_t MajorID, uint8_t IRQ, void *Handler);
int (*OverrideInterruptHandler)(dev_t MajorID, uint8_t IRQ, void *Handler);
int (*UnregisterInterruptHandler)(dev_t MajorID, uint8_t IRQ, void *Handler);
int (*UnregisterAllInterruptHandlers)(dev_t MajorID, void *Handler);
/* /dev/... */
dev_t (*RegisterDevice)(dev_t MajorID, char Prefix[8], void *Open, void *Close, void *Read, void *Write, void *Ioctl);
int (*UnregisterDevice)(dev_t MajorID, dev_t MinorID);
/* Logging */
void (*KPrint)(dev_t MajorID, const char *Format, va_list args);
void (*KernelLog)(dev_t MajorID, const char *Format, va_list args);
/* Memory */
void *(*RequestPages)(dev_t MajorID, size_t Pages);
void (*FreePages)(dev_t MajorID, void *Pointer, size_t Pages);
/* Mapping */
void (*AppendMapFlag)(dev_t MajorID, void *Address, PageMapFlags Flag);
void (*RemoveMapFlag)(dev_t MajorID, void *Address, PageMapFlags Flag);
void (*MapPages)(dev_t MajorID, void *PhysicalAddress, void *VirtualAddress, size_t Pages, uint32_t Flags);
void (*UnmapPages)(dev_t MajorID, void *VirtualAddress, size_t Pages);
/* Scheduling */
pid_t (*CreateKernelProcess)(dev_t MajorID, const char *Name);
pid_t (*CreateKernelThread)(dev_t MajorID, pid_t pId, const char *Name, void *EntryPoint, void *Argument);
pid_t (*GetCurrentProcess)(dev_t MajorID);
int (*KillProcess)(dev_t MajorID, pid_t pId, int ExitCode);
int (*KillThread)(dev_t MajorID, pid_t tId, pid_t pId, int ExitCode);
void (*Yield)(dev_t MajorID);
void (*Sleep)(dev_t MajorID, uint64_t Milliseconds);
/* PCI */
__PCIArray *(*GetPCIDevices)(dev_t MajorID, uint16_t Vendors[], uint16_t Devices[]);
void (*InitializePCI)(dev_t MajorID, void *Header);
uint32_t (*GetBAR)(dev_t MajorID, uint8_t Index, void *Header);
/* Kernel std API */
void *(*memcpy)(dev_t MajorID, void *Destination, const void *Source, size_t Length);
void *(*memset)(dev_t MajorID, void *Destination, int Value, size_t Length);
void *(*memmove)(dev_t MajorID, void *Destination, const void *Source, size_t Length);
int (*memcmp)(dev_t MajorID, const void *Left, const void *Right, size_t Length);
size_t (*strlen)(dev_t MajorID, const char *String);
char *(*strcpy)(dev_t MajorID, char *Destination, const char *Source);
char *(*strcat)(dev_t MajorID, char *Destination, const char *Source);
int (*strcmp)(dev_t MajorID, const char *Left, const char *Right);
int (*strncmp)(dev_t MajorID, const char *Left, const char *Right, size_t Length);
char *(*strchr)(dev_t MajorID, const char *String, int Character);
char *(*strrchr)(dev_t MajorID, const char *String, int Character);
char *(*strstr)(dev_t MajorID, const char *Haystack, const char *Needle);
} __driverAPI;
#endif // !__FENNIX_API_DRIVER_FUNCTIONS_H__

604
include/interface/errno.h Normal file
View File

@ -0,0 +1,604 @@
/*
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/>.
*/
#ifndef __FENNIX_KERNEL_ERRNO_H__
#define __FENNIX_KERNEL_ERRNO_H__
/**
* The documentation for these error codes are from:
* https://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html
*
* Full list:
* https://pubs.opengroup.org/onlinepubs/9699919799.2018edition/basedefs/errno.h.html
*/
typedef enum
{
/**
* No Error
*/
EOK = 0,
/**
* Argument list too long. The sum of the number of bytes used by the
* new process image's argument list and environment list is greater
* than the system-imposed limit of {ARG_MAX} bytes.
* or:
* Lack of space in an output buffer.
* or:
* Argument is greater than the system-imposed maximum.
*/
E2BIG = 1,
/**
* Permission denied. An attempt was made to access a file in a way
* forbidden by its file access permissions.
*/
EACCES = 2,
/**
* Address in use. The specified address is in use.
*/
EADDRINUSE = 3,
/**
* Address not available. The specified address is not available from
* the local system.
*/
EADDRNOTAVAIL = 4,
/**
* Address family not supported. The implementation does not support
* the specified address family, or the specified address is not a
* valid address for the address family of the specified socket.
*/
EAFNOSUPPORT = 5,
/**
* Resource temporarily unavailable. This is a temporary condition
* and later calls to the same routine may complete normally.
*/
EAGAIN = 6,
/**
* Connection already in progress. A connection request is already in
* progress for the specified socket.
*/
EALREADY = 7,
/**
* Bad file descriptor. A file descriptor argument is out of range,
* refers to no open file, or a read (write) request is made to a
* file that is only open for writing (reading).
*/
EBADF = 8,
/**
* Bad message. During a read(), getmsg(), getpmsg(), or ioctl()
* I_RECVFD request to a STREAMS device, a message arrived at the
* head of the STREAM that is inappropriate for the function
* receiving the message.
* read()
* Message waiting to be read on a STREAM is not a data message.
* getmsg() or getpmsg()
* A file descriptor was received instead of a control message.
* ioctl()
* Control or data information was received instead of a file
* descriptor when I_RECVFD was specified.
*/
EBADMSG = 9,
/**
* Resource busy. An attempt was made to make use of a system
* resource that is not currently available, as it is being
* used by another process in a manner that would have
* conflicted with the request being made by this process.
*/
EBUSY = 10,
/**
* Operation canceled. The associated asynchronous operation was
* canceled before completion.
*/
ECANCELED = 11,
/**
* No child process. A wait(), waitid(), or waitpid() function was
* executed by a process that had no existing or unwaited-for
* child process.
*/
ECHILD = 12,
/**
* Connection aborted. The connection has been aborted.
*/
ECONNABORTED = 13,
/**
* Connection refused. An attempt to connect to a socket was refused
* because there was no process listening or because the queue of
* connection requests was full and the underlying protocol does not
* support retransmissions.
*/
ECONNREFUSED = 14,
/**
* Connection reset. The connection was forcibly closed by the peer.
*/
ECONNRESET = 15,
/**
* Resource deadlock would occur. An attempt was made to lock a system
* resource that would have resulted in a deadlock situation.
*/
EDEADLK = 16,
/**
* Destination address required. No bind address was established.
*/
EDESTADDRREQ = 17,
/**
* Domain error. An input argument is outside the defined domain of the
* mathematical function (defined in the ISO C standard).
*/
EDOM = 18,
/**
* Reserved.
*/
EDQUOT = 19,
/**
* File exists. An existing file was mentioned in an inappropriate
* context; for example, as a new link name in the link() function.
*/
EEXIST = 20,
/**
* Bad address. The system detected an invalid address in attempting
* to use an argument of a call. The reliable detection of this error
* cannot be guaranteed, and when not detected may result in the
* generation of a signal, indicating an address violation, which is
* sent to the process.
*/
EFAULT = 21,
/**
* File too large. The size of a file would exceed the maximum file
* size of an implementation or offset maximum established in the
* corresponding file description.
*/
EFBIG = 22,
/**
* Host is unreachable. The destination host cannot be reached
* (probably because the host is down or a remote router cannot
* reach it).
*/
EHOSTUNREACH = 23,
/**
* Identifier removed. Returned during XSI interprocess communication
* if an identifier has been removed from the system.
*/
EIDRM = 24,
/**
* Illegal byte sequence. A wide-character code has been detected that
* does not correspond to a valid character, or a byte sequence does
* not form a valid wide-character code (defined in the ISO C standard).
*/
EILSEQ = 25,
/**
* Operation in progress. This code is used to indicate that an
* asynchronous operation has not yet completed.
* or:
* O_NONBLOCK is set for the socket file descriptor and the connection
* cannot be immediately established.
*/
EINPROGRESS = 26,
/**
* Interrupted function call. An asynchronous signal was caught by the
* process during the execution of an interruptible function. If the
* signal handler performs a normal return, the interrupted function
* call may return this condition (see the Base Definitions volume
* of POSIX.1-2017, <signal.h>).
*/
EINTR = 27,
/**
* Invalid argument. Some invalid argument was supplied; for example,
* specifying an undefined signal in a signal() function or a
* kill() function.
*/
EINVAL = 28,
/**
* Input/output error. Some physical input or output error has occurred.
* This error may be reported on a subsequent operation on the same
* file descriptor. Any other error-causing operation on the same file
* descriptor may cause the [EIO] error indication to be lost.
*/
EIO = 29,
/**
* Socket is connected. The specified socket is already connected.
*/
EISCONN = 30,
/**
* Is a directory. An attempt was made to open a directory with write
* mode specified.
*/
EISDIR = 31,
/**
* Symbolic link loop. A loop exists in symbolic links encountered
* during pathname resolution. This error may also be returned if
* more than {SYMLOOP_MAX} symbolic links are encountered during
* pathname resolution.
*/
ELOOP = 32,
/**
* File descriptor value too large or too many open streams. An
* attempt was made to open a file descriptor with a value greater
* than or equal to {OPEN_MAX}, or an attempt was made to open more
* than the maximum number of streams allowed in the process.
*/
EMFILE = 33,
/**
* Too many links. An attempt was made to have the link count of a
* single file exceed {LINK_MAX}.
*/
EMLINK = 34,
/**
* Message too large. A message sent on a transport provider was
* larger than an internal message buffer or some other network limit.
* or:
* Inappropriate message buffer length.
*/
EMSGSIZE = 35,
/**
* Reserved.
*/
EMULTIHOP = 36,
/**
* Filename too long. The length of a pathname exceeds {PATH_MAX} and
* the implementation considers this to be an error, or a pathname
* component is longer than {NAME_MAX}. This error may also occur
* when pathname substitution, as a result of encountering a
* symbolic link during pathname resolution, results in a pathname
* string the size of which exceeds {PATH_MAX}.
*/
ENAMETOOLONG = 37,
/**
* Network is down. The local network interface used to reach the
* destination is down.
*/
ENETDOWN = 38,
/**
* The connection was aborted by the network.
*/
ENETRESET = 39,
/**
* Network unreachable. No route to the network is present.
*/
ENETUNREACH = 40,
/**
* Too many files open in system. Too many files are currently open
* in the system. The system has reached its predefined limit for
* simultaneously open files and temporarily cannot accept requests
* to open another one.
*/
ENFILE = 41,
/**
* No buffer space available. Insufficient buffer resources were
* available in the system to perform the socket operation.
*/
ENOBUFS = 42,
/**
* No message available. No message is available on the STREAM head
* read queue.
*/
ENODATA = 43,
/**
* No such device. An attempt was made to apply an inappropriate
* function to a device; for example, trying to read a write-only
* device such as a printer.
*/
ENODEV = 44,
/**
* No such file or directory. A component of a specified pathname
* does not exist, or the pathname is an empty string.
*/
ENOENT = 45,
/**
* Executable file format error. A request is made to execute a file
* that, although it has appropriate privileges, is not in the
* format required by the implementation for executable files.
*/
ENOEXEC = 46,
/**
* No locks available. A system-imposed limit on the number of
* simultaneous file and record locks has been reached and no more
* are currently available.
*/
ENOLCK = 47,
/**
* Reserved.
*/
ENOLINK = 48,
/**
* Not enough space. The new process image requires more memory than
* is allowed by the hardware or system-imposed memory management
* constraints.
*/
ENOMEM = 49,
/**
* No message of the desired type. The message queue does not contain
* a message of the required type during XSI interprocess communication.
*/
ENOMSG = 50,
/**
* Protocol not available. The protocol option specified to
* setsockopt() is not supported by the implementation.
*/
ENOPROTOOPT = 51,
/**
* No space left on a device. During the write() function on a
* regular file or when extending a directory, there is no free
* space left on the device.
*/
ENOSPC = 52,
/**
* No STREAM resources. Insufficient STREAMS memory resources are
* available to perform a STREAMS-related function. This is a
* temporary condition; it may be recovered from if other
* processes release resources.
*/
ENOSR = 53,
/**
* Not a STREAM. A STREAM function was attempted on a file descriptor
* that was not associated with a STREAMS device.
*/
ENOSTR = 54,
/**
* Functionality not supported. An attempt was made to use optional
* functionality that is not supported in this implementation.
*/
ENOSYS = 55,
/**
* Socket not connected. The socket is not connected.
*/
ENOTCONN = 56,
/**
* Not a directory. A component of the specified pathname exists, but
* it is not a directory, when a directory was expected; or an
* attempt was made to create a non-directory file, and the specified
* pathname contains at least one non- <slash> character and ends
* with one or more trailing <slash> characters.
*/
ENOTDIR = 57,
/**
* Directory not empty. A directory other than an empty directory
* was supplied when an empty directory was expected.
*/
ENOTEMPTY = 58,
/**
* State not recoverable. The state protected by a robust mutex
* is not recoverable.
*/
ENOTRECOVERABLE = 59,
/**
* Not a socket. The file descriptor does not refer to a socket.
*/
ENOTSOCK = 60,
/**
* Not supported. The implementation does not support the requested
* feature or value.
*/
ENOTSUP = 61,
/**
* Inappropriate I/O control operation. A control function has been
* attempted for a file or special file for which the operation
* is inappropriate.
*/
ENOTTY = 62,
/**
* No such device or address. Input or output on a special file
* refers to a device that does not exist, or makes a request
* beyond the capabilities of the device. It may also occur when,
* for example, a tape drive is not on-line.
*/
ENXIO = 63,
/**
* Operation not supported on socket. The type of socket (address
* family or protocol) does not support the requested operation.
*/
EOPNOTSUPP = 64,
/**
* Value too large to be stored in data type. An operation was
* attempted which would generate a value that is outside the
* range of values that can be represented in the relevant data
* type or that are allowed for a given data item.
*/
EOVERFLOW = 65,
/**
* Previous owner died. The owner of a robust mutex terminated
* while holding the mutex lock.
*/
EOWNERDEAD = 66,
/**
* Operation not permitted. An attempt was made to perform an
* operation limited to processes with appropriate privileges or
* to the owner of a file or other resource.
*/
EPERM = 67,
/**
* Broken pipe. A write was attempted on a socket, pipe, or FIFO
* for which there is no process to read the data.
*/
EPIPE = 68,
/**
* Protocol error. Some protocol error occurred. This error is
* device-specific, but is generally not related to a
* hardware failure.
*/
EPROTO = 69,
/**
* Protocol not supported. The protocol is not supported by the
* address family, or the protocol is not supported by
* the implementation.
*/
EPROTONOSUPPORT = 70,
/**
* Protocol wrong type for socket. The socket type is not
* supported by the protocol.
*/
EPROTOTYPE = 71,
/**
* Result too large or too small. The result of the function
* is too large (overflow) or too small (underflow) to be
* represented in the available space.
*/
ERANGE = 72,
/**
* Read-only file system. An attempt was made to modify a file
* or directory on a file system that is read-only.
*/
EROFS = 73,
/**
* Invalid seek. An attempt was made to access the file offset
* associated with a pipe or FIFO.
*/
ESPIPE = 74,
/**
* No such process. No process can be found corresponding to that
* specified by the given process ID.
*/
ESRCH = 75,
/**
* Reserved.
*/
ESTALE = 76,
/**
* STREAM ioctl() timeout. The timer set for a STREAMS ioctl() call
* has expired. The cause of this error is device-specific and could
* indicate either a hardware or software failure, or a timeout
* value that is too short for the specific operation. The status
* of the ioctl() operation is unspecified.
*/
ETIME = 77,
/**
* Connection timed out. The connection to a remote machine has
* timed out.
* If the connection timed out during execution of the function that
* reported this error (as opposed to timing out prior to the
* function being called), it is unspecified whether the function
* has completed some or all of the documented behavior associated
* with a successful completion of the function.
* or:
* Operation timed out. The time limit associated with the operation
* was exceeded before the operation completed.
*/
ETIMEDOUT = 78,
/**
* Text file busy. An attempt was made to execute a pure-procedure
* program that is currently open for writing, or an attempt has
* been made to open for writing a pure-procedure program that
* is being executed.
*/
ETXTBSY = 79,
/**
* Operation would block. An operation on a socket marked as
* non-blocking has encountered a situation such as no data available
* that otherwise would have caused the function to suspend execution.
*/
EWOULDBLOCK = 80,
/**
* Improper link. A link to a file on another file system was attempted.
*/
EXDEV = 81,
__ERRNO_MAX
} KernelErrors;
#include <types.h>
EXTERNC int *__errno_location(void) __attribute__((const));
#define errno (*__errno_location())
#ifdef __cplusplus
extern "C"
{
#endif
char *strerror(int errnum);
#ifdef __cplusplus
}
#endif
#endif // !__FENNIX_KERNEL_ERRNO_H__

378
include/interface/fs.h Normal file
View File

@ -0,0 +1,378 @@
/*
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/>.
*/
#ifndef __FENNIX_API_FILESYSTEM_H__
#define __FENNIX_API_FILESYSTEM_H__
#ifdef __kernel__
#include <types.h>
#endif
#define SEEK_SET 0
#define SEEK_CUR 1
#define SEEK_END 2
/**
* File type mask for the upper 32 bits of mode_t.
*
* @note Maybe it will be used in the future.
*/
#define S_IFMT32 037777600000
/**
* File type mask.
*
* This mask is used to extract the file type
* from the mode field of a stat structure.
*
* Doing bitwise AND with this mask will return
* the file type.
* Example: st_mode & S_IFMT
*
* Doing bitwise negation and AND with this mask
* will return the permissions.
* Example: st_mode & ~S_IFMT
*/
#define S_IFMT 0170000
/* Whiteout */
#define S_IFWHT 0160000
/* Socket */
#define S_IFSOCK 0140000
/* Symbolic link */
#define S_IFLNK 0120000
/* Regular file */
#define S_IFREG 0100000
/* Block device */
#define S_IFBLK 0060000
/* Directory */
#define S_IFDIR 0040000
/* Character device */
#define S_IFCHR 0020000
/* FIFO */
#define S_IFIFO 0010000
#define S_ISUID 04000
#define S_ISGID 02000
#define S_ISVTX 01000
/** Owner: RWX */
#define S_IRWXU 0700
/** Owner: R */
#define S_IRUSR 0400
/** Owner: W */
#define S_IWUSR 0200
/** Owner: X */
#define S_IXUSR 0100
/** Group: RWX */
#define S_IRWXG 0070
/** Group: R */
#define S_IRGRP 0040
/** Group: W */
#define S_IWGRP 0020
/** Group: X */
#define S_IXGRP 0010
/** Other: RWX */
#define S_IRWXO 0007
/** Other: R */
#define S_IROTH 0004
/** Other: W */
#define S_IWOTH 0002
/** Other: X */
#define S_IXOTH 0001
#define O_RDONLY 00
#define O_WRONLY 01
#define O_RDWR 02
#define O_CREAT 0100
#define O_EXCL 0200
#define O_TRUNC 01000
#define O_APPEND 02000
#define O_NOFOLLOW 0400000
#define O_CLOEXEC 02000000
#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
#define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR)
#define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK)
#define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
#define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO)
#define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK)
#define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK)
#define DT_UNKNOWN 0x0
#define DT_FIFO 0x1
#define DT_CHR 0x2
#define DT_DIR 0x4
#define DT_BLK 0x6
#define DT_REG 0x8
#define DT_LNK 0xA
#define DT_SOCK 0xC
#define DT_WHT 0xE
#define IFTODT(x) ((x) >> 12 & 0xF)
#define DTTOIF(x) ((x) << 12)
#define SYMLOOP_MAX 40
#ifndef __cplusplus
#define static_assert _Static_assert
#endif
#ifdef __LP64__
static_assert(sizeof(dev_t) == 8, "dev_t must be 64 bits");
static_assert(sizeof(ino_t) == 8, "ino_t must be 64 bits");
static_assert(sizeof(mode_t) == 4, "mode_t must be 32 bits");
static_assert(sizeof(nlink_t) == 4, "nlink_t must be 32 bits");
static_assert(sizeof(uid_t) == 4, "uid_t must be 32 bits");
static_assert(sizeof(gid_t) == 4, "gid_t must be 32 bits");
static_assert(sizeof(off_t) == 8, "off_t must be 64 bits");
static_assert(sizeof(time_t) == 8, "time_t must be 64 bits");
static_assert(sizeof(blksize_t) == 8, "blksize_t must be 64 bits");
static_assert(sizeof(blkcnt_t) == 8, "blkcnt_t must be 64 bits");
#else
static_assert(sizeof(dev_t) == 4, "dev_t must be 32 bits");
static_assert(sizeof(ino_t) == 4, "ino_t must be 32 bits");
static_assert(sizeof(mode_t) == 2, "mode_t must be 16 bits");
static_assert(sizeof(nlink_t) == 2, "nlink_t must be 16 bits");
static_assert(sizeof(uid_t) == 2, "uid_t must be 16 bits");
static_assert(sizeof(gid_t) == 2, "gid_t must be 16 bits");
static_assert(sizeof(off_t) == 4, "off_t must be 32 bits");
static_assert(sizeof(time_t) == 4, "time_t must be 32 bits");
static_assert(sizeof(blksize_t) == 4, "blksize_t must be 32 bits");
static_assert(sizeof(blkcnt_t) == 4, "blkcnt_t must be 32 bits");
#endif
#undef static_assert
struct kstat
{
/** Device ID of the file. */
dev_t Device;
/** Inode number. */
ino_t Index;
/** File type and mode. */
mode_t Mode;
/** Number of hard links. */
nlink_t HardLinks;
/** User ID of the file's owner. */
uid_t UserID;
/** Group ID of the file's owner. */
gid_t GroupID;
/** Device ID for special files. */
dev_t RawDevice;
/** Size of the file in bytes. */
off_t Size;
/** Time of last access. */
time_t AccessTime;
/** Time of last modification. */
time_t ModifyTime;
/** Time of last status change. */
time_t ChangeTime;
/** Optimal I/O block size. */
blksize_t BlockSize;
/** Number of blocks allocated. */
blkcnt_t Blocks;
/** Additional file attributes. */
mode_t Attribute;
#ifdef __cplusplus
dev_t MakeDevice(int Major, int Minor)
{
return ((Major & 0xFFF) << 8) |
(Minor & 0xFF);
}
int GetMajor()
{
return ((unsigned int)(Device) >> 8) & 0xFFF;
}
int GetMinor()
{
return Device & 0xFF;
}
void SetFileType(mode_t Type)
{
Mode = (Mode & ~S_IFMT) |
(Type & S_IFMT);
}
mode_t GetFileType() { return Mode & S_IFMT; }
void ClearFileType() { Mode = Mode & ~S_IFMT; }
bool IsType(mode_t Type) { return (Mode & S_IFMT) == Type; }
void SetPermissions(mode_t Permissions)
{
Mode = (Mode & S_IFMT) |
(Permissions & ~S_IFMT);
}
mode_t GetPermissions() { return Mode & ~S_IFMT; }
void ClearPermissions() { Mode = Mode & S_IFMT; }
#endif // __cplusplus
};
struct kdirent
{
ino_t d_ino;
off_t d_off;
unsigned short d_reclen;
unsigned char d_type;
char d_name[];
};
struct InodeOperations
{
int (*Lookup)(struct Inode *Parent, const char *Name, struct Inode **Result);
int (*Create)(struct Inode *Parent, const char *Name, mode_t Mode, struct Inode **Result);
int (*Remove)(struct Inode *Parent, const char *Name);
int (*Rename)(struct Inode *Parent, const char *OldName, const char *NewName);
ssize_t (*Read)(struct Inode *Node, void *Buffer, size_t Size, off_t Offset);
ssize_t (*Write)(struct Inode *Node, const void *Buffer, size_t Size, off_t Offset);
int (*Truncate)(struct Inode *Node, off_t Size);
int (*Open)(struct Inode *Node, int Flags, mode_t Mode);
int (*Close)(struct Inode *Node);
int (*Ioctl)(struct Inode *Node, unsigned long Request, void *Argp);
ssize_t (*ReadDir)(struct Inode *Node, struct kdirent *Buffer, size_t Size, off_t Offset, off_t Entries);
int (*MkDir)(struct Inode *Parent, const char *Name, mode_t Mode, struct Inode **Result);
int (*RmDir)(struct Inode *Parent, const char *Name);
int (*SymLink)(struct Inode *Parent, const char *Name, const char *Target, struct Inode **Result);
ssize_t (*ReadLink)(struct Inode *Node, char *Buffer, size_t Size);
off_t (*Seek)(struct Inode *Node, off_t Offset);
int (*Stat)(struct Inode *Node, struct kstat *Stat);
} __attribute__((packed));
#define I_FLAG_MOUNTPOINT 0x1
#define I_FLAG_CACHE_KEEP 0x2
struct Inode
{
dev_t Device, RawDevice;
ino_t Index;
mode_t Mode;
uint32_t Flags;
off_t Offset;
void *PrivateData;
#ifdef __cplusplus
/* ... */
void SetDevice(int Major, int Minor)
{
this->RawDevice = ((Major & 0xFFF) << 8) |
(Minor & 0xFF);
}
int GetMajor()
{
return ((unsigned int)(this->RawDevice) >> 8) & 0xFFF;
}
int GetMinor()
{
return this->RawDevice & 0xFF;
}
Inode()
{
Index = 0;
Mode = 0;
Device = 0;
RawDevice = 0;
Flags = 0;
PrivateData = nullptr;
}
~Inode() = default;
#else // __cplusplus
#define INODE_MAKEDEV(major, minor) \
((dev_t)(((major & 0xFFF) << 8) | \
(minor & 0xFF)))
#define INODE_MAJOR(rdev) \
((int)(((rdev) >> 8) & 0xFFF))
#define INODE_MINOR(rdev) \
((int)((rdev) & 0xFF))
#endif // __cplusplus
};
struct SuperBlockOperations
{
int (*AllocateInode)(struct FileSystemInfo *Info, struct Inode **Result);
int (*DeleteInode)(struct FileSystemInfo *Info, struct Inode *Node);
/**
* Synchronize the filesystem.
*
* Write all pending changes to the disk.
*
* @param Info Inode to synchronize. If NULL, synchronize all inodes.
*
* @return Zero on success, otherwise an error code.
*/
int (*Synchronize)(struct FileSystemInfo *Info, struct Inode *Node);
/**
* Destroy the filesystem.
*
* Unregister the filesystem and free all resources.
*
* @param Info Filesystem to destroy.
*
* @return Zero on success, otherwise an error code.
*/
int (*Destroy)(FileSystemInfo *Info);
} __attribute__((packed));
struct FileSystemInfo
{
const char *Name;
int Flags;
struct SuperBlockOperations SuperOps;
struct InodeOperations Ops;
void *PrivateData;
} __attribute__((packed));
dev_t RegisterFileSystem(FileSystemInfo *Info, struct Inode *Root);
int UnregisterFileSystem(dev_t Device);
#endif // !__FENNIX_API_FILESYSTEM_H__

View File

@ -0,0 +1,111 @@
/*
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/>.
*/
#ifndef __FENNIX_API_SYSCALLS_LIST_H__
#define __FENNIX_API_SYSCALLS_LIST_H__
#ifndef syscall0
static inline long syscall0(long syscall)
{
long ret;
__asm__ __volatile__("syscall"
: "=a"(ret)
: "a"(syscall)
: "rcx", "r11", "memory");
return ret;
}
#endif
#ifndef syscall1
static inline long syscall1(long syscall, long arg1)
{
long ret;
__asm__ __volatile__("syscall"
: "=a"(ret)
: "a"(syscall), "D"(arg1)
: "rcx", "r11", "memory");
return ret;
}
#endif
#ifndef syscall2
static inline long syscall2(long syscall, long arg1, long arg2)
{
long ret;
__asm__ __volatile__("syscall"
: "=a"(ret)
: "a"(syscall), "D"(arg1), "S"(arg2)
: "rcx", "r11", "memory");
return ret;
}
#endif
#ifndef syscall3
static inline long syscall3(long syscall, long arg1, long arg2, long arg3)
{
long ret;
__asm__ __volatile__("syscall"
: "=a"(ret)
: "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3)
: "rcx", "r11", "memory");
return ret;
}
#endif
#ifndef syscall4
static inline long syscall4(long syscall, long arg1, long arg2, long arg3, long arg4)
{
long ret;
register long r10 __asm__("r10") = arg4;
__asm__ __volatile__("syscall"
: "=a"(ret)
: "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3), "r"(r10)
: "rcx", "r11", "memory");
return ret;
}
#endif
#ifndef syscall5
static inline long syscall5(long syscall, long arg1, long arg2, long arg3, long arg4, long arg5)
{
long ret;
register long r10 __asm__("r10") = arg4;
register long r8 __asm__("r8") = arg5;
__asm__ __volatile__("syscall"
: "=a"(ret)
: "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3), "r"(r10), "r"(r8)
: "rcx", "r11", "memory");
return ret;
}
#endif
#ifndef syscall6
static inline long syscall6(long syscall, long arg1, long arg2, long arg3, long arg4, long arg5, long arg6)
{
long ret;
register long r10 __asm__("r10") = arg4;
register long r8 __asm__("r8") = arg5;
register long r9 __asm__("r9") = arg6;
__asm__ __volatile__("syscall"
: "=a"(ret)
: "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3), "r"(r10), "r"(r8), "r"(r9)
: "rcx", "r11", "memory");
return ret;
}
#endif
#endif // !__FENNIX_API_SYSCALLS_LIST_H__

View File

@ -15,5 +15,15 @@
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once
#include <std/smart_ptr.hpp>
#ifndef __FENNIX_KERNEL_KERNEL_CONSOLE_H__
#define __FENNIX_KERNEL_KERNEL_CONSOLE_H__
#include <termios.h>
namespace KernelConsole
{
void EarlyInit();
void LateInit();
}
#endif // !__FENNIX_KERNEL_KERNEL_CONSOLE_H__

118
include/kexcept/cxxabi.h Normal file
View File

@ -0,0 +1,118 @@
/*
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/>.
*/
#ifndef __FENNIX_KERNEL_CXXABI_H__
#define __FENNIX_KERNEL_CXXABI_H__
#include <types.h>
#include <kexcept/unwind.h>
#include <typeinfo>
namespace __cxxabiv1
{
#define ATEXIT_MAX_FUNCS 128
typedef unsigned uarch_t;
struct atexit_func_entry_t
{
void (*destructor_func)(void *);
void *obj_ptr;
void *dso_handle;
};
struct __cxa_exception
{
#ifdef __LP64__
char __padding[8];
uintptr_t referenceCount;
#endif
std::type_info *exceptionType;
void (*exceptionDestructor)(void *);
std::terminate_handler unexpectedHandler;
std::terminate_handler terminateHandler;
__cxa_exception *nextException;
int handlerCount;
#ifdef __arm__
__cxa_exception *nextPropagatingException;
int propagationCount;
#else
int handlerSwitchValue;
const unsigned char *actionRecord;
const unsigned char *languageSpecificData;
void *catchTemp;
void *adjustedPtr;
#endif
#ifndef __LP64__
uintptr_t referenceCount;
#endif
_Unwind_Exception unwindHeader;
};
struct __cxa_dependent_exception
{
#ifdef __LP64__
char __padding[8];
void *primaryException;
#endif
std::type_info *exceptionType;
void (*exceptionDestructor)(void *);
std::unexpected_handler unexpectedHandler;
std::terminate_handler terminateHandler;
__cxa_exception *nextException;
int handlerCount;
#ifdef __arm__
_Unwind_Exception *nextCleanup;
int cleanupCount;
#endif
int handlerSwitchValue;
const char *actionRecord;
const char *languageSpecificData;
void *catchTemp;
void *adjustedPtr;
#ifndef __LP64__
void *primaryException;
#endif
_Unwind_Exception unwindHeader;
};
struct __cxa_eh_globals
{
__cxa_exception *caughtExceptions;
unsigned int uncaughtExceptions;
};
enum ExceptionState
{
ES_None,
ES_Caught,
ES_Rethrown
};
}
struct ExceptionInfo
{
std::terminate_handler terminateHandler;
std::unexpected_handler unexpectedHandler;
_Unwind_Exception *exceptionObject;
__cxxabiv1::ExceptionState state;
__cxxabiv1::__cxa_eh_globals globals;
};
ExceptionInfo *GetExceptionInfo();
#endif // !__FENNIX_KERNEL_CXXABI_H__

74
include/kexcept/unwind.h Normal file
View File

@ -0,0 +1,74 @@
/*
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/>.
*/
#ifndef __FENNIX_KERNEL_UNWIND_H__
#define __FENNIX_KERNEL_UNWIND_H__
#include <types.h>
typedef enum
{
_URC_NO_REASON = 0,
_URC_FOREIGN_EXCEPTION_CAUGHT = 1,
_URC_FATAL_PHASE2_ERROR = 2,
_URC_FATAL_PHASE1_ERROR = 3,
_URC_NORMAL_STOP = 4,
_URC_END_OF_STACK = 5,
_URC_HANDLER_FOUND = 6,
_URC_INSTALL_CONTEXT = 7,
_URC_CONTINUE_UNWIND = 8
} _Unwind_Reason_Code;
typedef void *_Unwind_Context_Reg_Val;
typedef unsigned _Unwind_Exception_Class __attribute__((__mode__(__DI__)));
typedef unsigned _Unwind_Ptr __attribute__((__mode__(__pointer__)));
typedef unsigned _Unwind_Word __attribute__((__mode__(__unwind_word__)));
typedef signed _Unwind_Sword __attribute__((__mode__(__unwind_word__)));
typedef int _Unwind_Action;
#define _UA_SEARCH_PHASE 1
#define _UA_CLEANUP_PHASE 2
#define _UA_HANDLER_FRAME 4
#define _UA_FORCE_UNWIND 8
#define _UA_END_OF_STACK 16
typedef void (*_Unwind_Exception_Cleanup_Fn)(_Unwind_Reason_Code, struct _Unwind_Exception *);
typedef _Unwind_Reason_Code (*_Unwind_Personality_Fn)(int, _Unwind_Action,
_Unwind_Exception_Class,
struct _Unwind_Exception *,
struct _Unwind_Context *);
struct _Unwind_Exception
{
_Unwind_Exception_Class exception_class;
_Unwind_Exception_Cleanup_Fn exception_cleanup;
_Unwind_Word private_1;
_Unwind_Word private_2;
} __attribute__((__aligned__));
struct _Unwind_Context
{
int __stub;
};
struct _Unwind_FrameState
{
_Unwind_Personality_Fn personality;
};
#endif // !__FENNIX_KERNEL_UNWIND_H__

View File

@ -94,6 +94,25 @@ public:
~spin_lock() = default;
};
class __sl_guard
{
private:
spin_lock &sl;
public:
__sl_guard(spin_lock &sl, const char *FunctionName) : sl(sl)
{
this->sl.lock(FunctionName);
}
~__sl_guard()
{
this->sl.unlock();
}
};
#define sl_guard(sl) __sl_guard CONCAT(sl_guard_, __COUNTER__)(sl, __FUNCTION__)
/** @brief Please use this macro to create a new smart lock. */
class SmartLockClass
{

76
include/macho.h Normal file
View File

@ -0,0 +1,76 @@
/*
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/>.
*/
#ifndef __FENNIX_KERNEL_MACH_O_H__
#define __FENNIX_KERNEL_MACH_O_H__
#include <types.h>
#define MH_MAGIC 0xfeedface
#define MH_CIGAM 0xcefaedfe
#define CPU_TYPE_ANY ((cpu_type_t) - 1)
#define CPU_TYPE_VAX ((cpu_type_t)1)
#define CPU_TYPE_ROMP ((cpu_type_t)2)
#define CPU_TYPE_NS32032 ((cpu_type_t)4)
#define CPU_TYPE_NS32332 ((cpu_type_t)5)
#define CPU_TYPE_MC680x0 ((cpu_type_t)6)
#define CPU_TYPE_I386 ((cpu_type_t)7)
#define CPU_TYPE_X86_64 ((cpu_type_t)(CPU_TYPE_I386 | CPU_ARCH_ABI64))
#define CPU_TYPE_MIPS ((cpu_type_t)8)
#define CPU_TYPE_NS32532 ((cpu_type_t)9)
#define CPU_TYPE_HPPA ((cpu_type_t)11)
#define CPU_TYPE_ARM ((cpu_type_t)12)
#define CPU_TYPE_MC88000 ((cpu_type_t)13)
#define CPU_TYPE_SPARC ((cpu_type_t)14)
#define CPU_TYPE_I860 ((cpu_type_t)15)
#define CPU_TYPE_I860_LITTLE ((cpu_type_t)16)
#define CPU_TYPE_RS6000 ((cpu_type_t)17)
#define CPU_TYPE_MC98000 ((cpu_type_t)18)
#define CPU_TYPE_POWERPC ((cpu_type_t)18)
#define CPU_ARCH_ABI64 0x1000000
#define CPU_TYPE_POWERPC64 ((cpu_type_t)(CPU_TYPE_POWERPC | CPU_ARCH_ABI64))
#define CPU_TYPE_VEO ((cpu_type_t)255)
typedef int cpu_type_t;
typedef int cpu_subtype_t;
struct mach_header
{
uint32_t magic;
cpu_type_t cputype;
cpu_subtype_t cpusubtype;
uint32_t filetype;
uint32_t ncmds;
uint32_t sizeofcmds;
uint32_t flags;
};
struct mach_header_64
{
uint32_t magic;
cpu_type_t cputype;
cpu_subtype_t cpusubtype;
uint32_t filetype;
uint32_t ncmds;
uint32_t sizeofcmds;
uint32_t flags;
uint32_t reserved;
};
#endif // !__FENNIX_KERNEL_MACH_O_H__

View File

@ -23,9 +23,9 @@
#include <boot/binfo.h>
#include <bitmap.hpp>
#include <lock.hpp>
#include <std.hpp>
#include <atomic>
#include <cstddef>
#include <atomic>
#include <new>
#endif // __cplusplus
#include <types.h>
@ -53,7 +53,7 @@ namespace Memory
/**
* @warning Not working as expected.
*
*
* FIXME: This allocator is not working as expected.
*/
rpmalloc_,
@ -73,24 +73,20 @@ namespace Memory
void InitializeMemoryManagement();
void CreatePageTable(Memory::PageTable *pt);
void *operator new(std::size_t Size);
void *operator new[](std::size_t Size);
void *operator new(std::size_t Size, std::align_val_t Alignment);
void operator delete(void *Pointer);
void operator delete[](void *Pointer);
void operator delete(void *Pointer, long unsigned int Size);
void operator delete[](void *Pointer, long unsigned int Size);
extern Memory::Physical KernelAllocator;
extern Memory::PageTable *KernelPageTable;
#endif // __cplusplus
#ifndef __FENNIX_KERNEL_STDLIB_H__
EXTERNC void *malloc(size_t Size);
EXTERNC void *calloc(size_t n, size_t Size);
EXTERNC void *realloc(void *Address, size_t Size);
EXTERNC void free(void *Address);
#endif // !__FENNIX_KERNEL_STDLIB_H__
#define kmalloc(Size) malloc(Size)
#define kcalloc(n, Size) calloc(n, Size)
#define krealloc(Address, Size) realloc(Address, Size)

View File

@ -44,7 +44,7 @@ namespace Memory
void InitBrk(uintptr_t Address)
{
function("%#lx", Address);
func("%#lx", Address);
HeapStart = Address;
Break = Address;
}

View File

@ -128,7 +128,7 @@ namespace NetworkIPv4
UNUSED(DestinationIP);
UNUSED(Data);
UNUSED(Length);
warn("Not implemented.");
warn("Not implemented");
return false;
}
};

View File

@ -53,7 +53,7 @@ namespace NetworkUDP
UNUSED(Socket);
UNUSED(Data);
UNUSED(Length);
warn("Not implemented.");
warn("Not implemented");
}
};

View File

@ -58,12 +58,12 @@ namespace Tasking::Scheduler
assert(!"GetProcessByID not implemented");
}
virtual TCB *GetThreadByID(TID ID, PCB* Parent)
virtual TCB *GetThreadByID(TID ID, PCB *Parent)
{
assert(!"GetThreadByID not implemented");
}
virtual std::list<PCB *> &GetProcessList()
virtual std::vector<PCB *> &GetProcessList()
{
assert(!"GetProcessList not implemented");
}
@ -111,7 +111,7 @@ namespace Tasking::Scheduler
NewLock(SchedulerLock);
public:
std::list<PCB *> ProcessList;
std::vector<PCB *> ProcessList;
PCB *IdleProcess = nullptr;
TCB *IdleThread = nullptr;
@ -119,8 +119,8 @@ namespace Tasking::Scheduler
bool RemoveThread(TCB *tcb) final;
bool RemoveProcess(PCB *pcb) final;
PCB *GetProcessByID(TID ID) final;
TCB *GetThreadByID(TID ID, PCB* Parent) final;
std::list<PCB *> &GetProcessList() final;
TCB *GetThreadByID(TID ID, PCB *Parent) final;
std::vector<PCB *> &GetProcessList() final;
void StartIdleProcess() final;
void StartScheduler() final;
void Yield() final;

View File

@ -19,7 +19,7 @@
#define __FENNIX_KERNEL_SMP_H__
#include <task.hpp>
#include <cxxabi.h>
#include <kexcept/cxxabi.h>
#include <types.h>
#include <atomic>
@ -39,31 +39,31 @@ struct CPUArchData
struct CPUData
{
/** @brief Used by CPU */
/** Used by CPU */
uintptr_t Stack;
/** @brief CPU ID. */
/** CPU ID. */
int ID;
/** @brief Local CPU error code. */
/** Local CPU error code. */
long ErrorCode;
/** @brief Current running process */
/** Current running process */
std::atomic<Tasking::PCB *> CurrentProcess;
/** @brief Current running thread */
/** Current running thread */
std::atomic<Tasking::TCB *> CurrentThread;
/** @brief Unwind data */
__cxa_eh_globals EHGlobals;
/** Exception information. */
ExceptionInfo Exception;
/** @brief Architecture-specific data. */
/** Architecture-specific data. */
CPUArchData Data;
/** @brief Checksum. Used to verify the integrity of the data. Must be equal to CPU_DATA_CHECKSUM (0xC0FFEE). */
/** Checksum. Used to verify the integrity of the data. Must be equal to CPU_DATA_CHECKSUM (0xC0FFEE). */
int Checksum;
/** @brief Is CPU online? */
/** Is CPU online? */
bool IsActive;
} __aligned(16);

44
include/static_vector Normal file
View File

@ -0,0 +1,44 @@
/*
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 <initializer_list>
#include <cassert>
#include <cstddef>
template <typename T, std::size_t N>
class static_vector
{
private:
T m_data[N];
std::size_t m_size;
public:
constexpr static_vector() : m_size(0) {}
constexpr static_vector(std::initializer_list<T> list) : m_size(0)
{
for (const T &value : list)
{
assert(m_size < N);
m_data[m_size++] = value;
}
}
constexpr T &operator[](std::size_t index) { return m_data[index]; }
constexpr const T &operator[](std::size_t index) const { return m_data[index]; }
constexpr std::size_t size() const { return m_size; }
};

View File

@ -20,174 +20,178 @@
#include <types.h>
#define ARCH_SET_GS 0x1001
#define ARCH_SET_FS 0x1002
#define ARCH_GET_FS 0x1003
#define ARCH_GET_GS 0x1004
#define linux_SEEK_SET 0
#define linux_SEEK_CUR 1
#define linux_SEEK_END 2
#define ARCH_GET_CPUID 0x1011
#define ARCH_SET_CPUID 0x1012
#define linux_ARCH_SET_GS 0x1001
#define linux_ARCH_SET_FS 0x1002
#define linux_ARCH_GET_FS 0x1003
#define linux_ARCH_GET_GS 0x1004
#define ARCH_GET_XCOMP_SUPP 0x1021
#define ARCH_GET_XCOMP_PERM 0x1022
#define ARCH_REQ_XCOMP_PERM 0x1023
#define ARCH_GET_XCOMP_GUEST_PERM 0x1024
#define ARCH_REQ_XCOMP_GUEST_PERM 0x1025
#define linux_ARCH_GET_CPUID 0x1011
#define linux_ARCH_SET_CPUID 0x1012
#define ARCH_XCOMP_TILECFG 17
#define ARCH_XCOMP_TILEDATA 18
#define linux_ARCH_GET_XCOMP_SUPP 0x1021
#define linux_ARCH_GET_XCOMP_PERM 0x1022
#define linux_ARCH_REQ_XCOMP_PERM 0x1023
#define linux_ARCH_GET_XCOMP_GUEST_PERM 0x1024
#define linux_ARCH_REQ_XCOMP_GUEST_PERM 0x1025
#define ARCH_MAP_VDSO_X32 0x2001
#define ARCH_MAP_VDSO_32 0x2002
#define ARCH_MAP_VDSO_64 0x2003
#define linux_ARCH_XCOMP_TILECFG 17
#define linux_ARCH_XCOMP_TILEDATA 18
#define ARCH_GET_UNTAG_MASK 0x4001
#define ARCH_ENABLE_TAGGED_ADDR 0x4002
#define ARCH_GET_MAX_TAG_BITS 0x4003
#define ARCH_FORCE_TAGGED_SVA 0x4004
#define linux_ARCH_MAP_VDSO_X32 0x2001
#define linux_ARCH_MAP_VDSO_32 0x2002
#define linux_ARCH_MAP_VDSO_64 0x2003
#define PROT_NONE 0
#define PROT_READ 1
#define PROT_WRITE 2
#define PROT_EXEC 4
#define PROT_GROWSDOWN 0x01000000
#define PROT_GROWSUP 0x02000000
#define linux_ARCH_GET_UNTAG_MASK 0x4001
#define linux_ARCH_ENABLE_TAGGED_ADDR 0x4002
#define linux_ARCH_GET_MAX_TAG_BITS 0x4003
#define linux_ARCH_FORCE_TAGGED_SVA 0x4004
#define MAP_TYPE 0x0f
#define linux_PROT_NONE 0
#define linux_PROT_READ 1
#define linux_PROT_WRITE 2
#define linux_PROT_EXEC 4
#define linux_PROT_GROWSDOWN 0x01000000
#define linux_PROT_GROWSUP 0x02000000
#define MAP_FILE 0
#define MAP_SHARED 0x01
#define MAP_PRIVATE 0x02
#define MAP_SHARED_VALIDATE 0x03
#define MAP_FIXED 0x10
#define MAP_ANONYMOUS 0x20
#define MAP_NORESERVE 0x4000
#define MAP_GROWSDOWN 0x0100
#define MAP_DENYWRITE 0x0800
#define MAP_EXECUTABLE 0x1000
#define MAP_LOCKED 0x2000
#define MAP_POPULATE 0x8000
#define MAP_NONBLOCK 0x10000
#define MAP_STACK 0x20000
#define MAP_HUGETLB 0x40000
#define MAP_SYNC 0x80000
#define MAP_FIXED_NOREPLACE 0x100000
#define linux_MAP_TYPE 0x0f
#define CLOCK_REALTIME 0
#define CLOCK_MONOTONIC 1
#define CLOCK_PROCESS_CPUTIME_ID 2
#define CLOCK_THREAD_CPUTIME_ID 3
#define CLOCK_MONOTONIC_RAW 4
#define CLOCK_REALTIME_COARSE 5
#define CLOCK_MONOTONIC_COARSE 6
#define CLOCK_BOOTTIME 7
#define CLOCK_REALTIME_ALARM 8
#define CLOCK_BOOTTIME_ALARM 9
#define CLOCK_SGI_CYCLE 10
#define CLOCK_TAI 11
#define linux_MAP_FILE 0
#define linux_MAP_SHARED 0x01
#define linux_MAP_PRIVATE 0x02
#define linux_MAP_SHARED_VALIDATE 0x03
#define linux_MAP_FIXED 0x10
#define linux_MAP_ANONYMOUS 0x20
#define linux_MAP_NORESERVE 0x4000
#define linux_MAP_GROWSDOWN 0x0100
#define linux_MAP_DENYWRITE 0x0800
#define linux_MAP_EXECUTABLE 0x1000
#define linux_MAP_LOCKED 0x2000
#define linux_MAP_POPULATE 0x8000
#define linux_MAP_NONBLOCK 0x10000
#define linux_MAP_STACK 0x20000
#define linux_MAP_HUGETLB 0x40000
#define linux_MAP_SYNC 0x80000
#define linux_MAP_FIXED_NOREPLACE 0x100000
#define GRND_NONBLOCK 0x1
#define GRND_RANDOM 0x2
#define GRND_INSECURE 0x4
#define linux_CLOCK_REALTIME 0
#define linux_CLOCK_MONOTONIC 1
#define linux_CLOCK_PROCESS_CPUTIME_ID 2
#define linux_CLOCK_THREAD_CPUTIME_ID 3
#define linux_CLOCK_MONOTONIC_RAW 4
#define linux_CLOCK_REALTIME_COARSE 5
#define linux_CLOCK_MONOTONIC_COARSE 6
#define linux_CLOCK_BOOTTIME 7
#define linux_CLOCK_REALTIME_ALARM 8
#define linux_CLOCK_BOOTTIME_ALARM 9
#define linux_CLOCK_SGI_CYCLE 10
#define linux_CLOCK_TAI 11
#define RLIMIT_CPU 0
#define RLIMIT_FSIZE 1
#define RLIMIT_DATA 2
#define RLIMIT_STACK 3
#define RLIMIT_CORE 4
#define RLIMIT_RSS 5
#define RLIMIT_NPROC 6
#define RLIMIT_NOFILE 7
#define RLIMIT_MEMLOCK 8
#define RLIMIT_AS 9
#define RLIMIT_LOCKS 10
#define RLIMIT_SIGPENDING 11
#define RLIMIT_MSGQUEUE 12
#define RLIMIT_NICE 13
#define RLIMIT_RTPRIO 14
#define RLIMIT_RTTIME 15
#define RLIMIT_NLIMITS 16
#define linux_GRND_NONBLOCK 0x1
#define linux_GRND_RANDOM 0x2
#define linux_GRND_INSECURE 0x4
#define F_DUPFD 0
#define F_GETFD 1
#define F_SETFD 2
#define F_GETFL 3
#define F_SETFL 4
#define linux_RLIMIT_CPU 0
#define linux_RLIMIT_FSIZE 1
#define linux_RLIMIT_DATA 2
#define linux_RLIMIT_STACK 3
#define linux_RLIMIT_CORE 4
#define linux_RLIMIT_RSS 5
#define linux_RLIMIT_NPROC 6
#define linux_RLIMIT_NOFILE 7
#define linux_RLIMIT_MEMLOCK 8
#define linux_RLIMIT_AS 9
#define linux_RLIMIT_LOCKS 10
#define linux_RLIMIT_SIGPENDING 11
#define linux_RLIMIT_MSGQUEUE 12
#define linux_RLIMIT_NICE 13
#define linux_RLIMIT_RTPRIO 14
#define linux_RLIMIT_RTTIME 15
#define linux_RLIMIT_NLIMITS 16
#define F_SETOWN 8
#define F_GETOWN 9
#define F_SETSIG 10
#define F_GETSIG 11
#define linux_F_DUPFD 0
#define linux_F_GETFD 1
#define linux_F_SETFD 2
#define linux_F_GETFL 3
#define linux_F_SETFL 4
#define linux_F_SETOWN 8
#define linux_F_GETOWN 9
#define linux_F_SETSIG 10
#define linux_F_GETSIG 11
#if __LONG_MAX == 0x7fffffffL
#define F_GETLK 12
#define F_SETLK 13
#define F_SETLKW 14
#define linux_F_GETLK 12
#define linux_F_SETLK 13
#define linux_F_SETLKW 14
#else
#define F_GETLK 5
#define F_SETLK 6
#define F_SETLKW 7
#define linux_F_GETLK 5
#define linux_F_SETLK 6
#define linux_F_SETLKW 7
#endif
#define F_SETOWN_EX 15
#define F_GETOWN_EX 16
#define F_GETOWNER_UIDS 17
#define linux_F_SETOWN_EX 15
#define linux_F_GETOWN_EX 16
#define linux_F_GETOWNER_UIDS 17
#define F_OFD_GETLK 36
#define F_OFD_SETLK 37
#define F_OFD_SETLKW 38
#define linux_F_OFD_GETLK 36
#define linux_F_OFD_SETLK 37
#define linux_F_OFD_SETLKW 38
#define F_DUPFD_CLOEXEC 1030
#define linux_F_DUPFD_CLOEXEC 1030
#define FD_CLOEXEC 1
#define linux_FD_CLOEXEC 1
#define DT_UNKNOWN 0
#define DT_FIFO 1
#define DT_CHR 2
#define DT_DIR 4
#define DT_BLK 6
#define DT_REG 8
#define DT_LNK 10
#define DT_SOCK 12
#define DT_WHT 14
#define linux_DT_UNKNOWN 0
#define linux_DT_FIFO 1
#define linux_DT_CHR 2
#define linux_DT_DIR 4
#define linux_DT_BLK 6
#define linux_DT_REG 8
#define linux_DT_LNK 10
#define linux_DT_SOCK 12
#define linux_DT_WHT 14
#define AT_FDCWD (-100)
#define AT_SYMLINK_NOFOLLOW 0x100
#define AT_REMOVEDIR 0x200
#define AT_SYMLINK_FOLLOW 0x400
#define AT_EACCESS 0x200
#define AT_NO_AUTOMOUNT 0x800
#define AT_EMPTY_PATH 0x1000
#define AT_STATX_SYNC_TYPE 0x6000
#define AT_STATX_SYNC_AS_STAT 0x0000
#define AT_STATX_FORCE_SYNC 0x2000
#define AT_STATX_DONT_SYNC 0x4000
#define AT_RECURSIVE 0x8000
#define linux_AT_FDCWD (-100)
#define linux_AT_SYMLINK_NOFOLLOW 0x100
#define linux_AT_REMOVEDIR 0x200
#define linux_AT_SYMLINK_FOLLOW 0x400
#define linux_AT_EACCESS 0x200
#define linux_AT_NO_AUTOMOUNT 0x800
#define linux_AT_EMPTY_PATH 0x1000
#define linux_AT_STATX_SYNC_TYPE 0x6000
#define linux_AT_STATX_SYNC_AS_STAT 0x0000
#define linux_AT_STATX_FORCE_SYNC 0x2000
#define linux_AT_STATX_DONT_SYNC 0x4000
#define linux_AT_RECURSIVE 0x8000
#define LINUX_REBOOT_MAGIC1 0xfee1dead
#define LINUX_REBOOT_MAGIC2 0x28121969
#define LINUX_REBOOT_MAGIC2A 0x05121996
#define LINUX_REBOOT_MAGIC2B 0x16041998
#define LINUX_REBOOT_MAGIC2C 0x20112000
#define linux_LINUX_REBOOT_MAGIC1 0xfee1dead
#define linux_LINUX_REBOOT_MAGIC2 0x28121969
#define linux_LINUX_REBOOT_MAGIC2A 0x05121996
#define linux_LINUX_REBOOT_MAGIC2B 0x16041998
#define linux_LINUX_REBOOT_MAGIC2C 0x20112000
#define LINUX_REBOOT_CMD_RESTART 0x01234567
#define LINUX_REBOOT_CMD_HALT 0xCDEF0123
#define LINUX_REBOOT_CMD_CAD_ON 0x89ABCDEF
#define LINUX_REBOOT_CMD_CAD_OFF 0x00000000
#define LINUX_REBOOT_CMD_POWER_OFF 0x4321FEDC
#define LINUX_REBOOT_CMD_RESTART2 0xA1B2C3D4
#define LINUX_REBOOT_CMD_SW_SUSPEND 0xD000FCE2
#define LINUX_REBOOT_CMD_KEXEC 0x45584543
#define linux_LINUX_REBOOT_CMD_RESTART 0x01234567
#define linux_LINUX_REBOOT_CMD_HALT 0xCDEF0123
#define linux_LINUX_REBOOT_CMD_CAD_ON 0x89ABCDEF
#define linux_LINUX_REBOOT_CMD_CAD_OFF 0x00000000
#define linux_LINUX_REBOOT_CMD_POWER_OFF 0x4321FEDC
#define linux_LINUX_REBOOT_CMD_RESTART2 0xA1B2C3D4
#define linux_LINUX_REBOOT_CMD_SW_SUSPEND 0xD000FCE2
#define linux_LINUX_REBOOT_CMD_KEXEC 0x45584543
#define SA_IMMUTABLE 0x00800000
#define linux_SA_IMMUTABLE 0x00800000
#define ITIMER_REAL 0
#define ITIMER_VIRTUAL 1
#define ITIMER_PROF 2
#define linux_ITIMER_REAL 0
#define linux_ITIMER_VIRTUAL 1
#define linux_ITIMER_PROF 2
#define RUSAGE_SELF 0
#define RUSAGE_CHILDREN (-1)
#define RUSAGE_THREAD 1
#define linux_RUSAGE_SELF 0
#define linux_RUSAGE_CHILDREN (-1)
#define linux_RUSAGE_THREAD 1
typedef long __kernel_long_t;
typedef unsigned long __kernel_ulong_t;
@ -249,19 +253,24 @@ struct rusage
struct linux_dirent
{
unsigned long d_ino; /* Inode number */
unsigned long d_off; /* Offset to next linux_dirent */
unsigned short d_reclen; /* Length of this linux_dirent */
char d_name[]; /* Filename (null-terminated) */
unsigned long d_ino;
unsigned long d_off;
unsigned short d_reclen;
char d_name[];
/**
* Getting d_type is not the same as linux_dirent64:
* https://github.com/torvalds/linux/blob/bfa8f18691ed2e978e4dd51190569c434f93e268/fs/readdir.c#L296
* "man 2 getdents" also is helpful
*/
};
struct linux_dirent64
{
ino64_t d_ino; /* 64-bit inode number */
off64_t d_off; /* 64-bit offset to next structure */
unsigned short d_reclen; /* Size of this dirent */
unsigned char d_type; /* File type */
char d_name[]; /* Filename (null-terminated) */
uint64_t d_ino;
int64_t d_off;
unsigned short d_reclen;
unsigned char d_type;
char d_name[];
};
struct linux_kstat

View File

@ -0,0 +1,408 @@
/*
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/>.
*/
#ifndef __FENNIX_KERNEL_LINUX_ERRNO_H__
#define __FENNIX_KERNEL_LINUX_ERRNO_H__
/** Operation not permitted */
#define linux_EPERM 1
/** No such file or directory */
#define linux_ENOENT 2
/** No such process */
#define linux_ESRCH 3
/** Interrupted system call */
#define linux_EINTR 4
/** I/O error */
#define linux_EIO 5
/** No such device or address */
#define linux_ENXIO 6
/** Argument list too long */
#define linux_E2BIG 7
/** Exec format error */
#define linux_ENOEXEC 8
/** Bad file number */
#define linux_EBADF 9
/** No child processes */
#define linux_ECHILD 10
/** Try again */
#define linux_EAGAIN 11
/** Out of memory */
#define linux_ENOMEM 12
/** Permission denied */
#define linux_EACCES 13
/** Bad address */
#define linux_EFAULT 14
/** Block device required */
#define linux_ENOTBLK 15
/** Device or resource busy */
#define linux_EBUSY 16
/** File exists */
#define linux_EEXIST 17
/** Cross-device link */
#define linux_EXDEV 18
/** No such device */
#define linux_ENODEV 19
/** Not a directory */
#define linux_ENOTDIR 20
/** Is a directory */
#define linux_EISDIR 21
/** Invalid argument */
#define linux_EINVAL 22
/** File table overflow */
#define linux_ENFILE 23
/** Too many open files */
#define linux_EMFILE 24
/** Not a typewriter */
#define linux_ENOTTY 25
/** Text file busy */
#define linux_ETXTBSY 26
/** File too large */
#define linux_EFBIG 27
/** No space left on device */
#define linux_ENOSPC 28
/** Illegal seek */
#define linux_ESPIPE 29
/** Read-only file system */
#define linux_EROFS 30
/** Too many links */
#define linux_EMLINK 31
/** Broken pipe */
#define linux_EPIPE 32
/** Math argument out of domain of func */
#define linux_EDOM 33
/** Math result not representable */
#define linux_ERANGE 34
/** Resource deadlock would occur */
#define linux_EDEADLK 35
/** File name too long */
#define linux_ENAMETOOLONG 36
/** No record locks available */
#define linux_ENOLCK 37
/** Function not implemented */
#define linux_ENOSYS 38
/** Directory not empty */
#define linux_ENOTEMPTY 39
/** Too many symbolic links encountered */
#define linux_ELOOP 40
/** No message of desired type */
#define linux_ENOMSG 42
/** Identifier removed */
#define linux_EIDRM 43
/** Channel number out of range */
#define linux_ECHRNG 44
/** Level 2 not synchronized */
#define linux_EL2NSYNC 45
/** Level 3 halted */
#define linux_EL3HLT 46
/** Level 3 reset */
#define linux_EL3RST 47
/** Link number out of range */
#define linux_ELNRNG 48
/** Protocol driver not attached */
#define linux_EUNATCH 49
/** No CSI structure available */
#define linux_ENOCSI 50
/** Level 2 halted */
#define linux_EL2HLT 51
/** Invalid exchange */
#define linux_EBADE 52
/** Invalid request descriptor */
#define linux_EBADR 53
/** Exchange full */
#define linux_EXFULL 54
/** No anode */
#define linux_ENOANO 55
/** Invalid request code */
#define linux_EBADRQC 56
/** Invalid slot */
#define linux_EBADSLT 57
/** Bad font file format */
#define linux_EBFONT 59
/** Device not a stream */
#define linux_ENOSTR 60
/** No data available */
#define linux_ENODATA 61
/** Timer expired */
#define linux_ETIME 62
/** Out of streams resources */
#define linux_ENOSR 63
/** Machine is not on the network */
#define linux_ENONET 64
/** Package not installed */
#define linux_ENOPKG 65
/** Object is remote */
#define linux_EREMOTE 66
/** Link has been severed */
#define linux_ENOLINK 67
/** Advertise error */
#define linux_EADV 68
/** Srmount error */
#define linux_ESRMNT 69
/** Communication error on send */
#define linux_ECOMM 70
/** Protocol error */
#define linux_EPROTO 71
/** Multihop attempted */
#define linux_EMULTIHOP 72
/** RFS specific error */
#define linux_EDOTDOT 73
/** Not a data message */
#define linux_EBADMSG 74
/** Value too large for defined data type */
#define linux_EOVERFLOW 75
/** Name not unique on network */
#define linux_ENOTUNIQ 76
/** File descriptor in bad state */
#define linux_EBADFD 77
/** Remote address changed */
#define linux_EREMCHG 78
/** Can not access a needed shared library */
#define linux_ELIBACC 79
/** Accessing a corrupted shared library */
#define linux_ELIBBAD 80
/** .lib section in a.out corrupted */
#define linux_ELIBSCN 81
/** Attempting to link in too many shared libraries */
#define linux_ELIBMAX 82
/** Cannot exec a shared library directly */
#define linux_ELIBEXEC 83
/** Illegal byte sequence */
#define linux_EILSEQ 84
/** Interrupted system call should be restarted */
#define linux_ERESTART 85
/** Streams pipe error */
#define linux_ESTRPIPE 86
/** Too many users */
#define linux_EUSERS 87
/** Socket operation on non-socket */
#define linux_ENOTSOCK 88
/** Destination address required */
#define linux_EDESTADDRREQ 89
/** Message too long */
#define linux_EMSGSIZE 90
/** Protocol wrong type for socket */
#define linux_EPROTOTYPE 91
/** Protocol not available */
#define linux_ENOPROTOOPT 92
/** Protocol not supported */
#define linux_EPROTONOSUPPORT 93
/** Socket type not supported */
#define linux_ESOCKTNOSUPPORT 94
/** Operation not supported on transport endpoint */
#define linux_EOPNOTSUPP 95
/** Protocol family not supported */
#define linux_EPFNOSUPPORT 96
/** Address family not supported by protocol */
#define linux_EAFNOSUPPORT 97
/** Address already in use */
#define linux_EADDRINUSE 98
/** Cannot assign requested address */
#define linux_EADDRNOTAVAIL 99
/** Network is down */
#define linux_ENETDOWN 100
/** Network is unreachable */
#define linux_ENETUNREACH 101
/** Network dropped connection because of reset */
#define linux_ENETRESET 102
/** Software caused connection abort */
#define linux_ECONNABORTED 103
/** Connection reset by peer */
#define linux_ECONNRESET 104
/** No buffer space available */
#define linux_ENOBUFS 105
/** Transport endpoint is already connected */
#define linux_EISCONN 106
/** Transport endpoint is not connected */
#define linux_ENOTCONN 107
/** Cannot send after transport endpoint shutdown */
#define linux_ESHUTDOWN 108
/** Too many references: cannot splice */
#define linux_ETOOMANYREFS 109
/** Connection timed out */
#define linux_ETIMEDOUT 110
/** Connection refused */
#define linux_ECONNREFUSED 111
/** Host is down */
#define linux_EHOSTDOWN 112
/** No route to host */
#define linux_EHOSTUNREACH 113
/** Operation already in progress */
#define linux_EALREADY 114
/** Operation now in progress */
#define linux_EINPROGRESS 115
/** Stale NFS file handle */
#define linux_ESTALE 116
/** Structure needs cleaning */
#define linux_EUCLEAN 117
/** Not a XENIX named type file */
#define linux_ENOTNAM 118
/** No XENIX semaphores available */
#define linux_ENAVAIL 119
/** Is a named type file */
#define linux_EISNAM 120
/** Remote I/O error */
#define linux_EREMOTEIO 121
/** Quota exceeded */
#define linux_EDQUOT 122
/** No medium found */
#define linux_ENOMEDIUM 123
/** Wrong medium type */
#define linux_EMEDIUMTYPE 124
/** Operation Canceled */
#define linux_ECANCELED 125
/** Required key not available */
#define linux_ENOKEY 126
/** Key has expired */
#define linux_EKEYEXPIRED 127
/** Key has been revoked */
#define linux_EKEYREVOKED 128
/** Key was rejected by service */
#define linux_EKEYREJECTED 129
/** Owner died */
#define linux_EOWNERDEAD 130
/** State not recoverable */
#define linux_ENOTRECOVERABLE 131
#endif // !__FENNIX_KERNEL_LINUX_ERRNO_H__

View File

@ -26,12 +26,13 @@
#include <memory.hpp>
#include <signal.hpp>
#include <ints.hpp>
#include <kexcept/cxxabi.h>
#include <debug.h>
#include <cwalk.h>
#include <vector>
#include <atomic>
#include <vector>
#include <abi.h>
#include <list>
#define RLIM_INFINITY (~0ULL)
@ -45,7 +46,6 @@ struct rlimit
namespace Tasking
{
using vfs::FileDescriptorTable;
using vfs::Node;
/** Instruction Pointer */
typedef __UINTPTR_TYPE__ IP;
@ -212,6 +212,7 @@ namespace Tasking
TaskArchitecture Architecture = TaskArchitecture::UnknownArchitecture;
TaskCompatibility Compatibility = TaskCompatibility::UnknownPlatform;
cwk_path_style PathStyle = CWK_STYLE_UNIX;
FileNode *RootNode = nullptr;
};
struct ThreadLocalStorage
@ -334,7 +335,7 @@ namespace Tasking
class PCB *Parent = nullptr;
IP EntryPoint = 0;
/* Statuses */
/* Status */
std::atomic_int ExitCode;
std::atomic<TaskState> State = TaskState::Waiting;
int ErrorNumber;
@ -377,6 +378,9 @@ namespace Tasking
pid_t tgid = 0;
} Linux{};
/* Kernel Exceptions */
ExceptionInfo KernelException{};
int SendSignal(int sig);
void SetState(TaskState state);
void SetExitCode(int code);
@ -411,7 +415,7 @@ namespace Tasking
~TCB();
};
class PCB : public vfs::Node
class PCB
{
private:
class Task *ctx = nullptr;
@ -434,6 +438,7 @@ namespace Tasking
PID ID = -1;
const char *Name = nullptr;
PCB *Parent = nullptr;
FileNode *ProcDirectory = nullptr;
/* Statuses */
std::atomic_int ExitCode;
@ -464,14 +469,14 @@ namespace Tasking
ThreadLocalStorage TLS{};
/* Filesystem */
Node *CurrentWorkingDirectory;
Node *Executable;
FileNode *CWD;
FileNode *Executable;
FileDescriptorTable *FileDescriptors;
/* stdio */
Node *stdin;
Node *stdout;
Node *stderr;
FileNode *stdin;
FileNode *stdout;
FileNode *stderr;
/* Memory */
Memory::PageTable *PageTable;
@ -480,12 +485,13 @@ namespace Tasking
/* Other */
Signal Signals;
mode_t FileCreationMask = S_IRUSR | S_IWUSR | S_IRGRP |
S_IWGRP | S_IROTH | S_IWOTH;
mode_t FileCreationMask = S_IRUSR | S_IWUSR |
S_IRGRP | S_IWGRP |
S_IROTH | S_IWOTH;
/* Threads & Children */
std::list<TCB *> Threads;
std::list<PCB *> Children;
std::vector<TCB *> Threads;
std::vector<PCB *> Children;
public:
class Task *GetContext() { return ctx; }
@ -494,7 +500,7 @@ namespace Tasking
void SetState(TaskState state);
void SetExitCode(int code);
void Rename(const char *name);
void SetWorkingDirectory(Node *node);
void SetWorkingDirectory(FileNode *node);
void SetExe(const char *path);
size_t GetSize();
TCB *GetThread(TID ID);
@ -538,7 +544,7 @@ namespace Tasking
public:
void *GetScheduler() { return Scheduler; }
PCB *GetKernelProcess() { return KernelProcess; }
std::list<PCB *> GetProcessList();
std::vector<PCB *> GetProcessList();
void Panic();
bool IsPanic();

View File

@ -18,6 +18,8 @@
#ifndef __FENNIX_KERNEL_TYPES_H__
#define __FENNIX_KERNEL_TYPES_H__
#include <stdbool.h>
#ifdef __cplusplus
#define EXTERNC extern "C"
#define START_EXTERNC \
@ -35,15 +37,11 @@
#define NULL 0
#else // __cplusplus
#define NULL ((void *)0)
#define bool _Bool
#endif // __cplusplus
#define asm __asm__
#define asmv __asm__ volatile
#define true 1
#define false 0
#define inf_loop while (1)
#define ilp inf_loop; /* Used for debugging */
@ -64,11 +62,6 @@
#define UNUSED(x) (void)(x)
#define CONCAT(x, y) x##y
#ifndef __cplusplus /* This conflicts with std */
#define toupper(c) ((c)-0x20 * (((c) >= 'a') && ((c) <= 'z')))
#define tolower(c) ((c) + 0x20 * (((c) >= 'A') && ((c) <= 'Z')))
#endif
#ifndef __va_list__
typedef __builtin_va_list va_list;
#endif
@ -77,8 +70,8 @@ typedef __builtin_va_list va_list;
#define va_end(v) __builtin_va_end(v)
#define va_arg(v, l) __builtin_va_arg(v, l)
#define ALIGN_UP(x, align) ((__typeof__(x))(((uintptr_t)(x) + ((align)-1)) & (~((align)-1))))
#define ALIGN_DOWN(x, align) ((__typeof__(x))((x) & (~((align)-1))))
#define ALIGN_UP(x, align) ((__typeof__(x))(((uintptr_t)(x) + ((align) - 1)) & (~((align) - 1))))
#define ALIGN_DOWN(x, align) ((__typeof__(x))((x) & (~((align) - 1))))
#define offsetof(type, member) __builtin_offsetof(type, member)
@ -96,8 +89,8 @@ typedef __builtin_va_list va_list;
_a < _b ? _a : _b; \
})
#define ROUND_UP(x, y) (((x) + (y)-1) & ~((y)-1))
#define ROUND_DOWN(x, y) ((x) & ~((y)-1))
#define ROUND_UP(x, y) (((x) + (y) - 1) & ~((y) - 1))
#define ROUND_DOWN(x, y) ((x) & ~((y) - 1))
#define VPOKE(type, address) (*((volatile type *)(address)))
#define POKE(type, address) (*((type *)(address)))
@ -399,21 +392,53 @@ typedef uint48_t uint_fast48_t;
(((x) & 0xff0000000000) >> 40)))
#define b64(x) __builtin_bswap64(x)
/* https://gcc.gnu.org/onlinedocs/gcc-9.5.0/gnat_ugn/Optimization-Levels.html */
/* https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html */
/** @brief No optimization (the default); generates unoptimized code but has the fastest compilation time. */
/** No optimization (the default); generates
* unoptimized code but has the fastest compilation time.
*/
#define O0 __attribute__((optimize("O0")))
/** @brief Moderate optimization; optimizes reasonably well but does not degrade compilation time significantly. */
/** Moderate optimization;
* optimizes reasonably well but does not degrade
* compilation time significantly. */
#define O1 __attribute__((optimize("O1")))
/** @brief Full optimization; generates highly optimized code and has the slowest compilation time. */
/** Full optimization; generates highly
* optimized code and has the slowest compilation time.
*/
#define O2 __attribute__((optimize("O2")))
/** @brief Full optimization as in -O2; also uses more aggressive automatic inlining of subprograms within a unit (Inlining of Subprograms) and attempts to vectorize loops. */
/** Full optimization as in -O2;
* also uses more aggressive automatic inlining of
* subprograms within a unit (Inlining of Subprograms)
* and attempts to vectorize loops. */
#define O3 __attribute__((optimize("O3")))
/** @brief Optimize space usage (code and data) of resulting program. */
/** Optimize space usage (code and data)
* of resulting program.
*/
#define Os __attribute__((optimize("Os")))
/** @brief Disregard strict standards compliance. -Ofast enables all -O3 optimizations. It also enables optimizations that are not valid for all standard-compliant programs. */
/** Disregard strict standards compliance.
* -Ofast enables all -O3 optimizations.
* It also enables optimizations that are not valid for
* all standard-compliant programs.
*/
#define Ofast __attribute__((optimize("Ofast")))
/** Optimize for size.
* -Oz enables all -Os optimizations that do not typically
* increase code size.
*/
#define Oz __attribute__((optimize("Oz")))
/** Optimize for debugging.
* -Og enables optimizations that do not interfere with
* debugging.
*/
#define Og __attribute__((optimize("Og")))
#define __unused __attribute__((unused))
#define __packed __attribute__((packed))
#define __naked __attribute__((naked))
@ -457,8 +482,6 @@ typedef uint48_t uint_fast48_t;
// sanitizer
#define __no_sanitize(x) __attribute__((no_sanitize(x)))
#define __no_sanitize_address __attribute__((no_sanitize_address))
/** @brief The no_address_safety_analysis is a deprecated alias of the no_sanitize_address attribute, new code should use no_sanitize_address. */
#define __no_address_safety_analysis __attribute__((no_address_safety_analysis))
#define __no_sanitize_thread __attribute__((no_sanitize_thread))
#define __no_sanitize_undefined __attribute__((no_sanitize_undefined))
#define __no_sanitize_coverage __attribute__((no_sanitize_coverage))
@ -471,10 +494,7 @@ typedef uint48_t uint_fast48_t;
#define likely(x) __builtin_expect(!!(x), 1)
#define unlikely(x) __builtin_expect(!!(x), 0)
#define PUBLIC __visibility("default")
#define PRIVATE __visibility("hidden")
#define NoSecurityAnalysis __no_stack_protector __no_sanitize_address __no_sanitize_undefined __no_address_safety_analysis __no_sanitize_thread
#define NoSecurityAnalysis __no_stack_protector __no_sanitize_address __no_sanitize_undefined __no_sanitize_thread
#define nsa NoSecurityAnalysis
#define NIF __no_instrument_function
@ -486,9 +506,16 @@ typedef uint48_t uint_fast48_t;
: "memory")
#define StackPush(stack, type, value) \
*((type *)--stack) = value;
*((type *)--stack) = value
#define StackPop(stack, type) \
*((type *)stack++)
#define ReturnLogError(ret, Format, ...) \
{ \
trace(Format, ##__VA_ARGS__); \
return ret; \
} \
while (0)
#endif // !__FENNIX_KERNEL_TYPES_H__