Refactor filesystem & stl code

This commit is contained in:
EnderIce2 2024-05-18 07:42:01 +03:00
parent 77a291d08b
commit 6801475243
Signed by untrusted user who does not match committer: enderice2
GPG Key ID: EACC3AD603BAB4DD
186 changed files with 15784 additions and 9746 deletions

View File

@ -42,18 +42,6 @@
],
"description": "Create kernel documentation brief."
},
"For Iteration": {
"prefix": [
"foritr",
],
"body": [
"forItr(${1:itr}, ${2:container})",
"{",
"\t$0",
"}"
],
"description": "Create for loop with iterator."
},
"License": {
"prefix": [
"license",
@ -77,134 +65,5 @@
"*/"
],
"description": "Create kernel license."
},
"Driver Code": {
"prefix": [
"driver",
],
"body": [
"/*",
"\tThis file is part of Fennix Kernel.",
"",
"\tFennix Kernel is free software: you can redistribute it and/or",
"\tmodify it under the terms of the GNU General Public License as",
"\tpublished by the Free Software Foundation, either version 3 of",
"\tthe License, or (at your option) any later version.",
"",
"\tFennix Kernel is distributed in the hope that it will be useful,",
"\tbut WITHOUT ANY WARRANTY; without even the implied warranty of",
"\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the",
"\tGNU General Public License for more details.",
"",
"\tYou should have received a copy of the GNU General Public License",
"\talong with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.",
"*/",
"",
"#include \"${1:driver}.hpp\"",
"",
"#include <debug.h>",
"",
"#include \"../../../kernel.h\"",
"",
"namespace Driver",
"{",
"\tint ${2:driver}::drvOpen(int Flags, mode_t Mode) { return 0; }",
"",
"\tint ${2:driver}::drvClose() { return 0; }",
"",
"\tsize_t ${2:driver}::drvRead(uint8_t *Buffer, size_t Size, off_t Offset) { return 0; }",
"",
"\tsize_t ${2:driver}::drvWrite(uint8_t *Buffer, size_t Size, off_t Offset) { return 0; }",
"",
"\tint ${2:driver}::drvIoctl(unsigned long Request, void *Argp) { return 0; }",
"",
"\tvoid ${2:driver}::OnInterruptReceived(CPU::TrapFrame *) {}",
"",
"\tvoid ${2:driver}::Panic() {}",
"",
"\t${2:driver}::${2:driver}(PCI::PCIDevice dev)",
"\t\t: Object(dev),",
"\t\t Interrupts::Handler(dev)",
"\t{",
"\t}",
"",
"\t${2:driver}::${2:driver}(int irq)",
"\t\t: Object(irq),",
"\t\t Interrupts::Handler(irq)",
"\t{",
"\t}",
"",
"\t${2:driver}::${2:driver}()",
"\t{",
"\t}",
"",
"\t${2:driver}::~${2:driver}()",
"\t{",
"\t\tif (GetError() != 0)",
"\t\t\treturn;",
"\t}",
"}",
"",
],
"description": "Kernel driver code template."
},
"Driver Header": {
"prefix": [
"driver",
],
"body": [
"/*",
"\tThis file is part of Fennix Kernel.",
"",
"\tFennix Kernel is free software: you can redistribute it and/or",
"\tmodify it under the terms of the GNU General Public License as",
"\tpublished by the Free Software Foundation, either version 3 of",
"\tthe License, or (at your option) any later version.",
"",
"\tFennix Kernel is distributed in the hope that it will be useful,",
"\tbut WITHOUT ANY WARRANTY; without even the implied warranty of",
"\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the",
"\tGNU General Public License for more details.",
"",
"\tYou should have received a copy of the GNU General Public License",
"\talong with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.",
"*/",
"",
"#pragma once",
"#include <driver.hpp>",
"",
"namespace Driver",
"{",
"\tclass ${1:driver} : public Object, public Interrupts::Handler",
"\t{",
"\tprivate:",
"\t\tvoid OnInterruptReceived(CPU::TrapFrame *Frame) final;",
"\t\tvoid Panic(Driver::DriverContext *ctx) final;",
"",
"\tpublic:",
"\t\tint drvOpen(int Flags, mode_t Mode);",
"\t\tint drvClose();",
"\t\tsize_t drvRead(uint8_t *Buffer, size_t Size, off_t Offset);",
"\t\tsize_t drvWrite(uint8_t *Buffer, size_t Size, off_t Offset);",
"\t\tint drvIoctl(unsigned long Request, void *Argp);",
"",
"\t\tconst char *drvName() final { return \"${2:MyDriver}\"; }",
"\t\tconst char *drvDescription() final { return \"${3:MyDescription}\"; }",
"\t\tconst char *drvVersion() final { return \"${4:0.0.0}\"; }",
"\t\tconst char *drvAuthor() final { return \"${5:Author}\"; }",
"\t\tconst char *drvLicense() final { return \"${6:License}\"; }",
"\t\tDriverType drvType() final { return DriverType_${7:Generic}; }",
"",
"\t\t${1:driver}(PCI::PCIDevice dev);",
"\t\t${1:driver}(int irq);",
"\t\t${1:driver}();",
"\t\t~${1:driver}();",
"\t};",
"}",
"",
],
"description": "Kernel driver header template."
}
}

View File

@ -6,15 +6,10 @@
"${workspaceFolder}/include",
"${workspaceFolder}/include/**",
"${workspaceFolder}/include_std",
"${workspaceFolder}/include_std/**"
"${workspaceFolder}/include_std/**",
"${workspaceFolder}/arch/amd64/include"
],
"defines": [
"__debug_vscode__",
"KERNEL_NAME=\"Fennix\"",
"KERNEL_ARCH=\"amd64\"",
"KERNEL_VERSION=\"1.0\"",
"GIT_COMMIT=\"0000000000000000000000000000000000000000\"",
"GIT_COMMIT_SHORT=\"0000000\"",
"a64",
"a86",
"DEBUG=\"1\""
@ -79,15 +74,13 @@
"${workspaceFolder}/include",
"${workspaceFolder}/include/**",
"${workspaceFolder}/include_std",
"${workspaceFolder}/include_std/**"
"${workspaceFolder}/include_std/**",
"${workspaceFolder}/arch/i386/include"
],
"forcedInclude": [
"${workspaceFolder}/.vscode/preinclude.h"
],
"defines": [
"__debug_vscode__",
"KERNEL_NAME=\"Fennix\"",
"KERNEL_ARCH=\"i386\"",
"KERNEL_VERSION=\"1.0\"",
"GIT_COMMIT=\"0000000000000000000000000000000000000000\"",
"GIT_COMMIT_SHORT=\"0000000\"",
"a32",
"a86",
"DEBUG=\"1\""
@ -152,15 +145,13 @@
"${workspaceFolder}/include",
"${workspaceFolder}/include/**",
"${workspaceFolder}/include_std",
"${workspaceFolder}/include_std/**"
"${workspaceFolder}/include_std/**",
"${workspaceFolder}/arch/aarch64/include"
],
"forcedInclude": [
"${workspaceFolder}/.vscode/preinclude.h"
],
"defines": [
"__debug_vscode__",
"KERNEL_NAME=\"Fennix\"",
"KERNEL_ARCH=\"aarch64\"",
"KERNEL_VERSION=\"1.0\"",
"GIT_COMMIT=\"0000000000000000000000000000000000000000\"",
"GIT_COMMIT_SHORT=\"0000000\"",
"aa64",
"DEBUG=\"1\""
],

View File

@ -5,3 +5,10 @@
#undef _WIN64
#undef __APPLE__
#undef __clang__
#define __vscode__ 1
#define __kernel__ 1
#define KERNEL_NAME "Fennix"
#define KERNEL_ARCH "amd64"
#define KERNEL_VERSION "1.0"
#define GIT_COMMIT "0000000000000000000000000000000000000000"
#define GIT_COMMIT_SHORT "0000000"

View File

@ -1,5 +1,5 @@
{
"C_Cpp.errorSquiggles": "Enabled",
"C_Cpp.errorSquiggles": "enabled",
"C_Cpp.autocompleteAddParentheses": true,
"C_Cpp.codeAnalysis.clangTidy.enabled": true,
"C_Cpp.clang_format_style": "Visual Studio",
@ -14,6 +14,10 @@
"clang-diagnostic-unknown-warning-option",
"clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling",
"clang-diagnostic-implicit-exception-spec-mismatch",
"clang-diagnostic-unknown-attributes"
"clang-diagnostic-unknown-attributes",
"clang-diagnostic-user-defined-literals",
"clang-diagnostic-non-pod-varargs",
"clang-diagnostic-non-pod-varargs",
"clang-diagnostic-non-pod-varargs"
]
}

View File

@ -17,6 +17,9 @@ RUST_TARGET_PATH = arch/$(OSARCH)/rust-target.json
GIT_COMMIT = $(shell git rev-parse HEAD)
GIT_COMMIT_SHORT = $(shell git rev-parse --short HEAD)
HEADERS = $(sort $(dir $(wildcard ./include/*))) $(sort $(dir $(wildcard ./include_std/*)))
INCLUDE_DIR = -I./include -I./include_std
BMP_SOURCES = $(shell find ./ -type f -name '*.bmp')
PSF_SOURCES = $(shell find ./ -type f -name '*.psf')
ifeq ($(OSARCH), amd64)
@ -24,43 +27,47 @@ S_SOURCES = $(shell find ./ -type f -name '*.S' -not -path "./arch/i386/*" -not
s_SOURCES = $(shell find ./ -type f -name '*.s' -not -path "./arch/i386/*" -not -path "./arch/aarch64/*")
C_SOURCES = $(shell find ./ -type f -name '*.c' -not -path "./arch/i386/*" -not -path "./arch/aarch64/*")
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp' -not -path "./arch/i386/*" -not -path "./arch/aarch64/*")
HEADERS += $(sort $(dir $(wildcard ./arch/amd64/include/*)))
INCLUDE_DIR += -I./arch/amd64/include
else ifeq ($(OSARCH), i386)
S_SOURCES = $(shell find ./ -type f -name '*.S' -not -path "./arch/amd64/*" -not -path "./arch/aarch64/*")
s_SOURCES = $(shell find ./ -type f -name '*.s' -not -path "./arch/amd64/*" -not -path "./arch/aarch64/*")
C_SOURCES = $(shell find ./ -type f -name '*.c' -not -path "./arch/amd64/*" -not -path "./arch/aarch64/*")
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp' -not -path "./arch/amd64/*" -not -path "./arch/aarch64/*")
HEADERS += $(sort $(dir $(wildcard ./arch/i386/include/*)))
INCLUDE_DIR += -I./arch/i386/include
else ifeq ($(OSARCH), aarch64)
S_SOURCES = $(shell find ./ -type f -name '*.S' -not -path "./arch/amd64/*" -not -path "./arch/i386/*")
s_SOURCES = $(shell find ./ -type f -name '*.s' -not -path "./arch/amd64/*" -not -path "./arch/i386/*")
C_SOURCES = $(shell find ./ -type f -name '*.c' -not -path "./arch/amd64/*" -not -path "./arch/i386/*")
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp' -not -path "./arch/amd64/*" -not -path "./arch/i386/*")
HEADERS += $(sort $(dir $(wildcard ./arch/aarch64/include/*)))
INCLUDE_DIR += -I./arch/aarch64/include
endif
HEADERS = $(sort $(dir $(wildcard ./include/*))) $(sort $(dir $(wildcard ./include_std/*)))
OBJ = $(C_SOURCES:.c=.o) $(CPP_SOURCES:.cpp=.o) $(ASM_SOURCES:.asm=.o) $(S_SOURCES:.S=.o) $(s_SOURCES:.s=.o) $(PSF_SOURCES:.psf=.o) $(BMP_SOURCES:.bmp=.o)
STACK_USAGE_OBJ = $(C_SOURCES:.c=.su) $(CPP_SOURCES:.cpp=.su)
GCNO_OBJ = $(C_SOURCES:.c=.gcno) $(CPP_SOURCES:.cpp=.gcno)
INCLUDE_DIR = -I./include -I./include_std
LDFLAGS := -Wl,-Map kernel.map -static -nostdlib -nodefaultlibs -nolibc
# Disable all warnings by adding "-w" in WARNCFLAG and if you want to treat the warnings as errors, add "-Werror"
# -Wconversion this may be re-added later
WARNCFLAG = -Wall -Wextra \
-Wfloat-equal -Wpointer-arith -Wcast-align \
-Wredundant-decls -Winit-self -Wswitch-default \
-Wstrict-overflow=5 -Wconversion -Wno-error=cpp -Werror \
-Wstrict-overflow=5 -Wno-error=cpp -Werror \
-Wno-unused-parameter
# https://gcc.gnu.org/onlinedocs/gcc/x86-Options.html
CFLAGS := \
$(INCLUDE_DIR) \
-D__kernel__='1' \
-DKERNEL_NAME='"$(OSNAME)"' \
-DKERNEL_ARCH='"$(OSARCH)"' \
-DKERNEL_VERSION='"$(KERNEL_VERSION)"' \
-DGIT_COMMIT='"$(GIT_COMMIT)"' \
-DGIT_COMMIT_SHORT='"$(GIT_COMMIT_SHORT)"'
SIMD_FLAGS := -msse -msse2 -msse3 -mssse3 -msse4.1 -msse4.2 -mavx -mavx2 -mavx512f
ifeq ($(OSARCH), amd64)
CFLAGS += -fno-pic -fno-pie -mno-red-zone -march=core2 \
@ -131,6 +138,7 @@ endif
$(KERNEL_FILENAME): $(OBJ)
$(info Linking $@)
$(CC) $(LDFLAGS) $(OBJ) -o $@
# $(CC) $(LDFLAGS) $(OBJ) -mno-red-zone -lgcc -o $@
%.o: %.c $(HEADERS)
$(info Compiling $<)
@ -139,7 +147,7 @@ $(KERNEL_FILENAME): $(OBJ)
# https://gcc.gnu.org/projects/cxx-status.html
%.o: %.cpp $(HEADERS)
$(info Compiling $<)
$(CPP) $(CFLAGS) $(CFLAG_STACK_PROTECTOR) $(WARNCFLAG) -std=c++20 -c $< -o $@ -fno-exceptions -fno-rtti
$(CPP) $(CFLAGS) $(CFLAG_STACK_PROTECTOR) $(WARNCFLAG) -std=c++20 -c $< -o $@ -fno-rtti
%.o: %.S
$(info Compiling $<)

View File

View File

View File

@ -62,6 +62,16 @@ SECTIONS
{
*(.data .data.*)
} :data
.eh_frame : AT(ADDR(.eh_frame) - KERNEL_VMA) ONLY_IF_RW
{
KEEP (*(.eh_frame .eh_frame.*))
} :data
.gcc_except_table : AT(ADDR(.gcc_except_table) - KERNEL_VMA) ONLY_IF_RW
{
KEEP (*(.gcc_except_table .gcc_except_table.*))
} :data
_kernel_data_end = ALIGN(CONSTANT(MAXPAGESIZE));
_kernel_rodata_start = ALIGN(CONSTANT(MAXPAGESIZE));
@ -85,6 +95,21 @@ SECTIONS
KEEP(*(.fini_array .dtors))
PROVIDE_HIDDEN (__fini_array_end = .);
} :rodata
.eh_frame_hdr : AT(ADDR(.eh_frame_hdr) - KERNEL_VMA)
{
*(.eh_frame_hdr .eh_frame_hdr.*)
} :rodata
.eh_frame : AT(ADDR(.eh_frame) - KERNEL_VMA) ONLY_IF_RO
{
KEEP (*(.eh_frame .eh_frame.*))
} :rodata
.gcc_except_table : AT(ADDR(.gcc_except_table) - KERNEL_VMA) ONLY_IF_RO
{
KEEP (*(.gcc_except_table .gcc_except_table.*))
} :rodata
_kernel_rodata_end = ALIGN(CONSTANT(MAXPAGESIZE));
_kernel_bss_start = ALIGN(CONSTANT(MAXPAGESIZE));

View File

@ -149,30 +149,30 @@ namespace Memory
PageMapLevel4 *PML4 = &this->pTable->Entries[Index.PMLIndex];
if (!PML4->Present)
goto ReturnError;
goto ReturnLogError;
PDPTE = (PageDirectoryPointerTableEntryPtr *)((uintptr_t)PML4->GetAddress() << 12);
if (!PDPTE || !PDPTE->Entries[Index.PDPTEIndex].Present)
goto ReturnError;
goto ReturnLogError;
if (PDPTE->Entries[Index.PDPTEIndex].PageSize)
return MapType::OneGiB;
PDE = (PageDirectoryEntryPtr *)((uintptr_t)PDPTE->Entries[Index.PDPTEIndex].GetAddress() << 12);
if (!PDE || !PDE->Entries[Index.PDEIndex].Present)
goto ReturnError;
goto ReturnLogError;
if (PDE->Entries[Index.PDEIndex].PageSize)
return MapType::TwoMiB;
PTE = (PageTableEntryPtr *)((uintptr_t)PDE->Entries[Index.PDEIndex].GetAddress() << 12);
if (!PTE)
goto ReturnError;
goto ReturnLogError;
if (PTE->Entries[Index.PTEIndex].Present)
return MapType::FourKiB;
ReturnError:
ReturnLogError:
return MapType::NoMapType;
}

View File

View File

@ -62,6 +62,16 @@ SECTIONS
{
*(.data .data.*)
} :data
.eh_frame : AT(ADDR(.eh_frame) - KERNEL_VMA) ONLY_IF_RW
{
KEEP (*(.eh_frame .eh_frame.*))
} :data
.gcc_except_table : AT(ADDR(.gcc_except_table) - KERNEL_VMA) ONLY_IF_RW
{
KEEP (*(.gcc_except_table .gcc_except_table.*))
} :data
_kernel_data_end = ALIGN(CONSTANT(MAXPAGESIZE));
_kernel_rodata_start = ALIGN(CONSTANT(MAXPAGESIZE));
@ -85,6 +95,21 @@ SECTIONS
KEEP(*(.fini_array .dtors))
PROVIDE_HIDDEN (__fini_array_end = .);
} :rodata
.eh_frame_hdr : AT(ADDR(.eh_frame_hdr) - KERNEL_VMA)
{
*(.eh_frame_hdr .eh_frame_hdr.*)
} :rodata
.eh_frame : AT(ADDR(.eh_frame) - KERNEL_VMA) ONLY_IF_RO
{
KEEP (*(.eh_frame .eh_frame.*))
} :rodata
.gcc_except_table : AT(ADDR(.gcc_except_table) - KERNEL_VMA) ONLY_IF_RO
{
KEEP (*(.gcc_except_table .gcc_except_table.*))
} :rodata
_kernel_rodata_end = ALIGN(CONSTANT(MAXPAGESIZE));
_kernel_bss_start = ALIGN(CONSTANT(MAXPAGESIZE));

172
core/console.cpp Normal file
View File

@ -0,0 +1,172 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include <kcon.hpp>
#include <filesystem/ioctl.hpp>
#include <memory.hpp>
#include <stropts.h>
#include <string.h>
namespace KernelConsole
{
termios term{};
winsize termSize{};
ssize_t KConRead(struct Inode *Node, void *Buffer, size_t Size, off_t Offset)
{
fixme("Reading %d bytes... \"%.*s\"", Size, Size, (char *)Buffer);
return Size;
}
ssize_t KConWrite(struct Inode *Node, const void *Buffer, size_t Size, off_t Offset)
{
fixme("Writing %d bytes... \"%.*s\"", Size, Size, (char *)Buffer);
return Size;
}
int KConIoctl(struct Inode *Node, unsigned long Request, void *Argp)
{
switch (Request)
{
case TCGETS:
{
struct termios *t = (struct termios *)Argp;
memcpy(t, &term, sizeof(struct termios));
return 0;
}
case TCSETS:
{
debug("TCSETS not supported");
return -EINVAL;
struct termios *t = (struct termios *)Argp;
memcpy(&term, t, sizeof(struct termios));
return 0;
}
case TIOCGPGRP:
{
*((pid_t *)Argp) = 0;
return 0;
}
case TIOCSPGRP:
{
*((pid_t *)Argp) = 0;
return 0;
}
case TIOCGWINSZ:
{
struct winsize *ws = (struct winsize *)Argp;
memcpy(ws, &termSize, sizeof(struct winsize));
return 0;
}
case TIOCSWINSZ:
{
debug("TIOCSWINSZ not supported");
return -EINVAL;
struct winsize *ws = (struct winsize *)Argp;
memcpy(&termSize, ws, sizeof(struct winsize));
return 0;
}
case TCSETSW:
case TCSETSF:
case TCGETA:
case TCSETA:
case TCSETAW:
case TCSETAF:
case TCSBRK:
case TCXONC:
case TCFLSH:
case TIOCEXCL:
case TIOCNXCL:
case TIOCSCTTY:
case TIOCOUTQ:
case TIOCSTI:
case TIOCMGET:
case TIOCMBIS:
case TIOCMBIC:
case TIOCMSET:
{
fixme("ioctl %#lx not implemented", Request);
return -ENOSYS;
}
case TIOCGPTN:
case 0xffffffff80045430: /* FIXME: ???? */
{
fixme("stub ioctl %#lx", Request);
int *n = (int *)Argp;
*n = -1;
break;
}
case TIOCSPTLCK:
{
fixme("stub ioctl %#lx", Request);
int *n = (int *)Argp;
*n = 0;
break;
}
default:
{
debug("Unknown ioctl %#lx", Request);
return -EINVAL;
}
}
return 0;
}
void EarlyInit()
{
/*
- ICRNL - Map Carriage Return to New Line
- IXON - Enable XON/XOFF flow control
- OPOST - Enable output processing
- ONLCR - Map New Line to Carriage Return - New Line
- CS8 - 8-bit characters
- CREAD - Enable receiver
- HUPCL - Hang up on last close
- ECHO - Echo input characters
- ICANON - Enable canonical input (enable line editing)
*/
term.c_iflag = /*ICRNL |*/ IXON;
term.c_oflag = OPOST | ONLCR;
term.c_cflag = CS8 | CREAD | HUPCL;
term.c_lflag = ECHO | ICANON;
term.c_cc[VEOF] = 0x04; /* ^D */
term.c_cc[VEOL] = 0x00; /* NUL */
term.c_cc[VERASE] = 0x7f; /* DEL */
term.c_cc[VINTR] = 0x03; /* ^C */
term.c_cc[VKILL] = 0x15; /* ^U */
term.c_cc[VMIN] = 1; /* Minimum number of characters for non-canonical read */
term.c_cc[VQUIT] = 0x1c; /* ^\ */
term.c_cc[VSTART] = 0x11; /* ^Q */
term.c_cc[VSTOP] = 0x13; /* ^S */
term.c_cc[VSUSP] = 0x1a; /* ^Z */
term.c_cc[VTIME] = 0; /* Timeout for non-canonical read */
term.c_cc[VWERASE] = 0x17; /* ^W */
}
void LateInit()
{
}
}

View File

