diff --git a/.vscode/c_boilerplates.code-snippets b/.vscode/c_boilerplates.code-snippets
index cd135d4..7baae13 100644
--- a/.vscode/c_boilerplates.code-snippets
+++ b/.vscode/c_boilerplates.code-snippets
@@ -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 .",
- "*/",
- "",
- "#include \"${1:driver}.hpp\"",
- "",
- "#include ",
- "",
- "#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 .",
- "*/",
- "",
- "#pragma once",
- "#include ",
- "",
- "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."
}
}
\ No newline at end of file
diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json
index f7afb05..a94312a 100644
--- a/.vscode/c_cpp_properties.json
+++ b/.vscode/c_cpp_properties.json
@@ -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\""
],
diff --git a/.vscode/preinclude.h b/.vscode/preinclude.h
index b1940aa..5f59e59 100644
--- a/.vscode/preinclude.h
+++ b/.vscode/preinclude.h
@@ -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"
diff --git a/.vscode/settings.json b/.vscode/settings.json
index 2d09fa1..f1b2296 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -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"
]
}
\ No newline at end of file
diff --git a/Makefile b/Makefile
index 1d763ec..2fb1332 100644
--- a/Makefile
+++ b/Makefile
@@ -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 $<)
diff --git a/arch/aarch64/include/.gitkeep b/arch/aarch64/include/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/arch/amd64/include/.gitkeep b/arch/amd64/include/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/arch/amd64/linker.ld b/arch/amd64/linker.ld
index 14cdd2c..006ca57 100644
--- a/arch/amd64/linker.ld
+++ b/arch/amd64/linker.ld
@@ -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));
diff --git a/arch/amd64/memory/vmm.cpp b/arch/amd64/memory/vmm.cpp
index f08a8d0..61086d6 100644
--- a/arch/amd64/memory/vmm.cpp
+++ b/arch/amd64/memory/vmm.cpp
@@ -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;
}
diff --git a/arch/i386/include/.gitkeep b/arch/i386/include/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/arch/i386/linker.ld b/arch/i386/linker.ld
index b4ed457..6455183 100644
--- a/arch/i386/linker.ld
+++ b/arch/i386/linker.ld
@@ -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));
diff --git a/core/console.cpp b/core/console.cpp
new file mode 100644
index 0000000..7294ae2
--- /dev/null
+++ b/core/console.cpp
@@ -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 .
+*/
+
+#include
+
+#include
+#include
+#include
+#include
+
+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()
+ {
+ }
+}
diff --git a/core/driver/api.cpp b/core/driver/api.cpp
index 71b475e..7f2c6cb 100644
--- a/core/driver/api.cpp
+++ b/core/driver/api.cpp
@@ -16,14 +16,16 @@
*/
#include
+#include
+#include
+#include
#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);
+static_assert(std::is_same_v);
diff --git a/core/driver/devfile/master.cpp b/core/driver/devfile/master.cpp
deleted file mode 100644
index 9c3b504..0000000
--- a/core/driver/devfile/master.cpp
+++ /dev/null
@@ -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 .
-*/
-
-#include
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#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 *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();
-
- 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 *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();
- }
-}
diff --git a/core/driver/devfile/slave.cpp b/core/driver/devfile/slave.cpp
deleted file mode 100644
index f1e79db..0000000
--- a/core/driver/devfile/slave.cpp
+++ /dev/null
@@ -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 .
-*/
-
-#include
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#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()
- {
- }
-}
diff --git a/core/driver/driver.cpp b/core/driver/driver.cpp
index 9c4e8ef..3db8f65 100644
--- a/core/driver/driver.cpp
+++ b/core/driver/driver.cpp
@@ -17,6 +17,7 @@
#include
+#include
#include
#include
#include
@@ -26,12 +27,64 @@
#include
#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};
+
+ 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 SymTab = Execute::ELFGetDynamicTag_x86_64(fd, DT_SYMTAB);
- std::vector StrTab = Execute::ELFGetDynamicTag_x86_64(fd, DT_STRTAB);
+ std::vector SymTab = Execute::ELFGetDynamicTag_x86_64(rDrv, DT_SYMTAB);
+ std::vector 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 SymTab = Execute::ELFGetDynamicTag_x86_64(fd, DT_SYMTAB);
- std::vector StrTab = Execute::ELFGetDynamicTag_x86_64(fd, DT_STRTAB);
+ std::vector SymTab = Execute::ELFGetDynamicTag_x86_64(rDrv, DT_SYMTAB);
+ std::vector 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};
-
- 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;
}
}
diff --git a/core/driver/scancode.cpp b/core/driver/scancode.cpp
index 5cfd730..4728fea 100644
--- a/core/driver/scancode.cpp
+++ b/core/driver/scancode.cpp
@@ -15,10 +15,9 @@
along with Fennix Kernel. If not, see .
*/
+#include
#include
-#include "../../driver.h"
-
static char ScanCodeConversionTableLower[] = {
[KEY_1] = '1',
[KEY_2] = '2',
diff --git a/core/interrupts_manager.cpp b/core/interrupts_manager.cpp
index eb12604..1a973c0 100644
--- a/core/interrupts_manager.cpp
+++ b/core/interrupts_manager.cpp
@@ -345,15 +345,15 @@ namespace Interrupts
#ifdef DEBUG
foreach (auto ev in RegisteredEvents)
{
- void *func = ev.IsHandler
- ? ev.Data
- : (void *)ev.Callback;
+ void *fct = ev.IsHandler
+ ? ev.Data
+ : (void *)ev.Callback;
const char *symbol = ev.IsHandler
? "class"
- : KernelSymbolTable->GetSymbol((uintptr_t)func);
+ : KernelSymbolTable->GetSymbol((uintptr_t)fct);
debug("Event IRQ%d [%#lx %s] has priority %ld",
- ev.IRQ, func, symbol, ev.Priority);
+ ev.IRQ, fct, symbol, ev.Priority);
}
#endif
}
diff --git a/core/memory/heap_allocators/rpmalloc/rpmalloc.c b/core/memory/heap_allocators/rpmalloc/rpmalloc.c
index 68bc2a0..11e6b0f 100644
--- a/core/memory/heap_allocators/rpmalloc/rpmalloc.c
+++ b/core/memory/heap_allocators/rpmalloc/rpmalloc.c
@@ -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); }
diff --git a/core/memory/heap_allocators/rpmalloc/rpmalloc_compat.cpp b/core/memory/heap_allocators/rpmalloc/rpmalloc_compat.cpp
index c366f51..58bd648 100644
--- a/core/memory/heap_allocators/rpmalloc/rpmalloc_compat.cpp
+++ b/core/memory/heap_allocators/rpmalloc/rpmalloc_compat.cpp
@@ -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;
}
diff --git a/core/memory/memory.cpp b/core/memory/memory.cpp
index 7a69f5c..db2b470 100644
--- a/core/memory/memory.cpp
+++ b/core/memory/memory.cpp
@@ -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);
-}
diff --git a/core/memory/va.cpp b/core/memory/va.cpp
index f0325b6..3e6e935 100644
--- a/core/memory/va.cpp
+++ b/core/memory/va.cpp
@@ -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()
diff --git a/core/memory/vma.cpp b/core/memory/vma.cpp
index fbae18f..acb72e5 100644
--- a/core/memory/vma.cpp
+++ b/core/memory/vma.cpp
@@ -36,9 +36,9 @@ namespace Memory
void *VirtualMemoryArea::RequestPages(size_t Count, bool User, bool Protect)
{
- function("%lld, %s, %s", Count,
- User ? "true" : "false",
- Protect ? "true" : "false");
+ func("%lld, %s, %s", Count,
+ User ? "true" : "false",
+ Protect ? "true" : "false");
void *Address = KernelAllocator.RequestPages(Count);
memset(Address, 0, Count * PAGE_SIZE);
@@ -61,7 +61,7 @@ namespace Memory
void VirtualMemoryArea::FreePages(void *Address, size_t Count)
{
- function("%#lx, %lld", Address, Count);
+ func("%#lx, %lld", Address, Count);
SmartLock(MgrLock);
forItr(itr, AllocatedPagesList)
@@ -104,7 +104,7 @@ namespace Memory
void VirtualMemoryArea::DetachAddress(void *Address)
{
- function("%#lx", Address);
+ func("%#lx", Address);
SmartLock(MgrLock);
forItr(itr, AllocatedPagesList)
@@ -128,12 +128,12 @@ namespace Memory
bool Read, bool Write, bool Exec,
bool Fixed, bool Shared)
{
- function("%#lx, %lld, %s, %s, %s, %s, %s", Address, Length,
- Read ? "true" : "false",
- Write ? "true" : "false",
- Exec ? "true" : "false",
- Fixed ? "true" : "false",
- Shared ? "true" : "false");
+ func("%#lx, %lld, %s, %s, %s, %s, %s", Address, Length,
+ Read ? "true" : "false",
+ Write ? "true" : "false",
+ Exec ? "true" : "false",
+ Fixed ? "true" : "false",
+ Shared ? "true" : "false");
Virtual vmm(this->Table);
@@ -191,7 +191,7 @@ namespace Memory
bool VirtualMemoryArea::HandleCoW(uintptr_t PFA)
{
- function("%#lx", PFA);
+ func("%#lx", PFA);
Virtual vmm(this->Table);
PageTableEntry *pte = vmm.GetPTE((void *)PFA);
@@ -269,7 +269,7 @@ namespace Memory
void VirtualMemoryArea::Fork(VirtualMemoryArea *Parent)
{
- function("%#lx", Parent);
+ func("%#lx", Parent);
assert(Parent);
debug("parent apl:%d sr:%d [P:%#lx C:%#lx]",
diff --git a/core/panic/diag.cpp b/core/panic/diag.cpp
index 3bacd89..cf5c7e8 100644
--- a/core/panic/diag.cpp
+++ b/core/panic/diag.cpp
@@ -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;
}
diff --git a/core/panic/ui.cpp b/core/panic/ui.cpp
index 94fe1ef..f9380b7 100644
--- a/core/panic/ui.cpp
+++ b/core/panic/ui.cpp
@@ -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 Plist = TaskManager->GetProcessList();
+ std::vector 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 */
diff --git a/core/symbols.cpp b/core/symbols.cpp
index fc4b348..8f25a51 100644
--- a/core/symbols.cpp
+++ b/core/symbols.cpp
@@ -40,15 +40,11 @@ namespace SymbolResolver
return Result.FunctionName;
}
- std::vector 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 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;
}
}
diff --git a/exec/binary_parse.cpp b/exec/binary_parse.cpp
index 1fccc49..cf61535 100644
--- a/exec/binary_parse.cpp
+++ b/exec/binary_parse.cpp
@@ -18,63 +18,65 @@
#include
#include
+#include
+#include
#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);
+ }
}
diff --git a/exec/elf/elf_loader.cpp b/exec/elf/elf_loader.cpp
index 4eff8f1..8c60315 100644
--- a/exec/elf/elf_loader.cpp
+++ b/exec/elf/elf_loader.cpp
@@ -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 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 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 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()
diff --git a/exec/elf/elf_parse.cpp b/exec/elf/elf_parse.cpp
index d7e8698..64e8a24 100644
--- a/exec/elf/elf_parse.cpp
+++ b/exec/elf/elf_parse.cpp
@@ -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 {};
}
diff --git a/exec/elf/parse/elf_get_dynamic_tag.cpp b/exec/elf/parse/elf_get_dynamic_tag.cpp
index 0f46e40..f66a424 100644
--- a/exec/elf/parse/elf_get_dynamic_tag.cpp
+++ b/exec/elf/parse/elf_get_dynamic_tag.cpp
@@ -21,16 +21,14 @@
namespace Execute
{
- std::vector ELFGetDynamicTag_x86_64(vfs::RefNode *fd,
+ std::vector ELFGetDynamicTag_x86_64(FileNode *fd,
DynamicArrayTags Tag)
{
#if defined(a64) || defined(aa64)
- off_t OldOffset = fd->seek(0, SEEK_CUR);
std::vector 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 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 {};
diff --git a/exec/elf/parse/elf_get_sections.cpp b/exec/elf/parse/elf_get_sections.cpp
index 86e8c2f..e078988 100644
--- a/exec/elf/parse/elf_get_sections.cpp
+++ b/exec/elf/parse/elf_get_sections.cpp
@@ -21,24 +21,20 @@
namespace Execute
{
- std::vector ELFGetSections_x86_64(vfs::RefNode *fd,
+ std::vector ELFGetSections_x86_64(FileNode *fd,
const char *SectionName)
{
#if defined(a64) || defined(aa64)
- off_t OldOffset = fd->seek(0, SEEK_CUR);
std::vector 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;
diff --git a/exec/elf/parse/elf_get_symbol_type.cpp b/exec/elf/parse/elf_get_symbol_type.cpp
index d6446b3..4adeac1 100644
--- a/exec/elf/parse/elf_get_symbol_type.cpp
+++ b/exec/elf/parse/elf_get_symbol_type.cpp
@@ -21,31 +21,28 @@
namespace Execute
{
- std::vector ELFGetSymbolType_x86_64(vfs::RefNode *fd,
+ std::vector ELFGetSymbolType_x86_64(FileNode *fd,
SegmentTypes Tag)
{
#if defined(a64) || defined(aa64)
- off_t OldOffset = fd->seek(0, SEEK_CUR);
std::vector 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 {};
diff --git a/exec/spawn.cpp b/exec/spawn.cpp
index 3d548a3..7885f25 100644
--- a/exec/spawn.cpp
+++ b/exec/spawn.cpp
@@ -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
- 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;
}
}
diff --git a/syscalls/native/lseek.cpp b/include/cbuf.hpp
similarity index 57%
rename from syscalls/native/lseek.cpp
rename to include/cbuf.hpp
index 9380788..c81d459 100644
--- a/syscalls/native/lseek.cpp
+++ b/include/cbuf.hpp
@@ -15,25 +15,31 @@
along with Fennix Kernel. If not, see .
*/
-#include
+#ifndef __FENNIX_KERNEL_CIRCULAR_BUFFER_H__
+#define __FENNIX_KERNEL_CIRCULAR_BUFFER_H__
-#include
+#include
#include
-#include
-#include
-#include
-#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__
diff --git a/include/convert.h b/include/convert.h
index 5f3cf0f..b78891c 100644
--- a/include/convert.h
+++ b/include/convert.h
@@ -17,6 +17,7 @@
#pragma once
#include
+#include
#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);
diff --git a/include/cwalk.h b/include/cwalk.h
index 463db64..18d6c23 100644
--- a/include/cwalk.h
+++ b/include/cwalk.h
@@ -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
+#include
+#include
#if defined(_WIN32) || defined(__CYGWIN__)
#define CWK_EXPORT __declspec(dllexport)
@@ -344,9 +345,10 @@ CWK_PUBLIC size_t cwk_path_change_extension(const char *path,
* This function creates a normalized version of the path within the specified
* buffer. This function will not write out more than the specified buffer can
* contain. However, the generated string is always null-terminated - even if
- * not the whole path is written out. The function returns the total number of
- * characters the complete buffer would have, even if it was not written out
- * completely. The path may be the same memory address as the buffer.
+ * not the whole path is written out. The returned value is the amount of
+ * characters which the resulting path would take if it was not truncated
+ * (excluding the null-terminating character). The path may be the same memory
+ * address as the buffer.
*
* The following will be true for the normalized path:
* 1) "../" will be resolved.
@@ -518,4 +520,4 @@ CWK_PUBLIC enum cwk_path_style cwk_path_get_style(void);
} // extern "C"
#endif
-#endif
\ No newline at end of file
+#endif
diff --git a/include/debug.h b/include/debug.h
index 4d6ce79..3db02ad 100644
--- a/include/debug.h
+++ b/include/debug.h
@@ -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__)
diff --git a/include/display.hpp b/include/display.hpp
index 5a93fae..34ea83e 100644
--- a/include/display.hpp
+++ b/include/display.hpp
@@ -24,6 +24,7 @@
#include
#include
#include
+#include
extern uintptr_t _binary_files_tamsyn_font_1_11_Tamsyn10x20b_psf_end;
extern uintptr_t _binary_files_tamsyn_font_1_11_Tamsyn10x20b_psf_size;
diff --git a/include/driver.hpp b/include/driver.hpp
index b5bdc0c..f6db9ee 100644
--- a/include/driver.hpp
+++ b/include/driver.hpp
@@ -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 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 *Slaves;
- std::unordered_map SlavesMap;
-
- std::list RawKeyQueue;
- std::list 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 *InterruptHandlers;
char Name[32] = {'\0'};
@@ -172,28 +67,18 @@ namespace Driver
private:
NewLock(ModuleInitLock);
std::unordered_map 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 &
GetDrivers() { return Drivers; }
+ void PreloadDrivers();
void LoadAllDrivers();
void UnloadAllDrivers();
void Panic();
diff --git a/include/exec.hpp b/include/exec.hpp
index a78c340..30a0720 100644
--- a/include/exec.hpp
+++ b/include/exec.hpp
@@ -22,7 +22,6 @@
#include
#include
-#include
#include
#include
#include
@@ -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 ELFGetSymbolType_x86_64(vfs::RefNode *fd, SegmentTypes Tag);
- std::vector ELFGetSymbolType_x86_32(vfs::RefNode *fd, SegmentTypes Tag);
+ std::vector ELFGetSymbolType_x86_64(FileNode *fd, SegmentTypes Tag);
+ std::vector ELFGetSymbolType_x86_32(FileNode *fd, SegmentTypes Tag);
- std::vector ELFGetSections_x86_64(vfs::RefNode *fd, const char *SectionName);
- std::vector ELFGetSections_x86_32(vfs::RefNode *fd, const char *SectionName);
+ std::vector ELFGetSections_x86_64(FileNode *fd, std::string SectionName);
+ std::vector ELFGetSections_x86_32(FileNode *fd, std::string SectionName);
- std::vector ELFGetDynamicTag_x86_64(vfs::RefNode *fd, DynamicArrayTags Tag);
- std::vector ELFGetDynamicTag_x86_32(vfs::RefNode *fd, DynamicArrayTags Tag);
+ std::vector ELFGetDynamicTag_x86_64(FileNode *fd, DynamicArrayTags Tag);
+ std::vector ELFGetDynamicTag_x86_32(FileNode *fd, DynamicArrayTags Tag);
}
#endif // !__FENNIX_KERNEL_FILE_EXECUTE_H__
diff --git a/include/filesystem.hpp b/include/filesystem.hpp
index a5f093b..c718dbf 100644
--- a/include/filesystem.hpp
+++ b/include/filesystem.hpp
@@ -20,309 +20,136 @@
#include
-#include
+#include
+#include
#include
#include
-#include
#include
#include
+#include
-#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 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 Children;
-
- std::vector 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 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 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 FileDescriptors;
- std::vector 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 &GetFileDescriptors() { return FileDescriptors; }
- std::vector &GetFileDescriptorsDuplicates() { return FildesDuplicates; }
- RefNode *GetRefNode(int FileDescriptor);
+ std::unordered_map 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;
};
}
diff --git a/include/filesystem/fat.hpp b/include/filesystem/fat.hpp
deleted file mode 100644
index 5c58054..0000000
--- a/include/filesystem/fat.hpp
+++ /dev/null
@@ -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 .
-*/
-
-#ifndef __FENNIX_KERNEL_FILESYSTEM_FAT_H__
-#define __FENNIX_KERNEL_FILESYSTEM_FAT_H__
-
-#include
-
-#include
-
-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__
diff --git a/include/filesystem/ioctl.hpp b/include/filesystem/ioctl.hpp
index ee5ae64..8c23231 100644
--- a/include/filesystem/ioctl.hpp
+++ b/include/filesystem/ioctl.hpp
@@ -20,7 +20,7 @@
#include
#include
-#include
+#include
#define _IOC_NRBITS 8
#define _IOC_TYPEBITS 8
diff --git a/include/filesystem/mounts.hpp b/include/filesystem/mounts.hpp
index feb2c8f..793a451 100644
--- a/include/filesystem/mounts.hpp
+++ b/include/filesystem/mounts.hpp
@@ -20,184 +20,53 @@
#include
-#include
#include
#include
-#include
+#include
#include
#include
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 ptysList;
+ std::unordered_map 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();
diff --git a/include/filesystem/ustar.hpp b/include/filesystem/ustar.hpp
index f87e7e7..58ac8cb 100644
--- a/include/filesystem/ustar.hpp
+++ b/include/filesystem/ustar.hpp
@@ -18,38 +18,40 @@
#ifndef __FENNIX_KERNEL_FILESYSTEM_USTAR_H__
#define __FENNIX_KERNEL_FILESYSTEM_USTAR_H__
-#include
-
#include
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 Children;
+ bool Deleted;
+ int Checksum;
+ };
+
private:
+ std::unordered_map 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__
diff --git a/driver.h b/include/interface/driver.h
similarity index 78%
rename from driver.h
rename to include/interface/driver.h
index ad5c26d..0644b21 100644
--- a/driver.h
+++ b/include/interface/driver.h
@@ -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);
diff --git a/include/interface/errno.h b/include/interface/errno.h
new file mode 100644
index 0000000..38aea8c
--- /dev/null
+++ b/include/interface/errno.h
@@ -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 .
+*/
+
+#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, ).
+ */
+ 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- character and ends
+ * with one or more trailing 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
+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__
diff --git a/include/interface/fs.h b/include/interface/fs.h
new file mode 100644
index 0000000..a60f2a6
--- /dev/null
+++ b/include/interface/fs.h
@@ -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 .
+*/
+
+#ifndef __FENNIX_API_FILESYSTEM_H__
+#define __FENNIX_API_FILESYSTEM_H__
+
+#ifdef __kernel__
+#include
+#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__
diff --git a/include/interface/syscalls.h b/include/interface/syscalls.h
new file mode 100644
index 0000000..f5936f7
--- /dev/null
+++ b/include/interface/syscalls.h
@@ -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 .
+*/
+
+#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__
diff --git a/include/kcon.hpp b/include/kcon.hpp
new file mode 100644
index 0000000..fd0df5e
--- /dev/null
+++ b/include/kcon.hpp
@@ -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 .
+*/
+
+#ifndef __FENNIX_KERNEL_KERNEL_CONSOLE_H__
+#define __FENNIX_KERNEL_KERNEL_CONSOLE_H__
+
+#include
+
+namespace KernelConsole
+{
+ void EarlyInit();
+ void LateInit();
+}
+
+#endif // !__FENNIX_KERNEL_KERNEL_CONSOLE_H__
diff --git a/include_std/cxxabi.h b/include/kexcept/cxxabi.h
similarity index 55%
rename from include_std/cxxabi.h
rename to include/kexcept/cxxabi.h
index 8e46836..f9b0955 100644
--- a/include_std/cxxabi.h
+++ b/include/kexcept/cxxabi.h
@@ -19,7 +19,7 @@
#define __FENNIX_KERNEL_CXXABI_H__
#include
-#include
+#include
#include
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
+ {
+ __cxa_exception *caughtExceptions;
+ unsigned int uncaughtExceptions;
+ };
+
+ enum ExceptionState
+ {
+ ES_None,
+ ES_Caught,
+ ES_Rethrown
+ };
}
-struct __cxa_eh_globals
+struct ExceptionInfo
{
- __cxxabiv1::__cxa_exception *caughtExceptions;
- unsigned int uncaughtExceptions;
-#ifdef __ARM_EABI_UNWINDER__
- __cxxabiv1::__cxa_exception *propagatingExceptions;
-#endif
+ 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__
diff --git a/include_std/unwind.h b/include/kexcept/unwind.h
similarity index 81%
rename from include_std/unwind.h
rename to include/kexcept/unwind.h
index 8c44540..f562a1f 100644
--- a/include_std/unwind.h
+++ b/include/kexcept/unwind.h
@@ -20,7 +20,7 @@
#include
-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__
diff --git a/include/lock.hpp b/include/lock.hpp
index a60be96..8d9ebb3 100644
--- a/include/lock.hpp
+++ b/include/lock.hpp
@@ -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
{
diff --git a/include/macho.h b/include/macho.h
new file mode 100644
index 0000000..ab87732
--- /dev/null
+++ b/include/macho.h
@@ -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 .
+*/
+
+#ifndef __FENNIX_KERNEL_MACH_O_H__
+#define __FENNIX_KERNEL_MACH_O_H__
+
+#include
+
+#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__
diff --git a/include/memory.hpp b/include/memory.hpp
index 162237c..d37884e 100644
--- a/include/memory.hpp
+++ b/include/memory.hpp
@@ -23,9 +23,9 @@
#include
#include
#include
-#include
-#include
#include
+#include
+#include
#endif // __cplusplus
#include
@@ -53,7 +53,7 @@ namespace Memory
/**
* @warning Not working as expected.
- *
+ *
* FIXME: This allocator is not working as expected.
*/
rpmalloc_,
@@ -73,24 +73,20 @@ namespace Memory
void InitializeMemoryManagement();
void CreatePageTable(Memory::PageTable *pt);
-void *operator new(std::size_t Size);
-void *operator new[](std::size_t Size);
-void *operator new(std::size_t Size, std::align_val_t Alignment);
-void operator delete(void *Pointer);
-void operator delete[](void *Pointer);
-void operator delete(void *Pointer, long unsigned int Size);
-void operator delete[](void *Pointer, long unsigned int Size);
-
extern Memory::Physical KernelAllocator;
extern Memory::PageTable *KernelPageTable;
#endif // __cplusplus
+#ifndef __FENNIX_KERNEL_STDLIB_H__
+
EXTERNC void *malloc(size_t Size);
EXTERNC void *calloc(size_t n, size_t Size);
EXTERNC void *realloc(void *Address, size_t Size);
EXTERNC void free(void *Address);
+#endif // !__FENNIX_KERNEL_STDLIB_H__
+
#define kmalloc(Size) malloc(Size)
#define kcalloc(n, Size) calloc(n, Size)
#define krealloc(Address, Size) realloc(Address, Size)
diff --git a/include/memory/brk.hpp b/include/memory/brk.hpp
index 857ad9c..c5fea97 100644
--- a/include/memory/brk.hpp
+++ b/include/memory/brk.hpp
@@ -44,7 +44,7 @@ namespace Memory
void InitBrk(uintptr_t Address)
{
- function("%#lx", Address);
+ func("%#lx", Address);
HeapStart = Address;
Break = Address;
}
diff --git a/include/net/ipv4.hpp b/include/net/ipv4.hpp
index 5ac2cd6..b7dbb17 100644
--- a/include/net/ipv4.hpp
+++ b/include/net/ipv4.hpp
@@ -128,7 +128,7 @@ namespace NetworkIPv4
UNUSED(DestinationIP);
UNUSED(Data);
UNUSED(Length);
- warn("Not implemented.");
+ warn("Not implemented");
return false;
}
};
diff --git a/include/net/udp.hpp b/include/net/udp.hpp
index 25dc6a9..798565b 100644
--- a/include/net/udp.hpp
+++ b/include/net/udp.hpp
@@ -53,7 +53,7 @@ namespace NetworkUDP
UNUSED(Socket);
UNUSED(Data);
UNUSED(Length);
- warn("Not implemented.");
+ warn("Not implemented");
}
};
diff --git a/include/scheduler.hpp b/include/scheduler.hpp
index 4c83c83..bd8640f 100644
--- a/include/scheduler.hpp
+++ b/include/scheduler.hpp
@@ -58,12 +58,12 @@ namespace Tasking::Scheduler
assert(!"GetProcessByID not implemented");
}
- virtual TCB *GetThreadByID(TID ID, PCB* Parent)
+ virtual TCB *GetThreadByID(TID ID, PCB *Parent)
{
assert(!"GetThreadByID not implemented");
}
- virtual std::list &GetProcessList()
+ virtual std::vector &GetProcessList()
{
assert(!"GetProcessList not implemented");
}
@@ -111,7 +111,7 @@ namespace Tasking::Scheduler
NewLock(SchedulerLock);
public:
- std::list ProcessList;
+ std::vector ProcessList;
PCB *IdleProcess = nullptr;
TCB *IdleThread = nullptr;
@@ -119,8 +119,8 @@ namespace Tasking::Scheduler
bool RemoveThread(TCB *tcb) final;
bool RemoveProcess(PCB *pcb) final;
PCB *GetProcessByID(TID ID) final;
- TCB *GetThreadByID(TID ID, PCB* Parent) final;
- std::list &GetProcessList() final;
+ TCB *GetThreadByID(TID ID, PCB *Parent) final;
+ std::vector &GetProcessList() final;
void StartIdleProcess() final;
void StartScheduler() final;
void Yield() final;
diff --git a/include/smp.hpp b/include/smp.hpp
index 20af0b6..96b50c6 100644
--- a/include/smp.hpp
+++ b/include/smp.hpp
@@ -19,7 +19,7 @@
#define __FENNIX_KERNEL_SMP_H__
#include
-#include
+#include
#include
#include
@@ -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 CurrentProcess;
- /** @brief Current running thread */
+ /** Current running thread */
std::atomic 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);
diff --git a/storage/devices/tty/ptym.cpp b/include/static_vector
similarity index 53%
rename from storage/devices/tty/ptym.cpp
rename to include/static_vector
index 45f7a25..7b4f1da 100644
--- a/storage/devices/tty/ptym.cpp
+++ b/include/static_vector
@@ -15,36 +15,30 @@
along with Fennix Kernel. If not, see .
*/
-#include
-#include
-#include
-#include
+#include
+#include
+#include
-#include "../../../kernel.h"
-
-namespace vfs
+template
+class static_vector
{
- size_t MasterPTY::read(uint8_t *Buffer,
- size_t Size,
- off_t Offset)
+private:
+ T m_data[N];
+ std::size_t m_size;
+
+public:
+ constexpr static_vector() : m_size(0) {}
+
+ constexpr static_vector(std::initializer_list list) : m_size(0)
{
- fixme("%.*s", Size, Buffer);
- return -ENOSYS;
+ for (const T &value : list)
+ {
+ assert(m_size < N);
+ m_data[m_size++] = value;
+ }
}
- size_t MasterPTY::write(uint8_t *Buffer,
- size_t Size,
- off_t Offset)
- {
- fixme("%.*s", Size, Buffer);
- return -ENOSYS;
- }
-
- MasterPTY::MasterPTY()
- {
- }
-
- MasterPTY::~MasterPTY()
- {
- }
-}
+ 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; }
+};
diff --git a/include/syscall/linux/defs.hpp b/include/syscall/linux/defs.hpp
index fe32a48..722852f 100644
--- a/include/syscall/linux/defs.hpp
+++ b/include/syscall/linux/defs.hpp
@@ -20,174 +20,178 @@
#include
-#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
diff --git a/include/syscall/linux/errno.h b/include/syscall/linux/errno.h
new file mode 100644
index 0000000..c78bf8d
--- /dev/null
+++ b/include/syscall/linux/errno.h
@@ -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 .
+*/
+
+#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__
diff --git a/include/task.hpp b/include/task.hpp
index 8294329..a329506 100644
--- a/include/task.hpp
+++ b/include/task.hpp
@@ -26,12 +26,13 @@
#include
#include
#include
+#include
#include
#include
#include
#include
+#include
#include
-#include
#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 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 Threads;
- std::list Children;
+ std::vector Threads;
+ std::vector 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 GetProcessList();
+ std::vector GetProcessList();
void Panic();
bool IsPanic();
diff --git a/include/types.h b/include/types.h
index 126945a..2be25af 100644
--- a/include/types.h
+++ b/include/types.h
@@ -18,6 +18,8 @@
#ifndef __FENNIX_KERNEL_TYPES_H__
#define __FENNIX_KERNEL_TYPES_H__
+#include
+
#ifdef __cplusplus
#define EXTERNC extern "C"
#define START_EXTERNC \
@@ -35,15 +37,11 @@
#define NULL 0
#else // __cplusplus
#define NULL ((void *)0)
-#define bool _Bool
#endif // __cplusplus
#define asm __asm__
#define asmv __asm__ volatile
-#define true 1
-#define false 0
-
#define inf_loop while (1)
#define ilp inf_loop; /* Used for debugging */
@@ -64,11 +62,6 @@
#define UNUSED(x) (void)(x)
#define CONCAT(x, y) x##y
-#ifndef __cplusplus /* This conflicts with std */
-#define toupper(c) ((c)-0x20 * (((c) >= 'a') && ((c) <= 'z')))
-#define tolower(c) ((c) + 0x20 * (((c) >= 'A') && ((c) <= 'Z')))
-#endif
-
#ifndef __va_list__
typedef __builtin_va_list va_list;
#endif
@@ -77,8 +70,8 @@ typedef __builtin_va_list va_list;
#define va_end(v) __builtin_va_end(v)
#define va_arg(v, l) __builtin_va_arg(v, l)
-#define ALIGN_UP(x, align) ((__typeof__(x))(((uintptr_t)(x) + ((align)-1)) & (~((align)-1))))
-#define ALIGN_DOWN(x, align) ((__typeof__(x))((x) & (~((align)-1))))
+#define ALIGN_UP(x, align) ((__typeof__(x))(((uintptr_t)(x) + ((align) - 1)) & (~((align) - 1))))
+#define ALIGN_DOWN(x, align) ((__typeof__(x))((x) & (~((align) - 1))))
#define offsetof(type, member) __builtin_offsetof(type, member)
@@ -96,8 +89,8 @@ typedef __builtin_va_list va_list;
_a < _b ? _a : _b; \
})
-#define ROUND_UP(x, y) (((x) + (y)-1) & ~((y)-1))
-#define ROUND_DOWN(x, y) ((x) & ~((y)-1))
+#define ROUND_UP(x, y) (((x) + (y) - 1) & ~((y) - 1))
+#define ROUND_DOWN(x, y) ((x) & ~((y) - 1))
#define VPOKE(type, address) (*((volatile type *)(address)))
#define POKE(type, address) (*((type *)(address)))
@@ -399,21 +392,53 @@ typedef uint48_t uint_fast48_t;
(((x) & 0xff0000000000) >> 40)))
#define b64(x) __builtin_bswap64(x)
-/* https://gcc.gnu.org/onlinedocs/gcc-9.5.0/gnat_ugn/Optimization-Levels.html */
+/* https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html */
-/** @brief No optimization (the default); generates unoptimized code but has the fastest compilation time. */
+/** No optimization (the default); generates
+ * unoptimized code but has the fastest compilation time.
+ */
#define O0 __attribute__((optimize("O0")))
-/** @brief Moderate optimization; optimizes reasonably well but does not degrade compilation time significantly. */
+
+/** Moderate optimization;
+ * optimizes reasonably well but does not degrade
+ * compilation time significantly. */
#define O1 __attribute__((optimize("O1")))
-/** @brief Full optimization; generates highly optimized code and has the slowest compilation time. */
+
+/** Full optimization; generates highly
+ * optimized code and has the slowest compilation time.
+ */
#define O2 __attribute__((optimize("O2")))
-/** @brief Full optimization as in -O2; also uses more aggressive automatic inlining of subprograms within a unit (Inlining of Subprograms) and attempts to vectorize loops. */
+
+/** Full optimization as in -O2;
+ * also uses more aggressive automatic inlining of
+ * subprograms within a unit (Inlining of Subprograms)
+ * and attempts to vectorize loops. */
#define O3 __attribute__((optimize("O3")))
-/** @brief Optimize space usage (code and data) of resulting program. */
+
+/** Optimize space usage (code and data)
+ * of resulting program.
+ */
#define Os __attribute__((optimize("Os")))
-/** @brief Disregard strict standards compliance. -Ofast enables all -O3 optimizations. It also enables optimizations that are not valid for all standard-compliant programs. */
+
+/** Disregard strict standards compliance.
+ * -Ofast enables all -O3 optimizations.
+ * It also enables optimizations that are not valid for
+ * all standard-compliant programs.
+ */
#define Ofast __attribute__((optimize("Ofast")))
+/** Optimize for size.
+ * -Oz enables all -Os optimizations that do not typically
+ * increase code size.
+ */
+#define Oz __attribute__((optimize("Oz")))
+
+/** Optimize for debugging.
+ * -Og enables optimizations that do not interfere with
+ * debugging.
+ */
+#define Og __attribute__((optimize("Og")))
+
#define __unused __attribute__((unused))
#define __packed __attribute__((packed))
#define __naked __attribute__((naked))
@@ -457,8 +482,6 @@ typedef uint48_t uint_fast48_t;
// sanitizer
#define __no_sanitize(x) __attribute__((no_sanitize(x)))
#define __no_sanitize_address __attribute__((no_sanitize_address))
-/** @brief The no_address_safety_analysis is a deprecated alias of the no_sanitize_address attribute, new code should use no_sanitize_address. */
-#define __no_address_safety_analysis __attribute__((no_address_safety_analysis))
#define __no_sanitize_thread __attribute__((no_sanitize_thread))
#define __no_sanitize_undefined __attribute__((no_sanitize_undefined))
#define __no_sanitize_coverage __attribute__((no_sanitize_coverage))
@@ -471,10 +494,7 @@ typedef uint48_t uint_fast48_t;
#define likely(x) __builtin_expect(!!(x), 1)
#define unlikely(x) __builtin_expect(!!(x), 0)
-#define PUBLIC __visibility("default")
-#define PRIVATE __visibility("hidden")
-
-#define NoSecurityAnalysis __no_stack_protector __no_sanitize_address __no_sanitize_undefined __no_address_safety_analysis __no_sanitize_thread
+#define NoSecurityAnalysis __no_stack_protector __no_sanitize_address __no_sanitize_undefined __no_sanitize_thread
#define nsa NoSecurityAnalysis
#define NIF __no_instrument_function
@@ -486,9 +506,16 @@ typedef uint48_t uint_fast48_t;
: "memory")
#define StackPush(stack, type, value) \
- *((type *)--stack) = value;
+ *((type *)--stack) = value
#define StackPop(stack, type) \
*((type *)stack++)
+#define ReturnLogError(ret, Format, ...) \
+ { \
+ trace(Format, ##__VA_ARGS__); \
+ return ret; \
+ } \
+ while (0)
+
#endif // !__FENNIX_KERNEL_TYPES_H__
diff --git a/include_std/algorithm b/include_std/algorithm
index d55c876..33830c1 100644
--- a/include_std/algorithm
+++ b/include_std/algorithm
@@ -42,12 +42,31 @@ namespace std
return d_last;
}
- template
- void swap(T &a, T &b)
+ template
+ 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
+ void swap(T &a, T &b) noexcept(std::is_nothrow_move_constructible::value && std::is_nothrow_move_assignable::value)
+ {
+ T temp = std::move(a);
+ a = std::move(b);
+ b = std::move(temp);
+ }
+
+ template
+ void swap(T2 (&a)[N], T2 (&b)[N]) noexcept(std::is_nothrow_swappable_v)
+ {
+ for (std::size_t i = 0; i < N; ++i)
+ std::swap(a[i], b[i]);
}
template
@@ -193,4 +212,116 @@ namespace std
}
return first;
}
+
+ template
+ constexpr bool equal(InputIt1 first1, InputIt1 last1, InputIt2 first2)
+ {
+ while (first1 != last1)
+ {
+ if (!(*first1 == *first2))
+ return false;
+
+ ++first1;
+ ++first2;
+ }
+ return true;
+ }
+
+ template
+ bool equal(ExecutionPolicy &&policy, ForwardIt1 first1, ForwardIt1 last1, ForwardIt2 first2)
+ {
+ while (first1 != last1)
+ {
+ if (!(*first1 == *first2))
+ return false;
+
+ ++first1;
+ ++first2;
+ }
+ return true;
+ }
+
+ template
+ 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
+ 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
+ constexpr bool equal(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2)
+ {
+ while (first1 != last1)
+ {
+ if (!(*first1 == *first2))
+ return false;
+
+ ++first1;
+ ++first2;
+ }
+ return true;
+ }
+
+ template
+ 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
+ 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
+ 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;
+ }
}
diff --git a/storage/devices/root.cpp b/include_std/cctype
similarity index 73%
rename from storage/devices/root.cpp
rename to include_std/cctype
index 435acd7..254c21f 100644
--- a/storage/devices/root.cpp
+++ b/include_std/cctype
@@ -15,18 +15,23 @@
along with Fennix Kernel. If not, see .
*/
-#include
+#pragma once
-#include "../../kernel.h"
-
-namespace vfs
+namespace std
{
- vfsRoot::vfsRoot(const char *Name, Virtual *vfs_ctx)
- : Node(nullptr,
- Name,
- MOUNTPOINT)
+ inline int tolower(int ch)
{
- this->vFS = fs;
- vfs_ctx->GetRootNode()->Children.push_back(this);
+ if (ch >= 'A' && ch <= 'Z')
+ return ch + ('a' - 'A');
+ else
+ return ch;
+ }
+
+ inline int toupper(int ch)
+ {
+ if (ch >= 'a' && ch <= 'z')
+ return ch - ('a' - 'A');
+ else
+ return ch;
}
}
diff --git a/include_std/cmath b/include_std/cmath
index abde42e..29e243f 100644
--- a/include_std/cmath
+++ b/include_std/cmath
@@ -17,9 +17,12 @@
#pragma once
+#include
+#include
+
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
+ 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
+ constexpr bool isnan(Integer num)
+ {
+ return num != num;
+ }
+
+ template
+ constexpr double fabs(Integer num)
+ {
+ return num < 0 ? -num : num;
+ }
+
+ template
+ constexpr double remainder(Integer x, Integer y)
+ {
+ return x - (int)(x / y) * y;
+ }
+
+ template
+ constexpr double copysign(Integer mag, Integer sgn)
+ {
+ return (sgn < 0) ? -mag : mag;
+ }
+
+ template
+ constexpr bool signbit(Integer num)
+ {
+ return num < 0;
+ }
+
+ template
+ 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
+ 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
+ constexpr double trunc(Integer num)
+ {
+ if (std::isinf(num))
+ return num;
+
+ if (std::isnan(num))
+ return num;
+
+ return static_cast(num);
+ }
+
+ template
+ constexpr double exp(Integer num)
+ {
+ double result = 1.0;
+ double term = 1.0;
+
+ for (int i = 1; i <= 10; ++i)
+ {
+ term *= static_cast(num) / i;
+ result += term;
+ }
+
+ return result;
+ }
}
diff --git a/include/smart_ptr.hpp b/include_std/coroutine
similarity index 94%
rename from include/smart_ptr.hpp
rename to include_std/coroutine
index 8556c33..0118550 100644
--- a/include/smart_ptr.hpp
+++ b/include_std/coroutine
@@ -15,5 +15,7 @@
along with Fennix Kernel. If not, see .
*/
-#pragma once
-#include
+namespace std
+{
+ /* FIXME: Implement */
+}
diff --git a/include/filesystem/termios.hpp b/include_std/ctype.h
similarity index 52%
rename from include/filesystem/termios.hpp
rename to include_std/ctype.h
index 906a247..8c2775e 100644
--- a/include/filesystem/termios.hpp
+++ b/include_std/ctype.h
@@ -15,35 +15,37 @@
along with Fennix Kernel. If not, see .
*/
-#ifndef __FENNIX_KERNEL_TERMIOS_H__
-#define __FENNIX_KERNEL_TERMIOS_H__
+#ifndef __FENNIX_KERNEL_C_TYPE_H__
+#define __FENNIX_KERNEL_C_TYPE_H__
#include
-#include
-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__
diff --git a/include_std/dlfcn.h b/include_std/dlfcn.h
index 1114b46..b53b5f4 100644
--- a/include_std/dlfcn.h
+++ b/include_std/dlfcn.h
@@ -15,7 +15,17 @@
along with Fennix Kernel. If not, see .
*/
-#ifndef _DLFCN_H
-#define _DLFCN_H
+#ifndef __FENNIX_KERNEL_DLFCN_H__
+#define __FENNIX_KERNEL_DLFCN_H__
-#endif // !_DLFCN_H
+#include
+
+typedef struct
+{
+ const char *dli_fname;
+ void *dli_fbase;
+ const char *dli_sname;
+ void *dli_saddr;
+} Dl_info;
+
+#endif // !__FENNIX_KERNEL_DLFCN_H__
diff --git a/include_std/errno.h b/include_std/errno.h
index 6fb98d0..6395b84 100644
--- a/include_std/errno.h
+++ b/include_std/errno.h
@@ -15,407 +15,9 @@
along with Fennix Kernel. If not, see .
*/
-#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
-/** 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
-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__
diff --git a/include_std/exception b/include_std/exception
index f36b0a6..ae47209 100644
--- a/include_std/exception
+++ b/include_std/exception
@@ -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__
diff --git a/include_std/functional b/include_std/functional
index c88bfbf..3e89d66 100644
--- a/include_std/functional
+++ b/include_std/functional
@@ -17,9 +17,13 @@
#pragma once
+#include