@ -16,14 +16,16 @@
*/
#include <driver.hpp>
#include <interface/driver.h>
#include <interface/fs.h>
#include <type_traits>
#include "../../kernel.h"
#include "../../driver.h"
// #define DEBUG_API
#ifdef DEBUG_API
#define dbg_api(Format, ...) function(Format, ##__VA_ARGS__)
#define dbg_api(Format, ...) func(Format, ##__VA_ARGS__)
#else
#define dbg_api(Format, ...)
#endif
@ -53,19 +55,19 @@ namespace Driver
{
case _drf_Entry:
drv->Entry = (int (*)())Function;
debug("Entry %#lx for %s", (uintptr_t)Function, drv->Path);
debug("Entry %#lx for %s", (uintptr_t)Function, drv->Path.c_str());
break;
case _drf_Final:
drv->Final = (int (*)())Function;
debug("Finalize %#lx for %s", (uintptr_t)Function, drv->Path);
debug("Finalize %#lx for %s", (uintptr_t)Function, drv->Path.c_str());
break;
case _drf_Panic:
drv->Panic = (int (*)())Function;
debug("Panic %#lx for %s", (uintptr_t)Function, drv->Path);
debug("Panic %#lx for %s", (uintptr_t)Function, drv->Path.c_str());
break;
case _drf_Probe:
drv->Probe = (int (*)())Function;
debug("Probe %#lx for %s", (uintptr_t)Function, drv->Path);
debug("Probe %#lx for %s", (uintptr_t)Function, drv->Path.c_str());
break;
default:
assert(!"Invalid driver function type");
@ -134,7 +136,7 @@ namespace Driver
{
if (ih.first == IRQ)
{
debug("Removing IRQ %d: %#lx for %s", IRQ, (uintptr_t)ih.second, drv->Path);
debug("Removing IRQ %d: %#lx for %s", IRQ, (uintptr_t)ih.second, drv->Path.c_str());
Interrupts::RemoveHandler((void (*)(CPU::TrapFrame *))ih.second, IRQ);
drv->InterruptHandlers->erase(IRQ);
break;
@ -177,7 +179,7 @@ namespace Driver
foreach (auto &i in * drv->InterruptHandlers)
{
Interrupts::RemoveHandler((void (*)(CPU::TrapFrame *))Handler, i.first);
debug("Removed IRQ %d: %#lx for %s", i.first, (uintptr_t)Handler, drv->Path);
debug("Removed IRQ %d: %#lx for %s", i.first, (uintptr_t)Handler, drv->Path.c_str());
}
drv->InterruptHandlers->clear();
return 0;
@ -185,217 +187,6 @@ namespace Driver
/* --------- */
dev_t RegisterInputDevice(dev_t MajorID, DeviceDriverType Type)
{
dbg_api("%d, %d", MajorID, Type);
switch (Type)
{
case ddt_Keyboard:
return DriverManager->InputKeyboardDev->Register(MajorID);
case ddt_Mouse:
return DriverManager->InputMouseDev->Register(MajorID);
/* ... */
default:
assert(!"Invalid input device type");
}
}
int UnregisterInputDevice(dev_t MajorID, dev_t MinorID, DeviceDriverType Type)
{
dbg_api("%d, %d, %d", MajorID, MinorID, Type);
switch (Type)
{
case ddt_Keyboard:
return DriverManager->InputKeyboardDev->Unregister(MajorID, MinorID);
case ddt_Mouse:
return DriverManager->InputMouseDev->Unregister(MajorID, MinorID);
/* ... */
default:
assert(!"Invalid input device type");
}
}
int ReportKeyboardEvent(dev_t MajorID, dev_t MinorID, uint8_t ScanCode)
{
dbg_api("%d, %d, %d", MajorID, MinorID, ScanCode);
return DriverManager->InputKeyboardDev->ReportKeyEvent(MajorID, MinorID, ScanCode);
}
int ReportRelativeMouseEvent(dev_t MajorID, dev_t MinorID, __MouseButtons Button, int X, int Y, int8_t Z)
{
dbg_api("%d, %d, %d, %d, %d, %d", MajorID, MinorID, Button, X, Y, Z);
return DriverManager->InputMouseDev->ReportMouseEvent(MajorID, MinorID,
Button.LeftButton, Button.RightButton, Button.MiddleButton,
Button.Button4, Button.Button5, Button.Button6, Button.Button7, Button.Button8,
X, Y, Z, true);
}
int ReportAbsoluteMouseEvent(dev_t MajorID, dev_t MinorID, __MouseButtons Button, uintptr_t X, uintptr_t Y, int8_t Z)
{
dbg_api("%d, %d, %d, %d, %d, %d", MajorID, MinorID, Button, X, Y, Z);
return DriverManager->InputMouseDev->ReportMouseEvent(MajorID, MinorID,
Button.LeftButton, Button.RightButton, Button.MiddleButton,
Button.Button4, Button.Button5, Button.Button6, Button.Button7, Button.Button8,
X, Y, Z, false);
}
/* --------- */
dev_t RegisterBlockDevice(dev_t MajorID, DeviceDriverType Type, void *Open, void *Close, void *Read, void *Write, void *Ioctl)
{
dbg_api("%d, %d, %#lx, %#lx, %#lx, %#lx, %#lx", MajorID, Type, Open, Close, Read, Write, Ioctl);
switch (Type)
{
case ddt_SATA:
{
dev_t ret = DriverManager->BlockSATADev->Register(MajorID);
DriverManager->BlockSATADev->NewBlock(MajorID, ret,
(SlaveDeviceFile::drvOpen_t)Open,
(SlaveDeviceFile::drvClose_t)Close,
(SlaveDeviceFile::drvRead_t)Read,
(SlaveDeviceFile::drvWrite_t)Write,
(SlaveDeviceFile::drvIoctl_t)Ioctl);
return ret;
}
case ddt_ATA:
{
dev_t ret = DriverManager->BlockHDDev->Register(MajorID);
DriverManager->BlockHDDev->NewBlock(MajorID, ret,
(SlaveDeviceFile::drvOpen_t)Open,
(SlaveDeviceFile::drvClose_t)Close,
(SlaveDeviceFile::drvRead_t)Read,
(SlaveDeviceFile::drvWrite_t)Write,
(SlaveDeviceFile::drvIoctl_t)Ioctl);
return ret;
}
case ddt_NVMe:
{
dev_t ret = DriverManager->BlockNVMeDev->Register(MajorID);
DriverManager->BlockNVMeDev->NewBlock(MajorID, ret,
(SlaveDeviceFile::drvOpen_t)Open,
(SlaveDeviceFile::drvClose_t)Close,
(SlaveDeviceFile::drvRead_t)Read,
(SlaveDeviceFile::drvWrite_t)Write,
(SlaveDeviceFile::drvIoctl_t)Ioctl);
return ret;
}
/* ... */
default:
assert(!"Invalid storage device type");
}
}
int UnregisterBlockDevice(dev_t MajorID, dev_t MinorID, DeviceDriverType Type)
{
dbg_api("%d, %d, %d", MajorID, MinorID, Type);
switch (Type)
{
case ddt_SATA:
return DriverManager->BlockSATADev->Unregister(MajorID, MinorID);
case ddt_ATA:
return DriverManager->BlockHDDev->Unregister(MajorID, MinorID);
case ddt_NVMe:
return DriverManager->BlockNVMeDev->Unregister(MajorID, MinorID);
/* ... */
default:
assert(!"Invalid storage device type");
}
}
/* --------- */
dev_t RegisterAudioDevice(dev_t MajorID, DeviceDriverType Type, void *Open, void *Close, void *Read, void *Write, void *Ioctl)
{
dbg_api("%d, %d, %#lx, %#lx, %#lx, %#lx, %#lx", MajorID, Type, Open, Close, Read, Write, Ioctl);
switch (Type)
{
case ddt_Audio:
{
dev_t ret = DriverManager->AudioDev->Register(MajorID);
DriverManager->AudioDev->NewAudio(MajorID, ret,
(SlaveDeviceFile::drvOpen_t)Open,
(SlaveDeviceFile::drvClose_t)Close,
(SlaveDeviceFile::drvRead_t)Read,
(SlaveDeviceFile::drvWrite_t)Write,
(SlaveDeviceFile::drvIoctl_t)Ioctl);
return ret;
}
/* ... */
default:
assert(!"Invalid audio device type");
}
}
int UnregisterAudioDevice(dev_t MajorID, dev_t MinorID, DeviceDriverType Type)
{
dbg_api("%d, %d, %d", MajorID, MinorID, Type);
switch (Type)
{
case ddt_Audio:
return DriverManager->AudioDev->Unregister(MajorID, MinorID);
/* ... */
default:
assert(!"Invalid audio device type");
}
}
/* --------- */
dev_t RegisterNetDevice(dev_t MajorID, DeviceDriverType Type, void *Open, void *Close, void *Read, void *Write, void *Ioctl)
{
dbg_api("%d, %d, %#lx, %#lx, %#lx, %#lx, %#lx", MajorID, Type, Open, Close, Read, Write, Ioctl);
switch (Type)
{
case ddt_Network:
{
dev_t ret = DriverManager->NetDev->Register(MajorID);
DriverManager->NetDev->NewNet(MajorID, ret,
(SlaveDeviceFile::drvOpen_t)Open,
(SlaveDeviceFile::drvClose_t)Close,
(SlaveDeviceFile::drvRead_t)Read,
(SlaveDeviceFile::drvWrite_t)Write,
(SlaveDeviceFile::drvIoctl_t)Ioctl);
return ret;
}
/* ... */
default:
assert(!"Invalid audio device type");
}
}
int UnregisterNetDevice(dev_t MajorID, dev_t MinorID, DeviceDriverType Type)
{
dbg_api("%d, %d, %d", MajorID, MinorID, Type);
switch (Type)
{
case ddt_Network:
return DriverManager->NetDev->Unregister(MajorID, MinorID);
/* ... */
default:
assert(!"Invalid audio device type");
}
}
int ReportNetworkPacket(dev_t MajorID, dev_t MinorID, void *Buffer, size_t Size)
{
dbg_api("%d, %d, %#lx, %d", MajorID, MinorID, Buffer, Size);
return DriverManager->NetDev->ReportNetworkPacket(MajorID, MinorID, Buffer, Size);
}
/* --------- */
void d_KPrint(dev_t MajorID, const char *Format, va_list args)
{
dbg_api("%d %s, %#lx", MajorID, Format, args);
@ -891,22 +682,6 @@ namespace Driver
api->UnregisterInterruptHandler = UnregisterInterruptHandler;
api->UnregisterAllInterruptHandlers = UnregisterAllInterruptHandlers;
api->RegisterInputDevice = RegisterInputDevice;
api->UnregisterInputDevice = UnregisterInputDevice;
api->ReportKeyboardEvent = ReportKeyboardEvent;
api->ReportRelativeMouseEvent = ReportRelativeMouseEvent;
api->ReportAbsoluteMouseEvent = ReportAbsoluteMouseEvent;
api->RegisterBlockDevice = RegisterBlockDevice;
api->UnregisterBlockDevice = UnregisterBlockDevice;
api->RegisterAudioDevice = RegisterAudioDevice;
api->UnregisterAudioDevice = UnregisterAudioDevice;
api->RegisterNetDevice = RegisterNetDevice;
api->UnregisterNetDevice = UnregisterNetDevice;
api->ReportNetworkPacket = ReportNetworkPacket;
api->KPrint = d_KPrint;
api->KernelLog = KernelLog;
@ -944,3 +719,28 @@ namespace Driver
api->strstr = api__strstr;
}
}
dev_t __api_RegisterFileSystem(FileSystemInfo *Info, struct Inode *Root)
{
return fs->RegisterFileSystem(Info, Root);
}
int __api_UnregisterFileSystem(dev_t Device)
{
return fs->UnregisterFileSystem(Device);
}
struct APISymbols
{
const char *Name;
void *Function;
};
static struct APISymbols APISymbols[] = {
{"RegisterFileSystem", (void *)__api_RegisterFileSystem},
{"UnregisterFileSystem", (void *)__api_UnregisterFileSystem},
};
/* Checking functions signatures */
static_assert(std::is_same_v<decltype(__api_RegisterFileSystem), decltype(RegisterFileSystem)>);
static_assert(std::is_same_v<decltype(__api_UnregisterFileSystem), decltype(UnregisterFileSystem)>);

View File

@ -1,327 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include <driver.hpp>
#include <memory.hpp>
#include <ints.hpp>
#include <task.hpp>
#include <printf.h>
#include <exec.hpp>
#include <cwalk.h>
#include <md5.h>
#include "../../../kernel.h"
#include "../../../driver.h"
using namespace vfs;
namespace Driver
{
int MasterDeviceFile::open(int Flags, mode_t Mode)
{
switch (this->DeviceType)
{
default:
if (this->SlavesMap.empty())
return -ENOSYS;
Slaves slave = this->SlavesMap.begin()->second;
return slave->begin()->second->open(Flags, Mode);
}
}
int MasterDeviceFile::close()
{
switch (this->DeviceType)
{
default:
if (this->SlavesMap.empty())
return -ENOSYS;
Slaves slave = this->SlavesMap.begin()->second;
return slave->begin()->second->close();
}
}
size_t MasterDeviceFile::read(uint8_t *Buffer,
size_t Size,
off_t Offset)
{
switch (this->DeviceType)
{
case ddt_Keyboard:
{
while (KeyQueue.empty())
TaskManager->Yield();
/* Request scancode */
if (Size == 2 && Buffer[1] == 0x00)
{
while (RawKeyQueue.empty())
TaskManager->Yield();
Buffer[0] = RawKeyQueue.front();
RawKeyQueue.pop_front();
return 1;
}
Buffer[0] = KeyQueue.front();
KeyQueue.pop_front();
return 1;
}
default:
if (this->SlavesMap.empty())
return 0;
Slaves slave = this->SlavesMap.begin()->second;
return slave->begin()->second->read(Buffer, Size, Offset);
}
}
size_t MasterDeviceFile::write(uint8_t *Buffer,
size_t Size,
off_t Offset)
{
switch (this->DeviceType)
{
default:
if (this->SlavesMap.empty())
return 0;
Slaves slave = this->SlavesMap.begin()->second;
return slave->begin()->second->write(Buffer, Size, Offset);
}
}
int MasterDeviceFile::ioctl(unsigned long Request,
void *Argp)
{
switch (this->DeviceType)
{
default:
if (this->SlavesMap.empty())
return -ENOSYS;
Slaves slave = this->SlavesMap.begin()->second;
return slave->begin()->second->ioctl(Request, Argp);
}
}
void MasterDeviceFile::ClearBuffers()
{
this->RawKeyQueue.clear();
this->KeyQueue.clear();
/* ... */
foreach (auto &sm in this->SlavesMap)
{
Slaves slave = sm.second;
foreach (auto &sdf in *slave)
sdf.second->ClearBuffers();
}
}
int MasterDeviceFile::ReportKeyEvent(maj_t ID, min_t MinorID, uint8_t ScanCode)
{
debug("New key event: %02x", ScanCode);
if (this->SlavesMap.find(ID) == this->SlavesMap.end())
return -EINVAL;
std::unordered_map<min_t, SlaveDeviceFile *> *slave = this->SlavesMap[ID];
if ((*slave).find(MinorID) == (*slave).end())
return -EINVAL;
/* We are master, keep a copy of the scancode and
converted key */
if (RawKeyQueue.size() > 16)
RawKeyQueue.pop_front();
RawKeyQueue.push_back(ScanCode);
if (KeyQueue.size() > 16)
KeyQueue.pop_front();
switch (ScanCode & ~KEY_PRESSED)
{
case KEY_LEFT_SHIFT:
case KEY_RIGHT_SHIFT:
{
if (ScanCode & KEY_PRESSED)
UpperCase = true;
else
UpperCase = false;
break;
}
case KEY_CAPS_LOCK:
{
if (ScanCode & KEY_PRESSED)
CapsLock = !CapsLock;
break;
}
default:
break;
}
if (ScanCode & KEY_PRESSED)
KeyQueue.push_back(GetScanCode(ScanCode, UpperCase || CapsLock));
SlaveDeviceFile *sdf = (*slave)[MinorID];
return sdf->ReportKeyEvent(ScanCode);
}
int MasterDeviceFile::ReportMouseEvent(maj_t ID, min_t MinorID,
bool LeftButton, bool RightButton, bool MiddleButton,
bool Button4, bool Button5, bool Button6, bool Button7, bool Button8,
uintptr_t X, uintptr_t Y, int8_t Z, bool Relative)
{
return -ENOSYS;
}
int MasterDeviceFile::ReportNetworkPacket(maj_t ID, min_t MinorID, void *Buffer, size_t Size)
{
/* TODO: Buffer must be allocated by the kernel */
return -ENOSYS;
}
int MasterDeviceFile::NewBlock(maj_t ID, min_t MinorID, drvOpen_t Open, drvClose_t Close,
drvRead_t Read, drvWrite_t Write, drvIoctl_t Ioctl)
{
assert(this->SlavesMap.find(ID) != this->SlavesMap.end());
Slaves slave = this->SlavesMap[ID];
assert((*slave).find(MinorID) != (*slave).end());
SlaveDeviceFile *sdf = (*slave)[MinorID];
sdf->Open = Open;
sdf->Close = Close;
sdf->Read = Read;
sdf->Write = Write;
sdf->Ioctl = Ioctl;
return 0;
}
int MasterDeviceFile::NewAudio(maj_t ID, min_t MinorID, drvOpen_t Open, drvClose_t Close,
drvRead_t Read, drvWrite_t Write, drvIoctl_t Ioctl)
{
assert(this->SlavesMap.find(ID) != this->SlavesMap.end());
Slaves slave = this->SlavesMap[ID];
assert((*slave).find(MinorID) != (*slave).end());
SlaveDeviceFile *sdf = (*slave)[MinorID];
sdf->Open = Open;
sdf->Close = Close;
sdf->Read = Read;
sdf->Write = Write;
sdf->Ioctl = Ioctl;
return 0;
}
int MasterDeviceFile::NewNet(maj_t ID, min_t MinorID, drvOpen_t Open, drvClose_t Close,
drvRead_t Read, drvWrite_t Write, drvIoctl_t Ioctl)
{
assert(this->SlavesMap.find(ID) != this->SlavesMap.end());
Slaves slave = this->SlavesMap[ID];
assert((*slave).find(MinorID) != (*slave).end());
SlaveDeviceFile *sdf = (*slave)[MinorID];
sdf->Open = Open;
sdf->Close = Close;
sdf->Read = Read;
sdf->Write = Write;
sdf->Ioctl = Ioctl;
return 0;
}
dev_t MasterDeviceFile::Register(maj_t ID)
{
debug("Registering slave device %d", ID);
Slaves slave;
if (this->SlavesMap.find(ID) != this->SlavesMap.end())
slave = this->SlavesMap[ID];
else
slave = new std::unordered_map<min_t, SlaveDeviceFile *>();
char name[24];
sprintf(name, "%s%ld", this->SlaveName, this->SlaveIDCounter);
SlaveDeviceFile *sdf = new SlaveDeviceFile(name,
this->SlaveParent,
this->DeviceType,
this->Type);
sdf->DeviceMajor = ID;
sdf->DeviceMinor = this->SlaveIDCounter;
(*slave)[this->SlaveIDCounter] = sdf;
this->SlavesMap[ID] = slave;
return this->SlaveIDCounter++;
}
int MasterDeviceFile::Unregister(maj_t ID, min_t MinorID)
{
debug("Unregistering slave device %d:%d", ID, MinorID);
if (this->SlavesMap.find(ID) == this->SlavesMap.end())
return -EINVAL;
std::unordered_map<min_t, SlaveDeviceFile *> *slave = this->SlavesMap[ID];
if ((*slave).find(MinorID) == (*slave).end())
return -EINVAL;
SlaveDeviceFile *sdf = (*slave)[MinorID];
delete sdf;
slave->erase(MinorID);
if (slave->empty())
{
delete slave;
this->SlavesMap.erase(ID);
}
return 0;
}
MasterDeviceFile::MasterDeviceFile(const char *MasterName,
const char *_SlaveName,
Node *Parent,
int Type)
: Node(Parent, MasterName, NodeType::FILE)
{
strncpy(this->SlaveName, _SlaveName, sizeof(this->Name));
this->DeviceType = Type;
this->SlaveParent = Parent;
switch (Type)
{
case ddt_Keyboard:
case ddt_Mouse:
case ddt_Joystick:
case ddt_Gamepad:
case ddt_Touchpad:
case ddt_Touchscreen:
this->Type = NodeType::CHARDEVICE;
break;
case ddt_SATA:
case ddt_ATA:
case ddt_NVMe:
this->Type = NodeType::BLOCKDEVICE;
break;
default:
break;
}
}
MasterDeviceFile::~MasterDeviceFile()
{
foreach (auto &sm in this->SlavesMap)
{
Slaves slave = sm.second;
foreach (auto &sdf in *slave)
delete sdf.second;
delete slave;
}
this->SlavesMap.clear();
}
}

View File

@ -1,131 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include <driver.hpp>
#include <memory.hpp>
#include <ints.hpp>
#include <task.hpp>
#include <printf.h>
#include <exec.hpp>
#include <cwalk.h>
#include <md5.h>
#include "../../../kernel.h"
#include "../../../driver.h"
using namespace vfs;
namespace Driver
{
int SlaveDeviceFile::open(int Flags, mode_t Mode)
{
switch (this->DeviceType)
{
default:
if (this->Open)
return this->Open(this->DeviceMajor, this->DeviceMinor,
Flags, Mode);
return -ENOSYS;
}
}
int SlaveDeviceFile::close()
{
switch (this->DeviceType)
{
default:
if (this->Close)
return this->Close(this->DeviceMajor, this->DeviceMinor);
return -ENOSYS;
}
}
size_t SlaveDeviceFile::read(uint8_t *Buffer,
size_t Size,
off_t Offset)
{
switch (this->DeviceType)
{
case ddt_Keyboard:
{
while (KeyQueue.empty())
TaskManager->Yield();
Buffer[0] = KeyQueue.front();
KeyQueue.pop_front();
return 1;
}
default:
if (this->Read)
return this->Read(this->DeviceMajor, this->DeviceMinor,
Buffer, Size, Offset);
return 0;
}
}
size_t SlaveDeviceFile::write(uint8_t *Buffer,
size_t Size,
off_t Offset)
{
switch (this->DeviceType)
{
default:
if (this->Write)
return this->Write(this->DeviceMajor, this->DeviceMinor,
Buffer, Size, Offset);
return 0;
}
}
int SlaveDeviceFile::ioctl(unsigned long Request,
void *Argp)
{
switch (this->DeviceType)
{
default:
if (this->Ioctl)
return this->Ioctl(this->DeviceMajor, this->DeviceMinor,
Request, Argp);
return -ENOSYS;
}
}
void SlaveDeviceFile::ClearBuffers()
{
KeyQueue.clear();
/* ... */
}
int SlaveDeviceFile::ReportKeyEvent(uint8_t ScanCode)
{
if (KeyQueue.size() > 16)
KeyQueue.pop_front();
KeyQueue.push_back(ScanCode);
return 0;
}
SlaveDeviceFile::SlaveDeviceFile(const char *Name, vfs::Node *Parent, int Type, vfs::NodeType NType)
: Node(Parent, Name, NType)
{
this->DeviceType = Type;
}
SlaveDeviceFile::~SlaveDeviceFile()
{
}
}

View File

@ -17,6 +17,7 @@
#include <driver.hpp>
#include <interface/driver.h>
#include <memory.hpp>
#include <ints.hpp>
#include <task.hpp>
@ -26,12 +27,64 @@
#include <md5.h>
#include "../../kernel.h"
#include "../../driver.h"
using namespace vfs;
namespace Driver
{
void Manager::PreloadDrivers()
{
debug("Initializing driver manager");
const char *DriverDirectory = Config.DriverDirectory;
FileNode *drvDirNode = fs->GetByPath(DriverDirectory, nullptr);
if (!drvDirNode)
{
error("Failed to open driver directory %s", DriverDirectory);
KPrint("Failed to open driver directory %s", DriverDirectory);
return;
}
foreach (const auto &drvNode in drvDirNode->Children)
{
debug("Checking driver %s", drvNode->Path.c_str());
if (!drvNode->IsRegularFile())
continue;
if (Execute::GetBinaryType(drvNode->Path) != Execute::BinTypeELF)
{
error("Driver %s is not an ELF binary", drvNode->Path.c_str());
continue;
}
Memory::VirtualMemoryArea *dVma = new Memory::VirtualMemoryArea(thisProcess->PageTable);
uintptr_t EntryPoint, BaseAddress;
int err = this->LoadDriverFile(EntryPoint, BaseAddress, dVma, drvNode);
debug("err = %d (%s)", err, strerror(err));
if (err != 0)
{
error("Failed to load driver %s: %s",
drvNode->Path.c_str(), strerror(err));
delete dVma;
continue;
}
Drivers[DriverIDCounter++] = {
.BaseAddress = BaseAddress,
.EntryPoint = EntryPoint,
.vma = dVma,
.Path = drvNode->Path,
.InterruptHandlers = new std::unordered_map<uint8_t, void *>};
dev_t countr = DriverIDCounter - 1;
const char *drvName;
size_t drvNameLen;
cwk_path_get_basename(drvNode->Path.c_str(), &drvName, &drvNameLen);
strncpy(Drivers[countr].Name, drvName, sizeof(Drivers[countr].Name));
}
}
void Manager::LoadAllDrivers()
{
if (Drivers.empty())
@ -56,7 +109,7 @@ namespace Driver
dApi->Base = Drv->BaseAddress;
PopulateDriverAPI(dApi);
debug("Calling driver %s at %#lx", Drv->Path, Drv->EntryPoint);
debug("Calling driver %s at %#lx", Drv->Path.c_str(), Drv->EntryPoint);
int (*DrvInit)(__driverAPI *) = (int (*)(__driverAPI *))Drv->EntryPoint;
Drv->ErrorCode = DrvInit(dApi);
if (Drv->ErrorCode < 0)
@ -64,7 +117,7 @@ namespace Driver
KPrint("FATAL: _start() failed for %s: %s",
Drv->Name, strerror(Drv->ErrorCode));
error("Failed to load driver %s: %s",
Drv->Path, strerror(Drv->ErrorCode));
Drv->Path.c_str(), strerror(Drv->ErrorCode));
Drv->vma->FreeAllPages();
continue;
@ -73,48 +126,36 @@ namespace Driver
KPrint("Loading driver %s", Drv->Name);
debug("Calling Probe()=%#lx on driver %s",
Drv->Probe, Drv->Path);
Drv->Probe, Drv->Path.c_str());
Drv->ErrorCode = Drv->Probe();
if (Drv->ErrorCode < 0)
{
KPrint("Probe() failed for %s: %s",
Drv->Name, strerror(Drv->ErrorCode));
error("Failed to probe driver %s: %s",
Drv->Path, strerror(Drv->ErrorCode));
Drv->Path.c_str(), strerror(Drv->ErrorCode));
Drv->vma->FreeAllPages();
continue;
}
debug("Calling driver Entry()=%#lx function on driver %s",
Drv->Entry, Drv->Path);
Drv->Entry, Drv->Path.c_str());
Drv->ErrorCode = Drv->Entry();
if (Drv->ErrorCode < 0)
{
KPrint("Entry() failed for %s: %s",
Drv->Name, strerror(Drv->ErrorCode));
error("Failed to initialize driver %s: %s",
Drv->Path, strerror(Drv->ErrorCode));
Drv->Path.c_str(), strerror(Drv->ErrorCode));
Drv->vma->FreeAllPages();
continue;
}
debug("Loaded driver %s", Drv->Path);
debug("Loaded driver %s", Drv->Path.c_str());
Drv->Initialized = true;
}
InputMouseDev->ClearBuffers();
InputKeyboardDev->ClearBuffers();
BlockSATADev->ClearBuffers();
BlockHDDev->ClearBuffers();
BlockNVMeDev->ClearBuffers();
AudioDev->ClearBuffers();
NetDev->ClearBuffers();
/* ... */
}
void Manager::UnloadAllDrivers()
@ -151,6 +192,9 @@ namespace Driver
void Manager::Panic()
{
Memory::Virtual vmm;
if (Drivers.size() == 0)
return;
foreach (auto Driver in Drivers)
{
if (!Driver.second.Initialized)
@ -168,21 +212,18 @@ namespace Driver
}
}
int Manager::LoadDriverFile(uintptr_t &EntryPoint,
uintptr_t &BaseAddress,
Memory::VirtualMemoryArea *dVma,
RefNode *rDrv)
int Manager::LoadDriverFile(uintptr_t &EntryPoint, uintptr_t &BaseAddress,
Memory::VirtualMemoryArea *dVma, FileNode *rDrv)
{
Elf64_Ehdr ELFHeader;
rDrv->seek(0, SEEK_SET);
rDrv->read((uint8_t *)&ELFHeader, sizeof(Elf64_Ehdr));
rDrv->Read(&ELFHeader, sizeof(Elf64_Ehdr), 0);
if (ELFHeader.e_type != ET_DYN)
{
error("Driver %s is not a shared object", rDrv->node->FullPath);
error("Driver %s is not a shared object", rDrv->Path.c_str());
return -ENOEXEC;
}
trace("Loading driver %s in memory", rDrv->node->Name);
trace("Loading driver %s in memory", rDrv->Name.c_str());
BaseAddress = 0;
{
@ -192,8 +233,7 @@ namespace Driver
size_t SegmentsSize = 0;
for (Elf64_Half i = 0; i < ELFHeader.e_phnum; i++)
{
rDrv->seek(ELFHeader.e_phoff + (i * sizeof(Elf64_Phdr)), SEEK_SET);
rDrv->read((uint8_t *)&ProgramHeader, sizeof(Elf64_Phdr));
rDrv->Read(&ProgramHeader, sizeof(Elf64_Phdr), ELFHeader.e_phoff + (i * sizeof(Elf64_Phdr)));
if (ProgramHeader.p_type == PT_LOAD ||
ProgramHeader.p_type == PT_DYNAMIC)
@ -217,8 +257,7 @@ namespace Driver
for (Elf64_Half i = 0; i < ELFHeader.e_phnum; i++)
{
rDrv->seek(ELFHeader.e_phoff + (i * sizeof(Elf64_Phdr)), SEEK_SET);
rDrv->read((uint8_t *)&ProgramHeader, sizeof(Elf64_Phdr));
rDrv->Read(&ProgramHeader, sizeof(Elf64_Phdr), ELFHeader.e_phoff + (i * sizeof(Elf64_Phdr)));
switch (ProgramHeader.p_type)
{
@ -237,8 +276,7 @@ namespace Driver
if (ProgramHeader.p_filesz > 0)
{
rDrv->seek(ProgramHeader.p_offset, SEEK_SET);
rDrv->read((uint8_t *)SegmentDestination, ProgramHeader.p_filesz);
rDrv->Read(SegmentDestination, ProgramHeader.p_filesz, ProgramHeader.p_offset);
}
if (ProgramHeader.p_memsz - ProgramHeader.p_filesz > 0)
@ -264,8 +302,7 @@ namespace Driver
if (ProgramHeader.p_filesz > 0)
{
rDrv->seek(ProgramHeader.p_offset, SEEK_SET);
rDrv->read((uint8_t *)DynamicSegmentDestination, ProgramHeader.p_filesz);
rDrv->Read(DynamicSegmentDestination, ProgramHeader.p_filesz, ProgramHeader.p_offset);
}
if (ProgramHeader.p_memsz - ProgramHeader.p_filesz > 0)
@ -288,8 +325,7 @@ namespace Driver
Elf64_Phdr ProgramHeader;
for (Elf64_Half i = 0; i < ELFHeader.e_phnum; i++)
{
rDrv->seek(ELFHeader.e_phoff + (i * sizeof(Elf64_Phdr)), SEEK_SET);
rDrv->read((uint8_t *)&ProgramHeader, sizeof(Elf64_Phdr));
rDrv->Read(&ProgramHeader, sizeof(Elf64_Phdr), ELFHeader.e_phoff + (i * sizeof(Elf64_Phdr)));
if (ProgramHeader.p_type == PT_DYNAMIC)
{
@ -381,14 +417,11 @@ namespace Driver
break;
}
vfs::RefNode *fd = fs->Open(rDrv->node->FullPath);
std::vector<Elf64_Dyn> SymTab = Execute::ELFGetDynamicTag_x86_64(fd, DT_SYMTAB);
std::vector<Elf64_Dyn> StrTab = Execute::ELFGetDynamicTag_x86_64(fd, DT_STRTAB);
std::vector<Elf64_Dyn> SymTab = Execute::ELFGetDynamicTag_x86_64(rDrv, DT_SYMTAB);
std::vector<Elf64_Dyn> StrTab = Execute::ELFGetDynamicTag_x86_64(rDrv, DT_STRTAB);
Elf64_Sym *_SymTab = (Elf64_Sym *)((uintptr_t)BaseAddress + SymTab[0].d_un.d_ptr);
char *DynStr = (char *)((uintptr_t)BaseAddress + StrTab[0].d_un.d_ptr);
UNUSED(DynStr);
delete fd;
Elf64_Rela *Rela = (Elf64_Rela *)(BaseAddress + Dynamic->d_un.d_ptr);
for (size_t i = 0; i < (PltRelSize->d_un.d_val / sizeof(Elf64_Rela)); i++)
@ -431,14 +464,12 @@ namespace Driver
{
fixme("DT_SYMTAB");
break;
vfs::RefNode *fd = fs->Open(rDrv->node->FullPath);
std::vector<Elf64_Dyn> SymTab = Execute::ELFGetDynamicTag_x86_64(fd, DT_SYMTAB);
std::vector<Elf64_Dyn> StrTab = Execute::ELFGetDynamicTag_x86_64(fd, DT_STRTAB);
std::vector<Elf64_Dyn> SymTab = Execute::ELFGetDynamicTag_x86_64(rDrv, DT_SYMTAB);
std::vector<Elf64_Dyn> StrTab = Execute::ELFGetDynamicTag_x86_64(rDrv, DT_STRTAB);
Elf64_Sym *_SymTab = (Elf64_Sym *)((uintptr_t)BaseAddress + SymTab[0].d_un.d_ptr);
char *DynStr = (char *)((uintptr_t)BaseAddress + StrTab[0].d_un.d_ptr);
UNUSED(DynStr);
delete fd;
size_t symtabEntrySize = 0;
Elf64_Dyn *entrySizeDyn = Dynamic;
@ -476,8 +507,8 @@ namespace Driver
* this will create more issues :/ */
// if (strcmp(SymbolName, "DriverProbe") == 0)
// {
// Drivers[MajorIDCounter].Probe = (int (*)())(BaseAddress + s->st_value);
// debug("Found probe function at %#lx", Drivers[MajorIDCounter].Probe);
// Drivers[DriverIDCounter].Probe = (int (*)())(BaseAddress + s->st_value);
// debug("Found probe function at %#lx", Drivers[DriverIDCounter].Probe);
// }
}
break;
@ -498,7 +529,7 @@ namespace Driver
EntryPoint += BaseAddress;
debug("Driver %s has entry point %#lx and base %#lx",
rDrv->node->FullPath, EntryPoint, BaseAddress);
rDrv->Path.c_str(), EntryPoint, BaseAddress);
/* FIXME: Do not add to the KernelSymbolTable! */
// Memory::SmartHeap sh(rDrv->Size);
@ -510,79 +541,11 @@ namespace Driver
Manager::Manager()
{
debug("Initializing driver manager");
const char *DriverDirectory = Config.DriverDirectory;
RefNode *drvDirNode = fs->Open(DriverDirectory);
if (!drvDirNode)
{
error("Failed to open driver directory %s", DriverDirectory);
KPrint("Failed to open driver directory %s", DriverDirectory);
return;
}
foreach (auto drvNode in drvDirNode->node->Children)
{
if (drvNode->Type != vfs::FILE)
continue;
if (Execute::GetBinaryType(drvNode->FullPath) != Execute::BinTypeELF)
{
error("Driver %s is not an ELF binary", drvNode->FullPath);
continue;
}
RefNode *rDrv = drvNode->CreateReference();
Memory::VirtualMemoryArea *dVma =
new Memory::VirtualMemoryArea(thisProcess->PageTable);
uintptr_t EntryPoint, BaseAddress;
int err = this->LoadDriverFile(EntryPoint, BaseAddress, dVma, rDrv);
debug("err = %d (%s)", err, strerror(err));
if (err != 0)
{
error("Failed to load driver %s: %s",
drvNode->FullPath, strerror(err));
delete rDrv;
delete dVma;
continue;
}
delete rDrv;
Drivers[MajorIDCounter++] = {
.BaseAddress = BaseAddress,
.EntryPoint = EntryPoint,
.vma = dVma,
.Path = drvNode->FullPath,
.InterruptHandlers = new std::unordered_map<uint8_t, void *>};
dev_t countr = MajorIDCounter - 1;
const char *drvName;
size_t drvNameLen;
cwk_path_get_basename(drvNode->FullPath, &drvName, &drvNameLen);
strncpy(Drivers[countr].Name, drvName, sizeof(Drivers[countr].Name));
}
delete drvDirNode;
InputMouseDev = new MasterDeviceFile("mice", "mouse", DevFS, ddt_Mouse);
InputKeyboardDev = new MasterDeviceFile("key", "kbd", DevFS, ddt_Keyboard);
BlockSATADev = new MasterDeviceFile("sd", "sd", DevFS, ddt_SATA);
BlockHDDev = new MasterDeviceFile("hd", "hd", DevFS, ddt_ATA);
BlockNVMeDev = new MasterDeviceFile("nvme", "nvme", DevFS, ddt_NVMe);
AudioDev = new MasterDeviceFile("audio", "snd", DevFS, ddt_Audio);
NetDev = new MasterDeviceFile("network", "net", DevFS, ddt_Network);
}
Manager::~Manager()
{
debug("Unloading drivers");
UnloadAllDrivers();
delete InputMouseDev;
delete InputKeyboardDev;
}
}

View File

@ -15,10 +15,9 @@
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include <interface/driver.h>
#include <driver.hpp>
#include "../../driver.h"
static char ScanCodeConversionTableLower[] = {
[KEY_1] = '1',
[KEY_2] = '2',

View File

@ -345,15 +345,15 @@ namespace Interrupts
#ifdef DEBUG
foreach (auto ev in RegisteredEvents)
{
void *func = ev.IsHandler
void *fct = ev.IsHandler
? ev.Data
: (void *)ev.Callback;
const char *symbol = ev.IsHandler
? "class"
: KernelSymbolTable->GetSymbol((uintptr_t)func);
: KernelSymbolTable->GetSymbol((uintptr_t)fct);
debug("Event IRQ%d [%#lx %s] has priority %ld",
ev.IRQ, func, symbol, ev.Priority);
ev.IRQ, fct, symbol, ev.Priority);
}
#endif
}

View File

@ -173,7 +173,7 @@ typedef volatile _Atomic(int64_t) atomic64_t;
typedef volatile _Atomic(void *) atomicptr_t;
/* Intellisense errors */
#ifndef __debug_vscode__
#ifndef __vscode__
static FORCEINLINE int32_t atomic_load32(atomic32_t *src) { return atomic_load_explicit(src, memory_order_relaxed); }
static FORCEINLINE void atomic_store32(atomic32_t *dst, int32_t val) { atomic_store_explicit(dst, val, memory_order_relaxed); }

View File

@ -86,6 +86,6 @@ EXTERNC int __rpmalloc_munmap(void *addr, size_t length)
EXTERNC int __rpmalloc_posix_madvise(void *addr, size_t length, int advice)
{
function("%#lx %d %d", addr, length, advice);
func("%#lx %d %d", addr, length, advice);
return 0;
}

View File

@ -427,7 +427,11 @@ NIF void InitializeMemoryManagement()
void *malloc(size_t Size)
{
assert(Size > 0);
if (Size == 0)
{
warn("Attempt to allocate 0 bytes");
Size = 16;
}
memdbg("malloc(%d)->[%s]", Size,
KernelSymbolTable ? KernelSymbolTable->GetSymbol((uintptr_t)__builtin_return_address(0))
@ -474,7 +478,11 @@ void *malloc(size_t Size)
void *calloc(size_t n, size_t Size)
{
assert(Size > 0);
if (Size == 0)
{
warn("Attempt to allocate 0 bytes");
Size = 16;
}
memdbg("calloc(%d, %d)->[%s]", n, Size,
KernelSymbolTable ? KernelSymbolTable->GetSymbol((uintptr_t)__builtin_return_address(0))
@ -521,7 +529,11 @@ void *calloc(size_t n, size_t Size)
void *realloc(void *Address, size_t Size)
{
assert(Size > 0);
if (Size == 0)
{
warn("Attempt to allocate 0 bytes");
Size = 16;
}
memdbg("realloc(%#lx, %d)->[%s]", Address, Size,
KernelSymbolTable ? KernelSymbolTable->GetSymbol((uintptr_t)__builtin_return_address(0))
@ -568,7 +580,11 @@ void *realloc(void *Address, size_t Size)
void free(void *Address)
{
assert(Address != nullptr);
if (Address == nullptr)
{
warn("Attempt to free a null pointer");
return;
}
memdbg("free(%#lx)->[%s]", Address,
KernelSymbolTable ? KernelSymbolTable->GetSymbol((uintptr_t)__builtin_return_address(0))
@ -609,105 +625,3 @@ void free(void *Address)
}
}
}
void *operator new(std::size_t Size)
{
assert(Size > 0);
memdbg("new(%d)->[%s]", Size,
KernelSymbolTable ? KernelSymbolTable->GetSymbol((uintptr_t)__builtin_return_address(0))
: "Unknown");
void *ret = malloc(Size);
return ret;
}
void *operator new[](std::size_t Size)
{
assert(Size > 0);
memdbg("new[](%d)->[%s]", Size,
KernelSymbolTable ? KernelSymbolTable->GetSymbol((uintptr_t)__builtin_return_address(0))
: "Unknown");
void *ret = malloc(Size);
return ret;
}
void *operator new(std::size_t Size, std::align_val_t Alignment)
{
assert(Size > 0);
memdbg("new(%d, %d)->[%s]", Size, Alignment,
KernelSymbolTable ? KernelSymbolTable->GetSymbol((uintptr_t)__builtin_return_address(0))
: "Unknown");
fixme("operator new with alignment(%#lx) is not implemented",
Alignment);
void *ret = malloc(Size);
return ret;
}
void operator delete(void *Pointer)
{
assert(Pointer != nullptr);
memdbg("delete(%#lx)->[%s]", Pointer,
KernelSymbolTable ? KernelSymbolTable->GetSymbol((uintptr_t)__builtin_return_address(0))
: "Unknown");
free(Pointer);
}
void operator delete[](void *Pointer)
{
assert(Pointer != nullptr);
memdbg("delete[](%#lx)->[%s]", Pointer,
KernelSymbolTable ? KernelSymbolTable->GetSymbol((uintptr_t)__builtin_return_address(0))
: "Unknown");
free(Pointer);
}
void operator delete(void *Pointer, long unsigned int Size)
{
assert(Pointer != nullptr);
assert(Size > 0);
memdbg("delete(%#lx, %d)->[%s]",
Pointer, Size,
KernelSymbolTable ? KernelSymbolTable->GetSymbol((uintptr_t)__builtin_return_address(0))
: "Unknown");
free(Pointer);
}
void operator delete[](void *Pointer, long unsigned int Size)
{
assert(Pointer != nullptr);
assert(Size > 0);
memdbg("delete[](%#lx, %d)->[%s]",
Pointer, Size,
KernelSymbolTable ? KernelSymbolTable->GetSymbol((uintptr_t)__builtin_return_address(0))
: "Unknown");
free(Pointer);
}
void operator delete(void *Pointer, unsigned long Size, std::align_val_t Alignment)
{
assert(Pointer != nullptr);
assert(Size > 0);
memdbg("delete(%#lx, %d, %d)->[%s]",
Pointer, Size, Alignment,
KernelSymbolTable ? KernelSymbolTable->GetSymbol((uintptr_t)__builtin_return_address(0))
: "Unknown");
fixme("operator delete with alignment is not implemented");
free(Pointer);
}

View File

@ -27,7 +27,7 @@ namespace Memory
{
VirtualAllocation::AllocatedPages VirtualAllocation::RequestPages(size_t Count)
{
function("%lld", Count);
func("%lld", Count);
void *pAddress = KernelAllocator.RequestPages(Count);
memset(pAddress, 0, FROM_PAGES(Count));
@ -79,7 +79,7 @@ namespace Memory
void VirtualAllocation::FreePages(void *Address, size_t Count)
{
function("%#lx, %lld", Address, Count);
func("%#lx, %lld", Address, Count);
SmartLock(MgrLock);
foreach (auto &apl in AllocatedPagesList)
@ -110,7 +110,7 @@ namespace Memory
void VirtualAllocation::MapTo(AllocatedPages ap, PageTable *TargetTable)
{
function("%#lx, %#lx", ap.VirtualAddress, TargetTable);
func("%#lx, %#lx", ap.VirtualAddress, TargetTable);
Virtual vmm(TargetTable);
vmm.Map(ap.VirtualAddress, ap.PhysicalAddress, FROM_PAGES(ap.PageCount), RW | KRsv | G);
@ -120,7 +120,7 @@ namespace Memory
: BaseAddress(Base), CurrentBase(Base),
Table((PageTable *)CPU::PageTable())
{
function("%#lx", Base);
func("%#lx", Base);
}
VirtualAllocation::~VirtualAllocation()

View File

@ -36,7 +36,7 @@ namespace Memory
void *VirtualMemoryArea::RequestPages(size_t Count, bool User, bool Protect)
{
function("%lld, %s, %s", Count,
func("%lld, %s, %s", Count,
User ? "true" : "false",
Protect ? "true" : "false");
@ -61,7 +61,7 @@ namespace Memory
void VirtualMemoryArea::FreePages(void *Address, size_t Count)
{
function("%#lx, %lld", Address, Count);
func("%#lx, %lld", Address, Count);
SmartLock(MgrLock);
forItr(itr, AllocatedPagesList)
@ -104,7 +104,7 @@ namespace Memory
void VirtualMemoryArea::DetachAddress(void *Address)
{
function("%#lx", Address);
func("%#lx", Address);
SmartLock(MgrLock);
forItr(itr, AllocatedPagesList)
@ -128,7 +128,7 @@ namespace Memory
bool Read, bool Write, bool Exec,
bool Fixed, bool Shared)
{
function("%#lx, %lld, %s, %s, %s, %s, %s", Address, Length,
func("%#lx, %lld, %s, %s, %s, %s, %s", Address, Length,
Read ? "true" : "false",
Write ? "true" : "false",
Exec ? "true" : "false",
@ -191,7 +191,7 @@ namespace Memory
bool VirtualMemoryArea::HandleCoW(uintptr_t PFA)
{
function("%#lx", PFA);
func("%#lx", PFA);
Virtual vmm(this->Table);
PageTableEntry *pte = vmm.GetPTE((void *)PFA);
@ -269,7 +269,7 @@ namespace Memory
void VirtualMemoryArea::Fork(VirtualMemoryArea *Parent)
{
function("%#lx", Parent);
func("%#lx", Parent);
assert(Parent);
debug("parent apl:%d sr:%d [P:%#lx C:%#lx]",

View File

@ -65,7 +65,7 @@ struct DiagnosticFile
} Data;
};
nsa bool WriteDiagDataToNode(vfs::RefNode *refFile)
nsa bool WriteDiagDataToNode(FileNode *node)
{
uintptr_t KStart = (uintptr_t)&_kernel_start;
uintptr_t kEnd = (uintptr_t)&_kernel_end;
@ -89,8 +89,8 @@ nsa bool WriteDiagDataToNode(vfs::RefNode *refFile)
file->Data.KernelMemoryLength = uint32_t(kSize);
memcpy(file->Data.KernelMemory, (void *)KStart, kSize);
ExPrint("\eFAFAFAWriting to %s\n", refFile->node->FullPath);
size_t w = refFile->write(buf, fileSize);
ExPrint("\eFAFAFAWriting to %s\n", node->Path.c_str());
size_t w = node->Write(buf, fileSize, 0);
if (w != fileSize)
{
debug("%d out of %d bytes written", w, fileSize);
@ -111,7 +111,12 @@ nsa void DiagnosticDataCollection()
ExPrint("\n\eFAFAFAPlease wait while we collect some diagnostic information...\n");
ExPrint("This may take a while...\n");
vfs::Node *panicDir = fs->CreateIfNotExists("/var/panic", vfs::DIRECTORY);
mode_t mode = S_IRWXU |
S_IRWXG |
S_IROTH |
S_IFDIR;
FileNode *panicDir = fs->ForceCreate(nullptr, "/var/panic", mode);
if (!panicDir)
{
ExPrint("\eFF0000Failed to create /var/panic\n");
@ -119,6 +124,7 @@ nsa void DiagnosticDataCollection()
return;
}
FileNode *dumpFile;
Time::Clock clock = Time::ReadClock();
char filename[64];
for (int i = 0; i < INT32_MAX; i++)
@ -128,18 +134,18 @@ nsa void DiagnosticDataCollection()
if (fs->PathExists(filename, panicDir))
continue;
fs->Create(filename, vfs::FILE, panicDir);
mode = S_IRWXU |
S_IRWXG |
S_IROTH |
S_IFREG;
dumpFile = fs->Create(panicDir, filename, mode);
break;
}
vfs::RefNode *refFile = fs->Open(filename, panicDir);
if (!WriteDiagDataToNode(refFile))
{
delete refFile;
if (!WriteDiagDataToNode(dumpFile))
return;
}
ExPrint("You can find the diagnostic file in /var/panic/%s\n", filename);
Display->UpdateBuffer();
delete refFile;
}

View File

@ -517,7 +517,7 @@ nsa void DisplayStackScreen(CPU::ExceptionFrame *Frame)
sym, offset);
}
else
ExPrint("\eFF5555???\n");
ExPrint("\eFF5555??? \eFFAAAA<- Exception\n");
if (!sf || !sf->ip || !sf->bp)
{
@ -591,7 +591,7 @@ nsa void DisplayProcessScreen(CPU::ExceptionFrame *Frame, bool IgnoreReady = tru
if (Display->GetWidth > 800 && Display->GetHeight > 600)
textLimit = 128;
std::list<Tasking::PCB *> Plist = TaskManager->GetProcessList();
std::vector<Tasking::PCB *> Plist = TaskManager->GetProcessList();
ExPrint("\n\eFAFAFAProcess list (%ld):\n", Plist.size());
bool pRdy = false;
@ -626,7 +626,7 @@ nsa void DisplayProcessScreen(CPU::ExceptionFrame *Frame, bool IgnoreReady = tru
Process->ID, StatusColor[Process->State.load()],
StatusString[Process->State.load()],
Process->Executable
? Process->Executable->Name
? Process->Executable->Name.c_str()
: "none");
bool tRdy = false;
@ -766,6 +766,29 @@ nsa void DisplayAssertionFailed(const char *File, int Line, const char *Expressi
ExPrint(" This is a kernel bug.\n");
ExPrint(" Please create a new issue on \e00AAFFhttps://github.com/Fennix-Project/Fennix\eFAFAFA for further assistance.\n");
CPU::ExceptionFrame ef;
// Fill only the necessary fields
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wframe-address"
/* Jump over HandleAssertionFailed, and ip will be the function where it failed */
void *fun = __builtin_return_address(1);
/* Jump over this, HandleAssertionFailed & ip */
void *stk = __builtin_frame_address(2);
#pragma GCC diagnostic pop
#ifdef __x86_64__
asmv("movq %%cr3, %0" : "=r"(ef.cr3));
ef.rip = (uint64_t)fun;
ef.rbp = ef.rsp = (uint64_t)stk;
#elif defined(__i386__)
asmv("movl %%cr3, %0" : "=r"(ef.cr3));
ef.eip = (uint32_t)fun;
ef.ebp = ef.esp = (uint32_t)stk;
#endif
DisplayStackScreen(&ef);
Display->UpdateBuffer();
/* TODO: Add additional info */

View File

@ -40,15 +40,11 @@ namespace SymbolResolver
return Result.FunctionName;
}
std::vector<SymbolTable> rSymTable = this->SymTable;
rSymTable.reverse();
foreach (auto st in rSymTable)
for (auto it = this->SymTable.rbegin(); it != this->SymTable.rend(); ++it)
{
if (unlikely(st.Address <= Address &&
st.Address > Result.Address))
if (unlikely(it->Address <= Address && it->Address > Result.Address))
{
Result = st;
Result = *it;
break;
}
}
@ -72,14 +68,11 @@ namespace SymbolResolver
return Result.Address;
}
std::vector<SymbolTable> rSymTable = this->SymTable;
rSymTable.reverse();
foreach (auto st in rSymTable)
for (auto it = this->SymTable.rbegin(); it != this->SymTable.rend(); ++it)
{
if (unlikely(strcmp(st.FunctionName, Name) == 0))
if (unlikely(strcmp(it->FunctionName, Name) == 0))
{
Result = st;
Result = *it;
break;
}
}

View File

@ -18,63 +18,65 @@
#include <exec.hpp>
#include <msexec.h>
#include <macho.h>
#include <memory>
#include "../kernel.h"
namespace Execute
{
BinaryType GetBinaryType(const char *Path)
BinaryType GetBinaryType(FileNode *Node)
{
debug("Checking binary type of %s(ptr: %#lx)",
Path, Path);
debug("Checking binary type of %s", Node->Path.c_str());
BinaryType Type;
vfs::RefNode *fd = fs->Open(Path);
if (fd == nullptr)
{
debug("Failed to open file %s", Path);
return (BinaryType)-ENOENT;
}
if (Node == nullptr)
ReturnLogError((BinaryType)-ENOENT, "Node is null");
debug("File opened: %s, descriptor %d", Path, fd);
Memory::SmartHeap sh = Memory::SmartHeap(1024);
fd->read(sh, 128);
Elf32_Ehdr ELFHeader;
Node->Read(&ELFHeader, sizeof(Elf32_Ehdr), 0);
Elf32_Ehdr *ELFHeader = (Elf32_Ehdr *)sh.Get();
IMAGE_DOS_HEADER *MZHeader = (IMAGE_DOS_HEADER *)sh.Get();
mach_header MachHeader;
Node->Read(&MachHeader, sizeof(mach_header), 0);
IMAGE_DOS_HEADER MZHeader;
Node->Read(&MZHeader, sizeof(IMAGE_DOS_HEADER), 0);
/* Check ELF header. */
if (ELFHeader->e_ident[EI_MAG0] == ELFMAG0 &&
ELFHeader->e_ident[EI_MAG1] == ELFMAG1 &&
ELFHeader->e_ident[EI_MAG2] == ELFMAG2 &&
ELFHeader->e_ident[EI_MAG3] == ELFMAG3)
if (ELFHeader.e_ident[EI_MAG0] == ELFMAG0 &&
ELFHeader.e_ident[EI_MAG1] == ELFMAG1 &&
ELFHeader.e_ident[EI_MAG2] == ELFMAG2 &&
ELFHeader.e_ident[EI_MAG3] == ELFMAG3)
{
debug("Image - ELF");
Type = BinaryType::BinTypeELF;
goto Success;
}
/* Check MZ header. */
else if (MZHeader->e_magic == IMAGE_DOS_SIGNATURE)
if (MachHeader.magic == MH_MAGIC || MachHeader.magic == MH_CIGAM)
{
fd->seek(MZHeader->e_lfanew, SEEK_SET);
fd->read(sh, 512);
IMAGE_NT_HEADERS *PEHeader =
(IMAGE_NT_HEADERS *)(((char *)sh.Get()) +
MZHeader->e_lfanew);
debug("Image - Mach-O");
Type = BinaryType::BinTypeMachO;
goto Success;
}
IMAGE_OS2_HEADER *NEHeader =
(IMAGE_OS2_HEADER *)(((char *)sh.Get()) +
MZHeader->e_lfanew);
/* Check MZ header. */
else if (MZHeader.e_magic == IMAGE_DOS_SIGNATURE)
{
IMAGE_NT_HEADERS PEHeader;
Node->Read(&PEHeader, sizeof(IMAGE_NT_HEADERS), MZHeader.e_lfanew);
IMAGE_OS2_HEADER NEHeader;
Node->Read(&NEHeader, sizeof(IMAGE_OS2_HEADER), MZHeader.e_lfanew);
/* TODO: LE, EDOS */
if (PEHeader->Signature == IMAGE_NT_SIGNATURE)
if (PEHeader.Signature == IMAGE_NT_SIGNATURE)
{
debug("Image - PE");
Type = BinaryType::BinTypePE;
goto Success;
}
else if (NEHeader->ne_magic == IMAGE_OS2_SIGNATURE)
else if (NEHeader.ne_magic == IMAGE_OS2_SIGNATURE)
{
debug("Image - NE");
Type = BinaryType::BinTypeNE;
@ -92,7 +94,12 @@ namespace Execute
Type = BinaryType::BinTypeUnknown;
Success:
delete fd;
return Type;
}
BinaryType GetBinaryType(std::string Path)
{
FileNode *node = fs->GetByPath(Path.c_str(), nullptr);
return GetBinaryType(node);
}
}

View File

@ -33,15 +33,16 @@ using namespace vfs;
namespace Execute
{
void ELFObject::GenerateAuxiliaryVector_x86_32(Memory::VirtualMemoryArea *vma,
vfs::RefNode *fd,
FileNode *fd,
Elf32_Ehdr ELFHeader,
uint32_t EntryPoint,
uint32_t BaseAddress)
{
assert(!"Function not implemented");
}
void ELFObject::GenerateAuxiliaryVector_x86_64(Memory::VirtualMemoryArea *vma,
vfs::RefNode *fd,
FileNode *fd,
Elf64_Ehdr ELFHeader,
uint64_t EntryPoint,
uint64_t BaseAddress)
@ -50,8 +51,8 @@ namespace Execute
char *aux_platform = (char *)vma->RequestPages(1, true); /* TODO: 4KiB is too much for this */
strcpy(aux_platform, "x86_64");
void *execfn_str = vma->RequestPages(TO_PAGES(strlen(fd->node->FullPath) + 1), true);
strcpy((char *)execfn_str, fd->node->FullPath);
void *execfn_str = vma->RequestPages(TO_PAGES(fd->Path.size() + 1), true);
strcpy((char *)execfn_str, fd->Path.c_str());
void *at_random = vma->RequestPages(1, true);
*(uint64_t *)at_random = Random::rand16();
@ -93,22 +94,21 @@ namespace Execute
#endif
}
void ELFObject::LoadExec_x86_32(vfs::RefNode *, PCB *)
void ELFObject::LoadExec_x86_32(FileNode *, PCB *)
{
stub;
assert(!"Function not implemented");
}
void ELFObject::LoadExec_x86_64(vfs::RefNode *fd, PCB *TargetProcess)
void ELFObject::LoadExec_x86_64(FileNode *fd, PCB *TargetProcess)
{
#if defined(a64)
std::vector<Elf64_Phdr> PhdrINTERP = ELFGetSymbolType_x86_64(fd, PT_INTERP);
foreach (auto Interp in PhdrINTERP)
{
Memory::SmartHeap InterpreterPath = Memory::SmartHeap(256);
fd->seek(Interp.p_offset, SEEK_SET);
fd->read(InterpreterPath, 256);
fd->Read(InterpreterPath, 256, Interp.p_offset);
vfs::RefNode *ifd = fs->Open((const char *)InterpreterPath.Get());
FileNode *ifd = fs->GetByPath((const char *)InterpreterPath.Get(), TargetProcess->Info.RootNode);
if (ifd == nullptr)
{
warn("Failed to open interpreter file: %s",
@ -121,7 +121,6 @@ namespace Execute
{
warn("Interpreter %s is not an ELF file",
(const char *)InterpreterPath.Get());
delete ifd;
continue;
}
@ -130,15 +129,13 @@ namespace Execute
/* FIXME: specify argv[1] as the location for the interpreter */
debug("Interpreter loaded successfully");
delete ifd;
return;
}
}
}
Elf64_Ehdr ELFHeader;
fd->seek(0, SEEK_SET);
fd->read((uint8_t *)&ELFHeader, sizeof(Elf64_Ehdr));
Elf64_Ehdr ELFHeader{};
fd->Read(&ELFHeader, sizeof(Elf64_Ehdr), 0);
uintptr_t EntryPoint = ELFHeader.e_entry;
debug("Entry point is %#lx", EntryPoint);
@ -152,8 +149,7 @@ namespace Execute
Elf64_Phdr ProgramHeader;
for (Elf64_Half i = 0; i < ELFHeader.e_phnum; i++)
{
fd->seek(ELFHeader.e_phoff + (i * sizeof(Elf64_Phdr)), SEEK_SET);
fd->read((uint8_t *)&ProgramHeader, sizeof(Elf64_Phdr));
fd->Read(&ProgramHeader, sizeof(Elf64_Phdr), ELFHeader.e_phoff + (i * sizeof(Elf64_Phdr)));
switch (ProgramHeader.p_type)
{
case PT_LOAD:
@ -182,10 +178,8 @@ namespace Execute
if (ProgramHeader.p_filesz > 0)
{
debug("%d %#lx %d", ProgramHeader.p_offset,
(uint8_t *)pAddr + SegDestOffset, ProgramHeader.p_filesz);
fd->seek(ProgramHeader.p_offset, SEEK_SET);
fd->read((uint8_t *)pAddr + SegDestOffset, ProgramHeader.p_filesz);
debug("%d %#lx %d", ProgramHeader.p_offset, (uint8_t *)pAddr + SegDestOffset, ProgramHeader.p_filesz);
fd->Read((uint8_t *)pAddr + SegDestOffset, ProgramHeader.p_filesz, ProgramHeader.p_offset);
}
if (ProgramHeader.p_memsz - ProgramHeader.p_filesz > 0)
@ -203,40 +197,35 @@ namespace Execute
case PT_NOTE:
{
Elf64_Nhdr NoteHeader;
fd->seek(ProgramHeader.p_offset, SEEK_SET);
fd->read((uint8_t *)&NoteHeader, sizeof(Elf64_Nhdr));
fd->Read(&NoteHeader, sizeof(Elf64_Nhdr), ProgramHeader.p_offset);
switch (NoteHeader.n_type)
{
case NT_PRSTATUS:
{
Elf64_Prstatus prstatus;
fd->seek(ProgramHeader.p_offset + sizeof(Elf64_Nhdr), SEEK_SET);
fd->read((uint8_t *)&prstatus, sizeof(Elf64_Prstatus));
fd->Read(&prstatus, sizeof(Elf64_Prstatus), ProgramHeader.p_offset + sizeof(Elf64_Nhdr));
debug("PRSTATUS: %#lx", prstatus.pr_reg[0]);
break;
}
case NT_PRPSINFO:
{
Elf64_Prpsinfo prpsinfo;
fd->seek(ProgramHeader.p_offset + sizeof(Elf64_Nhdr), SEEK_SET);
fd->read((uint8_t *)&prpsinfo, sizeof(Elf64_Prpsinfo));
fd->Read(&prpsinfo, sizeof(Elf64_Prpsinfo), ProgramHeader.p_offset + sizeof(Elf64_Nhdr));
debug("PRPSINFO: %s", prpsinfo.pr_fname);
break;
}
case NT_PLATFORM:
{
char platform[256];
fd->seek(ProgramHeader.p_offset + sizeof(Elf64_Nhdr), SEEK_SET);
fd->read((uint8_t *)&platform, 256);
fd->Read(&platform, sizeof(platform), ProgramHeader.p_offset + sizeof(Elf64_Nhdr));
debug("PLATFORM: %s", platform);
break;
}
case NT_AUXV:
{
Elf64_auxv_t auxv;
fd->seek(ProgramHeader.p_offset + sizeof(Elf64_Nhdr), SEEK_SET);
fd->read((uint8_t *)&auxv, sizeof(Elf64_auxv_t));
fd->Read(&auxv, sizeof(Elf64_auxv_t), ProgramHeader.p_offset + sizeof(Elf64_Nhdr));
debug("AUXV: %#lx", auxv.a_un.a_val);
break;
}
@ -254,8 +243,7 @@ namespace Execute
debug("TLS Size: %ld (%ld pages)",
tlsSize, TO_PAGES(tlsSize));
void *tlsMemory = vma->RequestPages(TO_PAGES(tlsSize));
fd->seek(ProgramHeader.p_offset, SEEK_SET);
fd->read((uint8_t *)tlsMemory, tlsSize);
fd->Read(tlsMemory, tlsSize, ProgramHeader.p_offset);
TargetProcess->TLS = {
.pBase = uintptr_t(tlsMemory),
.vBase = ProgramHeader.p_vaddr,
@ -323,23 +311,22 @@ namespace Execute
#endif
}
void ELFObject::LoadDyn_x86_32(vfs::RefNode *, PCB *)
void ELFObject::LoadDyn_x86_32(FileNode *, PCB *)
{
stub;
assert(!"Function not implemented");
}
void ELFObject::LoadDyn_x86_64(vfs::RefNode *fd, PCB *TargetProcess)
void ELFObject::LoadDyn_x86_64(FileNode *fd, PCB *TargetProcess)
{
#if defined(a64)
std::vector<Elf64_Phdr> PhdrINTERP = ELFGetSymbolType_x86_64(fd, PT_INTERP);
foreach (auto Interp in PhdrINTERP)
{
Memory::SmartHeap InterpreterPath = Memory::SmartHeap(256);
fd->seek(Interp.p_offset, SEEK_SET);
fd->read(InterpreterPath, 256);
fd->Read(InterpreterPath, 256, Interp.p_offset);
InterpreterPath = InterpreterPath;
vfs::RefNode *ifd = fs->Open((const char *)InterpreterPath.Get());
FileNode *ifd = fs->GetByPath((const char *)InterpreterPath.Get(), TargetProcess->Info.RootNode);
if (ifd == nullptr)
{
warn("Failed to open interpreter file: %s",
@ -352,22 +339,19 @@ namespace Execute
{
warn("Interpreter %s is not an ELF file",
(const char *)InterpreterPath.Get());
delete ifd;
continue;
}
if (LoadInterpreter(ifd, TargetProcess))
{
debug("Interpreter loaded successfully");
delete ifd;
return;
}
}
}
Elf64_Ehdr ELFHeader;
fd->seek(0, SEEK_SET);
fd->read((uint8_t *)&ELFHeader, sizeof(Elf64_Ehdr));
fd->Read(&ELFHeader, sizeof(Elf64_Ehdr), 0);
uintptr_t EntryPoint = ELFHeader.e_entry;
debug("Entry point is %#lx", EntryPoint);
@ -383,8 +367,7 @@ namespace Execute
size_t SegmentsSize = 0;
for (Elf64_Half i = 0; i < ELFHeader.e_phnum; i++)
{
fd->seek(ELFHeader.e_phoff + (i * sizeof(Elf64_Phdr)), SEEK_SET);
fd->read((uint8_t *)&ProgramHeader, sizeof(Elf64_Phdr));
fd->Read(&ProgramHeader, sizeof(Elf64_Phdr), ELFHeader.e_phoff + (i * sizeof(Elf64_Phdr)));
if (ProgramHeader.p_type == PT_LOAD ||
ProgramHeader.p_type == PT_DYNAMIC)
@ -408,8 +391,7 @@ namespace Execute
for (Elf64_Half i = 0; i < ELFHeader.e_phnum; i++)
{
fd->seek(ELFHeader.e_phoff + (i * sizeof(Elf64_Phdr)), SEEK_SET);
fd->read((uint8_t *)&ProgramHeader, sizeof(Elf64_Phdr));
fd->Read(&ProgramHeader, sizeof(Elf64_Phdr), ELFHeader.e_phoff + (i * sizeof(Elf64_Phdr)));
switch (ProgramHeader.p_type)
{
@ -428,8 +410,7 @@ namespace Execute
if (ProgramHeader.p_filesz > 0)
{
fd->seek(ProgramHeader.p_offset, SEEK_SET);
fd->read((uint8_t *)SegmentDestination, ProgramHeader.p_filesz);
fd->Read(SegmentDestination, ProgramHeader.p_filesz, ProgramHeader.p_offset);
}
if (ProgramHeader.p_memsz - ProgramHeader.p_filesz > 0)
@ -455,8 +436,7 @@ namespace Execute
if (ProgramHeader.p_filesz > 0)
{
fd->seek(ProgramHeader.p_offset, SEEK_SET);
fd->read((uint8_t *)DynamicSegmentDestination, ProgramHeader.p_filesz);
fd->Read(DynamicSegmentDestination, ProgramHeader.p_filesz, ProgramHeader.p_offset);
}
if (ProgramHeader.p_memsz - ProgramHeader.p_filesz > 0)
@ -559,14 +539,11 @@ namespace Execute
// Elf64_Shdr shdr;
// for (Elf64_Half i = 0; i < ELFHeader.e_shnum; i++)
// {
// fd->seek(ELFHeader.e_shoff + i * sizeof(Elf64_Shdr), SEEK_SET);
// fd->read((uint8_t *)&shdr, sizeof(Elf64_Shdr));
// fd->Read(&shdr, sizeof(Elf64_Shdr), ELFHeader.e_shoff + i * sizeof(Elf64_Shdr));
// char sectionName[32];
// Elf64_Shdr n_shdr;
// fd->seek(ELFHeader.e_shoff + ELFHeader.e_shstrndx * sizeof(Elf64_Shdr), SEEK_SET);
// fd->read((uint8_t *)&n_shdr, sizeof(Elf64_Shdr));
// fd->seek(n_shdr.sh_offset + shdr.sh_name, SEEK_SET);
// fd->read((uint8_t *)sectionName, 32);
// fd->Read(&n_shdr, sizeof(Elf64_Shdr), ELFHeader.e_shoff + ELFHeader.e_shstrndx * sizeof(Elf64_Shdr));
// fd->Read(sectionName, sizeof(sectionName), n_shdr.sh_offset + shdr.sh_name);
// debug("shdr: %s", sectionName);
// if (strcmp(sectionName, ".rela.plt") == 0)
// {
@ -692,8 +669,7 @@ namespace Execute
// // STT_OBJECT
// Elf64_Xword numEntries = shdr.sh_size / shdr.sh_entsize;
// Elf64_Sym *SymArray = new Elf64_Sym[numEntries];
// fd->seek(shdr.sh_offset, SEEK_SET);
// fd->read((uint8_t *)SymArray, shdr.sh_size);
// fd->Read(SymArray, shdr.sh_size, shdr.sh_offset);
// debug("start %#lx (off %#lx), entries %ld",
// SymArray, shdr.sh_addr, numEntries);
// for (Elf64_Xword j = 0; j < numEntries; j++)
@ -734,10 +710,10 @@ namespace Execute
#endif
}
bool ELFObject::LoadInterpreter(vfs::RefNode *fd, PCB *TargetProcess)
bool ELFObject::LoadInterpreter(FileNode *fd, PCB *TargetProcess)
{
Elf32_Ehdr ELFHeader;
fd->read((uint8_t *)&ELFHeader, sizeof(Elf32_Ehdr));
fd->Read(&ELFHeader, sizeof(Elf32_Ehdr), 0);
switch (ELFHeader.e_type)
{
@ -805,24 +781,24 @@ namespace Execute
return false;
}
ELFObject::ELFObject(char *AbsolutePath,
ELFObject::ELFObject(std::string AbsolutePath,
PCB *TargetProcess,
const char **argv,
const char **envp)
{
if (GetBinaryType(AbsolutePath) != BinaryType::BinTypeELF)
{
error("%s is not an ELF file or is invalid.", AbsolutePath);
error("%s is not an ELF file or is invalid.", AbsolutePath.c_str());
return;
}
vfs::RefNode *fd = fs->Open(AbsolutePath);
FileNode *fd = fs->GetByPath(AbsolutePath.c_str(), TargetProcess->Info.RootNode);
if (fd == nullptr)
{
error("Failed to open %s, errno: %d", AbsolutePath, fd);
error("Failed to open %s, errno: %d", AbsolutePath.c_str(), fd);
return;
}
debug("Opened %s", AbsolutePath);
debug("Opened %s", AbsolutePath.c_str());
int argc = 0;
int envc = 0;
@ -833,17 +809,15 @@ namespace Execute
envc++;
Elf32_Ehdr ELFHeader;
fd->read((uint8_t *)&ELFHeader, sizeof(Elf32_Ehdr));
fd->Read(&ELFHeader, sizeof(Elf32_Ehdr), 0);
std::vector<Elf64_Phdr> PhdrINTERP = ELFGetSymbolType_x86_64(fd, PT_INTERP);
const char *ElfInterpPath = nullptr;
if (!PhdrINTERP.empty() && ELFHeader.e_type == ET_DYN)
{
fd->seek(PhdrINTERP.front().p_offset, SEEK_SET);
ElfInterpPath = new char[256];
fd->read((uint8_t *)ElfInterpPath, 256);
fd->Read(ElfInterpPath, 256, PhdrINTERP.front().p_offset);
debug("Interpreter: %s", ElfInterpPath);
fd->seek(0, SEEK_SET);
argc++;
}
@ -945,8 +919,6 @@ namespace Execute
break;
}
}
delete fd;
}
ELFObject::~ELFObject()

View File

@ -58,7 +58,7 @@ namespace Execute
return StringTable + Offset;
}
Elf64_Sym *ELFLookupSymbol(Elf64_Ehdr *Header, const char *Name)
Elf64_Sym *ELFLookupSymbol(Elf64_Ehdr *Header, std::string Name)
{
Elf64_Shdr *SymbolTable = nullptr;
Elf64_Shdr *StringTable = nullptr;
@ -86,36 +86,31 @@ namespace Execute
{
Elf64_Sym *Symbol = (Elf64_Sym *)((uintptr_t)Header + SymbolTable->sh_offset + (i * sizeof(Elf64_Sym)));
char *String = (char *)((uintptr_t)Header + StringTable->sh_offset + Symbol->st_name);
if (strcmp(String, Name) == 0)
if (strcmp(String, Name.c_str()) == 0)
return Symbol;
}
return nullptr;
}
Elf64_Sym ELFLookupSymbol(vfs::RefNode *fd, const char *Name)
Elf64_Sym ELFLookupSymbol(FileNode *fd, std::string Name)
{
#if defined(a64)
off_t OldOffset = fd->seek(0, SEEK_CUR);
Elf64_Ehdr Header{};
fd->Read(&Header, sizeof(Elf64_Ehdr), 0);
Elf64_Ehdr Header;
fd->seek(0, SEEK_SET);
fd->read((uint8_t *)&Header, sizeof(Elf64_Ehdr));
Elf64_Shdr SymbolTable;
Elf64_Shdr StringTable;
Elf64_Shdr SymbolTable{};
Elf64_Shdr StringTable{};
for (Elf64_Half i = 0; i < Header.e_shnum; i++)
{
Elf64_Shdr shdr;
fd->seek(Header.e_shoff + (i * sizeof(Elf64_Shdr)), SEEK_SET);
fd->read((uint8_t *)&shdr, sizeof(Elf64_Shdr));
fd->Read(&shdr, sizeof(Elf64_Shdr), Header.e_shoff + (i * sizeof(Elf64_Shdr)));
switch (shdr.sh_type)
{
case SHT_SYMTAB:
SymbolTable = shdr;
fd->seek(Header.e_shoff + (shdr.sh_link * sizeof(Elf64_Shdr)), SEEK_SET);
fd->read((uint8_t *)&StringTable, sizeof(Elf64_Shdr));
fd->Read(&StringTable, sizeof(Elf64_Shdr), Header.e_shoff + (shdr.sh_link * sizeof(Elf64_Shdr)));
break;
default:
{
@ -124,11 +119,9 @@ namespace Execute
}
}
if (SymbolTable.sh_name == 0 ||
StringTable.sh_name == 0)
if (SymbolTable.sh_name == 0 || StringTable.sh_name == 0)
{
error("Symbol table not found.");
fd->seek(OldOffset, SEEK_SET);
return {};
}
@ -136,22 +129,16 @@ namespace Execute
{
// Elf64_Sym *Symbol = (Elf64_Sym *)((uintptr_t)Header + SymbolTable->sh_offset + (i * sizeof(Elf64_Sym)));
Elf64_Sym Symbol;
fd->seek(SymbolTable.sh_offset + (i * sizeof(Elf64_Sym)), SEEK_SET);
fd->read((uint8_t *)&Symbol, sizeof(Elf64_Sym));
fd->Read(&Symbol, sizeof(Elf64_Sym), SymbolTable.sh_offset + (i * sizeof(Elf64_Sym)));
// char *String = (char *)((uintptr_t)Header + StringTable->sh_offset + Symbol->st_name);
char String[256];
fd->seek(StringTable.sh_offset + Symbol.st_name, SEEK_SET);
fd->read((uint8_t *)&String, 256);
fd->Read(&String, sizeof(String), StringTable.sh_offset + Symbol.st_name);
if (strcmp(String, Name) == 0)
{
fd->seek(OldOffset, SEEK_SET);
if (strcmp(String, Name.c_str()) == 0)
return Symbol;
}
}
error("Symbol not found.");
fd->seek(OldOffset, SEEK_SET);
#endif
return {};
}

View File

@ -21,16 +21,14 @@
namespace Execute
{
std::vector<Elf64_Dyn> ELFGetDynamicTag_x86_64(vfs::RefNode *fd,
std::vector<Elf64_Dyn> ELFGetDynamicTag_x86_64(FileNode *fd,
DynamicArrayTags Tag)
{
#if defined(a64) || defined(aa64)
off_t OldOffset = fd->seek(0, SEEK_CUR);
std::vector<Elf64_Dyn> Ret;
Elf64_Ehdr ELFHeader;
fd->seek(0, SEEK_SET);
fd->read((uint8_t *)&ELFHeader, sizeof(Elf64_Ehdr));
Elf64_Ehdr ELFHeader{};
fd->Read(&ELFHeader, sizeof(Elf64_Ehdr), 0);
std::vector<Elf64_Phdr> DYNAMICPhdrs = ELFGetSymbolType_x86_64(fd, PT_DYNAMIC);
@ -42,11 +40,10 @@ namespace Execute
foreach (auto Phdr in DYNAMICPhdrs)
{
Elf64_Dyn Dynamic;
Elf64_Dyn Dynamic{};
for (size_t i = 0; i < Phdr.p_filesz / sizeof(Elf64_Dyn); i++)
{
fd->seek(Phdr.p_offset + (i * sizeof(Elf64_Dyn)), SEEK_SET);
fd->read((uint8_t *)&Dynamic, sizeof(Elf64_Dyn));
fd->Read(&Dynamic, sizeof(Elf64_Dyn), Phdr.p_offset + (i * sizeof(Elf64_Dyn)));
if (Dynamic.d_tag != Tag)
continue;
@ -57,7 +54,6 @@ namespace Execute
}
}
fd->seek(OldOffset, SEEK_SET);
return Ret;
#elif defined(a32)
return {};

View File

@ -21,24 +21,20 @@
namespace Execute
{
std::vector<Elf64_Shdr> ELFGetSections_x86_64(vfs::RefNode *fd,
std::vector<Elf64_Shdr> ELFGetSections_x86_64(FileNode *fd,
const char *SectionName)
{
#if defined(a64) || defined(aa64)
off_t OldOffset = fd->seek(0, SEEK_CUR);
std::vector<Elf64_Shdr> Ret;
Elf64_Ehdr ELFHeader;
fd->seek(0, SEEK_SET);
fd->read((uint8_t *)&ELFHeader, sizeof(Elf64_Ehdr));
Elf64_Ehdr ELFHeader{};
fd->Read(&ELFHeader, sizeof(Elf64_Ehdr), 0);
Elf64_Shdr *SectionHeaders = new Elf64_Shdr[ELFHeader.e_shnum];
fd->seek(ELFHeader.e_shoff, SEEK_SET);
fd->read((uint8_t *)SectionHeaders, sizeof(Elf64_Shdr) * ELFHeader.e_shnum);
fd->Read(SectionHeaders, sizeof(Elf64_Shdr) * ELFHeader.e_shnum, ELFHeader.e_shoff);
char *SectionNames = new char[SectionHeaders[ELFHeader.e_shstrndx].sh_size];
fd->seek(SectionHeaders[ELFHeader.e_shstrndx].sh_offset, SEEK_SET);
fd->read((uint8_t *)SectionNames, SectionHeaders[ELFHeader.e_shstrndx].sh_size);
fd->Read(SectionNames, SectionHeaders[ELFHeader.e_shstrndx].sh_size, SectionHeaders[ELFHeader.e_shstrndx].sh_offset);
for (Elf64_Half i = 0; i < ELFHeader.e_shnum; ++i)
{
@ -47,7 +43,6 @@ namespace Execute
Ret.push_back(SectionHeaders[i]);
}
fd->seek(OldOffset, SEEK_SET);
delete[] SectionHeaders;
delete[] SectionNames;
return Ret;

View File

@ -21,31 +21,28 @@
namespace Execute
{
std::vector<Elf64_Phdr> ELFGetSymbolType_x86_64(vfs::RefNode *fd,
std::vector<Elf64_Phdr> ELFGetSymbolType_x86_64(FileNode *fd,
SegmentTypes Tag)
{
#if defined(a64) || defined(aa64)
off_t OldOffset = fd->seek(0, SEEK_CUR);
std::vector<Elf64_Phdr> Ret;
Elf64_Ehdr ELFHeader;
fd->seek(0, SEEK_SET);
fd->read((uint8_t *)&ELFHeader, sizeof(Elf64_Ehdr));
Elf64_Ehdr ELFHeader{};
fd->Read(&ELFHeader, sizeof(Elf64_Ehdr), 0);
Elf64_Phdr ProgramHeaders;
fd->seek(ELFHeader.e_phoff, SEEK_SET);
fd->read((uint8_t *)&ProgramHeaders, sizeof(Elf64_Phdr));
Elf64_Phdr ProgramHeaders{};
fd->Read(&ProgramHeaders, sizeof(Elf64_Phdr), ELFHeader.e_phoff);
off_t currentOffset = ELFHeader.e_phoff;
for (Elf64_Half i = 0; i < ELFHeader.e_phnum; i++)
{
if (ProgramHeaders.p_type == Tag)
Ret.push_back(ProgramHeaders);
fd->seek(sizeof(Elf64_Phdr), SEEK_CUR);
fd->read((uint8_t *)&ProgramHeaders, sizeof(Elf64_Phdr));
currentOffset += sizeof(Elf64_Phdr);
fd->Read(&ProgramHeaders, sizeof(Elf64_Phdr), currentOffset);
}
fd->seek(OldOffset, SEEK_SET);
return Ret;
#elif defined(a32)
return {};

View File

@ -35,15 +35,12 @@ namespace Execute
Tasking::TaskCompatibility Compatibility,
bool Critical)
{
vfs::RefNode *fd = fs->Open(Path);
FileNode *fd = fs->GetByPath(Path, nullptr);
if (fd == nullptr)
return -ENOENT;
if (fd->node->Type == vfs::NodeType::DIRECTORY)
{
delete fd;
return -EISDIR;
}
if (!fd->IsRegularFile())
return -ENOEXEC;
switch (GetBinaryType(Path))
{
@ -53,7 +50,7 @@ namespace Execute
const char *BaseName;
cwk_path_get_basename(Path, &BaseName, nullptr);
Elf32_Ehdr ELFHeader;
fd->read((uint8_t *)&ELFHeader, sizeof(Elf32_Ehdr));
fd->Read(&ELFHeader, sizeof(Elf32_Ehdr), 0);
switch (ELFHeader.e_machine)
{
@ -119,22 +116,20 @@ namespace Execute
if (Parent == nullptr)
Parent = thisProcess;
Process = TaskManager->CreateProcess(Parent,
BaseName,
Process = TaskManager->CreateProcess(Parent, BaseName,
TaskExecutionMode::User,
false, 0, 0);
Process->Info.Compatibility = Compatibility;
Process->Info.Architecture = Arch;
}
Process->SetWorkingDirectory(fs->GetNodeFromPath(Path)->Parent);
Process->SetWorkingDirectory(fs->GetByPath(Path, nullptr)->Parent);
Process->SetExe(Path);
ELFObject *obj = new ELFObject(Path, Process, argv, envp);
if (!obj->IsValid)
{
error("Failed to load ELF object");
delete fd;
delete Process;
return -ENOEXEC;
}
@ -142,23 +137,20 @@ namespace Execute
vfs::FileDescriptorTable *pfdt = Parent->FileDescriptors;
vfs::FileDescriptorTable *fdt = Process->FileDescriptors;
auto ForkStdio = [pfdt, fdt](Node *SearchNode)
auto ForkStdio = [pfdt, fdt](FileNode *SearchNode)
{
if (unlikely(SearchNode == nullptr))
return false;
std::vector<FileDescriptorTable::Fildes>
pfds = pfdt->GetFileDescriptors();
foreach (auto ffd in pfds)
foreach (const auto &ffd in pfdt->FileMap)
{
if (ffd.Flags & O_CLOEXEC)
if (ffd.second.Flags & O_CLOEXEC)
continue;
if (ffd.Handle->node == SearchNode)
if (ffd.second.Node == SearchNode)
{
fdt->_open(ffd.Handle->node->FullPath,
ffd.Flags, ffd.Mode);
fdt->usr_open(ffd.second.Node->Path.c_str(),
ffd.second.Flags, ffd.second.Mode);
return true;
}
}
@ -166,37 +158,31 @@ namespace Execute
};
if (!ForkStdio(Parent->stdin))
fdt->_open("/dev/kcon", O_RDWR, 0666);
fdt->usr_open("/dev/kcon", O_RDWR, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
if (!ForkStdio(Parent->stdout))
fdt->_open("/dev/kcon", O_RDWR, 0666);
fdt->usr_open("/dev/kcon", O_RDWR, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
if (!ForkStdio(Parent->stderr))
fdt->_open("/dev/kcon", O_RDWR, 0666);
fdt->usr_open("/dev/kcon", O_RDWR, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
TCB *Thread = nullptr;
{
CriticalSection cs;
Thread = TaskManager->CreateThread(Process,
obj->InstructionPointer,
Thread = TaskManager->CreateThread(Process, obj->InstructionPointer,
obj->argv, obj->envp, obj->auxv,
Arch,
Compatibility);
Arch, Compatibility);
Thread->SetCritical(Critical);
}
delete fd;
return Thread->ID;
}
default:
{
debug("Unknown binary type: %d",
GetBinaryType(Path));
delete fd;
debug("Unknown binary type: %d", GetBinaryType(Path));
return -ENOEXEC;
}
}
delete fd;
return -ENOEXEC;
}
}

View File

@ -15,25 +15,31 @@
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include <syscalls.hpp>
#ifndef __FENNIX_KERNEL_CIRCULAR_BUFFER_H__
#define __FENNIX_KERNEL_CIRCULAR_BUFFER_H__
#include <memory.hpp>
#include <types.h>
#include <lock.hpp>
#include <exec.hpp>
#include <errno.h>
#include <debug.h>
#include "../../syscalls.h"
#include "../../kernel.h"
using Tasking::PCB;
/* https://pubs.opengroup.org/onlinepubs/009604499/functions/lseek.html */
off_t sys_lseek(SysFrm *, int fildes,
off_t offset, int whence)
class CircularBuffer
{
function("%d, %d, %d", fildes, offset, whence);
PCB *pcb = thisProcess;
vfs::FileDescriptorTable *fdt = pcb->FileDescriptors;
return fdt->_lseek(fildes, offset, whence);
}
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();
};
#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.

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

@ -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__

View File

@ -194,40 +194,22 @@ typedef enum
typedef enum
{
ddt_Keyboard,
ddt_Mouse,
ddt_Joystick,
ddt_Gamepad,
ddt_Touchpad,
ddt_Touchscreen,
IOCTL_AUDIO_GET_VOLUME = 0,
IOCTL_AUDIO_SET_VOLUME = 1,
ddt_SATA,
ddt_ATA,
ddt_NVMe,
IOCTL_AUDIO_GET_MUTE = 2,
IOCTL_AUDIO_SET_MUTE = 3,
ddt_Audio,
IOCTL_AUDIO_GET_SAMPLE_RATE = 4,
IOCTL_AUDIO_SET_SAMPLE_RATE = 5,
ddt_Network,
} DeviceDriverType;
typedef enum
{
IOCTL_AUDIO_GET_VOLUME,
IOCTL_AUDIO_SET_VOLUME,
IOCTL_AUDIO_GET_MUTE,
IOCTL_AUDIO_SET_MUTE,
IOCTL_AUDIO_GET_SAMPLE_RATE,
IOCTL_AUDIO_SET_SAMPLE_RATE,
IOCTL_AUDIO_GET_CHANNELS,
IOCTL_AUDIO_SET_CHANNELS,
IOCTL_AUDIO_GET_CHANNELS = 6,
IOCTL_AUDIO_SET_CHANNELS = 7,
} AudioIoctl;
typedef enum
{
IOCTL_NET_GET_MAC,
IOCTL_NET_GET_MAC = 0,
} NetIoctl;
typedef enum
@ -261,25 +243,9 @@ typedef struct
int (*UnregisterInterruptHandler)(dev_t MajorID, uint8_t IRQ, void *Handler);
int (*UnregisterAllInterruptHandlers)(dev_t MajorID, void *Handler);
/* Input */
dev_t (*RegisterInputDevice)(dev_t MajorID, DeviceDriverType Type);
int (*UnregisterInputDevice)(dev_t MajorID, dev_t MinorID, DeviceDriverType Type);
int (*ReportKeyboardEvent)(dev_t MajorID, dev_t MinorID, uint8_t ScanCode);
int (*ReportRelativeMouseEvent)(dev_t MajorID, dev_t MinorID, __MouseButtons Button, int X, int Y, int8_t Z);
int (*ReportAbsoluteMouseEvent)(dev_t MajorID, dev_t MinorID, __MouseButtons Button, uintptr_t X, uintptr_t Y, int8_t Z);
/* Storage */
dev_t (*RegisterBlockDevice)(dev_t MajorID, DeviceDriverType Type, void *Open, void *Close, void *Read, void *Write, void *Ioctl);
int (*UnregisterBlockDevice)(dev_t MajorID, dev_t MinorID, DeviceDriverType Type);
/* Audio */
dev_t (*RegisterAudioDevice)(dev_t MajorID, DeviceDriverType Type, void *Open, void *Close, void *Read, void *Write, void *Ioctl);
int (*UnregisterAudioDevice)(dev_t MajorID, dev_t MinorID, DeviceDriverType Type);
/* Network */
dev_t (*RegisterNetDevice)(dev_t MajorID, DeviceDriverType Type, void *Open, void *Close, void *Read, void *Write, void *Ioctl);
int (*UnregisterNetDevice)(dev_t MajorID, dev_t MinorID, DeviceDriverType Type);
int (*ReportNetworkPacket)(dev_t MajorID, dev_t MinorID, void *Buffer, size_t Size);
/* /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);

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__

29
include/kcon.hpp Normal file
View File

@ -0,0 +1,29 @@
/*
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_KERNEL_CONSOLE_H__
#define __FENNIX_KERNEL_KERNEL_CONSOLE_H__
#include <termios.h>
namespace KernelConsole
{
void EarlyInit();
void LateInit();
}
#endif // !__FENNIX_KERNEL_KERNEL_CONSOLE_H__

View File

@ -19,7 +19,7 @@
#define __FENNIX_KERNEL_CXXABI_H__
#include <types.h>
#include <unwind.h>
#include <kexcept/unwind.h>
#include <typeinfo>
namespace __cxxabiv1
@ -37,33 +37,82 @@ namespace __cxxabiv1
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_EABI_UNWINDER__
#ifdef __arm__
__cxa_exception *nextPropagatingException;
int propagationCount;
#else
int handlerSwitchValue;
const unsigned char *actionRecord;
const unsigned char *languageSpecificData;
_Unwind_Ptr catchTemp;
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
{
__cxxabiv1::__cxa_exception *caughtExceptions;
__cxa_exception *caughtExceptions;
unsigned int uncaughtExceptions;
#ifdef __ARM_EABI_UNWINDER__
__cxxabiv1::__cxa_exception *propagatingExceptions;
#endif
};
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__

View File

@ -20,7 +20,7 @@
#include <types.h>
enum _Unwind_Reason_Code
typedef enum
{
_URC_NO_REASON = 0,
_URC_FOREIGN_EXCEPTION_CAUGHT = 1,
@ -31,7 +31,7 @@ enum _Unwind_Reason_Code
_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__)));
@ -40,20 +40,15 @@ typedef unsigned _Unwind_Word __attribute__((__mode__(__unwind_word__)));
typedef signed _Unwind_Sword __attribute__((__mode__(__unwind_word__)));
typedef int _Unwind_Action;
enum _UA : _Unwind_Action
{
_UA_SEARCH_PHASE = 1,
_UA_CLEANUP_PHASE = 2,
_UA_HANDLER_FRAME = 4,
_UA_FORCE_UNWIND = 8,
_UA_END_OF_STACK = 16
};
#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 void (*_Unwind_Exception_Cleanup_Fn)(_Unwind_Reason_Code, struct _Unwind_Exception *);
typedef _Unwind_Reason_Code (*_Unwind_Personality_Fn)(int,
_Unwind_Action,
typedef _Unwind_Reason_Code (*_Unwind_Personality_Fn)(int, _Unwind_Action,
_Unwind_Exception_Class,
struct _Unwind_Exception *,
struct _Unwind_Context *);
@ -66,13 +61,14 @@ struct _Unwind_Exception
_Unwind_Word private_2;
} __attribute__((__aligned__));
struct _Unwind_Context;
struct _Unwind_Context
{
int __stub;
};
struct _Unwind_FrameState
{
_Unwind_Personality_Fn personality;
};
EXTERNC _Unwind_Reason_Code _Unwind_RaiseException(_Unwind_Exception *Exception);
#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>
@ -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

@ -63,7 +63,7 @@ namespace Tasking::Scheduler
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;
@ -120,7 +120,7 @@ namespace Tasking::Scheduler
bool RemoveProcess(PCB *pcb) final;
PCB *GetProcessByID(TID ID) final;
TCB *GetThreadByID(TID ID, PCB *Parent) final;
std::list<PCB *> &GetProcessList() 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);

View File

@ -15,36 +15,30 @@
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include <filesystem/mounts.hpp>
#include <filesystem/ioctl.hpp>
#include <string.h>
#include <errno.h>
#include <initializer_list>
#include <cassert>
#include <cstddef>
#include "../../../kernel.h"
template <typename T, std::size_t N>
class static_vector
{
private:
T m_data[N];
std::size_t m_size;
namespace vfs
{
size_t MasterPTY::read(uint8_t *Buffer,
size_t Size,
off_t Offset)
{
fixme("%.*s", Size, Buffer);
return -ENOSYS;
}
public:
constexpr static_vector() : m_size(0) {}
size_t MasterPTY::write(uint8_t *Buffer,
size_t Size,
off_t Offset)
constexpr static_vector(std::initializer_list<T> list) : m_size(0)
{
fixme("%.*s", Size, Buffer);
return -ENOSYS;
}
MasterPTY::MasterPTY()
{
}
MasterPTY::~MasterPTY()
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
@ -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__

View File

@ -42,12 +42,31 @@ namespace std
return d_last;
}
template <typename T>
void swap(T &a, T &b)
template <typename InputIt, typename OutputIt, typename UnaryOperation>
OutputIt transform(InputIt first, InputIt last, OutputIt result, UnaryOperation op)
{
T temp = move(a);
a = move(b);
b = move(temp);
while (first != last)
{
*result = op(*first);
++first;
++result;
}
return result;
};
template <class T>
void swap(T &a, T &b) noexcept(std::is_nothrow_move_constructible<T>::value && std::is_nothrow_move_assignable<T>::value)
{
T temp = std::move(a);
a = std::move(b);
b = std::move(temp);
}
template <class T2, std::size_t N>
void swap(T2 (&a)[N], T2 (&b)[N]) noexcept(std::is_nothrow_swappable_v<T2>)
{
for (std::size_t i = 0; i < N; ++i)
std::swap(a[i], b[i]);
}
template <typename T>
@ -193,4 +212,116 @@ namespace std
}
return first;
}
template <class InputIt1, class InputIt2>
constexpr bool equal(InputIt1 first1, InputIt1 last1, InputIt2 first2)
{
while (first1 != last1)
{
if (!(*first1 == *first2))
return false;
++first1;
++first2;
}
return true;
}
template <class ExecutionPolicy, class ForwardIt1, class ForwardIt2>
bool equal(ExecutionPolicy &&policy, ForwardIt1 first1, ForwardIt1 last1, ForwardIt2 first2)
{
while (first1 != last1)
{
if (!(*first1 == *first2))
return false;
++first1;
++first2;
}
return true;
}
template <class InputIt1, class InputIt2, class BinaryPred>
constexpr bool equal(InputIt1 first1, InputIt1 last1, InputIt2 first2, BinaryPred p)
{
while (first1 != last1)
{
if (!p(*first1, *first2))
return false;
++first1;
++first2;
}
return true;
}
template <class ExecutionPolicy, class ForwardIt1, class ForwardIt2, class BinaryPred>
bool equal(ExecutionPolicy &&policy, ForwardIt1 first1, ForwardIt1 last1, ForwardIt2 first2, BinaryPred p)
{
while (first1 != last1)
{
if (!p(*first1, *first2))
return false;
++first1;
++first2;
}
return true;
}
template <class InputIt1, class InputIt2>
constexpr bool equal(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2)
{
while (first1 != last1)
{
if (!(*first1 == *first2))
return false;
++first1;
++first2;
}
return true;
}
template <class ExecutionPolicy, class ForwardIt1, class ForwardIt2>
bool equal(ExecutionPolicy &&policy, ForwardIt1 first1, ForwardIt1 last1, ForwardIt2 first2, ForwardIt2 last2)
{
while (first1 != last1)
{
if (!(*first1 == *first2))
return false;
++first1;
++first2;
}
return true;
}
template <class InputIt1, class InputIt2, class BinaryPred>
constexpr bool equal(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2, BinaryPred p)
{
while (first1 != last1)
{
if (!p(*first1, *first2))
return false;
++first1;
++first2;
}
return true;
}
template <class ExecutionPolicy, class ForwardIt1, class ForwardIt2, class BinaryPred>
bool equal(ExecutionPolicy &&policy, ForwardIt1 first1, ForwardIt1 last1, ForwardIt2 first2, ForwardIt2 last2, BinaryPred p)
{
while (first1 != last1)
{
if (!p(*first1, *first2))
return false;
++first1;
++first2;
}
return true;
}
}

View File

@ -15,18 +15,23 @@
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include <filesystem/mounts.hpp>
#pragma once
#include "../../kernel.h"
namespace std
{
inline int tolower(int ch)
{
if (ch >= 'A' && ch <= 'Z')
return ch + ('a' - 'A');
else
return ch;
}
namespace vfs
inline int toupper(int ch)
{
vfsRoot::vfsRoot(const char *Name, Virtual *vfs_ctx)
: Node(nullptr,
Name,
MOUNTPOINT)
{
this->vFS = fs;
vfs_ctx->GetRootNode()->Children.push_back(this);
if (ch >= 'a' && ch <= 'z')
return ch - ('a' - 'A');
else
return ch;
}
}

View File

@ -17,9 +17,12 @@
#pragma once
#include <cfloat>
#include <type_traits>
namespace std
{
double sin(double x)
constexpr double sin(double x)
{
const int NUM_TERMS = 10;
@ -35,7 +38,7 @@ namespace std
return result;
}
float powf(float base, float exp)
constexpr float powf(float base, float exp)
{
float result = 1.0;
for (int i = 0; i < (int)exp; ++i)
@ -43,7 +46,7 @@ namespace std
return result;
}
double pow(double base, double exp)
constexpr double pow(double base, double exp)
{
double result = 1.0;
for (int i = 0; i < (int)exp; ++i)
@ -51,7 +54,7 @@ namespace std
return result;
}
long double powl(long double base, long double exp)
constexpr long double powl(long double base, long double exp)
{
long double result = 1.0;
for (long i = 0; i < (long)exp; ++i)
@ -59,24 +62,121 @@ namespace std
return result;
}
float fabsf(float num)
constexpr float fabsf(float num)
{
if (num < 0)
return -num;
return num;
}
double fabs(double num)
constexpr double fabs(double num)
{
if (num < 0)
return -num;
return num;
}
long double fabsl(long double num)
constexpr long double fabsl(long double num)
{
if (num < 0)
return -num;
return num;
}
template <class Integer>
constexpr bool isinf(Integer num)
{
union
{
unsigned long u;
double f;
} ieee754;
ieee754.f = num;
bool a = ((unsigned)(ieee754.u >> 32) & 0x7fffffff) == 0x7ff00000;
bool b = ((unsigned)ieee754.u == 0);
return a && b;
}
template <class Integer>
constexpr bool isnan(Integer num)
{
return num != num;
}
template <class Integer>
constexpr double fabs(Integer num)
{
return num < 0 ? -num : num;
}
template <class Integer>
constexpr double remainder(Integer x, Integer y)
{
return x - (int)(x / y) * y;
}
template <class Integer>
constexpr double copysign(Integer mag, Integer sgn)
{
return (sgn < 0) ? -mag : mag;
}
template <class Integer>
constexpr bool signbit(Integer num)
{
return num < 0;
}
template <class Integer>
constexpr double fmod(Integer x, Integer y)
{
#pragma STDC FENV_ACCESS ON
double result = std::remainder(std::fabs(x), y = std::fabs(y));
if (std::signbit(result))
result += (double)y;
return std::copysign(result, x);
}
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wfloat-equal"
template <class Integer>
constexpr double ceil(Integer num)
{
// int i = (int)num;
// return i + (i < num);
double remainder = std::fmod((double)num, 1.0);
return num >= 0 ? (remainder == 0 ? num : num + 1 - remainder) : num - remainder;
}
#pragma GCC diagnostic pop
template <class Integer>
constexpr double trunc(Integer num)
{
if (std::isinf(num))
return num;
if (std::isnan(num))
return num;
return static_cast<int>(num);
}
template <class Integer>
constexpr double exp(Integer num)
{
double result = 1.0;
double term = 1.0;
for (int i = 1; i <= 10; ++i)
{
term *= static_cast<double>(num) / i;
result += term;
}
return result;
}
}

View File

@ -15,5 +15,7 @@
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once
#include <std/smart_ptr.hpp>
namespace std
{
/* FIXME: Implement */
}

View File

@ -15,35 +15,37 @@
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_C_TYPE_H__
#define __FENNIX_KERNEL_C_TYPE_H__
#include <types.h>
#include <filesystem/termios-bits.hpp>
typedef unsigned char cc_t;
typedef unsigned int speed_t;
typedef unsigned int tcflag_t;
START_EXTERNC
#define NCCS 32
struct termios
{
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;
};
int isalnum(int);
int isalpha(int);
int isascii(int);
struct winsize
{
unsigned short ws_row;
unsigned short ws_col;
unsigned short ws_xpixel;
unsigned short ws_ypixel;
};
int isblank(int);
int iscntrl(int);
int isdigit(int);
int isgraph(int);
int islower(int);
int isprint(int);
int ispunct(int);
int isspace(int);
int isupper(int);
int isxdigit(int);
#endif // !__FENNIX_KERNEL_TERMIOS_H__
int toascii(int);
int tolower(int);
int toupper(int);
#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
END_EXTERNC
#endif // !__FENNIX_KERNEL_C_TYPE_H__

View File

@ -15,7 +15,17 @@
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef _DLFCN_H
#define _DLFCN_H
#ifndef __FENNIX_KERNEL_DLFCN_H__
#define __FENNIX_KERNEL_DLFCN_H__
#endif // !_DLFCN_H
#include <types.h>
typedef struct
{
const char *dli_fname;
void *dli_fbase;
const char *dli_sname;
void *dli_saddr;
} Dl_info;
#endif // !__FENNIX_KERNEL_DLFCN_H__

View File

@ -15,407 +15,9 @@
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef _ERRNO_H
#define _ERRNO_H
#ifndef __FENNIX_KERNEL_STD_ERRNO_H__
#define __FENNIX_KERNEL_STD_ERRNO_H__
/** Operation not permitted */
#define EPERM 1
#include <interface/errno.h>
/** No such file or directory */
#define ENOENT 2
/** No such process */
#define ESRCH 3
/** Interrupted system call */
#define EINTR 4
/** I/O error */
#define EIO 5
/** No such device or address */
#define ENXIO 6
/** Argument list too long */
#define E2BIG 7
/** Exec format error */
#define ENOEXEC 8
/** Bad file number */
#define EBADF 9
/** No child processes */
#define ECHILD 10
/** Try again */
#define EAGAIN 11
/** Out of memory */
#define ENOMEM 12
/** Permission denied */
#define EACCES 13
/** Bad address */
#define EFAULT 14
/** Block device required */
#define ENOTBLK 15
/** Device or resource busy */
#define EBUSY 16
/** File exists */
#define EEXIST 17
/** Cross-device link */
#define EXDEV 18
/** No such device */
#define ENODEV 19
/** Not a directory */
#define ENOTDIR 20
/** Is a directory */
#define EISDIR 21
/** Invalid argument */
#define EINVAL 22
/** File table overflow */
#define ENFILE 23
/** Too many open files */
#define EMFILE 24
/** Not a typewriter */
#define ENOTTY 25
/** Text file busy */
#define ETXTBSY 26
/** File too large */
#define EFBIG 27
/** No space left on device */
#define ENOSPC 28
/** Illegal seek */
#define ESPIPE 29
/** Read-only file system */
#define EROFS 30
/** Too many links */
#define EMLINK 31
/** Broken pipe */
#define EPIPE 32
/** Math argument out of domain of func */
#define EDOM 33
/** Math result not representable */
#define ERANGE 34
/** Resource deadlock would occur */
#define EDEADLK 35
/** File name too long */
#define ENAMETOOLONG 36
/** No record locks available */
#define ENOLCK 37
/** Function not implemented */
#define ENOSYS 38
/** Directory not empty */
#define ENOTEMPTY 39
/** Too many symbolic links encountered */
#define ELOOP 40
/** No message of desired type */
#define ENOMSG 42
/** Identifier removed */
#define EIDRM 43
/** Channel number out of range */
#define ECHRNG 44
/** Level 2 not synchronized */
#define EL2NSYNC 45
/** Level 3 halted */
#define EL3HLT 46
/** Level 3 reset */
#define EL3RST 47
/** Link number out of range */
#define ELNRNG 48
/** Protocol driver not attached */
#define EUNATCH 49
/** No CSI structure available */
#define ENOCSI 50
/** Level 2 halted */
#define EL2HLT 51
/** Invalid exchange */
#define EBADE 52
/** Invalid request descriptor */
#define EBADR 53
/** Exchange full */
#define EXFULL 54
/** No anode */
#define ENOANO 55
/** Invalid request code */
#define EBADRQC 56
/** Invalid slot */
#define EBADSLT 57
/** Bad font file format */
#define EBFONT 59
/** Device not a stream */
#define ENOSTR 60
/** No data available */
#define ENODATA 61
/** Timer expired */
#define ETIME 62
/** Out of streams resources */
#define ENOSR 63
/** Machine is not on the network */
#define ENONET 64
/** Package not installed */
#define ENOPKG 65
/** Object is remote */
#define EREMOTE 66
/** Link has been severed */
#define ENOLINK 67
/** Advertise error */
#define EADV 68
/** Srmount error */
#define ESRMNT 69
/** Communication error on send */
#define ECOMM 70
/** Protocol error */
#define EPROTO 71
/** Multihop attempted */
#define EMULTIHOP 72
/** RFS specific error */
#define EDOTDOT 73
/** Not a data message */
#define EBADMSG 74
/** Value too large for defined data type */
#define EOVERFLOW 75
/** Name not unique on network */
#define ENOTUNIQ 76
/** File descriptor in bad state */
#define EBADFD 77
/** Remote address changed */
#define EREMCHG 78
/** Can not access a needed shared library */
#define ELIBACC 79
/** Accessing a corrupted shared library */
#define ELIBBAD 80
/** .lib section in a.out corrupted */
#define ELIBSCN 81
/** Attempting to link in too many shared libraries */
#define ELIBMAX 82
/** Cannot exec a shared library directly */
#define ELIBEXEC 83
/** Illegal byte sequence */
#define EILSEQ 84
/** Interrupted system call should be restarted */
#define ERESTART 85
/** Streams pipe error */
#define ESTRPIPE 86
/** Too many users */
#define EUSERS 87
/** Socket operation on non-socket */
#define ENOTSOCK 88
/** Destination address required */
#define EDESTADDRREQ 89
/** Message too long */
#define EMSGSIZE 90
/** Protocol wrong type for socket */
#define EPROTOTYPE 91
/** Protocol not available */
#define ENOPROTOOPT 92
/** Protocol not supported */
#define EPROTONOSUPPORT 93
/** Socket type not supported */
#define ESOCKTNOSUPPORT 94
/** Operation not supported on transport endpoint */
#define EOPNOTSUPP 95
/** Protocol family not supported */
#define EPFNOSUPPORT 96
/** Address family not supported by protocol */
#define EAFNOSUPPORT 97
/** Address already in use */
#define EADDRINUSE 98
/** Cannot assign requested address */
#define EADDRNOTAVAIL 99
/** Network is down */
#define ENETDOWN 100
/** Network is unreachable */
#define ENETUNREACH 101
/** Network dropped connection because of reset */
#define ENETRESET 102
/** Software caused connection abort */
#define ECONNABORTED 103
/** Connection reset by peer */
#define ECONNRESET 104
/** No buffer space available */
#define ENOBUFS 105
/** Transport endpoint is already connected */
#define EISCONN 106
/** Transport endpoint is not connected */
#define ENOTCONN 107
/** Cannot send after transport endpoint shutdown */
#define ESHUTDOWN 108
/** Too many references: cannot splice */
#define ETOOMANYREFS 109
/** Connection timed out */
#define ETIMEDOUT 110
/** Connection refused */
#define ECONNREFUSED 111
/** Host is down */
#define EHOSTDOWN 112
/** No route to host */
#define EHOSTUNREACH 113
/** Operation already in progress */
#define EALREADY 114
/** Operation now in progress */
#define EINPROGRESS 115
/** Stale NFS file handle */
#define ESTALE 116
/** Structure needs cleaning */
#define EUCLEAN 117
/** Not a XENIX named type file */
#define ENOTNAM 118
/** No XENIX semaphores available */
#define ENAVAIL 119
/** Is a named type file */
#define EISNAM 120
/** Remote I/O error */
#define EREMOTEIO 121
/** Quota exceeded */
#define EDQUOT 122
/** No medium found */
#define ENOMEDIUM 123
/** Wrong medium type */
#define EMEDIUMTYPE 124
/** Operation Canceled */
#define ECANCELED 125
/** Required key not available */
#define ENOKEY 126
/** Key has expired */
#define EKEYEXPIRED 127
/** Key has been revoked */
#define EKEYREVOKED 128
/** Key was rejected by service */
#define EKEYREJECTED 129
/** Owner died */
#define EOWNERDEAD 130
/** State not recoverable */
#define ENOTRECOVERABLE 131
#include <types.h>
EXTERNC int *__errno_location(void) __attribute__((const));
#define errno (*__errno_location())
#ifdef __cplusplus
extern "C"
{
#endif
const char *strerror(int errnum);
#ifdef __cplusplus
}
#endif
#endif // !_ERRNO_H
#endif // !__FENNIX_KERNEL_STD_ERRNO_H__

View File

@ -26,16 +26,22 @@ namespace std
{
public:
exception() noexcept {}
virtual ~exception() noexcept;
exception(const exception &) = default;
exception &operator=(const exception &) = default;
exception(exception &&) = default;
exception &operator=(exception &&) = default;
virtual const char *what() const noexcept;
exception(const exception &) noexcept = default;
virtual ~exception() noexcept = default;
exception &operator=(const exception &) noexcept = default;
virtual const char *what() const noexcept { return "Exception"; }
};
typedef void (*terminate_handler)();
typedef void (*unexpected_handler)();
[[noreturn]] void terminate() noexcept;
std::terminate_handler set_terminate(std::terminate_handler f) noexcept;
std::terminate_handler get_terminate() noexcept;
[[noreturn]] void unexpected();
std::unexpected_handler set_unexpected(std::unexpected_handler f) noexcept;
std::unexpected_handler get_unexpected() noexcept;
}
#endif // !__FENNIX_KERNEL_EXCEPTION_H__

View File

@ -17,9 +17,13 @@
#pragma once
#include <types.h>
#include <algorithm>
#include <typeinfo>
namespace std
{
template <typename T>
template <typename T = void>
struct equal_to
{
bool operator()(const T &lhs, const T &rhs) const
@ -58,4 +62,193 @@ namespace std
return static_cast<size_t>(hash);
}
};
template <class T>
class reference_wrapper;
template <class>
class function; /* undefined */
template <class R, class... Args>
class function<R(Args...)>
{
private:
class impl_base
{
public:
virtual ~impl_base() = default;
virtual R invoke(Args...) const = 0;
#ifdef __GXX_RTTI
virtual const std::type_info &target_type() const noexcept = 0;
#endif
virtual impl_base *clone() const = 0;
};
template <class F>
class impl : public impl_base
{
public:
F _f;
template <class G>
impl(G &&f)
: _f(std::forward<G>(f))
{
}
R invoke(Args... args) const override
{
return _f(std::forward<Args>(args)...);
}
#ifdef __GXX_RTTI
const std::type_info &target_type() const noexcept override
{
return typeid(F);
}
#endif
impl_base *clone() const override
{
return new impl<F>(_f);
}
};
impl_base *_ptr;
public:
using result_type = R;
function() noexcept
: _ptr(nullptr)
{
}
function(std::nullptr_t) noexcept
: _ptr(nullptr)
{
}
function(const function &other)
: _ptr(other._ptr)
{
}
function(function &&other) noexcept
: _ptr(other._ptr)
{
other._ptr = nullptr;
}
template <class F>
function(F &&f)
: _ptr(new impl<F>(std::forward<F>(f)))
{
}
~function()
{
delete _ptr;
}
function &operator=(const function &other)
{
if (this != &other)
{
delete _ptr;
_ptr = other._ptr ? other._ptr->clone() : nullptr;
}
return *this;
}
function &operator=(function &&other)
{
if (this != &other)
{
delete _ptr;
_ptr = other._ptr;
other._ptr = nullptr;
}
return *this;
}
function &operator=(std::nullptr_t) noexcept
{
delete _ptr;
_ptr = nullptr;
return *this;
}
template <class F>
function &operator=(F &&f)
{
delete _ptr;
_ptr = new impl<F>(std::forward<F>(f));
return *this;
}
template <class F>
function &operator=(std::reference_wrapper<F> f) noexcept
{
delete _ptr;
_ptr = new impl<std::reference_wrapper<F>>(f);
return *this;
}
void swap(function &other) noexcept
{
std::swap(_ptr, other._ptr);
}
explicit operator bool() const noexcept
{
return _ptr != nullptr;
}
R operator()(Args... args) const
{
return _ptr->invoke(std::forward<Args>(args)...);
}
#ifdef __GXX_RTTI
const std::type_info &target_type() const noexcept
{
return _ptr ? _ptr->target_type() : typeid(void);
}
template <class T>
T *target() noexcept
{
return _ptr && _ptr->target_type() == typeid(T) ? &static_cast<impl<T> *>(_ptr)->_f : nullptr;
}
template <class T>
const T *target() const noexcept
{
return _ptr && _ptr->target_type() == typeid(T) ? &static_cast<impl<T> *>(_ptr)->_f : nullptr;
}
#endif
};
template <class R, class... Args>
void swap(std::function<R(Args...)> &lhs, std::function<R(Args...)> &rhs) noexcept
{
lhs.swap(rhs);
}
template <class R, class... ArgTypes>
bool operator==(const std::function<R(ArgTypes...)> &f, std::nullptr_t) noexcept
{
return !f;
}
template <class T = void>
struct less
{
constexpr bool operator()(const T &lhs, const T &rhs) const
{
return lhs < rhs;
}
};
}

View File

@ -21,28 +21,41 @@
namespace std
{
template <typename T>
template <typename _E>
class initializer_list
{
public:
typedef _E value_type;
typedef const _E &reference;
typedef const _E &const_reference;
typedef size_t size_type;
typedef const _E *iterator;
typedef const _E *const_iterator;
private:
const T *array;
size_t len;
iterator array;
size_type len;
public:
initializer_list() : array(nullptr), len(0) {}
size_t size() const { return len; }
const T *begin() const { return array; }
const T *end() const { return begin() + size(); }
constexpr initializer_list(const_iterator a, size_type l)
: array(a), len(l) {}
constexpr initializer_list()
: array(nullptr), len(0) {}
constexpr size_type size() const { return len; }
constexpr const_iterator begin() const { return array; }
constexpr const_iterator end() const { return begin() + size(); }
};
template <class E>
const E *begin(std::initializer_list<E> il)
constexpr const E *begin(initializer_list<E> il)
{
return il.begin();
}
template <class E>
constexpr const E *end(std::initializer_list<E> il)
constexpr const E *end(initializer_list<E> il)
{
return il.end();
}

23
include_std/inttypes.h Normal file
View File

@ -0,0 +1,23 @@
/*
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_INTTYPES_H__
#define __FENNIX_KERNEL_INTTYPES_H__
#include <types.h>
#endif // !__FENNIX_KERNEL_INTTYPES_H__

286
include_std/ios Normal file
View File

@ -0,0 +1,286 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once
#include <system_error>
#include <string>
#include <vector>
#include <locale>
#ifdef in
#undef in
#endif /* deprecated macro in */
namespace std
{
enum class io_errc
{
stream = 1,
};
typedef long long streamsize;
class ios_base
{
public:
#pragma region Member types and constants
typedef int openmode;
static constexpr openmode app = 1;
static constexpr openmode binary = 2;
static constexpr openmode in = 4;
static constexpr openmode out = 8;
static constexpr openmode trunc = 16;
static constexpr openmode ate = 32;
static constexpr openmode noreplace = 64;
typedef int fmtflags;
static constexpr fmtflags dec = 1;
static constexpr fmtflags oct = 2;
static constexpr fmtflags hex = 4;
static constexpr fmtflags basefield = dec | oct | hex;
static constexpr fmtflags left = 1;
static constexpr fmtflags right = 2;
static constexpr fmtflags internal = 4;
static constexpr fmtflags adjustfield = left | right | internal;
static constexpr fmtflags scientific = 1;
static constexpr fmtflags fixed = 2;
static constexpr fmtflags floatfield = scientific | fixed;
static constexpr fmtflags boolalpha = 1;
static constexpr fmtflags showbase = 2;
static constexpr fmtflags showpoint = 4;
static constexpr fmtflags showpos = 8;
static constexpr fmtflags skipws = 16;
static constexpr fmtflags unitbuf = 32;
static constexpr fmtflags uppercase = 64;
typedef int iostate;
static constexpr iostate goodbit = 0;
static constexpr iostate badbit = 1;
static constexpr iostate failbit = 2;
static constexpr iostate eofbit = 4;
typedef int seekdir;
static constexpr seekdir beg = 0;
static constexpr seekdir end = 1;
static constexpr seekdir cur = 2;
enum event
{
erase_event,
imbue_event,
copyfmt_event
};
typedef void (*event_callback)(event type, ios_base &ios, int index);
#pragma endregion Member types and constants
#pragma region Member Functions
protected:
ios_base();
public:
ios_base(const ios_base &) = delete;
virtual ~ios_base() = default;
ios_base &operator=(const ios_base &) = delete;
#pragma endregion Member Functions
#pragma region Formatting
fmtflags flags() const
{
return _flags;
}
fmtflags flags(fmtflags flags)
{
fmtflags old = _flags;
_flags = flags;
return old;
}
fmtflags setf(fmtflags flags)
{
fmtflags old = _flags;
_flags |= flags;
return old;
}
fmtflags setf(fmtflags flags, fmtflags mask)
{
fmtflags old = _flags;
_flags &= ~mask;
_flags |= flags;
return old;
}
void unsetf(fmtflags flags)
{
_flags &= ~flags;
}
streamsize precision() const
{
return _precision;
}
streamsize precision(streamsize new_precision)
{
streamsize old = _precision;
_precision = new_precision;
return old;
}
streamsize width() const
{
return _width;
}
streamsize width(streamsize new_width)
{
streamsize old = _width;
_width = new_width;
return old;
}
#pragma endregion Formatting
#pragma region Locales
std::locale imbue(const std::locale &loc)
{
std::locale old = _loc;
_loc = loc;
__call_event(imbue_event, *this, 0);
return old;
}
std::locale getloc() const
{
return _loc;
}
#pragma endregion Locales
#pragma region Internal Extensible Array
static int xalloc()
{
static int index = 0;
return index++;
}
long &iword(int index)
{
static std::vector<long> iwords;
if ((size_t)index >= iwords.size())
iwords.resize(index + 1);
return iwords[index];
}
void *&pword(int index)
{
static std::vector<void *> pwords;
if ((size_t)index >= pwords.size())
pwords.resize(index + 1);
return pwords[index];
}
#pragma endregion Internal Extensible Array
#pragma region Miscellaneous
void register_callback(event_callback function, int index)
{
_event_callback = function;
__call_event(imbue_event, *this, index);
}
static bool sync_with_stdio(bool sync = true)
{
return false;
}
#pragma endregion Miscellaneous
#pragma region Member Classes
class failure
{
public:
explicit failure(const std::string &message, const std::error_code &ec = std::io_errc::stream)
{
}
explicit failure(const char *message, const std::error_code &ec = std::io_errc::stream)
{
}
failure(const failure &other) noexcept
{
}
failure &operator=(const failure &other) noexcept
{
return *this;
}
virtual const char *what() const noexcept
{
return nullptr;
}
};
class Init
{
public:
Init() = default;
~Init() = default;
};
#pragma endregion Member Classes
private:
fmtflags _flags = skipws;
streamsize _precision = 6;
streamsize _width = 0;
std::locale _loc = std::locale::classic();
static event_callback _event_callback;
static void __call_event(event type, ios_base &ios, int index)
{
if (_event_callback)
_event_callback(type, ios, index);
}
};
template <class CharT, class Traits = std::char_traits<CharT>>
class basic_ios : public std::ios_base
{
};
typedef basic_ios<char> ios;
typedef basic_ios<wchar_t> wios;
}

View File

@ -15,23 +15,22 @@
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include <filesystem/mounts.hpp>
#include <errno.h>
#pragma once
#include "../../kernel.h"
#include <ostream>
#include <istream>
namespace vfs
namespace std
{
size_t NullDevice::read(uint8_t *Buffer, size_t Size, off_t Offset)
{
return Size;
}
extern std::istream cin;
extern std::wistream wcin;
size_t NullDevice::write(uint8_t *Buffer, size_t Size, off_t Offset)
{
return Size;
}
extern std::ostream cout;
extern std::wostream wcout;
NullDevice::NullDevice() : Node(DevFS, "null", CHARDEVICE) {}
NullDevice::~NullDevice() {}
extern std::ostream cerr;
extern std::wostream wcerr;
extern std::ostream clog;
extern std::wostream wclog;
}

79
include_std/istream Normal file
View File

@ -0,0 +1,79 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once
#include <streambuf>
#include <ostream>
#include <string>
#include <ios>
namespace std
{
template <class CharT, class Traits = std::char_traits<CharT>>
class basic_istream : virtual public std::basic_ios<CharT, Traits>
{
};
template <class CharT, class Traits = std::char_traits<CharT>>
class basic_iostream : public basic_istream<CharT, Traits>, public basic_ostream<CharT, Traits>
{
private:
void init(std::basic_streambuf<CharT, Traits> *sb)
{
this->basic_istream<CharT, Traits>::rdbuf(sb);
this->basic_ostream<CharT, Traits>::rdbuf(sb);
}
public:
typedef CharT char_type;
typedef Traits::char_type traits_type;
typedef Traits::int_type int_type;
typedef Traits::pos_type pos_type;
typedef Traits::off_type off_type;
explicit basic_iostream(std::basic_streambuf<CharT, Traits> *sb)
{
this->init(sb);
}
basic_iostream(const basic_iostream &other) = delete;
virtual ~basic_iostream() = default;
basic_iostream &operator=(const basic_iostream &other) = delete;
protected:
basic_iostream(basic_iostream &&other)
{
this->rdbuf(other.rdbuf());
other.rdbuf(nullptr);
}
basic_iostream &operator=(basic_iostream &&other);
void swap(basic_iostream &other)
{
std::swap(this->rdbuf(), other.rdbuf());
}
};
typedef basic_istream<char> istream;
typedef basic_istream<wchar_t> wistream;
typedef basic_iostream<char> iostream;
typedef basic_iostream<wchar_t> wiostream;
}

View File

@ -43,26 +43,21 @@ namespace std
{
};
template <class Iter>
class reverse_iterator
{
public:
/* FIXME: missing implementation */
};
template <class Iter>
struct iterator_traits
{
public:
typedef Iter::difference_type difference_type;
/* FIXME: missing implementation */
using difference_type = typename Iter::difference_type;
using value_type = typename Iter::value_type;
using pointer = typename Iter::pointer;
using reference = typename Iter::reference;
using iterator_category = typename Iter::iterator_category;
};
template <class It>
constexpr typename std::iterator_traits<It>::difference_type __do_distance(It first, It last, std::input_iterator_tag)
template <class InputIt>
constexpr typename std::iterator_traits<InputIt>::difference_type __do_distance(InputIt first, InputIt last, std::input_iterator_tag)
{
typename std::iterator_traits<It>::difference_type result = 0;
typename std::iterator_traits<InputIt>::difference_type result = 0;
while (first != last)
{
++first;
@ -71,8 +66,8 @@ namespace std
return result;
}
template <class It>
constexpr typename std::iterator_traits<It>::difference_type __do_distance(It first, It last, std::random_access_iterator_tag)
template <class InputIt>
constexpr typename std::iterator_traits<InputIt>::difference_type __do_distance(InputIt first, InputIt last, std::random_access_iterator_tag)
{
return last - first;
}
@ -82,4 +77,56 @@ namespace std
{
return __do_distance(first, last, typename std::iterator_traits<InputIt>::iterator_category());
}
template <class InputIt>
void __do_advance(InputIt &it, typename std::iterator_traits<InputIt>::difference_type n, std::input_iterator_tag)
{
while (n > 0)
{
--n;
++it;
}
}
template <class InputIt>
void __do_advance(InputIt &it, typename std::iterator_traits<InputIt>::difference_type n, std::bidirectional_iterator_tag)
{
while (n > 0)
{
--n;
++it;
}
while (n < 0)
{
++n;
--it;
}
}
template <class InputIt>
void __do_advance(InputIt &it, typename std::iterator_traits<InputIt>::difference_type n, std::random_access_iterator_tag)
{
it += n;
}
template <class InputIt, class Distance>
constexpr void advance(InputIt &it, Distance n)
{
__do_advance(it, typename std::iterator_traits<InputIt>::difference_type(n),
typename std::iterator_traits<InputIt>::iterator_category());
}
template <class BidirIt>
constexpr BidirIt prev(BidirIt it, typename std::iterator_traits<BidirIt>::difference_type n = 1)
{
std::advance(it, -n);
return it;
}
template <class InputIt>
constexpr InputIt next(InputIt it, typename std::iterator_traits<InputIt>::difference_type n = 1)
{
std::advance(it, n);
return it;
}
}

File diff suppressed because it is too large Load Diff

159
include_std/locale Normal file
View File

@ -0,0 +1,159 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once
#include <cstddef>
#include <cassert>
#include <string>
namespace std
{
class locale
{
public:
#pragma region Member Types
class id
{
public:
id() = default;
id(const id &) = delete;
};
class facet
{
private:
std::size_t refs;
public:
explicit facet(std::size_t refs = 0)
{
this->refs = refs;
}
facet(const facet &) = delete;
protected:
virtual ~facet() = default;
};
typedef int category;
#pragma endregion Member Types
#pragma region Member Objects
static const category none = 0;
static const category collate = 1;
static const category ctype = 2;
static const category monetary = 4;
static const category numeric = 8;
static const category time = 16;
static const category messages = 32;
static const category all = collate | ctype | monetary | numeric | time | messages;
#pragma endregion Member Objects
#pragma region Member Functions
locale() noexcept
{
assert(!"Function not implemented");
}
locale(const locale &other) noexcept
{
assert(!"Function not implemented");
}
explicit locale(const char *std_name)
{
assert(!"Function not implemented");
}
explicit locale(const std::string &std_name)
{
assert(!"Function not implemented");
}
locale(const locale &other, const char *std_name, category cats)
{
assert(!"Function not implemented");
}
locale(const locale &other, const std::string &std_name, category cats)
{
assert(!"Function not implemented");
}
template <class Facet>
locale(const locale &other, Facet *f)
{
assert(!"Function not implemented");
}
locale(const locale &other, const locale &one, category cats)
{
assert(!"Function not implemented");
}
~locale()
{
assert(!"Function not implemented");
}
const locale &operator=(const locale &other) noexcept
{
assert(!"Function not implemented");
}
template <class Facet>
locale combine(const locale &other) const
{
assert(!"Function not implemented");
}
std::string name() const
{
assert(!"Function not implemented");
}
bool operator==(const locale &other) const
{
assert(!"Function not implemented");
}
template <class CharT, class Traits, class Alloc>
bool operator()(const basic_string<CharT, Traits, Alloc> &s1, const basic_string<CharT, Traits, Alloc> &s2) const
{
assert(!"Function not implemented");
}
static locale global(const locale &loc)
{
assert(!"Function not implemented");
}
static const locale &classic()
{
assert(!"Function not implemented");
}
#pragma endregion Member Functions
};
}

View File

@ -18,12 +18,136 @@
#pragma once
#include <type_traits>
#include <functional>
#include <cstddef>
#include <utility>
#include <limits>
#include <new>
#include <debug.h>
namespace std
{
namespace __memory__detail
{
template <class>
constexpr bool is_unbounded_array_v = false;
template <class T>
constexpr bool is_unbounded_array_v<T[]> = true;
template <class>
constexpr bool is_bounded_array_v = false;
template <class T, std::size_t N>
constexpr bool is_bounded_array_v<T[N]> = true;
}
template <class T, class... Args>
constexpr T *construct_at(T *p, Args &&...args)
{
return ::new (static_cast<void *>(p)) T(std::forward<Args>(args)...);
}
template <class T>
constexpr void destroy_at(T *p)
{
p->~T();
}
template <class T>
T *addressof(T &arg)
{
return reinterpret_cast<T *>(&const_cast<char &>(reinterpret_cast<const volatile char &>(arg)));
}
template <class T>
const T *addressof(const T &&) = delete;
template <class InputIt, class Size, class NoThrowForwardIt>
NoThrowForwardIt uninitialized_copy_n(InputIt first, Size count, NoThrowForwardIt d_first)
{
using ValueType = typename std::iterator_traits<NoThrowForwardIt>::value_type;
NoThrowForwardIt current = d_first;
try
{
for (Size i = 0; i < count; ++i, (void)++current, ++first)
{
::new (static_cast<void *>(std::addressof(*current))) ValueType(*first);
}
return current;
}
catch (...)
{
for (; d_first != current; ++d_first)
{
d_first->~ValueType();
}
throw;
}
}
template <class ExecutionPolicy, class ForwardIt, class Size, class NoThrowForwardIt>
NoThrowForwardIt uninitialized_copy_n(ExecutionPolicy &&policy, ForwardIt first, Size count, NoThrowForwardIt d_first)
{
return uninitialized_copy_n(first, count, d_first);
}
template <class ForwardIt, class Size, class T>
ForwardIt uninitialized_fill_n(ForwardIt first, Size count, const T &value)
{
using V = typename std::iterator_traits<ForwardIt>::value_type;
ForwardIt current = first;
try
{
for (; count > 0; ++current, (void)--count)
::new (static_cast<void *>(std::addressof(*current))) V(value);
return current;
}
catch (...)
{
for (; first != current; ++first)
first->~V();
throw;
}
}
template <class ExecutionPolicy, class ForwardIt, class Size, class T>
ForwardIt uninitialized_fill_n(ExecutionPolicy &&policy, ForwardIt first, Size count, const T &value)
{
return uninitialized_fill_n(first, count, value);
}
template <class Ptr>
struct pointer_traits
{
using pointer = Ptr;
using element_type = typename Ptr::element_type;
using difference_type = typename Ptr::difference_type;
template <class U>
using rebind = typename Ptr::template rebind<U>;
static pointer pointer_to(element_type &r) noexcept
{
return Ptr::pointer_to(r);
}
};
template <class T>
struct pointer_traits<T *>
{
using pointer = T *;
using element_type = T;
using difference_type = std::ptrdiff_t;
template <class U>
using rebind = U *;
static pointer pointer_to(element_type &r) noexcept
{
return std::addressof(r);
}
};
template <class Pointer, class SizeType = std::size_t>
struct allocation_result
{
@ -31,6 +155,73 @@ namespace std
SizeType count;
};
template <class Alloc>
struct allocator_traits
{
typedef Alloc allocator_type;
typedef typename Alloc::value_type value_type;
typedef typename Alloc::pointer pointer;
typedef typename Alloc::const_pointer const_pointer;
// typedef typename Alloc::void_pointer void_pointer;
// typedef typename Alloc::const_void_pointer const_void_pointer;
// typedef typename std::pointer_traits<pointer>::rebind<void> void_pointer;
// typedef typename std::pointer_traits<pointer>::rebind<const void> const_void_pointer;
typedef typename Alloc::difference_type difference_type;
typedef typename Alloc::size_type size_type;
// typedef typename Alloc::propagate_on_container_copy_assignment propagate_on_container_copy_assignment;
typedef typename std::false_type propagate_on_container_copy_assignment;
typedef typename Alloc::propagate_on_container_move_assignment propagate_on_container_move_assignment;
typedef typename std::false_type propagate_on_container_swap;
typedef typename Alloc::is_always_equal is_always_equal;
template <class T>
using rebind_alloc = typename Alloc::template rebind<T>::other;
template <class T>
using rebind_traits = allocator_traits<rebind_alloc<T>>;
[[nodiscard]] static constexpr pointer allocate(Alloc &a, size_type n)
{
return a.allocate(n);
}
// [[nodiscard]] static constexpr pointer allocate(Alloc &a, size_type n, const_void_pointer hint)
// {
// return a.allocate(n, hint);
// }
[[nodiscard]] static constexpr std::allocation_result<pointer, size_type> allocate_at_least(Alloc &a, size_type n)
{
return a.allocate_at_least(n);
}
static constexpr void deallocate(Alloc &a, pointer p, size_type n)
{
a.deallocate(p, n);
}
template <class T, class... Args>
static constexpr void construct(Alloc &a, T *p, Args &&...args)
{
std::construct_at(p, std::forward<Args>(args)...);
}
template <class T>
static constexpr void destroy(Alloc &a, T *p)
{
std::destroy_at(p);
}
static constexpr size_type max_size(const Alloc &a)
{
return a.max_size();
}
static constexpr Alloc select_on_container_copy_construction(const Alloc &a)
{
return a;
}
};
template <class T>
struct allocator
{
@ -64,9 +255,7 @@ namespace std
std::allocation_result<T *, std::size_t> allocate_at_least(std::size_t n)
{
if (n > max_size())
return {nullptr, 0};
return {allocate(n), n};
return {static_cast<T *>(::operator new(n * sizeof(T))), n};
}
void deallocate(T *p, std::size_t n)
@ -74,35 +263,344 @@ namespace std
::operator delete(p);
}
size_type max_size() const
{
return std::numeric_limits<size_type>::max() / sizeof(T);
}
void construct(pointer p, const_reference val)
{
::new ((void *)p) T(val);
}
template <class U, class... Args>
void construct(U *p, Args &&...args)
{
::new ((void *)p) U(std::forward<Args>(args)...);
}
void destroy(pointer p) { p->~T(); }
template <class U>
void destroy(U *p) { p->~U(); }
pointer address(reference x) const { return &x; }
const_pointer address(const_reference x) const { return &x; }
};
template <class T>
T *addressof(T &arg)
struct default_delete
{
return reinterpret_cast<T *>(&const_cast<char &>(reinterpret_cast<const volatile char &>(arg)));
constexpr default_delete() noexcept = default;
template <class U>
constexpr default_delete(const default_delete<U> &d) noexcept {}
constexpr void operator()(T *ptr) const { delete ptr; }
};
template <class T>
struct default_delete<T[]>
{
constexpr default_delete() noexcept = default;
template <class U>
constexpr default_delete(const default_delete<U[]> &d) noexcept {}
template <class U>
constexpr void operator()(U *ptr) const { delete[] ptr; }
};
template <class T, class Deleter = std::default_delete<T>>
class unique_ptr
{
public:
using pointer = T *; // std::remove_reference<Deleter>::type::pointer;
using element_type = T;
using deleter_type = Deleter;
private:
pointer _ptr;
public:
#pragma region Member Functions
constexpr unique_ptr() noexcept : _ptr(nullptr) {}
constexpr unique_ptr(std::nullptr_t) noexcept : _ptr(nullptr) {}
constexpr explicit unique_ptr(pointer p) noexcept : _ptr(p) {}
// constexpr unique_ptr(pointer p, /* TODO */ d1) noexcept : _ptr(p) {}
// constexpr unique_ptr(pointer p, /* TODO */ d2) noexcept : _ptr(p) {}
constexpr unique_ptr(unique_ptr &&u) noexcept : _ptr(u.release()) {}
template <class U, class E>
constexpr unique_ptr(unique_ptr<U, E> &&u) noexcept : _ptr(u.release()) {}
unique_ptr(const unique_ptr &) = delete;
~unique_ptr()
{
if (_ptr == nullptr)
return;
Deleter d;
d(_ptr);
}
constexpr unique_ptr &operator=(unique_ptr &&r) noexcept
{
reset(r.release());
return *this;
}
template <class U, class E>
constexpr unique_ptr &operator=(unique_ptr<U, E> &&r) noexcept
{
reset(r.release());
return *this;
}
constexpr unique_ptr &operator=(std::nullptr_t) noexcept
{
reset();
return *this;
}
unique_ptr &operator=(const unique_ptr &) = delete;
#pragma endregion Member Functions
#pragma region Modifiers
constexpr pointer release() noexcept
{
pointer p = _ptr;
_ptr = nullptr;
return p;
}
constexpr void reset(pointer ptr = pointer()) noexcept
{
Deleter d;
d(_ptr);
_ptr = ptr;
}
void swap(unique_ptr &other) noexcept
{
pointer tmp = _ptr;
_ptr = other._ptr;
other._ptr = tmp;
}
#pragma endregion Modifiers
#pragma region Observers
constexpr pointer get() const noexcept { return _ptr; }
constexpr Deleter &get_deleter() noexcept { return _ptr; }
constexpr const Deleter &get_deleter() const noexcept { return _ptr; }
constexpr explicit operator bool() const noexcept { return get() != nullptr; }
#pragma endregion Observers
#pragma region Element Access
constexpr typename std::add_lvalue_reference<T>::type operator*() const noexcept(noexcept(*std::declval<pointer>())) { return *_ptr; }
constexpr pointer operator->() const noexcept { return _ptr; }
#pragma endregion Element Access
};
template <class T, class Deleter>
class unique_ptr<T[], Deleter>
{
public:
using pointer = T *; // std::remove_reference<Deleter>::type::pointer;
using element_type = T;
using deleter_type = Deleter;
private:
pointer _ptr;
public:
#pragma region Member Functions
constexpr unique_ptr() noexcept : _ptr(nullptr) {}
constexpr unique_ptr(std::nullptr_t) noexcept : _ptr(nullptr) {}
template <class U>
constexpr explicit unique_ptr(U p) noexcept : _ptr(p) {}
// template <class U>
// constexpr unique_ptr(U p, /* TODO */ d1) noexcept : _ptr(p) {}
// template <class U>
// constexpr unique_ptr(U p, /* TODO */ d2) noexcept : _ptr(p) {}
constexpr unique_ptr(unique_ptr &&u) noexcept : _ptr(u.release()) {}
template <class U, class E>
constexpr unique_ptr(unique_ptr<U, E> &&u) noexcept : _ptr(u.release()) {}
unique_ptr(const unique_ptr &) = delete;
~unique_ptr()
{
if (_ptr == nullptr)
return;
Deleter d;
d(_ptr);
}
constexpr unique_ptr &operator=(unique_ptr &&r) noexcept
{
reset(r.release());
return *this;
}
template <class U, class E>
constexpr unique_ptr &operator=(unique_ptr<U, E> &&r) noexcept
{
reset(r.release());
return *this;
}
constexpr unique_ptr &operator=(std::nullptr_t) noexcept
{
reset();
return *this;
}
unique_ptr &operator=(const unique_ptr &) = delete;
#pragma endregion Member Functions
#pragma region Modifiers
constexpr pointer release() noexcept
{
pointer p = _ptr;
_ptr = nullptr;
return p;
}
template <class U>
constexpr void reset(U ptr) noexcept
{
Deleter d;
d(_ptr);
_ptr = ptr;
}
constexpr void reset(std::nullptr_t = nullptr) noexcept
{
Deleter d;
d(_ptr);
_ptr = nullptr;
}
void swap(unique_ptr &other) noexcept
{
pointer tmp = _ptr;
_ptr = other._ptr;
other._ptr = tmp;
}
#pragma endregion Modifiers
#pragma region Observers
constexpr pointer get() const noexcept { return _ptr; }
constexpr Deleter &get_deleter() noexcept { return _ptr; }
constexpr const Deleter &get_deleter() const noexcept { return _ptr; }
constexpr explicit operator bool() const noexcept { return get() != nullptr; }
#pragma endregion Observers
#pragma region Element Access
constexpr T &operator[](std::size_t i) const { return _ptr[i]; }
#pragma endregion Element Access
};
template <class T, class... Args>
std::enable_if_t<!std::is_array<T>::value, std::unique_ptr<T>>
make_unique(Args &&...args)
{
return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}
template <class T>
const T *addressof(const T &&) = delete;
std::enable_if_t<__memory__detail::is_unbounded_array_v<T>, std::unique_ptr<T>>
make_unique(std::size_t n)
{
return std::unique_ptr<T>(new std::remove_extent_t<T>[n]());
}
template <class T, class... Args>
std::enable_if_t<__memory__detail::is_bounded_array_v<T>> make_unique(Args &&...) = delete;
template <class T>
requires(!std::is_array_v<T>)
std::unique_ptr<T> make_unique_for_overwrite()
{
return std::unique_ptr<T>(new T);
}
template <class T>
requires std::is_unbounded_array_v<T>
std::unique_ptr<T> make_unique_for_overwrite(std::size_t n)
{
return std::unique_ptr<T>(new std::remove_extent_t<T>[n]);
}
template <class T, class... Args>
requires std::is_bounded_array_v<T>
void make_unique_for_overwrite(Args &&...) = delete;
template <class T1, class D1, class T2, class D2>
constexpr bool operator==(const unique_ptr<T1, D1> &x, const unique_ptr<T2, D2> &y) { return x.get() == y.get(); }
template <class T1, class D1, class T2, class D2>
bool operator<(const unique_ptr<T1, D1> &x, const unique_ptr<T2, D2> &y)
{
return std::less<typename std::common_type<typename unique_ptr<T1, D1>::pointer, typename unique_ptr<T2, D2>::pointer>::type>()(x.get(), y.get());
}
template <class T1, class D1, class T2, class D2>
bool operator<=(const unique_ptr<T1, D1> &x, const unique_ptr<T2, D2> &y) { return !(y < x); }
template <class T1, class D1, class T2, class D2>
bool operator>(const unique_ptr<T1, D1> &x, const unique_ptr<T2, D2> &y) { return y < x; }
template <class T1, class D1, class T2, class D2>
bool operator>=(const unique_ptr<T1, D1> &x, const unique_ptr<T2, D2> &y) { return !(x < y); }
// operator<=>(const unique_ptr<T1, D1> &x, const unique_ptr<T2, D2> &y);
template <class T, class D>
constexpr bool operator==(const unique_ptr<T, D> &x, std::nullptr_t) noexcept { return !x; }
template <class T, class D>
constexpr bool operator<(const unique_ptr<T, D> &x, std::nullptr_t) { return std::less<typename unique_ptr<T, D>::pointer>()(x.get(), nullptr); }
template <class T, class D>
constexpr bool operator<(std::nullptr_t, const unique_ptr<T, D> &y) { return std::less<typename unique_ptr<T, D>::pointer>()(nullptr, y.get()); }
template <class T, class D>
constexpr bool operator<=(const unique_ptr<T, D> &x, std::nullptr_t) { return !(nullptr < x); }
template <class T, class D>
constexpr bool operator<=(std::nullptr_t, const unique_ptr<T, D> &y) { return !(y < nullptr); }
template <class T, class D>
constexpr bool operator>(const unique_ptr<T, D> &x, std::nullptr_t) { return nullptr < x; }
template <class T, class D>
constexpr bool operator>(std::nullptr_t, const unique_ptr<T, D> &y) { return y < nullptr; }
template <class T, class D>
constexpr bool operator>=(const unique_ptr<T, D> &x, std::nullptr_t) { return !(x < nullptr); }
template <class T, class D>
constexpr bool operator>=(std::nullptr_t, const unique_ptr<T, D> &y) { return !(nullptr < y); }
// operator<=>(const unique_ptr<T, D> &x, std::nullptr_t);
// template <class CharT, class Traits, class Y, class D>
// std::basic_ostream<CharT, Traits> &operator<<(std::basic_ostream<CharT, Traits> &os, const std::unique_ptr<Y, D> &p)
// {
// return os << p.get();
// }
template <class T, class D>
void swap(std::unique_ptr<T, D> &lhs, std::unique_ptr<T, D> &rhs) noexcept
{
lhs.swap(rhs);
}
}

23
include_std/memory.h Normal file
View File

@ -0,0 +1,23 @@
/*
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_STD_MEMORY_H__
#define __FENNIX_KERNEL_STD_MEMORY_H__
#include <convert.h>
#endif // !__FENNIX_KERNEL_STD_MEMORY_H__

143
include_std/new Normal file
View File

@ -0,0 +1,143 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once
#include <cstddef>
#include <exception>
namespace std
{
enum class align_val_t : std::size_t
{
};
struct nothrow_t
{
explicit nothrow_t() = default;
};
extern const std::nothrow_t nothrow;
struct destroying_delete_t
{
explicit destroying_delete_t() = default;
};
inline constexpr destroying_delete_t destroying_delete{};
typedef void (*new_handler)();
std::new_handler set_new_handler(std::new_handler new_p) noexcept;
std::new_handler get_new_handler() noexcept;
class bad_alloc : public exception
{
public:
bad_alloc() noexcept = default;
bad_alloc(const bad_alloc &other) noexcept = default;
bad_alloc &operator=(const bad_alloc &other) noexcept = default;
virtual const char *what() const noexcept
{
return "bad_alloc";
}
};
class bad_array_new_length : public bad_alloc
{
public:
bad_array_new_length() noexcept = default;
bad_array_new_length(const bad_array_new_length &other) noexcept = default;
virtual ~bad_array_new_length() = default;
bad_array_new_length &operator=(const bad_array_new_length &other) noexcept
{
return *this;
}
virtual const char *what() const noexcept
{
return "bad_array_new_length";
}
};
}
[[nodiscard]] void *operator new(std::size_t count);
[[nodiscard]] void *operator new[](std::size_t count);
// [[nodiscard]] void *operator new(std::size_t count, std::align_val_t al);
// [[nodiscard]] void *operator new[](std::size_t count, std::align_val_t al);
// [[nodiscard]] void *operator new(std::size_t count, const std::nothrow_t &tag) noexcept;
// [[nodiscard]] void *operator new[](std::size_t count, const std::nothrow_t &tag) noexcept;
// [[nodiscard]] void *operator new(std::size_t count, std::align_val_t al, const std::nothrow_t &) noexcept;
// [[nodiscard]] void *operator new[](std::size_t count, std::align_val_t al, const std::nothrow_t &) noexcept;
[[nodiscard]] void *operator new(std::size_t count, void *ptr) noexcept;
[[nodiscard]] void *operator new[](std::size_t count, void *ptr) noexcept;
// void *operator new(std::size_t count, ...);
// void *operator new[](std::size_t count, ...);
// void *operator new(std::size_t count, std::align_val_t al, ...);
// void *operator new[](std::size_t count, std::align_val_t al, ...);
// void *T::operator new(std::size_t count);
// void *T::operator new[](std::size_t count);
// void *T::operator new(std::size_t count, std::align_val_t al);
// void *T::operator new[](std::size_t count, std::align_val_t al);
// void *T::operator new(std::size_t count, ...);
// void *T::operator new[](std::size_t count, ...);
// void *T::operator new(std::size_t count, std::align_val_t al, ...);
// void *T::operator new[](std::size_t count, std::align_val_t al, ...);
void operator delete(void *ptr) noexcept;
void operator delete[](void *ptr) noexcept;
// void operator delete(void *ptr, std::align_val_t al) noexcept;
// void operator delete[](void *ptr, std::align_val_t al) noexcept;
void operator delete(void *ptr, std::size_t sz) noexcept;
// void operator delete[](void *ptr, std::size_t sz) noexcept;
// void operator delete(void *ptr, std::size_t sz, std::align_val_t al) noexcept;
// void operator delete[](void *ptr, std::size_t sz, std::align_val_t al) noexcept;
// void operator delete(void *ptr, const std::nothrow_t &tag) noexcept;
// void operator delete[](void *ptr, const std::nothrow_t &tag) noexcept;
// void operator delete(void *ptr, std::align_val_t al, const std::nothrow_t &tag) noexcept;
// void operator delete[](void *ptr, std::align_val_t al, const std::nothrow_t &tag) noexcept;
// void operator delete(void *ptr, void *place) noexcept;
// void operator delete[](void *ptr, void *place) noexcept;
// void operator delete(void *ptr, ...);
// void operator delete[](void *ptr, ...);
// void T::operator delete(void *ptr);
// void T::operator delete[](void *ptr);
// void T::operator delete(void *ptr, std::align_val_t al);
// void T::operator delete[](void *ptr, std::align_val_t al);
// void T::operator delete(void *ptr, std::size_t sz);
// void T::operator delete[](void *ptr, std::size_t sz);
// void T::operator delete(void *ptr, std::size_t sz, std::align_val_t al);
// void T::operator delete[](void *ptr, std::size_t sz, std::align_val_t al);
// void T::operator delete(void *ptr, args...);
// void T::operator delete[](void *ptr, args...);
// void T::operator delete(T *ptr, std::destroying_delete_t);
// void T::operator delete(T *ptr, std::destroying_delete_t, std::align_val_t al);
// void T::operator delete(T *ptr, std::destroying_delete_t, std::size_t sz);
// void T::operator delete(T *ptr, std::destroying_delete_t, std::size_t sz, std::align_val_t al);

View File

@ -15,29 +15,26 @@
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include <filesystem/mounts.hpp>
#include <errno.h>
#pragma once
#include "../../kernel.h"
#include <string>
#include <ios>
using namespace vfs;
namespace vfs
namespace std
{
size_t ZeroDevice::read(uint8_t *Buffer, size_t Size, off_t Offset)
template <class CharT, class Traits = std::char_traits<CharT>>
class basic_ostream : virtual public std::basic_ios<CharT, Traits>
{
if (Size <= 0)
return 0;
};
memset(Buffer, 0, Size);
return Size;
template <class CharT, class Traits>
std::basic_ostream<CharT, Traits> &endl(std::basic_ostream<CharT, Traits> &os)
{
os.put(os.widen('\n'));
os.flush();
return os;
}
size_t ZeroDevice::write(uint8_t *Buffer, size_t Size, off_t Offset)
{
return Size;
}
ZeroDevice::ZeroDevice() : Node(DevFS, "zero", CHARDEVICE) {}
ZeroDevice::~ZeroDevice() {}
typedef basic_ostream<char> ostream;
typedef basic_ostream<wchar_t> wostream;
}

23
include_std/signal.h Normal file
View File

@ -0,0 +1,23 @@
/*
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_STD_SIGNAL_H__
#define __FENNIX_KERNEL_STD_SIGNAL_H__
#include <types.h>
#endif // !__FENNIX_KERNEL_STD_SIGNAL_H__

View File

@ -1,68 +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/>.
*/
/* This function includes all the standard headers and defines some useful macros.
* Note: This std implementation is not complete.
*/
#ifndef __FENNIX_KERNEL_STD_H__
#define __FENNIX_KERNEL_STD_H__
#include <types.h>
/**
* @brief // stub namespace for std::align_val_t and new operator
* @note // Found on https://gcc.gnu.org/legacy-ml/gcc-patches/2016-09/msg00628.html for "_ZnwmSt11align_val_t" compiler error
*/
namespace std
{
typedef __SIZE_TYPE__ size_t;
static const size_t npos = -1;
enum class align_val_t : std::size_t
{
};
template <typename InputIt, typename OutputIt, typename UnaryOperation>
OutputIt transform(InputIt first, InputIt last, OutputIt result, UnaryOperation op)
{
while (first != last)
{
*result = op(*first);
++first;
++result;
}
return result;
};
inline __always_inline int tolower(int c)
{
if (c >= 'A' && c <= 'Z')
return c + ('a' - 'A');
else
return c;
}
inline __always_inline int toupper(int c)
{
if (c >= 'a' && c <= 'z')
return c - ('a' - 'A');
else
return c;
}
}
#endif // !__FENNIX_KERNEL_STD_H__

View File

@ -1,266 +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_STD_SMART_POINTER_H__
#define __FENNIX_KERNEL_STD_SMART_POINTER_H__
#include <types.h>
#include <type_traits>
#include <debug.h>
// show debug messages
// #define DEBUG_SMARTPOINTERS 1
#ifdef DEBUG_SMARTPOINTERS
#define spdbg(m, ...) debug(m, ##__VA_ARGS__)
#else
#define spdbg(m, ...)
#endif
namespace std
{
/**
* @brief A smart pointer class
*
* This class is a smart pointer class. It is used to manage the lifetime of
* objects. It is a reference counted pointer, so when the last reference to
* the object is removed, the object is deleted.
*
* Basic Usage:
* smart_ptr<char> pointer(new char());
* *pointer = 'a';
* printf("%c", *pointer); // Prints "a"
*/
template <class T>
class smart_ptr
{
T *RealPointer;
public:
explicit smart_ptr(T *Pointer = nullptr)
{
spdbg("Smart pointer created (%#lx)", this->RealPointer);
this->RealPointer = Pointer;
}
~smart_ptr()
{
spdbg("Smart pointer deleted (%#lx)", this->RealPointer);
delete this->RealPointer, this->RealPointer = nullptr;
}
T &operator*()
{
spdbg("Smart pointer dereferenced (%#lx)", this->RealPointer);
return *this->RealPointer;
}
T *operator->()
{
spdbg("Smart pointer dereferenced (%#lx)", this->RealPointer);
return this->RealPointer;
}
T *get()
{
spdbg("Smart pointer returned (%#lx)", this->RealPointer);
return this->RealPointer;
}
};
template <class T>
class auto_ptr
{
};
template <class T>
class unique_ptr
{
};
template <class T>
class weak_ptr
{
};
template <typename T>
class shared_ptr
{
private:
class counter
{
private:
unsigned int RefCount{};
public:
counter() : RefCount(0) { spdbg("Counter %#lx created", this); };
counter(const counter &) = delete;
counter &operator=(const counter &) = delete;
~counter() { spdbg("Counter %#lx deleted", this); }
void reset()
{
this->RefCount = 0;
spdbg("reset");
}
unsigned int get()
{
return this->RefCount;
spdbg("return");
}
void operator++()
{
this->RefCount++;
spdbg("increment");
}
void operator++(int)
{
this->RefCount++;
spdbg("increment");
}
void operator--()
{
this->RefCount--;
spdbg("decrement");
}
void operator--(int)
{
this->RefCount--;
spdbg("decrement");
}
};
counter *ReferenceCounter;
T *RealPointer;
public:
explicit shared_ptr(T *Pointer = nullptr)
{
this->RealPointer = Pointer;
this->ReferenceCounter = new counter();
spdbg("[%#lx] Shared pointer created (ptr=%#lx, ref=%#lx)", this, Pointer, this->ReferenceCounter);
if (Pointer)
(*this->ReferenceCounter)++;
}
shared_ptr(shared_ptr<T> &SPtr)
{
spdbg("[%#lx] Shared pointer copied (ptr=%#lx, ref=%#lx)", this, SPtr.RealPointer, SPtr.ReferenceCounter);
this->RealPointer = SPtr.RealPointer;
this->ReferenceCounter = SPtr.ReferenceCounter;
(*this->ReferenceCounter)++;
}
~shared_ptr()
{
spdbg("[%#lx] Shared pointer destructor called", this);
(*this->ReferenceCounter)--;
if (this->ReferenceCounter->get() == 0)
{
spdbg("[%#lx] Shared pointer deleted (ptr=%#lx, ref=%#lx)", this, this->RealPointer, this->ReferenceCounter);
delete this->ReferenceCounter, this->ReferenceCounter = nullptr;
delete this->RealPointer, this->RealPointer = nullptr;
}
}
unsigned int get_count()
{
spdbg("[%#lx] Shared pointer count (%d)", this, this->ReferenceCounter->get());
return this->ReferenceCounter->get();
}
T *get()
{
spdbg("[%#lx] Shared pointer get (%#lx)", this, this->RealPointer);
return this->RealPointer;
}
T &operator*()
{
spdbg("[%#lx] Shared pointer dereference (ptr*=%#lx)", this, *this->RealPointer);
return *this->RealPointer;
}
T *operator->()
{
spdbg("[%#lx] Shared pointer dereference (ptr->%#lx)", this, this->RealPointer);
return this->RealPointer;
}
void reset(T *Pointer = nullptr)
{
if (this->RealPointer == Pointer)
return;
spdbg("[%#lx] Shared pointer reset (ptr=%#lx, ref=%#lx)", this, Pointer, this->ReferenceCounter);
(*this->ReferenceCounter)--;
if (this->ReferenceCounter->get() == 0)
{
delete this->RealPointer;
delete this->ReferenceCounter;
}
this->RealPointer = Pointer;
this->ReferenceCounter = new counter();
if (Pointer)
(*this->ReferenceCounter)++;
}
void reset()
{
spdbg("[%#lx] Shared pointer reset (ptr=%#lx, ref=%#lx)", this, this->RealPointer, this->ReferenceCounter);
if (this->ReferenceCounter->get() == 1)
{
delete this->RealPointer, this->RealPointer = nullptr;
delete this->ReferenceCounter, this->ReferenceCounter = nullptr;
}
else
{
(*this->ReferenceCounter)--;
}
}
void swap(shared_ptr<T> &Other)
{
spdbg("[%#lx] Shared pointer swap (ptr=%#lx, ref=%#lx <=> ptr=%#lx, ref=%#lx)",
this, this->RealPointer, this->ReferenceCounter, Other.RealPointer, Other.ReferenceCounter);
T *tempRealPointer = this->RealPointer;
counter *tempReferenceCounter = this->ReferenceCounter;
this->RealPointer = Other.RealPointer;
this->ReferenceCounter = Other.ReferenceCounter;
Other.RealPointer = tempRealPointer;
Other.ReferenceCounter = tempReferenceCounter;
}
};
template <typename T, typename... Args>
shared_ptr<T> make_shared(Args &&...args)
{
return shared_ptr<T>(new T(forward<Args>(args)...));
};
template <typename T, typename... Args>
smart_ptr<T> make_smart(Args &&...args)
{
return smart_ptr<T>(new T(forward<Args>(args)...));
};
}
#endif // !__FENNIX_KERNEL_STD_SMART_POINTER_H__

35
include_std/stdbool.h Normal file
View File

@ -0,0 +1,35 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef __FENNIX_KERNEL_header_H__
#define __FENNIX_KERNEL_header_H__
#include <types.h>
#ifndef __cplusplus
#define bool _Bool
#define true 1
#define false 0
#else
#define _Bool bool
#endif // !__cplusplus
#endif // !__FENNIX_KERNEL_header_H__

View File

@ -17,27 +17,103 @@
#pragma once
#include <assert.h>
#include <convert.h>
#include <cassert>
#include <new>
namespace std
{
class runtime_error
class __simple_string
{
private:
const char *m_what;
char *data;
size_t size;
public:
runtime_error(const char *what_arg) : m_what(what_arg) {}
const char *what() const { return this->m_what; }
__simple_string()
: data(nullptr),
size(0)
{
}
__simple_string(const char *str)
: data(nullptr),
size(0)
{
size = strlen(str);
data = new char[size + 1];
assert(data != nullptr);
memcpy(data, str, size);
data[size] = '\0';
}
__simple_string(const __simple_string &other)
: data(nullptr),
size(0)
{
size = other.size;
data = new char[size + 1];
assert(data != nullptr);
memcpy(data, other.data, size);
data[size] = '\0';
}
~__simple_string()
{
if (data)
delete[] data;
}
const char *c_str() const { return data; }
__simple_string &operator=(const __simple_string &other)
{
if (data)
delete[] data;
size = other.size;
data = new char[size + 1];
assert(data != nullptr);
memcpy(data, other.data, size);
data[size] = '\0';
return *this;
}
};
class out_of_range
class runtime_error : public exception
{
};
class logic_error : public exception
{
private:
__simple_string msg;
public:
out_of_range(const char *what_arg)
logic_error(const char *what_arg) : msg(what_arg) {}
logic_error(const logic_error &other) : msg(other.msg) {}
logic_error &operator=(const logic_error &other) noexcept
{
/* FIXME: This is a temporary assert */
assert(what_arg != nullptr);
msg = other.msg;
return *this;
}
virtual const char *what() const noexcept
{
return msg.c_str();
}
};
class out_of_range : public logic_error
{
public:
out_of_range(const char *what_arg) : logic_error(what_arg) {}
out_of_range(const out_of_range &other) = default;
out_of_range &operator=(const out_of_range &) = default;
out_of_range(out_of_range &&) = default;
out_of_range &operator=(out_of_range &&) = default;
virtual ~out_of_range() = default;
};
}

View File

@ -15,7 +15,42 @@
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef _STDIO_H
#define _STDIO_H
#ifndef __FENNIX_KERNEL_STDIO_H__
#define __FENNIX_KERNEL_STDIO_H__
#endif // !_STDIO_H
#include <types.h>
START_EXTERNC
#define FILENAME_MAX 4096
typedef struct
{
int st;
} FILE;
extern FILE *stdin;
extern FILE *stdout;
extern FILE *stderr;
#define stdin stdin
#define stdout stdout
#define stderr stderr
int printf(const char *format, ...) __attribute__((format(__printf__, (1), (2))));
int vprintf(const char *format, va_list arg) __attribute__((format(__printf__, ((1)), (0))));
int sprintf(char *s, const char *format, ...) __attribute__((format(__printf__, (2), (3))));
int vsprintf(char *s, const char *format, va_list arg) __attribute__((format(__printf__, ((2)), (0))));
int snprintf(char *s, size_t count, const char *format, ...) __attribute__((format(__printf__, (3), (4))));
int vsnprintf(char *s, size_t count, const char *format, va_list arg) __attribute__((format(__printf__, ((3)), (0))));
int asprintf(char **strp, const char *fmt, ...) __attribute__((format(__printf__, (2), (3))));
int vasprintf(char **strp, const char *fmt, va_list ap) __attribute__((format(__printf__, ((2)), (0))));
int fprintf(FILE *stream, const char *format, ...) __attribute__((format(__printf__, (2), (3))));
int fputs(const char *s, FILE *stream);
END_EXTERNC
#endif // !__FENNIX_KERNEL_STDIO_H__

View File

@ -15,7 +15,27 @@
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef _STDLIB_H
#define _STDLIB_H
#ifndef __FENNIX_KERNEL_STDLIB_H__
#define __FENNIX_KERNEL_STDLIB_H__
#endif // !_STDLIB_H
#include <types.h>
START_EXTERNC
#ifndef __FENNIX_KERNEL_INTERNAL_MEMORY_H__
void *malloc(size_t Size);
void *calloc(size_t n, size_t Size);
void *realloc(void *Address, size_t Size);
void free(void *Address);
#endif // !__FENNIX_KERNEL_INTERNAL_MEMORY_H__
void abort();
#define EXIT_FAILURE 1
#define EXIT_SUCCESS 0
END_EXTERNC
#endif // !__FENNIX_KERNEL_STDLIB_H__

312
include_std/streambuf Normal file
View File

@ -0,0 +1,312 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once
#include <algorithm>
#include <string>
#include <locale>
#include <ios>
namespace std
{
template <class CharT, class Traits = std::char_traits<CharT>>
class basic_streambuf
{
public:
typedef CharT char_type;
typedef Traits::char_type traits_type;
typedef Traits::int_type int_type;
typedef Traits::pos_type pos_type;
typedef Traits::off_type off_type;
private:
char_type *_eback;
char_type *_gptr;
char_type *_egptr;
char_type *_pbase;
char_type *_pptr;
char_type *_epptr;
public:
virtual ~basic_streambuf();
#pragma region Locales
std::locale pubimbue(const std::locale &loc)
{
return imbue(loc);
}
std::locale getloc() const
{
return imbue(std::locale());
}
#pragma endregion Locales
#pragma region Positioning
basic_streambuf<CharT, Traits> *pubsetbuf(char_type *s, std::streamsize n)
{
return setbuf(s, n);
}
pos_type pubseekoff(off_type off, std::ios_base::seekdir dir, std::ios_base::openmode which = ios_base::in | ios_base::out)
{
return seekoff(off, dir, which);
}
pos_type pubseekpos(pos_type pos, std::ios_base::openmode which = std::ios_base::in | std::ios_base::out)
{
return seekpos(pos, which);
}
int pubsync()
{
return sync();
}
#pragma endregion Positioning
#pragma region Get Area
std::streamsize in_avail()
{
return egptr() - gptr();
}
int_type snextc()
{
return gptr() == egptr() ? Traits::eof() : Traits::to_int_type(*gptr());
}
int_type sgetc()
{
return gptr() == egptr() ? underflow() : Traits::to_int_type(*gptr());
}
std::streamsize sgetn(char_type *s, std::streamsize count)
{
std::streamsize copied = 0;
while (copied < count)
{
if (gptr() == egptr())
{
if (underflow() == Traits::eof())
{
break;
}
}
*s++ = *gptr();
++copied;
}
return copied;
}
#pragma endregion Get Area
#pragma region Put Area
int_type sputc(char_type ch)
{
if (pptr() == epptr())
{
if (overflow(Traits::to_int_type(ch)) == Traits::eof())
{
return Traits::eof();
}
}
else
{
*pptr() = ch;
pbump(1);
}
return Traits::to_int_type(ch);
}
std::streamsize sputn(const char_type *s, std::streamsize count)
{
return xsputn(s, count);
}
#pragma endregion Put Area
#pragma region Putback
int_type sputbackc(char_type c)
{
if (gptr() == eback() || !Traits::eq(c, gptr()[-1]))
{
return Traits::eof();
}
gbump(-1);
return Traits::to_int_type(c);
}
int_type sungetc()
{
if (gptr() == eback())
{
return Traits::eof();
}
gbump(-1);
return Traits::to_int_type(*gptr());
}
#pragma endregion Putback
protected:
basic_streambuf()
: _eback(nullptr),
_gptr(nullptr),
_egptr(nullptr),
_pbase(nullptr),
_pptr(nullptr),
_epptr(nullptr)
{
}
basic_streambuf(const basic_streambuf &rhs)
: _eback(rhs._eback),
_gptr(rhs._gptr),
_egptr(rhs._egptr),
_pbase(rhs._pbase),
_pptr(rhs._pptr),
_epptr(rhs._epptr)
{
}
basic_streambuf &operator=(const basic_streambuf &other)
{
if (this == &other)
return *this;
_eback = other._eback;
_gptr = other._gptr;
_egptr = other._egptr;
_pbase = other._pbase;
_pptr = other._pptr;
_epptr = other._epptr;
return *this;
}
void swap(basic_streambuf &other)
{
std::swap(_eback, other._eback);
std::swap(_gptr, other._gptr);
std::swap(_egptr, other._egptr);
std::swap(_pbase, other._pbase);
std::swap(_pptr, other._pptr);
std::swap(_epptr, other._epptr);
}
#pragma region Locales
virtual void imbue(const std::locale &loc) = 0;
#pragma endregion Locales
#pragma region Positioning
virtual basic_streambuf<CharT, Traits> *setbuf(char_type *s, std::streamsize n) = 0;
virtual pos_type seekoff(off_type off, std::ios_base::seekdir dir, std::ios_base::openmode which = ios_base::in | ios_base::out) = 0;
virtual pos_type seekpos(pos_type pos, std::ios_base::openmode which = std::ios_base::in | std::ios_base::out) = 0;
virtual int sync() = 0;
#pragma endregion Positioning
#pragma region Get Area
virtual std::streamsize showmanyc() = 0;
virtual int_type underflow() = 0;
virtual int_type uflow() = 0;
virtual std::streamsize xsgetn(char_type *s, std::streamsize count) = 0;
char_type *eback() const
{
return _eback;
}
char_type *gptr() const
{
return _gptr;
}
char_type *egptr() const
{
return _egptr;
}
void gbump(int count)
{
_gptr += count;
}
void setg(char_type *gbeg, char_type *gcurr, char_type *gend)
{
_eback = gbeg;
_gptr = gcurr;
_egptr = gend;
}
#pragma endregion Get Area
#pragma region Put Area
virtual std::streamsize xsputn(const char_type *s, std::streamsize count) = 0;
virtual int_type overflow(int_type ch = Traits::eof()) = 0;
char_type *pbase() const
{
return _pbase;
}
char_type *pptr() const
{
return _pptr;
}
char_type *epptr() const
{
return _epptr;
}
void pbump(int count)
{
_pptr += count;
}
void setp(char_type *pbeg, char_type *pend)
{
_pbase = pbeg;
_pptr = pbeg;
_epptr = pend;
}
#pragma endregion Put Area
#pragma region Putback
virtual int_type pbackfail(int_type c = Traits::eof()) = 0;
#pragma endregion Putback
};
typedef basic_streambuf<char> streambuf;
typedef basic_streambuf<wchar_t> wstreambuf;
}

File diff suppressed because it is too large Load Diff

62
include_std/string_view Normal file
View File

@ -0,0 +1,62 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once
#include <string>
#include <ostream>
namespace std
{
typedef basic_string_view<char> string_view;
typedef basic_string_view<wchar_t> wstring_view;
typedef basic_string_view<char8_t> u8string_view;
typedef basic_string_view<char16_t> u16string_view;
typedef basic_string_view<char32_t> u32string_view;
template <class CharT, class Traits>
std::basic_ostream<CharT, Traits> &operator<<(std::basic_ostream<CharT, Traits> &os, std::basic_string_view<CharT, Traits> v)
{
os.write(v.data(), v.size());
return os;
}
constexpr std::string_view operator""sv(const char *str, std::size_t len) noexcept
{
return std::string_view{str, len};
}
constexpr std::u8string_view operator""sv(const char8_t *str, std::size_t len) noexcept
{
return std::u8string_view{str, len};
}
constexpr std::u16string_view operator""sv(const char16_t *str, std::size_t len) noexcept
{
return std::u16string_view{str, len};
}
constexpr std::u32string_view operator""sv(const char32_t *str, std::size_t len) noexcept
{
return std::u32string_view{str, len};
}
constexpr std::wstring_view operator""sv(const wchar_t *str, std::size_t len) noexcept
{
return std::wstring_view{str, len};
}
}

View File

@ -18,7 +18,7 @@
#pragma once
#include <types.h>
/* stubs */
/* stubs for rpmalloc.c */
#ifndef MAP_PRIVATE
#define MAP_PRIVATE 0x0

58
include_std/system_error Normal file
View File

@ -0,0 +1,58 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once
namespace std
{
class error_category
{
/* https://en.cppreference.com/w/cpp/error/error_category */
};
class error_code
{
public:
error_code() noexcept
{
}
error_code(int ec, const error_category &ecat) noexcept
{
}
template <class ErrorCodeEnum>
error_code(ErrorCodeEnum e) noexcept
{
}
error_code(const error_code &other) = default;
error_code(error_code &&other) = default;
template <class ErrorCodeEnum>
error_code &operator=(ErrorCodeEnum e) noexcept
{
return *this;
}
error_code &operator=(const error_code &other) = default;
error_code &operator=(error_code &&other) = default;
/* https://en.cppreference.com/w/cpp/error/error_code */
};
}

View File

@ -15,8 +15,10 @@
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef __FENNIX_KERNEL_TERMIOS_BITS_H__
#define __FENNIX_KERNEL_TERMIOS_BITS_H__
#ifndef __FENNIX_KERNEL_TERMIOS_H__
#define __FENNIX_KERNEL_TERMIOS_H__
#include <types.h>
/* c_cc */
#define VINTR 0
@ -157,4 +159,29 @@
#define CMSPAR 010000000000
#define CRTSCTS 020000000000
#endif // !__FENNIX_KERNEL_TERMIOS_BITS_H__
typedef unsigned char cc_t;
typedef unsigned int speed_t;
typedef unsigned int tcflag_t;
#define NCCS 32
struct termios
{
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;
};
struct winsize
{
unsigned short ws_row;
unsigned short ws_col;
unsigned short ws_xpixel;
unsigned short ws_ypixel;
};
#endif // !__FENNIX_KERNEL_TERMIOS_H__

27
include_std/tuple Normal file
View File

@ -0,0 +1,27 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once
#include <type_traits>
#include <cstddef>
namespace std
{
template <class... Types>
class tuple;
}

Some files were not shown because too many files have changed in this diff Show More