mirror of
https://github.com/Fennix-Project/Kernel.git
synced 2025-05-25 22:14:37 +00:00
Refactor filesystem & stl code
This commit is contained in:
parent
77a291d08b
commit
6801475243
141
.vscode/c_boilerplates.code-snippets
vendored
141
.vscode/c_boilerplates.code-snippets
vendored
@ -42,18 +42,6 @@
|
||||
],
|
||||
"description": "Create kernel documentation brief."
|
||||
},
|
||||
"For Iteration": {
|
||||
"prefix": [
|
||||
"foritr",
|
||||
],
|
||||
"body": [
|
||||
"forItr(${1:itr}, ${2:container})",
|
||||
"{",
|
||||
"\t$0",
|
||||
"}"
|
||||
],
|
||||
"description": "Create for loop with iterator."
|
||||
},
|
||||
"License": {
|
||||
"prefix": [
|
||||
"license",
|
||||
@ -77,134 +65,5 @@
|
||||
"*/"
|
||||
],
|
||||
"description": "Create kernel license."
|
||||
},
|
||||
"Driver Code": {
|
||||
"prefix": [
|
||||
"driver",
|
||||
],
|
||||
"body": [
|
||||
"/*",
|
||||
"\tThis file is part of Fennix Kernel.",
|
||||
"",
|
||||
"\tFennix Kernel is free software: you can redistribute it and/or",
|
||||
"\tmodify it under the terms of the GNU General Public License as",
|
||||
"\tpublished by the Free Software Foundation, either version 3 of",
|
||||
"\tthe License, or (at your option) any later version.",
|
||||
"",
|
||||
"\tFennix Kernel is distributed in the hope that it will be useful,",
|
||||
"\tbut WITHOUT ANY WARRANTY; without even the implied warranty of",
|
||||
"\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the",
|
||||
"\tGNU General Public License for more details.",
|
||||
"",
|
||||
"\tYou should have received a copy of the GNU General Public License",
|
||||
"\talong with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.",
|
||||
"*/",
|
||||
"",
|
||||
"#include \"${1:driver}.hpp\"",
|
||||
"",
|
||||
"#include <debug.h>",
|
||||
"",
|
||||
"#include \"../../../kernel.h\"",
|
||||
"",
|
||||
"namespace Driver",
|
||||
"{",
|
||||
"\tint ${2:driver}::drvOpen(int Flags, mode_t Mode) { return 0; }",
|
||||
"",
|
||||
"\tint ${2:driver}::drvClose() { return 0; }",
|
||||
"",
|
||||
"\tsize_t ${2:driver}::drvRead(uint8_t *Buffer, size_t Size, off_t Offset) { return 0; }",
|
||||
"",
|
||||
"\tsize_t ${2:driver}::drvWrite(uint8_t *Buffer, size_t Size, off_t Offset) { return 0; }",
|
||||
"",
|
||||
"\tint ${2:driver}::drvIoctl(unsigned long Request, void *Argp) { return 0; }",
|
||||
"",
|
||||
"\tvoid ${2:driver}::OnInterruptReceived(CPU::TrapFrame *) {}",
|
||||
"",
|
||||
"\tvoid ${2:driver}::Panic() {}",
|
||||
"",
|
||||
"\t${2:driver}::${2:driver}(PCI::PCIDevice dev)",
|
||||
"\t\t: Object(dev),",
|
||||
"\t\t Interrupts::Handler(dev)",
|
||||
"\t{",
|
||||
"\t}",
|
||||
"",
|
||||
"\t${2:driver}::${2:driver}(int irq)",
|
||||
"\t\t: Object(irq),",
|
||||
"\t\t Interrupts::Handler(irq)",
|
||||
"\t{",
|
||||
"\t}",
|
||||
"",
|
||||
"\t${2:driver}::${2:driver}()",
|
||||
"\t{",
|
||||
"\t}",
|
||||
"",
|
||||
"\t${2:driver}::~${2:driver}()",
|
||||
"\t{",
|
||||
"\t\tif (GetError() != 0)",
|
||||
"\t\t\treturn;",
|
||||
"\t}",
|
||||
"}",
|
||||
"",
|
||||
|
||||
],
|
||||
"description": "Kernel driver code template."
|
||||
},
|
||||
"Driver Header": {
|
||||
"prefix": [
|
||||
"driver",
|
||||
],
|
||||
"body": [
|
||||
"/*",
|
||||
"\tThis file is part of Fennix Kernel.",
|
||||
"",
|
||||
"\tFennix Kernel is free software: you can redistribute it and/or",
|
||||
"\tmodify it under the terms of the GNU General Public License as",
|
||||
"\tpublished by the Free Software Foundation, either version 3 of",
|
||||
"\tthe License, or (at your option) any later version.",
|
||||
"",
|
||||
"\tFennix Kernel is distributed in the hope that it will be useful,",
|
||||
"\tbut WITHOUT ANY WARRANTY; without even the implied warranty of",
|
||||
"\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the",
|
||||
"\tGNU General Public License for more details.",
|
||||
"",
|
||||
"\tYou should have received a copy of the GNU General Public License",
|
||||
"\talong with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.",
|
||||
"*/",
|
||||
"",
|
||||
"#pragma once",
|
||||
"#include <driver.hpp>",
|
||||
"",
|
||||
"namespace Driver",
|
||||
"{",
|
||||
"\tclass ${1:driver} : public Object, public Interrupts::Handler",
|
||||
"\t{",
|
||||
"\tprivate:",
|
||||
"\t\tvoid OnInterruptReceived(CPU::TrapFrame *Frame) final;",
|
||||
"\t\tvoid Panic(Driver::DriverContext *ctx) final;",
|
||||
"",
|
||||
"\tpublic:",
|
||||
"\t\tint drvOpen(int Flags, mode_t Mode);",
|
||||
"\t\tint drvClose();",
|
||||
"\t\tsize_t drvRead(uint8_t *Buffer, size_t Size, off_t Offset);",
|
||||
"\t\tsize_t drvWrite(uint8_t *Buffer, size_t Size, off_t Offset);",
|
||||
"\t\tint drvIoctl(unsigned long Request, void *Argp);",
|
||||
"",
|
||||
"\t\tconst char *drvName() final { return \"${2:MyDriver}\"; }",
|
||||
"\t\tconst char *drvDescription() final { return \"${3:MyDescription}\"; }",
|
||||
"\t\tconst char *drvVersion() final { return \"${4:0.0.0}\"; }",
|
||||
"\t\tconst char *drvAuthor() final { return \"${5:Author}\"; }",
|
||||
"\t\tconst char *drvLicense() final { return \"${6:License}\"; }",
|
||||
"\t\tDriverType drvType() final { return DriverType_${7:Generic}; }",
|
||||
"",
|
||||
"\t\t${1:driver}(PCI::PCIDevice dev);",
|
||||
"\t\t${1:driver}(int irq);",
|
||||
"\t\t${1:driver}();",
|
||||
"\t\t~${1:driver}();",
|
||||
"\t};",
|
||||
"}",
|
||||
"",
|
||||
|
||||
],
|
||||
"description": "Kernel driver header template."
|
||||
}
|
||||
}
|
33
.vscode/c_cpp_properties.json
vendored
33
.vscode/c_cpp_properties.json
vendored
@ -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\""
|
||||
],
|
||||
|
7
.vscode/preinclude.h
vendored
7
.vscode/preinclude.h
vendored
@ -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"
|
||||
|
8
.vscode/settings.json
vendored
8
.vscode/settings.json
vendored
@ -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"
|
||||
]
|
||||
}
|
20
Makefile
20
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 $<)
|
||||
|
0
arch/aarch64/include/.gitkeep
Normal file
0
arch/aarch64/include/.gitkeep
Normal file
0
arch/amd64/include/.gitkeep
Normal file
0
arch/amd64/include/.gitkeep
Normal file
@ -62,6 +62,16 @@ SECTIONS
|
||||
{
|
||||
*(.data .data.*)
|
||||
} :data
|
||||
|
||||
.eh_frame : AT(ADDR(.eh_frame) - KERNEL_VMA) ONLY_IF_RW
|
||||
{
|
||||
KEEP (*(.eh_frame .eh_frame.*))
|
||||
} :data
|
||||
|
||||
.gcc_except_table : AT(ADDR(.gcc_except_table) - KERNEL_VMA) ONLY_IF_RW
|
||||
{
|
||||
KEEP (*(.gcc_except_table .gcc_except_table.*))
|
||||
} :data
|
||||
_kernel_data_end = ALIGN(CONSTANT(MAXPAGESIZE));
|
||||
|
||||
_kernel_rodata_start = ALIGN(CONSTANT(MAXPAGESIZE));
|
||||
@ -85,6 +95,21 @@ SECTIONS
|
||||
KEEP(*(.fini_array .dtors))
|
||||
PROVIDE_HIDDEN (__fini_array_end = .);
|
||||
} :rodata
|
||||
|
||||
.eh_frame_hdr : AT(ADDR(.eh_frame_hdr) - KERNEL_VMA)
|
||||
{
|
||||
*(.eh_frame_hdr .eh_frame_hdr.*)
|
||||
} :rodata
|
||||
|
||||
.eh_frame : AT(ADDR(.eh_frame) - KERNEL_VMA) ONLY_IF_RO
|
||||
{
|
||||
KEEP (*(.eh_frame .eh_frame.*))
|
||||
} :rodata
|
||||
|
||||
.gcc_except_table : AT(ADDR(.gcc_except_table) - KERNEL_VMA) ONLY_IF_RO
|
||||
{
|
||||
KEEP (*(.gcc_except_table .gcc_except_table.*))
|
||||
} :rodata
|
||||
_kernel_rodata_end = ALIGN(CONSTANT(MAXPAGESIZE));
|
||||
|
||||
_kernel_bss_start = ALIGN(CONSTANT(MAXPAGESIZE));
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
0
arch/i386/include/.gitkeep
Normal file
0
arch/i386/include/.gitkeep
Normal file
@ -62,6 +62,16 @@ SECTIONS
|
||||
{
|
||||
*(.data .data.*)
|
||||
} :data
|
||||
|
||||
.eh_frame : AT(ADDR(.eh_frame) - KERNEL_VMA) ONLY_IF_RW
|
||||
{
|
||||
KEEP (*(.eh_frame .eh_frame.*))
|
||||
} :data
|
||||
|
||||
.gcc_except_table : AT(ADDR(.gcc_except_table) - KERNEL_VMA) ONLY_IF_RW
|
||||
{
|
||||
KEEP (*(.gcc_except_table .gcc_except_table.*))
|
||||
} :data
|
||||
_kernel_data_end = ALIGN(CONSTANT(MAXPAGESIZE));
|
||||
|
||||
_kernel_rodata_start = ALIGN(CONSTANT(MAXPAGESIZE));
|
||||
@ -85,6 +95,21 @@ SECTIONS
|
||||
KEEP(*(.fini_array .dtors))
|
||||
PROVIDE_HIDDEN (__fini_array_end = .);
|
||||
} :rodata
|
||||
|
||||
.eh_frame_hdr : AT(ADDR(.eh_frame_hdr) - KERNEL_VMA)
|
||||
{
|
||||
*(.eh_frame_hdr .eh_frame_hdr.*)
|
||||
} :rodata
|
||||
|
||||
.eh_frame : AT(ADDR(.eh_frame) - KERNEL_VMA) ONLY_IF_RO
|
||||
{
|
||||
KEEP (*(.eh_frame .eh_frame.*))
|
||||
} :rodata
|
||||
|
||||
.gcc_except_table : AT(ADDR(.gcc_except_table) - KERNEL_VMA) ONLY_IF_RO
|
||||
{
|
||||
KEEP (*(.gcc_except_table .gcc_except_table.*))
|
||||
} :rodata
|
||||
_kernel_rodata_end = ALIGN(CONSTANT(MAXPAGESIZE));
|
||||
|
||||
_kernel_bss_start = ALIGN(CONSTANT(MAXPAGESIZE));
|
||||
|
172
core/console.cpp
Normal file
172
core/console.cpp
Normal file
@ -0,0 +1,172 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <kcon.hpp>
|
||||
|
||||
#include <filesystem/ioctl.hpp>
|
||||
#include <memory.hpp>
|
||||
#include <stropts.h>
|
||||
#include <string.h>
|
||||
|
||||
namespace KernelConsole
|
||||
{
|
||||
termios term{};
|
||||
winsize termSize{};
|
||||
|
||||
ssize_t KConRead(struct Inode *Node, void *Buffer, size_t Size, off_t Offset)
|
||||
{
|
||||
fixme("Reading %d bytes... \"%.*s\"", Size, Size, (char *)Buffer);
|
||||
return Size;
|
||||
}
|
||||
|
||||
ssize_t KConWrite(struct Inode *Node, const void *Buffer, size_t Size, off_t Offset)
|
||||
{
|
||||
fixme("Writing %d bytes... \"%.*s\"", Size, Size, (char *)Buffer);
|
||||
return Size;
|
||||
}
|
||||
|
||||
int KConIoctl(struct Inode *Node, unsigned long Request, void *Argp)
|
||||
{
|
||||
switch (Request)
|
||||
{
|
||||
case TCGETS:
|
||||
{
|
||||
struct termios *t = (struct termios *)Argp;
|
||||
memcpy(t, &term, sizeof(struct termios));
|
||||
return 0;
|
||||
}
|
||||
case TCSETS:
|
||||
{
|
||||
debug("TCSETS not supported");
|
||||
return -EINVAL;
|
||||
|
||||
struct termios *t = (struct termios *)Argp;
|
||||
memcpy(&term, t, sizeof(struct termios));
|
||||
return 0;
|
||||
}
|
||||
case TIOCGPGRP:
|
||||
{
|
||||
*((pid_t *)Argp) = 0;
|
||||
return 0;
|
||||
}
|
||||
case TIOCSPGRP:
|
||||
{
|
||||
*((pid_t *)Argp) = 0;
|
||||
return 0;
|
||||
}
|
||||
case TIOCGWINSZ:
|
||||
{
|
||||
struct winsize *ws = (struct winsize *)Argp;
|
||||
memcpy(ws, &termSize, sizeof(struct winsize));
|
||||
return 0;
|
||||
}
|
||||
case TIOCSWINSZ:
|
||||
{
|
||||
debug("TIOCSWINSZ not supported");
|
||||
return -EINVAL;
|
||||
|
||||
struct winsize *ws = (struct winsize *)Argp;
|
||||
memcpy(&termSize, ws, sizeof(struct winsize));
|
||||
return 0;
|
||||
}
|
||||
case TCSETSW:
|
||||
case TCSETSF:
|
||||
case TCGETA:
|
||||
case TCSETA:
|
||||
case TCSETAW:
|
||||
case TCSETAF:
|
||||
case TCSBRK:
|
||||
case TCXONC:
|
||||
case TCFLSH:
|
||||
case TIOCEXCL:
|
||||
case TIOCNXCL:
|
||||
case TIOCSCTTY:
|
||||
case TIOCOUTQ:
|
||||
case TIOCSTI:
|
||||
case TIOCMGET:
|
||||
case TIOCMBIS:
|
||||
case TIOCMBIC:
|
||||
case TIOCMSET:
|
||||
{
|
||||
fixme("ioctl %#lx not implemented", Request);
|
||||
return -ENOSYS;
|
||||
}
|
||||
case TIOCGPTN:
|
||||
case 0xffffffff80045430: /* FIXME: ???? */
|
||||
{
|
||||
fixme("stub ioctl %#lx", Request);
|
||||
|
||||
int *n = (int *)Argp;
|
||||
*n = -1;
|
||||
break;
|
||||
}
|
||||
case TIOCSPTLCK:
|
||||
{
|
||||
fixme("stub ioctl %#lx", Request);
|
||||
|
||||
int *n = (int *)Argp;
|
||||
*n = 0;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
debug("Unknown ioctl %#lx", Request);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void EarlyInit()
|
||||
{
|
||||
/*
|
||||
- ICRNL - Map Carriage Return to New Line
|
||||
- IXON - Enable XON/XOFF flow control
|
||||
|
||||
- OPOST - Enable output processing
|
||||
- ONLCR - Map New Line to Carriage Return - New Line
|
||||
|
||||
- CS8 - 8-bit characters
|
||||
- CREAD - Enable receiver
|
||||
- HUPCL - Hang up on last close
|
||||
|
||||
- ECHO - Echo input characters
|
||||
- ICANON - Enable canonical input (enable line editing)
|
||||
*/
|
||||
term.c_iflag = /*ICRNL |*/ IXON;
|
||||
term.c_oflag = OPOST | ONLCR;
|
||||
term.c_cflag = CS8 | CREAD | HUPCL;
|
||||
term.c_lflag = ECHO | ICANON;
|
||||
term.c_cc[VEOF] = 0x04; /* ^D */
|
||||
term.c_cc[VEOL] = 0x00; /* NUL */
|
||||
term.c_cc[VERASE] = 0x7f; /* DEL */
|
||||
term.c_cc[VINTR] = 0x03; /* ^C */
|
||||
term.c_cc[VKILL] = 0x15; /* ^U */
|
||||
term.c_cc[VMIN] = 1; /* Minimum number of characters for non-canonical read */
|
||||
term.c_cc[VQUIT] = 0x1c; /* ^\ */
|
||||
term.c_cc[VSTART] = 0x11; /* ^Q */
|
||||
term.c_cc[VSTOP] = 0x13; /* ^S */
|
||||
term.c_cc[VSUSP] = 0x1a; /* ^Z */
|
||||
term.c_cc[VTIME] = 0; /* Timeout for non-canonical read */
|
||||
term.c_cc[VWERASE] = 0x17; /* ^W */
|
||||
}
|
||||
|
||||
void LateInit()
|
||||
{
|
||||
}
|
||||
}
|
@ -16,14 +16,16 @@
|
||||
*/
|
||||
|
||||
#include <driver.hpp>
|
||||
#include <interface/driver.h>
|
||||
#include <interface/fs.h>
|
||||
#include <type_traits>
|
||||
|
||||
#include "../../kernel.h"
|
||||
#include "../../driver.h"
|
||||
|
||||
// #define DEBUG_API
|
||||
|
||||
#ifdef DEBUG_API
|
||||
#define dbg_api(Format, ...) function(Format, ##__VA_ARGS__)
|
||||
#define dbg_api(Format, ...) func(Format, ##__VA_ARGS__)
|
||||
#else
|
||||
#define dbg_api(Format, ...)
|
||||
#endif
|
||||
@ -53,19 +55,19 @@ namespace Driver
|
||||
{
|
||||
case _drf_Entry:
|
||||
drv->Entry = (int (*)())Function;
|
||||
debug("Entry %#lx for %s", (uintptr_t)Function, drv->Path);
|
||||
debug("Entry %#lx for %s", (uintptr_t)Function, drv->Path.c_str());
|
||||
break;
|
||||
case _drf_Final:
|
||||
drv->Final = (int (*)())Function;
|
||||
debug("Finalize %#lx for %s", (uintptr_t)Function, drv->Path);
|
||||
debug("Finalize %#lx for %s", (uintptr_t)Function, drv->Path.c_str());
|
||||
break;
|
||||
case _drf_Panic:
|
||||
drv->Panic = (int (*)())Function;
|
||||
debug("Panic %#lx for %s", (uintptr_t)Function, drv->Path);
|
||||
debug("Panic %#lx for %s", (uintptr_t)Function, drv->Path.c_str());
|
||||
break;
|
||||
case _drf_Probe:
|
||||
drv->Probe = (int (*)())Function;
|
||||
debug("Probe %#lx for %s", (uintptr_t)Function, drv->Path);
|
||||
debug("Probe %#lx for %s", (uintptr_t)Function, drv->Path.c_str());
|
||||
break;
|
||||
default:
|
||||
assert(!"Invalid driver function type");
|
||||
@ -134,7 +136,7 @@ namespace Driver
|
||||
{
|
||||
if (ih.first == IRQ)
|
||||
{
|
||||
debug("Removing IRQ %d: %#lx for %s", IRQ, (uintptr_t)ih.second, drv->Path);
|
||||
debug("Removing IRQ %d: %#lx for %s", IRQ, (uintptr_t)ih.second, drv->Path.c_str());
|
||||
Interrupts::RemoveHandler((void (*)(CPU::TrapFrame *))ih.second, IRQ);
|
||||
drv->InterruptHandlers->erase(IRQ);
|
||||
break;
|
||||
@ -177,7 +179,7 @@ namespace Driver
|
||||
foreach (auto &i in * drv->InterruptHandlers)
|
||||
{
|
||||
Interrupts::RemoveHandler((void (*)(CPU::TrapFrame *))Handler, i.first);
|
||||
debug("Removed IRQ %d: %#lx for %s", i.first, (uintptr_t)Handler, drv->Path);
|
||||
debug("Removed IRQ %d: %#lx for %s", i.first, (uintptr_t)Handler, drv->Path.c_str());
|
||||
}
|
||||
drv->InterruptHandlers->clear();
|
||||
return 0;
|
||||
@ -185,217 +187,6 @@ namespace Driver
|
||||
|
||||
/* --------- */
|
||||
|
||||
dev_t RegisterInputDevice(dev_t MajorID, DeviceDriverType Type)
|
||||
{
|
||||
dbg_api("%d, %d", MajorID, Type);
|
||||
|
||||
switch (Type)
|
||||
{
|
||||
case ddt_Keyboard:
|
||||
return DriverManager->InputKeyboardDev->Register(MajorID);
|
||||
case ddt_Mouse:
|
||||
return DriverManager->InputMouseDev->Register(MajorID);
|
||||
/* ... */
|
||||
default:
|
||||
assert(!"Invalid input device type");
|
||||
}
|
||||
}
|
||||
|
||||
int UnregisterInputDevice(dev_t MajorID, dev_t MinorID, DeviceDriverType Type)
|
||||
{
|
||||
dbg_api("%d, %d, %d", MajorID, MinorID, Type);
|
||||
|
||||
switch (Type)
|
||||
{
|
||||
case ddt_Keyboard:
|
||||
return DriverManager->InputKeyboardDev->Unregister(MajorID, MinorID);
|
||||
case ddt_Mouse:
|
||||
return DriverManager->InputMouseDev->Unregister(MajorID, MinorID);
|
||||
/* ... */
|
||||
default:
|
||||
assert(!"Invalid input device type");
|
||||
}
|
||||
}
|
||||
|
||||
int ReportKeyboardEvent(dev_t MajorID, dev_t MinorID, uint8_t ScanCode)
|
||||
{
|
||||
dbg_api("%d, %d, %d", MajorID, MinorID, ScanCode);
|
||||
|
||||
return DriverManager->InputKeyboardDev->ReportKeyEvent(MajorID, MinorID, ScanCode);
|
||||
}
|
||||
|
||||
int ReportRelativeMouseEvent(dev_t MajorID, dev_t MinorID, __MouseButtons Button, int X, int Y, int8_t Z)
|
||||
{
|
||||
dbg_api("%d, %d, %d, %d, %d, %d", MajorID, MinorID, Button, X, Y, Z);
|
||||
|
||||
return DriverManager->InputMouseDev->ReportMouseEvent(MajorID, MinorID,
|
||||
Button.LeftButton, Button.RightButton, Button.MiddleButton,
|
||||
Button.Button4, Button.Button5, Button.Button6, Button.Button7, Button.Button8,
|
||||
X, Y, Z, true);
|
||||
}
|
||||
|
||||
int ReportAbsoluteMouseEvent(dev_t MajorID, dev_t MinorID, __MouseButtons Button, uintptr_t X, uintptr_t Y, int8_t Z)
|
||||
{
|
||||
dbg_api("%d, %d, %d, %d, %d, %d", MajorID, MinorID, Button, X, Y, Z);
|
||||
|
||||
return DriverManager->InputMouseDev->ReportMouseEvent(MajorID, MinorID,
|
||||
Button.LeftButton, Button.RightButton, Button.MiddleButton,
|
||||
Button.Button4, Button.Button5, Button.Button6, Button.Button7, Button.Button8,
|
||||
X, Y, Z, false);
|
||||
}
|
||||
|
||||
/* --------- */
|
||||
|
||||
dev_t RegisterBlockDevice(dev_t MajorID, DeviceDriverType Type, void *Open, void *Close, void *Read, void *Write, void *Ioctl)
|
||||
{
|
||||
dbg_api("%d, %d, %#lx, %#lx, %#lx, %#lx, %#lx", MajorID, Type, Open, Close, Read, Write, Ioctl);
|
||||
|
||||
switch (Type)
|
||||
{
|
||||
case ddt_SATA:
|
||||
{
|
||||
dev_t ret = DriverManager->BlockSATADev->Register(MajorID);
|
||||
DriverManager->BlockSATADev->NewBlock(MajorID, ret,
|
||||
(SlaveDeviceFile::drvOpen_t)Open,
|
||||
(SlaveDeviceFile::drvClose_t)Close,
|
||||
(SlaveDeviceFile::drvRead_t)Read,
|
||||
(SlaveDeviceFile::drvWrite_t)Write,
|
||||
(SlaveDeviceFile::drvIoctl_t)Ioctl);
|
||||
return ret;
|
||||
}
|
||||
case ddt_ATA:
|
||||
{
|
||||
dev_t ret = DriverManager->BlockHDDev->Register(MajorID);
|
||||
DriverManager->BlockHDDev->NewBlock(MajorID, ret,
|
||||
(SlaveDeviceFile::drvOpen_t)Open,
|
||||
(SlaveDeviceFile::drvClose_t)Close,
|
||||
(SlaveDeviceFile::drvRead_t)Read,
|
||||
(SlaveDeviceFile::drvWrite_t)Write,
|
||||
(SlaveDeviceFile::drvIoctl_t)Ioctl);
|
||||
return ret;
|
||||
}
|
||||
case ddt_NVMe:
|
||||
{
|
||||
dev_t ret = DriverManager->BlockNVMeDev->Register(MajorID);
|
||||
DriverManager->BlockNVMeDev->NewBlock(MajorID, ret,
|
||||
(SlaveDeviceFile::drvOpen_t)Open,
|
||||
(SlaveDeviceFile::drvClose_t)Close,
|
||||
(SlaveDeviceFile::drvRead_t)Read,
|
||||
(SlaveDeviceFile::drvWrite_t)Write,
|
||||
(SlaveDeviceFile::drvIoctl_t)Ioctl);
|
||||
return ret;
|
||||
}
|
||||
/* ... */
|
||||
default:
|
||||
assert(!"Invalid storage device type");
|
||||
}
|
||||
}
|
||||
|
||||
int UnregisterBlockDevice(dev_t MajorID, dev_t MinorID, DeviceDriverType Type)
|
||||
{
|
||||
dbg_api("%d, %d, %d", MajorID, MinorID, Type);
|
||||
|
||||
switch (Type)
|
||||
{
|
||||
case ddt_SATA:
|
||||
return DriverManager->BlockSATADev->Unregister(MajorID, MinorID);
|
||||
case ddt_ATA:
|
||||
return DriverManager->BlockHDDev->Unregister(MajorID, MinorID);
|
||||
case ddt_NVMe:
|
||||
return DriverManager->BlockNVMeDev->Unregister(MajorID, MinorID);
|
||||
/* ... */
|
||||
default:
|
||||
assert(!"Invalid storage device type");
|
||||
}
|
||||
}
|
||||
|
||||
/* --------- */
|
||||
|
||||
dev_t RegisterAudioDevice(dev_t MajorID, DeviceDriverType Type, void *Open, void *Close, void *Read, void *Write, void *Ioctl)
|
||||
{
|
||||
dbg_api("%d, %d, %#lx, %#lx, %#lx, %#lx, %#lx", MajorID, Type, Open, Close, Read, Write, Ioctl);
|
||||
|
||||
switch (Type)
|
||||
{
|
||||
case ddt_Audio:
|
||||
{
|
||||
dev_t ret = DriverManager->AudioDev->Register(MajorID);
|
||||
DriverManager->AudioDev->NewAudio(MajorID, ret,
|
||||
(SlaveDeviceFile::drvOpen_t)Open,
|
||||
(SlaveDeviceFile::drvClose_t)Close,
|
||||
(SlaveDeviceFile::drvRead_t)Read,
|
||||
(SlaveDeviceFile::drvWrite_t)Write,
|
||||
(SlaveDeviceFile::drvIoctl_t)Ioctl);
|
||||
return ret;
|
||||
}
|
||||
/* ... */
|
||||
default:
|
||||
assert(!"Invalid audio device type");
|
||||
}
|
||||
}
|
||||
|
||||
int UnregisterAudioDevice(dev_t MajorID, dev_t MinorID, DeviceDriverType Type)
|
||||
{
|
||||
dbg_api("%d, %d, %d", MajorID, MinorID, Type);
|
||||
|
||||
switch (Type)
|
||||
{
|
||||
case ddt_Audio:
|
||||
return DriverManager->AudioDev->Unregister(MajorID, MinorID);
|
||||
/* ... */
|
||||
default:
|
||||
assert(!"Invalid audio device type");
|
||||
}
|
||||
}
|
||||
|
||||
/* --------- */
|
||||
|
||||
dev_t RegisterNetDevice(dev_t MajorID, DeviceDriverType Type, void *Open, void *Close, void *Read, void *Write, void *Ioctl)
|
||||
{
|
||||
dbg_api("%d, %d, %#lx, %#lx, %#lx, %#lx, %#lx", MajorID, Type, Open, Close, Read, Write, Ioctl);
|
||||
|
||||
switch (Type)
|
||||
{
|
||||
case ddt_Network:
|
||||
{
|
||||
dev_t ret = DriverManager->NetDev->Register(MajorID);
|
||||
DriverManager->NetDev->NewNet(MajorID, ret,
|
||||
(SlaveDeviceFile::drvOpen_t)Open,
|
||||
(SlaveDeviceFile::drvClose_t)Close,
|
||||
(SlaveDeviceFile::drvRead_t)Read,
|
||||
(SlaveDeviceFile::drvWrite_t)Write,
|
||||
(SlaveDeviceFile::drvIoctl_t)Ioctl);
|
||||
return ret;
|
||||
}
|
||||
/* ... */
|
||||
default:
|
||||
assert(!"Invalid audio device type");
|
||||
}
|
||||
}
|
||||
|
||||
int UnregisterNetDevice(dev_t MajorID, dev_t MinorID, DeviceDriverType Type)
|
||||
{
|
||||
dbg_api("%d, %d, %d", MajorID, MinorID, Type);
|
||||
|
||||
switch (Type)
|
||||
{
|
||||
case ddt_Network:
|
||||
return DriverManager->NetDev->Unregister(MajorID, MinorID);
|
||||
/* ... */
|
||||
default:
|
||||
assert(!"Invalid audio device type");
|
||||
}
|
||||
}
|
||||
|
||||
int ReportNetworkPacket(dev_t MajorID, dev_t MinorID, void *Buffer, size_t Size)
|
||||
{
|
||||
dbg_api("%d, %d, %#lx, %d", MajorID, MinorID, Buffer, Size);
|
||||
|
||||
return DriverManager->NetDev->ReportNetworkPacket(MajorID, MinorID, Buffer, Size);
|
||||
}
|
||||
|
||||
/* --------- */
|
||||
|
||||
void d_KPrint(dev_t MajorID, const char *Format, va_list args)
|
||||
{
|
||||
dbg_api("%d %s, %#lx", MajorID, Format, args);
|
||||
@ -891,22 +682,6 @@ namespace Driver
|
||||
api->UnregisterInterruptHandler = UnregisterInterruptHandler;
|
||||
api->UnregisterAllInterruptHandlers = UnregisterAllInterruptHandlers;
|
||||
|
||||
api->RegisterInputDevice = RegisterInputDevice;
|
||||
api->UnregisterInputDevice = UnregisterInputDevice;
|
||||
api->ReportKeyboardEvent = ReportKeyboardEvent;
|
||||
api->ReportRelativeMouseEvent = ReportRelativeMouseEvent;
|
||||
api->ReportAbsoluteMouseEvent = ReportAbsoluteMouseEvent;
|
||||
|
||||
api->RegisterBlockDevice = RegisterBlockDevice;
|
||||
api->UnregisterBlockDevice = UnregisterBlockDevice;
|
||||
|
||||
api->RegisterAudioDevice = RegisterAudioDevice;
|
||||
api->UnregisterAudioDevice = UnregisterAudioDevice;
|
||||
|
||||
api->RegisterNetDevice = RegisterNetDevice;
|
||||
api->UnregisterNetDevice = UnregisterNetDevice;
|
||||
api->ReportNetworkPacket = ReportNetworkPacket;
|
||||
|
||||
api->KPrint = d_KPrint;
|
||||
api->KernelLog = KernelLog;
|
||||
|
||||
@ -944,3 +719,28 @@ namespace Driver
|
||||
api->strstr = api__strstr;
|
||||
}
|
||||
}
|
||||
|
||||
dev_t __api_RegisterFileSystem(FileSystemInfo *Info, struct Inode *Root)
|
||||
{
|
||||
return fs->RegisterFileSystem(Info, Root);
|
||||
}
|
||||
|
||||
int __api_UnregisterFileSystem(dev_t Device)
|
||||
{
|
||||
return fs->UnregisterFileSystem(Device);
|
||||
}
|
||||
|
||||
struct APISymbols
|
||||
{
|
||||
const char *Name;
|
||||
void *Function;
|
||||
};
|
||||
|
||||
static struct APISymbols APISymbols[] = {
|
||||
{"RegisterFileSystem", (void *)__api_RegisterFileSystem},
|
||||
{"UnregisterFileSystem", (void *)__api_UnregisterFileSystem},
|
||||
};
|
||||
|
||||
/* Checking functions signatures */
|
||||
static_assert(std::is_same_v<decltype(__api_RegisterFileSystem), decltype(RegisterFileSystem)>);
|
||||
static_assert(std::is_same_v<decltype(__api_UnregisterFileSystem), decltype(UnregisterFileSystem)>);
|
||||
|
@ -1,327 +0,0 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <driver.hpp>
|
||||
|
||||
#include <memory.hpp>
|
||||
#include <ints.hpp>
|
||||
#include <task.hpp>
|
||||
#include <printf.h>
|
||||
#include <exec.hpp>
|
||||
#include <cwalk.h>
|
||||
#include <md5.h>
|
||||
|
||||
#include "../../../kernel.h"
|
||||
#include "../../../driver.h"
|
||||
|
||||
using namespace vfs;
|
||||
|
||||
namespace Driver
|
||||
{
|
||||
int MasterDeviceFile::open(int Flags, mode_t Mode)
|
||||
{
|
||||
switch (this->DeviceType)
|
||||
{
|
||||
default:
|
||||
if (this->SlavesMap.empty())
|
||||
return -ENOSYS;
|
||||
Slaves slave = this->SlavesMap.begin()->second;
|
||||
return slave->begin()->second->open(Flags, Mode);
|
||||
}
|
||||
}
|
||||
|
||||
int MasterDeviceFile::close()
|
||||
{
|
||||
switch (this->DeviceType)
|
||||
{
|
||||
default:
|
||||
if (this->SlavesMap.empty())
|
||||
return -ENOSYS;
|
||||
Slaves slave = this->SlavesMap.begin()->second;
|
||||
return slave->begin()->second->close();
|
||||
}
|
||||
}
|
||||
|
||||
size_t MasterDeviceFile::read(uint8_t *Buffer,
|
||||
size_t Size,
|
||||
off_t Offset)
|
||||
{
|
||||
switch (this->DeviceType)
|
||||
{
|
||||
case ddt_Keyboard:
|
||||
{
|
||||
while (KeyQueue.empty())
|
||||
TaskManager->Yield();
|
||||
|
||||
/* Request scancode */
|
||||
if (Size == 2 && Buffer[1] == 0x00)
|
||||
{
|
||||
while (RawKeyQueue.empty())
|
||||
TaskManager->Yield();
|
||||
|
||||
Buffer[0] = RawKeyQueue.front();
|
||||
RawKeyQueue.pop_front();
|
||||
return 1;
|
||||
}
|
||||
|
||||
Buffer[0] = KeyQueue.front();
|
||||
KeyQueue.pop_front();
|
||||
return 1;
|
||||
}
|
||||
default:
|
||||
if (this->SlavesMap.empty())
|
||||
return 0;
|
||||
Slaves slave = this->SlavesMap.begin()->second;
|
||||
return slave->begin()->second->read(Buffer, Size, Offset);
|
||||
}
|
||||
}
|
||||
|
||||
size_t MasterDeviceFile::write(uint8_t *Buffer,
|
||||
size_t Size,
|
||||
off_t Offset)
|
||||
{
|
||||
switch (this->DeviceType)
|
||||
{
|
||||
default:
|
||||
if (this->SlavesMap.empty())
|
||||
return 0;
|
||||
Slaves slave = this->SlavesMap.begin()->second;
|
||||
return slave->begin()->second->write(Buffer, Size, Offset);
|
||||
}
|
||||
}
|
||||
|
||||
int MasterDeviceFile::ioctl(unsigned long Request,
|
||||
void *Argp)
|
||||
{
|
||||
switch (this->DeviceType)
|
||||
{
|
||||
default:
|
||||
if (this->SlavesMap.empty())
|
||||
return -ENOSYS;
|
||||
Slaves slave = this->SlavesMap.begin()->second;
|
||||
return slave->begin()->second->ioctl(Request, Argp);
|
||||
}
|
||||
}
|
||||
|
||||
void MasterDeviceFile::ClearBuffers()
|
||||
{
|
||||
this->RawKeyQueue.clear();
|
||||
this->KeyQueue.clear();
|
||||
/* ... */
|
||||
|
||||
foreach (auto &sm in this->SlavesMap)
|
||||
{
|
||||
Slaves slave = sm.second;
|
||||
foreach (auto &sdf in *slave)
|
||||
sdf.second->ClearBuffers();
|
||||
}
|
||||
}
|
||||
|
||||
int MasterDeviceFile::ReportKeyEvent(maj_t ID, min_t MinorID, uint8_t ScanCode)
|
||||
{
|
||||
debug("New key event: %02x", ScanCode);
|
||||
if (this->SlavesMap.find(ID) == this->SlavesMap.end())
|
||||
return -EINVAL;
|
||||
|
||||
std::unordered_map<min_t, SlaveDeviceFile *> *slave = this->SlavesMap[ID];
|
||||
if ((*slave).find(MinorID) == (*slave).end())
|
||||
return -EINVAL;
|
||||
|
||||
/* We are master, keep a copy of the scancode and
|
||||
converted key */
|
||||
|
||||
if (RawKeyQueue.size() > 16)
|
||||
RawKeyQueue.pop_front();
|
||||
RawKeyQueue.push_back(ScanCode);
|
||||
|
||||
if (KeyQueue.size() > 16)
|
||||
KeyQueue.pop_front();
|
||||
|
||||
switch (ScanCode & ~KEY_PRESSED)
|
||||
{
|
||||
case KEY_LEFT_SHIFT:
|
||||
case KEY_RIGHT_SHIFT:
|
||||
{
|
||||
if (ScanCode & KEY_PRESSED)
|
||||
UpperCase = true;
|
||||
else
|
||||
UpperCase = false;
|
||||
break;
|
||||
}
|
||||
case KEY_CAPS_LOCK:
|
||||
{
|
||||
if (ScanCode & KEY_PRESSED)
|
||||
CapsLock = !CapsLock;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (ScanCode & KEY_PRESSED)
|
||||
KeyQueue.push_back(GetScanCode(ScanCode, UpperCase || CapsLock));
|
||||
|
||||
SlaveDeviceFile *sdf = (*slave)[MinorID];
|
||||
return sdf->ReportKeyEvent(ScanCode);
|
||||
}
|
||||
|
||||
int MasterDeviceFile::ReportMouseEvent(maj_t ID, min_t MinorID,
|
||||
bool LeftButton, bool RightButton, bool MiddleButton,
|
||||
bool Button4, bool Button5, bool Button6, bool Button7, bool Button8,
|
||||
uintptr_t X, uintptr_t Y, int8_t Z, bool Relative)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
int MasterDeviceFile::ReportNetworkPacket(maj_t ID, min_t MinorID, void *Buffer, size_t Size)
|
||||
{
|
||||
/* TODO: Buffer must be allocated by the kernel */
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
int MasterDeviceFile::NewBlock(maj_t ID, min_t MinorID, drvOpen_t Open, drvClose_t Close,
|
||||
drvRead_t Read, drvWrite_t Write, drvIoctl_t Ioctl)
|
||||
{
|
||||
assert(this->SlavesMap.find(ID) != this->SlavesMap.end());
|
||||
Slaves slave = this->SlavesMap[ID];
|
||||
assert((*slave).find(MinorID) != (*slave).end());
|
||||
SlaveDeviceFile *sdf = (*slave)[MinorID];
|
||||
sdf->Open = Open;
|
||||
sdf->Close = Close;
|
||||
sdf->Read = Read;
|
||||
sdf->Write = Write;
|
||||
sdf->Ioctl = Ioctl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int MasterDeviceFile::NewAudio(maj_t ID, min_t MinorID, drvOpen_t Open, drvClose_t Close,
|
||||
drvRead_t Read, drvWrite_t Write, drvIoctl_t Ioctl)
|
||||
{
|
||||
assert(this->SlavesMap.find(ID) != this->SlavesMap.end());
|
||||
Slaves slave = this->SlavesMap[ID];
|
||||
assert((*slave).find(MinorID) != (*slave).end());
|
||||
SlaveDeviceFile *sdf = (*slave)[MinorID];
|
||||
sdf->Open = Open;
|
||||
sdf->Close = Close;
|
||||
sdf->Read = Read;
|
||||
sdf->Write = Write;
|
||||
sdf->Ioctl = Ioctl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int MasterDeviceFile::NewNet(maj_t ID, min_t MinorID, drvOpen_t Open, drvClose_t Close,
|
||||
drvRead_t Read, drvWrite_t Write, drvIoctl_t Ioctl)
|
||||
{
|
||||
assert(this->SlavesMap.find(ID) != this->SlavesMap.end());
|
||||
Slaves slave = this->SlavesMap[ID];
|
||||
assert((*slave).find(MinorID) != (*slave).end());
|
||||
SlaveDeviceFile *sdf = (*slave)[MinorID];
|
||||
sdf->Open = Open;
|
||||
sdf->Close = Close;
|
||||
sdf->Read = Read;
|
||||
sdf->Write = Write;
|
||||
sdf->Ioctl = Ioctl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
dev_t MasterDeviceFile::Register(maj_t ID)
|
||||
{
|
||||
debug("Registering slave device %d", ID);
|
||||
Slaves slave;
|
||||
if (this->SlavesMap.find(ID) != this->SlavesMap.end())
|
||||
slave = this->SlavesMap[ID];
|
||||
else
|
||||
slave = new std::unordered_map<min_t, SlaveDeviceFile *>();
|
||||
|
||||
char name[24];
|
||||
sprintf(name, "%s%ld", this->SlaveName, this->SlaveIDCounter);
|
||||
SlaveDeviceFile *sdf = new SlaveDeviceFile(name,
|
||||
this->SlaveParent,
|
||||
this->DeviceType,
|
||||
this->Type);
|
||||
|
||||
sdf->DeviceMajor = ID;
|
||||
sdf->DeviceMinor = this->SlaveIDCounter;
|
||||
|
||||
(*slave)[this->SlaveIDCounter] = sdf;
|
||||
this->SlavesMap[ID] = slave;
|
||||
return this->SlaveIDCounter++;
|
||||
}
|
||||
|
||||
int MasterDeviceFile::Unregister(maj_t ID, min_t MinorID)
|
||||
{
|
||||
debug("Unregistering slave device %d:%d", ID, MinorID);
|
||||
if (this->SlavesMap.find(ID) == this->SlavesMap.end())
|
||||
return -EINVAL;
|
||||
|
||||
std::unordered_map<min_t, SlaveDeviceFile *> *slave = this->SlavesMap[ID];
|
||||
if ((*slave).find(MinorID) == (*slave).end())
|
||||
return -EINVAL;
|
||||
|
||||
SlaveDeviceFile *sdf = (*slave)[MinorID];
|
||||
delete sdf;
|
||||
slave->erase(MinorID);
|
||||
if (slave->empty())
|
||||
{
|
||||
delete slave;
|
||||
this->SlavesMap.erase(ID);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
MasterDeviceFile::MasterDeviceFile(const char *MasterName,
|
||||
const char *_SlaveName,
|
||||
Node *Parent,
|
||||
int Type)
|
||||
: Node(Parent, MasterName, NodeType::FILE)
|
||||
{
|
||||
strncpy(this->SlaveName, _SlaveName, sizeof(this->Name));
|
||||
this->DeviceType = Type;
|
||||
this->SlaveParent = Parent;
|
||||
|
||||
switch (Type)
|
||||
{
|
||||
case ddt_Keyboard:
|
||||
case ddt_Mouse:
|
||||
case ddt_Joystick:
|
||||
case ddt_Gamepad:
|
||||
case ddt_Touchpad:
|
||||
case ddt_Touchscreen:
|
||||
this->Type = NodeType::CHARDEVICE;
|
||||
break;
|
||||
case ddt_SATA:
|
||||
case ddt_ATA:
|
||||
case ddt_NVMe:
|
||||
this->Type = NodeType::BLOCKDEVICE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
MasterDeviceFile::~MasterDeviceFile()
|
||||
{
|
||||
foreach (auto &sm in this->SlavesMap)
|
||||
{
|
||||
Slaves slave = sm.second;
|
||||
foreach (auto &sdf in *slave)
|
||||
delete sdf.second;
|
||||
delete slave;
|
||||
}
|
||||
this->SlavesMap.clear();
|
||||
}
|
||||
}
|
@ -1,131 +0,0 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <driver.hpp>
|
||||
|
||||
#include <memory.hpp>
|
||||
#include <ints.hpp>
|
||||
#include <task.hpp>
|
||||
#include <printf.h>
|
||||
#include <exec.hpp>
|
||||
#include <cwalk.h>
|
||||
#include <md5.h>
|
||||
|
||||
#include "../../../kernel.h"
|
||||
#include "../../../driver.h"
|
||||
|
||||
using namespace vfs;
|
||||
|
||||
namespace Driver
|
||||
{
|
||||
int SlaveDeviceFile::open(int Flags, mode_t Mode)
|
||||
{
|
||||
switch (this->DeviceType)
|
||||
{
|
||||
default:
|
||||
if (this->Open)
|
||||
return this->Open(this->DeviceMajor, this->DeviceMinor,
|
||||
Flags, Mode);
|
||||
return -ENOSYS;
|
||||
}
|
||||
}
|
||||
|
||||
int SlaveDeviceFile::close()
|
||||
{
|
||||
switch (this->DeviceType)
|
||||
{
|
||||
default:
|
||||
if (this->Close)
|
||||
return this->Close(this->DeviceMajor, this->DeviceMinor);
|
||||
return -ENOSYS;
|
||||
}
|
||||
}
|
||||
|
||||
size_t SlaveDeviceFile::read(uint8_t *Buffer,
|
||||
size_t Size,
|
||||
off_t Offset)
|
||||
{
|
||||
switch (this->DeviceType)
|
||||
{
|
||||
case ddt_Keyboard:
|
||||
{
|
||||
while (KeyQueue.empty())
|
||||
TaskManager->Yield();
|
||||
|
||||
Buffer[0] = KeyQueue.front();
|
||||
KeyQueue.pop_front();
|
||||
return 1;
|
||||
}
|
||||
default:
|
||||
if (this->Read)
|
||||
return this->Read(this->DeviceMajor, this->DeviceMinor,
|
||||
Buffer, Size, Offset);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
size_t SlaveDeviceFile::write(uint8_t *Buffer,
|
||||
size_t Size,
|
||||
off_t Offset)
|
||||
{
|
||||
switch (this->DeviceType)
|
||||
{
|
||||
default:
|
||||
if (this->Write)
|
||||
return this->Write(this->DeviceMajor, this->DeviceMinor,
|
||||
Buffer, Size, Offset);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int SlaveDeviceFile::ioctl(unsigned long Request,
|
||||
void *Argp)
|
||||
{
|
||||
switch (this->DeviceType)
|
||||
{
|
||||
default:
|
||||
if (this->Ioctl)
|
||||
return this->Ioctl(this->DeviceMajor, this->DeviceMinor,
|
||||
Request, Argp);
|
||||
return -ENOSYS;
|
||||
}
|
||||
}
|
||||
|
||||
void SlaveDeviceFile::ClearBuffers()
|
||||
{
|
||||
KeyQueue.clear();
|
||||
/* ... */
|
||||
}
|
||||
|
||||
int SlaveDeviceFile::ReportKeyEvent(uint8_t ScanCode)
|
||||
{
|
||||
if (KeyQueue.size() > 16)
|
||||
KeyQueue.pop_front();
|
||||
KeyQueue.push_back(ScanCode);
|
||||
return 0;
|
||||
}
|
||||
|
||||
SlaveDeviceFile::SlaveDeviceFile(const char *Name, vfs::Node *Parent, int Type, vfs::NodeType NType)
|
||||
: Node(Parent, Name, NType)
|
||||
{
|
||||
this->DeviceType = Type;
|
||||
}
|
||||
|
||||
SlaveDeviceFile::~SlaveDeviceFile()
|
||||
{
|
||||
}
|
||||
}
|
@ -17,6 +17,7 @@
|
||||
|
||||
#include <driver.hpp>
|
||||
|
||||
#include <interface/driver.h>
|
||||
#include <memory.hpp>
|
||||
#include <ints.hpp>
|
||||
#include <task.hpp>
|
||||
@ -26,12 +27,64 @@
|
||||
#include <md5.h>
|
||||
|
||||
#include "../../kernel.h"
|
||||
#include "../../driver.h"
|
||||
|
||||
using namespace vfs;
|
||||
|
||||
namespace Driver
|
||||
{
|
||||
void Manager::PreloadDrivers()
|
||||
{
|
||||
debug("Initializing driver manager");
|
||||
const char *DriverDirectory = Config.DriverDirectory;
|
||||
FileNode *drvDirNode = fs->GetByPath(DriverDirectory, nullptr);
|
||||
if (!drvDirNode)
|
||||
{
|
||||
error("Failed to open driver directory %s", DriverDirectory);
|
||||
KPrint("Failed to open driver directory %s", DriverDirectory);
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (const auto &drvNode in drvDirNode->Children)
|
||||
{
|
||||
debug("Checking driver %s", drvNode->Path.c_str());
|
||||
if (!drvNode->IsRegularFile())
|
||||
continue;
|
||||
|
||||
if (Execute::GetBinaryType(drvNode->Path) != Execute::BinTypeELF)
|
||||
{
|
||||
error("Driver %s is not an ELF binary", drvNode->Path.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
Memory::VirtualMemoryArea *dVma = new Memory::VirtualMemoryArea(thisProcess->PageTable);
|
||||
|
||||
uintptr_t EntryPoint, BaseAddress;
|
||||
int err = this->LoadDriverFile(EntryPoint, BaseAddress, dVma, drvNode);
|
||||
debug("err = %d (%s)", err, strerror(err));
|
||||
if (err != 0)
|
||||
{
|
||||
error("Failed to load driver %s: %s",
|
||||
drvNode->Path.c_str(), strerror(err));
|
||||
|
||||
delete dVma;
|
||||
continue;
|
||||
}
|
||||
|
||||
Drivers[DriverIDCounter++] = {
|
||||
.BaseAddress = BaseAddress,
|
||||
.EntryPoint = EntryPoint,
|
||||
.vma = dVma,
|
||||
.Path = drvNode->Path,
|
||||
.InterruptHandlers = new std::unordered_map<uint8_t, void *>};
|
||||
|
||||
dev_t countr = DriverIDCounter - 1;
|
||||
const char *drvName;
|
||||
size_t drvNameLen;
|
||||
cwk_path_get_basename(drvNode->Path.c_str(), &drvName, &drvNameLen);
|
||||
strncpy(Drivers[countr].Name, drvName, sizeof(Drivers[countr].Name));
|
||||
}
|
||||
}
|
||||
|
||||
void Manager::LoadAllDrivers()
|
||||
{
|
||||
if (Drivers.empty())
|
||||
@ -56,7 +109,7 @@ namespace Driver
|
||||
dApi->Base = Drv->BaseAddress;
|
||||
PopulateDriverAPI(dApi);
|
||||
|
||||
debug("Calling driver %s at %#lx", Drv->Path, Drv->EntryPoint);
|
||||
debug("Calling driver %s at %#lx", Drv->Path.c_str(), Drv->EntryPoint);
|
||||
int (*DrvInit)(__driverAPI *) = (int (*)(__driverAPI *))Drv->EntryPoint;
|
||||
Drv->ErrorCode = DrvInit(dApi);
|
||||
if (Drv->ErrorCode < 0)
|
||||
@ -64,7 +117,7 @@ namespace Driver
|
||||
KPrint("FATAL: _start() failed for %s: %s",
|
||||
Drv->Name, strerror(Drv->ErrorCode));
|
||||
error("Failed to load driver %s: %s",
|
||||
Drv->Path, strerror(Drv->ErrorCode));
|
||||
Drv->Path.c_str(), strerror(Drv->ErrorCode));
|
||||
|
||||
Drv->vma->FreeAllPages();
|
||||
continue;
|
||||
@ -73,48 +126,36 @@ namespace Driver
|
||||
KPrint("Loading driver %s", Drv->Name);
|
||||
|
||||
debug("Calling Probe()=%#lx on driver %s",
|
||||
Drv->Probe, Drv->Path);
|
||||
Drv->Probe, Drv->Path.c_str());
|
||||
Drv->ErrorCode = Drv->Probe();
|
||||
if (Drv->ErrorCode < 0)
|
||||
{
|
||||
KPrint("Probe() failed for %s: %s",
|
||||
Drv->Name, strerror(Drv->ErrorCode));
|
||||
error("Failed to probe driver %s: %s",
|
||||
Drv->Path, strerror(Drv->ErrorCode));
|
||||
Drv->Path.c_str(), strerror(Drv->ErrorCode));
|
||||
|
||||
Drv->vma->FreeAllPages();
|
||||
continue;
|
||||
}
|
||||
|
||||
debug("Calling driver Entry()=%#lx function on driver %s",
|
||||
Drv->Entry, Drv->Path);
|
||||
Drv->Entry, Drv->Path.c_str());
|
||||
Drv->ErrorCode = Drv->Entry();
|
||||
if (Drv->ErrorCode < 0)
|
||||
{
|
||||
KPrint("Entry() failed for %s: %s",
|
||||
Drv->Name, strerror(Drv->ErrorCode));
|
||||
error("Failed to initialize driver %s: %s",
|
||||
Drv->Path, strerror(Drv->ErrorCode));
|
||||
Drv->Path.c_str(), strerror(Drv->ErrorCode));
|
||||
|
||||
Drv->vma->FreeAllPages();
|
||||
continue;
|
||||
}
|
||||
|
||||
debug("Loaded driver %s", Drv->Path);
|
||||
debug("Loaded driver %s", Drv->Path.c_str());
|
||||
Drv->Initialized = true;
|
||||
}
|
||||
|
||||
InputMouseDev->ClearBuffers();
|
||||
InputKeyboardDev->ClearBuffers();
|
||||
|
||||
BlockSATADev->ClearBuffers();
|
||||
BlockHDDev->ClearBuffers();
|
||||
BlockNVMeDev->ClearBuffers();
|
||||
|
||||
AudioDev->ClearBuffers();
|
||||
|
||||
NetDev->ClearBuffers();
|
||||
/* ... */
|
||||
}
|
||||
|
||||
void Manager::UnloadAllDrivers()
|
||||
@ -151,6 +192,9 @@ namespace Driver
|
||||
void Manager::Panic()
|
||||
{
|
||||
Memory::Virtual vmm;
|
||||
if (Drivers.size() == 0)
|
||||
return;
|
||||
|
||||
foreach (auto Driver in Drivers)
|
||||
{
|
||||
if (!Driver.second.Initialized)
|
||||
@ -168,21 +212,18 @@ namespace Driver
|
||||
}
|
||||
}
|
||||
|
||||
int Manager::LoadDriverFile(uintptr_t &EntryPoint,
|
||||
uintptr_t &BaseAddress,
|
||||
Memory::VirtualMemoryArea *dVma,
|
||||
RefNode *rDrv)
|
||||
int Manager::LoadDriverFile(uintptr_t &EntryPoint, uintptr_t &BaseAddress,
|
||||
Memory::VirtualMemoryArea *dVma, FileNode *rDrv)
|
||||
{
|
||||
Elf64_Ehdr ELFHeader;
|
||||
rDrv->seek(0, SEEK_SET);
|
||||
rDrv->read((uint8_t *)&ELFHeader, sizeof(Elf64_Ehdr));
|
||||
rDrv->Read(&ELFHeader, sizeof(Elf64_Ehdr), 0);
|
||||
if (ELFHeader.e_type != ET_DYN)
|
||||
{
|
||||
error("Driver %s is not a shared object", rDrv->node->FullPath);
|
||||
error("Driver %s is not a shared object", rDrv->Path.c_str());
|
||||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
trace("Loading driver %s in memory", rDrv->node->Name);
|
||||
trace("Loading driver %s in memory", rDrv->Name.c_str());
|
||||
|
||||
BaseAddress = 0;
|
||||
{
|
||||
@ -192,8 +233,7 @@ namespace Driver
|
||||
size_t SegmentsSize = 0;
|
||||
for (Elf64_Half i = 0; i < ELFHeader.e_phnum; i++)
|
||||
{
|
||||
rDrv->seek(ELFHeader.e_phoff + (i * sizeof(Elf64_Phdr)), SEEK_SET);
|
||||
rDrv->read((uint8_t *)&ProgramHeader, sizeof(Elf64_Phdr));
|
||||
rDrv->Read(&ProgramHeader, sizeof(Elf64_Phdr), ELFHeader.e_phoff + (i * sizeof(Elf64_Phdr)));
|
||||
|
||||
if (ProgramHeader.p_type == PT_LOAD ||
|
||||
ProgramHeader.p_type == PT_DYNAMIC)
|
||||
@ -217,8 +257,7 @@ namespace Driver
|
||||
|
||||
for (Elf64_Half i = 0; i < ELFHeader.e_phnum; i++)
|
||||
{
|
||||
rDrv->seek(ELFHeader.e_phoff + (i * sizeof(Elf64_Phdr)), SEEK_SET);
|
||||
rDrv->read((uint8_t *)&ProgramHeader, sizeof(Elf64_Phdr));
|
||||
rDrv->Read(&ProgramHeader, sizeof(Elf64_Phdr), ELFHeader.e_phoff + (i * sizeof(Elf64_Phdr)));
|
||||
|
||||
switch (ProgramHeader.p_type)
|
||||
{
|
||||
@ -237,8 +276,7 @@ namespace Driver
|
||||
|
||||
if (ProgramHeader.p_filesz > 0)
|
||||
{
|
||||
rDrv->seek(ProgramHeader.p_offset, SEEK_SET);
|
||||
rDrv->read((uint8_t *)SegmentDestination, ProgramHeader.p_filesz);
|
||||
rDrv->Read(SegmentDestination, ProgramHeader.p_filesz, ProgramHeader.p_offset);
|
||||
}
|
||||
|
||||
if (ProgramHeader.p_memsz - ProgramHeader.p_filesz > 0)
|
||||
@ -264,8 +302,7 @@ namespace Driver
|
||||
|
||||
if (ProgramHeader.p_filesz > 0)
|
||||
{
|
||||
rDrv->seek(ProgramHeader.p_offset, SEEK_SET);
|
||||
rDrv->read((uint8_t *)DynamicSegmentDestination, ProgramHeader.p_filesz);
|
||||
rDrv->Read(DynamicSegmentDestination, ProgramHeader.p_filesz, ProgramHeader.p_offset);
|
||||
}
|
||||
|
||||
if (ProgramHeader.p_memsz - ProgramHeader.p_filesz > 0)
|
||||
@ -288,8 +325,7 @@ namespace Driver
|
||||
Elf64_Phdr ProgramHeader;
|
||||
for (Elf64_Half i = 0; i < ELFHeader.e_phnum; i++)
|
||||
{
|
||||
rDrv->seek(ELFHeader.e_phoff + (i * sizeof(Elf64_Phdr)), SEEK_SET);
|
||||
rDrv->read((uint8_t *)&ProgramHeader, sizeof(Elf64_Phdr));
|
||||
rDrv->Read(&ProgramHeader, sizeof(Elf64_Phdr), ELFHeader.e_phoff + (i * sizeof(Elf64_Phdr)));
|
||||
|
||||
if (ProgramHeader.p_type == PT_DYNAMIC)
|
||||
{
|
||||
@ -381,14 +417,11 @@ namespace Driver
|
||||
break;
|
||||
}
|
||||
|
||||
vfs::RefNode *fd = fs->Open(rDrv->node->FullPath);
|
||||
|
||||
std::vector<Elf64_Dyn> SymTab = Execute::ELFGetDynamicTag_x86_64(fd, DT_SYMTAB);
|
||||
std::vector<Elf64_Dyn> StrTab = Execute::ELFGetDynamicTag_x86_64(fd, DT_STRTAB);
|
||||
std::vector<Elf64_Dyn> SymTab = Execute::ELFGetDynamicTag_x86_64(rDrv, DT_SYMTAB);
|
||||
std::vector<Elf64_Dyn> StrTab = Execute::ELFGetDynamicTag_x86_64(rDrv, DT_STRTAB);
|
||||
Elf64_Sym *_SymTab = (Elf64_Sym *)((uintptr_t)BaseAddress + SymTab[0].d_un.d_ptr);
|
||||
char *DynStr = (char *)((uintptr_t)BaseAddress + StrTab[0].d_un.d_ptr);
|
||||
UNUSED(DynStr);
|
||||
delete fd;
|
||||
|
||||
Elf64_Rela *Rela = (Elf64_Rela *)(BaseAddress + Dynamic->d_un.d_ptr);
|
||||
for (size_t i = 0; i < (PltRelSize->d_un.d_val / sizeof(Elf64_Rela)); i++)
|
||||
@ -431,14 +464,12 @@ namespace Driver
|
||||
{
|
||||
fixme("DT_SYMTAB");
|
||||
break;
|
||||
vfs::RefNode *fd = fs->Open(rDrv->node->FullPath);
|
||||
|
||||
std::vector<Elf64_Dyn> SymTab = Execute::ELFGetDynamicTag_x86_64(fd, DT_SYMTAB);
|
||||
std::vector<Elf64_Dyn> StrTab = Execute::ELFGetDynamicTag_x86_64(fd, DT_STRTAB);
|
||||
std::vector<Elf64_Dyn> SymTab = Execute::ELFGetDynamicTag_x86_64(rDrv, DT_SYMTAB);
|
||||
std::vector<Elf64_Dyn> StrTab = Execute::ELFGetDynamicTag_x86_64(rDrv, DT_STRTAB);
|
||||
Elf64_Sym *_SymTab = (Elf64_Sym *)((uintptr_t)BaseAddress + SymTab[0].d_un.d_ptr);
|
||||
char *DynStr = (char *)((uintptr_t)BaseAddress + StrTab[0].d_un.d_ptr);
|
||||
UNUSED(DynStr);
|
||||
delete fd;
|
||||
|
||||
size_t symtabEntrySize = 0;
|
||||
Elf64_Dyn *entrySizeDyn = Dynamic;
|
||||
@ -476,8 +507,8 @@ namespace Driver
|
||||
* this will create more issues :/ */
|
||||
// if (strcmp(SymbolName, "DriverProbe") == 0)
|
||||
// {
|
||||
// Drivers[MajorIDCounter].Probe = (int (*)())(BaseAddress + s->st_value);
|
||||
// debug("Found probe function at %#lx", Drivers[MajorIDCounter].Probe);
|
||||
// Drivers[DriverIDCounter].Probe = (int (*)())(BaseAddress + s->st_value);
|
||||
// debug("Found probe function at %#lx", Drivers[DriverIDCounter].Probe);
|
||||
// }
|
||||
}
|
||||
break;
|
||||
@ -498,7 +529,7 @@ namespace Driver
|
||||
EntryPoint += BaseAddress;
|
||||
|
||||
debug("Driver %s has entry point %#lx and base %#lx",
|
||||
rDrv->node->FullPath, EntryPoint, BaseAddress);
|
||||
rDrv->Path.c_str(), EntryPoint, BaseAddress);
|
||||
|
||||
/* FIXME: Do not add to the KernelSymbolTable! */
|
||||
// Memory::SmartHeap sh(rDrv->Size);
|
||||
@ -510,79 +541,11 @@ namespace Driver
|
||||
|
||||
Manager::Manager()
|
||||
{
|
||||
debug("Initializing driver manager");
|
||||
const char *DriverDirectory = Config.DriverDirectory;
|
||||
RefNode *drvDirNode = fs->Open(DriverDirectory);
|
||||
if (!drvDirNode)
|
||||
{
|
||||
error("Failed to open driver directory %s", DriverDirectory);
|
||||
KPrint("Failed to open driver directory %s", DriverDirectory);
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (auto drvNode in drvDirNode->node->Children)
|
||||
{
|
||||
if (drvNode->Type != vfs::FILE)
|
||||
continue;
|
||||
|
||||
if (Execute::GetBinaryType(drvNode->FullPath) != Execute::BinTypeELF)
|
||||
{
|
||||
error("Driver %s is not an ELF binary", drvNode->FullPath);
|
||||
continue;
|
||||
}
|
||||
|
||||
RefNode *rDrv = drvNode->CreateReference();
|
||||
|
||||
Memory::VirtualMemoryArea *dVma =
|
||||
new Memory::VirtualMemoryArea(thisProcess->PageTable);
|
||||
|
||||
uintptr_t EntryPoint, BaseAddress;
|
||||
int err = this->LoadDriverFile(EntryPoint, BaseAddress, dVma, rDrv);
|
||||
debug("err = %d (%s)", err, strerror(err));
|
||||
if (err != 0)
|
||||
{
|
||||
error("Failed to load driver %s: %s",
|
||||
drvNode->FullPath, strerror(err));
|
||||
|
||||
delete rDrv;
|
||||
delete dVma;
|
||||
continue;
|
||||
}
|
||||
delete rDrv;
|
||||
|
||||
Drivers[MajorIDCounter++] = {
|
||||
.BaseAddress = BaseAddress,
|
||||
.EntryPoint = EntryPoint,
|
||||
.vma = dVma,
|
||||
.Path = drvNode->FullPath,
|
||||
.InterruptHandlers = new std::unordered_map<uint8_t, void *>};
|
||||
|
||||
dev_t countr = MajorIDCounter - 1;
|
||||
const char *drvName;
|
||||
size_t drvNameLen;
|
||||
cwk_path_get_basename(drvNode->FullPath, &drvName, &drvNameLen);
|
||||
strncpy(Drivers[countr].Name, drvName, sizeof(Drivers[countr].Name));
|
||||
}
|
||||
|
||||
delete drvDirNode;
|
||||
|
||||
InputMouseDev = new MasterDeviceFile("mice", "mouse", DevFS, ddt_Mouse);
|
||||
InputKeyboardDev = new MasterDeviceFile("key", "kbd", DevFS, ddt_Keyboard);
|
||||
|
||||
BlockSATADev = new MasterDeviceFile("sd", "sd", DevFS, ddt_SATA);
|
||||
BlockHDDev = new MasterDeviceFile("hd", "hd", DevFS, ddt_ATA);
|
||||
BlockNVMeDev = new MasterDeviceFile("nvme", "nvme", DevFS, ddt_NVMe);
|
||||
|
||||
AudioDev = new MasterDeviceFile("audio", "snd", DevFS, ddt_Audio);
|
||||
|
||||
NetDev = new MasterDeviceFile("network", "net", DevFS, ddt_Network);
|
||||
}
|
||||
|
||||
Manager::~Manager()
|
||||
{
|
||||
debug("Unloading drivers");
|
||||
UnloadAllDrivers();
|
||||
delete InputMouseDev;
|
||||
delete InputKeyboardDev;
|
||||
}
|
||||
}
|
||||
|
@ -15,10 +15,9 @@
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <interface/driver.h>
|
||||
#include <driver.hpp>
|
||||
|
||||
#include "../../driver.h"
|
||||
|
||||
static char ScanCodeConversionTableLower[] = {
|
||||
[KEY_1] = '1',
|
||||
[KEY_2] = '2',
|
||||
|
@ -345,15 +345,15 @@ namespace Interrupts
|
||||
#ifdef DEBUG
|
||||
foreach (auto ev in RegisteredEvents)
|
||||
{
|
||||
void *func = ev.IsHandler
|
||||
? ev.Data
|
||||
: (void *)ev.Callback;
|
||||
void *fct = ev.IsHandler
|
||||
? ev.Data
|
||||
: (void *)ev.Callback;
|
||||
const char *symbol = ev.IsHandler
|
||||
? "class"
|
||||
: KernelSymbolTable->GetSymbol((uintptr_t)func);
|
||||
: KernelSymbolTable->GetSymbol((uintptr_t)fct);
|
||||
|
||||
debug("Event IRQ%d [%#lx %s] has priority %ld",
|
||||
ev.IRQ, func, symbol, ev.Priority);
|
||||
ev.IRQ, fct, symbol, ev.Priority);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -173,7 +173,7 @@ typedef volatile _Atomic(int64_t) atomic64_t;
|
||||
typedef volatile _Atomic(void *) atomicptr_t;
|
||||
|
||||
/* Intellisense errors */
|
||||
#ifndef __debug_vscode__
|
||||
#ifndef __vscode__
|
||||
|
||||
static FORCEINLINE int32_t atomic_load32(atomic32_t *src) { return atomic_load_explicit(src, memory_order_relaxed); }
|
||||
static FORCEINLINE void atomic_store32(atomic32_t *dst, int32_t val) { atomic_store_explicit(dst, val, memory_order_relaxed); }
|
||||
|
@ -86,6 +86,6 @@ EXTERNC int __rpmalloc_munmap(void *addr, size_t length)
|
||||
|
||||
EXTERNC int __rpmalloc_posix_madvise(void *addr, size_t length, int advice)
|
||||
{
|
||||
function("%#lx %d %d", addr, length, advice);
|
||||
func("%#lx %d %d", addr, length, advice);
|
||||
return 0;
|
||||
}
|
||||
|
@ -427,7 +427,11 @@ NIF void InitializeMemoryManagement()
|
||||
|
||||
void *malloc(size_t Size)
|
||||
{
|
||||
assert(Size > 0);
|
||||
if (Size == 0)
|
||||
{
|
||||
warn("Attempt to allocate 0 bytes");
|
||||
Size = 16;
|
||||
}
|
||||
|
||||
memdbg("malloc(%d)->[%s]", Size,
|
||||
KernelSymbolTable ? KernelSymbolTable->GetSymbol((uintptr_t)__builtin_return_address(0))
|
||||
@ -474,7 +478,11 @@ void *malloc(size_t Size)
|
||||
|
||||
void *calloc(size_t n, size_t Size)
|
||||
{
|
||||
assert(Size > 0);
|
||||
if (Size == 0)
|
||||
{
|
||||
warn("Attempt to allocate 0 bytes");
|
||||
Size = 16;
|
||||
}
|
||||
|
||||
memdbg("calloc(%d, %d)->[%s]", n, Size,
|
||||
KernelSymbolTable ? KernelSymbolTable->GetSymbol((uintptr_t)__builtin_return_address(0))
|
||||
@ -521,7 +529,11 @@ void *calloc(size_t n, size_t Size)
|
||||
|
||||
void *realloc(void *Address, size_t Size)
|
||||
{
|
||||
assert(Size > 0);
|
||||
if (Size == 0)
|
||||
{
|
||||
warn("Attempt to allocate 0 bytes");
|
||||
Size = 16;
|
||||
}
|
||||
|
||||
memdbg("realloc(%#lx, %d)->[%s]", Address, Size,
|
||||
KernelSymbolTable ? KernelSymbolTable->GetSymbol((uintptr_t)__builtin_return_address(0))
|
||||
@ -568,7 +580,11 @@ void *realloc(void *Address, size_t Size)
|
||||
|
||||
void free(void *Address)
|
||||
{
|
||||
assert(Address != nullptr);
|
||||
if (Address == nullptr)
|
||||
{
|
||||
warn("Attempt to free a null pointer");
|
||||
return;
|
||||
}
|
||||
|
||||
memdbg("free(%#lx)->[%s]", Address,
|
||||
KernelSymbolTable ? KernelSymbolTable->GetSymbol((uintptr_t)__builtin_return_address(0))
|
||||
@ -609,105 +625,3 @@ void free(void *Address)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void *operator new(std::size_t Size)
|
||||
{
|
||||
assert(Size > 0);
|
||||
|
||||
memdbg("new(%d)->[%s]", Size,
|
||||
KernelSymbolTable ? KernelSymbolTable->GetSymbol((uintptr_t)__builtin_return_address(0))
|
||||
: "Unknown");
|
||||
|
||||
void *ret = malloc(Size);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void *operator new[](std::size_t Size)
|
||||
{
|
||||
assert(Size > 0);
|
||||
|
||||
memdbg("new[](%d)->[%s]", Size,
|
||||
KernelSymbolTable ? KernelSymbolTable->GetSymbol((uintptr_t)__builtin_return_address(0))
|
||||
: "Unknown");
|
||||
|
||||
void *ret = malloc(Size);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void *operator new(std::size_t Size, std::align_val_t Alignment)
|
||||
{
|
||||
assert(Size > 0);
|
||||
|
||||
memdbg("new(%d, %d)->[%s]", Size, Alignment,
|
||||
KernelSymbolTable ? KernelSymbolTable->GetSymbol((uintptr_t)__builtin_return_address(0))
|
||||
: "Unknown");
|
||||
|
||||
fixme("operator new with alignment(%#lx) is not implemented",
|
||||
Alignment);
|
||||
|
||||
void *ret = malloc(Size);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void operator delete(void *Pointer)
|
||||
{
|
||||
assert(Pointer != nullptr);
|
||||
|
||||
memdbg("delete(%#lx)->[%s]", Pointer,
|
||||
KernelSymbolTable ? KernelSymbolTable->GetSymbol((uintptr_t)__builtin_return_address(0))
|
||||
: "Unknown");
|
||||
|
||||
free(Pointer);
|
||||
}
|
||||
|
||||
void operator delete[](void *Pointer)
|
||||
{
|
||||
assert(Pointer != nullptr);
|
||||
|
||||
memdbg("delete[](%#lx)->[%s]", Pointer,
|
||||
KernelSymbolTable ? KernelSymbolTable->GetSymbol((uintptr_t)__builtin_return_address(0))
|
||||
: "Unknown");
|
||||
|
||||
free(Pointer);
|
||||
}
|
||||
|
||||
void operator delete(void *Pointer, long unsigned int Size)
|
||||
{
|
||||
assert(Pointer != nullptr);
|
||||
assert(Size > 0);
|
||||
|
||||
memdbg("delete(%#lx, %d)->[%s]",
|
||||
Pointer, Size,
|
||||
KernelSymbolTable ? KernelSymbolTable->GetSymbol((uintptr_t)__builtin_return_address(0))
|
||||
: "Unknown");
|
||||
|
||||
free(Pointer);
|
||||
}
|
||||
|
||||
void operator delete[](void *Pointer, long unsigned int Size)
|
||||
{
|
||||
assert(Pointer != nullptr);
|
||||
assert(Size > 0);
|
||||
|
||||
memdbg("delete[](%#lx, %d)->[%s]",
|
||||
Pointer, Size,
|
||||
KernelSymbolTable ? KernelSymbolTable->GetSymbol((uintptr_t)__builtin_return_address(0))
|
||||
: "Unknown");
|
||||
|
||||
free(Pointer);
|
||||
}
|
||||
|
||||
void operator delete(void *Pointer, unsigned long Size, std::align_val_t Alignment)
|
||||
{
|
||||
assert(Pointer != nullptr);
|
||||
assert(Size > 0);
|
||||
|
||||
memdbg("delete(%#lx, %d, %d)->[%s]",
|
||||
Pointer, Size, Alignment,
|
||||
KernelSymbolTable ? KernelSymbolTable->GetSymbol((uintptr_t)__builtin_return_address(0))
|
||||
: "Unknown");
|
||||
|
||||
fixme("operator delete with alignment is not implemented");
|
||||
|
||||
free(Pointer);
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ namespace Memory
|
||||
{
|
||||
VirtualAllocation::AllocatedPages VirtualAllocation::RequestPages(size_t Count)
|
||||
{
|
||||
function("%lld", Count);
|
||||
func("%lld", Count);
|
||||
|
||||
void *pAddress = KernelAllocator.RequestPages(Count);
|
||||
memset(pAddress, 0, FROM_PAGES(Count));
|
||||
@ -79,7 +79,7 @@ namespace Memory
|
||||
|
||||
void VirtualAllocation::FreePages(void *Address, size_t Count)
|
||||
{
|
||||
function("%#lx, %lld", Address, Count);
|
||||
func("%#lx, %lld", Address, Count);
|
||||
|
||||
SmartLock(MgrLock);
|
||||
foreach (auto &apl in AllocatedPagesList)
|
||||
@ -110,7 +110,7 @@ namespace Memory
|
||||
|
||||
void VirtualAllocation::MapTo(AllocatedPages ap, PageTable *TargetTable)
|
||||
{
|
||||
function("%#lx, %#lx", ap.VirtualAddress, TargetTable);
|
||||
func("%#lx, %#lx", ap.VirtualAddress, TargetTable);
|
||||
|
||||
Virtual vmm(TargetTable);
|
||||
vmm.Map(ap.VirtualAddress, ap.PhysicalAddress, FROM_PAGES(ap.PageCount), RW | KRsv | G);
|
||||
@ -120,7 +120,7 @@ namespace Memory
|
||||
: BaseAddress(Base), CurrentBase(Base),
|
||||
Table((PageTable *)CPU::PageTable())
|
||||
{
|
||||
function("%#lx", Base);
|
||||
func("%#lx", Base);
|
||||
}
|
||||
|
||||
VirtualAllocation::~VirtualAllocation()
|
||||
|
@ -36,9 +36,9 @@ namespace Memory
|
||||
|
||||
void *VirtualMemoryArea::RequestPages(size_t Count, bool User, bool Protect)
|
||||
{
|
||||
function("%lld, %s, %s", Count,
|
||||
User ? "true" : "false",
|
||||
Protect ? "true" : "false");
|
||||
func("%lld, %s, %s", Count,
|
||||
User ? "true" : "false",
|
||||
Protect ? "true" : "false");
|
||||
|
||||
void *Address = KernelAllocator.RequestPages(Count);
|
||||
memset(Address, 0, Count * PAGE_SIZE);
|
||||
@ -61,7 +61,7 @@ namespace Memory
|
||||
|
||||
void VirtualMemoryArea::FreePages(void *Address, size_t Count)
|
||||
{
|
||||
function("%#lx, %lld", Address, Count);
|
||||
func("%#lx, %lld", Address, Count);
|
||||
|
||||
SmartLock(MgrLock);
|
||||
forItr(itr, AllocatedPagesList)
|
||||
@ -104,7 +104,7 @@ namespace Memory
|
||||
|
||||
void VirtualMemoryArea::DetachAddress(void *Address)
|
||||
{
|
||||
function("%#lx", Address);
|
||||
func("%#lx", Address);
|
||||
|
||||
SmartLock(MgrLock);
|
||||
forItr(itr, AllocatedPagesList)
|
||||
@ -128,12 +128,12 @@ namespace Memory
|
||||
bool Read, bool Write, bool Exec,
|
||||
bool Fixed, bool Shared)
|
||||
{
|
||||
function("%#lx, %lld, %s, %s, %s, %s, %s", Address, Length,
|
||||
Read ? "true" : "false",
|
||||
Write ? "true" : "false",
|
||||
Exec ? "true" : "false",
|
||||
Fixed ? "true" : "false",
|
||||
Shared ? "true" : "false");
|
||||
func("%#lx, %lld, %s, %s, %s, %s, %s", Address, Length,
|
||||
Read ? "true" : "false",
|
||||
Write ? "true" : "false",
|
||||
Exec ? "true" : "false",
|
||||
Fixed ? "true" : "false",
|
||||
Shared ? "true" : "false");
|
||||
|
||||
Virtual vmm(this->Table);
|
||||
|
||||
@ -191,7 +191,7 @@ namespace Memory
|
||||
|
||||
bool VirtualMemoryArea::HandleCoW(uintptr_t PFA)
|
||||
{
|
||||
function("%#lx", PFA);
|
||||
func("%#lx", PFA);
|
||||
Virtual vmm(this->Table);
|
||||
PageTableEntry *pte = vmm.GetPTE((void *)PFA);
|
||||
|
||||
@ -269,7 +269,7 @@ namespace Memory
|
||||
|
||||
void VirtualMemoryArea::Fork(VirtualMemoryArea *Parent)
|
||||
{
|
||||
function("%#lx", Parent);
|
||||
func("%#lx", Parent);
|
||||
assert(Parent);
|
||||
|
||||
debug("parent apl:%d sr:%d [P:%#lx C:%#lx]",
|
||||
|
@ -65,7 +65,7 @@ struct DiagnosticFile
|
||||
} Data;
|
||||
};
|
||||
|
||||
nsa bool WriteDiagDataToNode(vfs::RefNode *refFile)
|
||||
nsa bool WriteDiagDataToNode(FileNode *node)
|
||||
{
|
||||
uintptr_t KStart = (uintptr_t)&_kernel_start;
|
||||
uintptr_t kEnd = (uintptr_t)&_kernel_end;
|
||||
@ -89,8 +89,8 @@ nsa bool WriteDiagDataToNode(vfs::RefNode *refFile)
|
||||
file->Data.KernelMemoryLength = uint32_t(kSize);
|
||||
memcpy(file->Data.KernelMemory, (void *)KStart, kSize);
|
||||
|
||||
ExPrint("\eFAFAFAWriting to %s\n", refFile->node->FullPath);
|
||||
size_t w = refFile->write(buf, fileSize);
|
||||
ExPrint("\eFAFAFAWriting to %s\n", node->Path.c_str());
|
||||
size_t w = node->Write(buf, fileSize, 0);
|
||||
if (w != fileSize)
|
||||
{
|
||||
debug("%d out of %d bytes written", w, fileSize);
|
||||
@ -111,7 +111,12 @@ nsa void DiagnosticDataCollection()
|
||||
ExPrint("\n\eFAFAFAPlease wait while we collect some diagnostic information...\n");
|
||||
ExPrint("This may take a while...\n");
|
||||
|
||||
vfs::Node *panicDir = fs->CreateIfNotExists("/var/panic", vfs::DIRECTORY);
|
||||
mode_t mode = S_IRWXU |
|
||||
S_IRWXG |
|
||||
S_IROTH |
|
||||
S_IFDIR;
|
||||
|
||||
FileNode *panicDir = fs->ForceCreate(nullptr, "/var/panic", mode);
|
||||
if (!panicDir)
|
||||
{
|
||||
ExPrint("\eFF0000Failed to create /var/panic\n");
|
||||
@ -119,6 +124,7 @@ nsa void DiagnosticDataCollection()
|
||||
return;
|
||||
}
|
||||
|
||||
FileNode *dumpFile;
|
||||
Time::Clock clock = Time::ReadClock();
|
||||
char filename[64];
|
||||
for (int i = 0; i < INT32_MAX; i++)
|
||||
@ -128,18 +134,18 @@ nsa void DiagnosticDataCollection()
|
||||
if (fs->PathExists(filename, panicDir))
|
||||
continue;
|
||||
|
||||
fs->Create(filename, vfs::FILE, panicDir);
|
||||
mode = S_IRWXU |
|
||||
S_IRWXG |
|
||||
S_IROTH |
|
||||
S_IFREG;
|
||||
|
||||
dumpFile = fs->Create(panicDir, filename, mode);
|
||||
break;
|
||||
}
|
||||
|
||||
vfs::RefNode *refFile = fs->Open(filename, panicDir);
|
||||
if (!WriteDiagDataToNode(refFile))
|
||||
{
|
||||
delete refFile;
|
||||
if (!WriteDiagDataToNode(dumpFile))
|
||||
return;
|
||||
}
|
||||
|
||||
ExPrint("You can find the diagnostic file in /var/panic/%s\n", filename);
|
||||
Display->UpdateBuffer();
|
||||
delete refFile;
|
||||
}
|
||||
|
@ -517,7 +517,7 @@ nsa void DisplayStackScreen(CPU::ExceptionFrame *Frame)
|
||||
sym, offset);
|
||||
}
|
||||
else
|
||||
ExPrint("\eFF5555???\n");
|
||||
ExPrint("\eFF5555??? \eFFAAAA<- Exception\n");
|
||||
|
||||
if (!sf || !sf->ip || !sf->bp)
|
||||
{
|
||||
@ -591,7 +591,7 @@ nsa void DisplayProcessScreen(CPU::ExceptionFrame *Frame, bool IgnoreReady = tru
|
||||
if (Display->GetWidth > 800 && Display->GetHeight > 600)
|
||||
textLimit = 128;
|
||||
|
||||
std::list<Tasking::PCB *> Plist = TaskManager->GetProcessList();
|
||||
std::vector<Tasking::PCB *> Plist = TaskManager->GetProcessList();
|
||||
|
||||
ExPrint("\n\eFAFAFAProcess list (%ld):\n", Plist.size());
|
||||
bool pRdy = false;
|
||||
@ -626,7 +626,7 @@ nsa void DisplayProcessScreen(CPU::ExceptionFrame *Frame, bool IgnoreReady = tru
|
||||
Process->ID, StatusColor[Process->State.load()],
|
||||
StatusString[Process->State.load()],
|
||||
Process->Executable
|
||||
? Process->Executable->Name
|
||||
? Process->Executable->Name.c_str()
|
||||
: "none");
|
||||
|
||||
bool tRdy = false;
|
||||
@ -766,6 +766,29 @@ nsa void DisplayAssertionFailed(const char *File, int Line, const char *Expressi
|
||||
ExPrint(" This is a kernel bug.\n");
|
||||
ExPrint(" Please create a new issue on \e00AAFFhttps://github.com/Fennix-Project/Fennix\eFAFAFA for further assistance.\n");
|
||||
|
||||
CPU::ExceptionFrame ef;
|
||||
// Fill only the necessary fields
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wframe-address"
|
||||
|
||||
/* Jump over HandleAssertionFailed, and ip will be the function where it failed */
|
||||
void *fun = __builtin_return_address(1);
|
||||
/* Jump over this, HandleAssertionFailed & ip */
|
||||
void *stk = __builtin_frame_address(2);
|
||||
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
#ifdef __x86_64__
|
||||
asmv("movq %%cr3, %0" : "=r"(ef.cr3));
|
||||
ef.rip = (uint64_t)fun;
|
||||
ef.rbp = ef.rsp = (uint64_t)stk;
|
||||
#elif defined(__i386__)
|
||||
asmv("movl %%cr3, %0" : "=r"(ef.cr3));
|
||||
ef.eip = (uint32_t)fun;
|
||||
ef.ebp = ef.esp = (uint32_t)stk;
|
||||
#endif
|
||||
DisplayStackScreen(&ef);
|
||||
Display->UpdateBuffer();
|
||||
|
||||
/* TODO: Add additional info */
|
||||
|
@ -40,15 +40,11 @@ namespace SymbolResolver
|
||||
return Result.FunctionName;
|
||||
}
|
||||
|
||||
std::vector<SymbolTable> rSymTable = this->SymTable;
|
||||
rSymTable.reverse();
|
||||
|
||||
foreach (auto st in rSymTable)
|
||||
for (auto it = this->SymTable.rbegin(); it != this->SymTable.rend(); ++it)
|
||||
{
|
||||
if (unlikely(st.Address <= Address &&
|
||||
st.Address > Result.Address))
|
||||
if (unlikely(it->Address <= Address && it->Address > Result.Address))
|
||||
{
|
||||
Result = st;
|
||||
Result = *it;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -72,14 +68,11 @@ namespace SymbolResolver
|
||||
return Result.Address;
|
||||
}
|
||||
|
||||
std::vector<SymbolTable> rSymTable = this->SymTable;
|
||||
rSymTable.reverse();
|
||||
|
||||
foreach (auto st in rSymTable)
|
||||
for (auto it = this->SymTable.rbegin(); it != this->SymTable.rend(); ++it)
|
||||
{
|
||||
if (unlikely(strcmp(st.FunctionName, Name) == 0))
|
||||
if (unlikely(strcmp(it->FunctionName, Name) == 0))
|
||||
{
|
||||
Result = st;
|
||||
Result = *it;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -18,63 +18,65 @@
|
||||
#include <exec.hpp>
|
||||
|
||||
#include <msexec.h>
|
||||
#include <macho.h>
|
||||
#include <memory>
|
||||
|
||||
#include "../kernel.h"
|
||||
|
||||
namespace Execute
|
||||
{
|
||||
BinaryType GetBinaryType(const char *Path)
|
||||
BinaryType GetBinaryType(FileNode *Node)
|
||||
{
|
||||
debug("Checking binary type of %s(ptr: %#lx)",
|
||||
Path, Path);
|
||||
debug("Checking binary type of %s", Node->Path.c_str());
|
||||
BinaryType Type;
|
||||
vfs::RefNode *fd = fs->Open(Path);
|
||||
|
||||
if (fd == nullptr)
|
||||
{
|
||||
debug("Failed to open file %s", Path);
|
||||
return (BinaryType)-ENOENT;
|
||||
}
|
||||
if (Node == nullptr)
|
||||
ReturnLogError((BinaryType)-ENOENT, "Node is null");
|
||||
|
||||
debug("File opened: %s, descriptor %d", Path, fd);
|
||||
Memory::SmartHeap sh = Memory::SmartHeap(1024);
|
||||
fd->read(sh, 128);
|
||||
Elf32_Ehdr ELFHeader;
|
||||
Node->Read(&ELFHeader, sizeof(Elf32_Ehdr), 0);
|
||||
|
||||
Elf32_Ehdr *ELFHeader = (Elf32_Ehdr *)sh.Get();
|
||||
IMAGE_DOS_HEADER *MZHeader = (IMAGE_DOS_HEADER *)sh.Get();
|
||||
mach_header MachHeader;
|
||||
Node->Read(&MachHeader, sizeof(mach_header), 0);
|
||||
|
||||
IMAGE_DOS_HEADER MZHeader;
|
||||
Node->Read(&MZHeader, sizeof(IMAGE_DOS_HEADER), 0);
|
||||
|
||||
/* Check ELF header. */
|
||||
if (ELFHeader->e_ident[EI_MAG0] == ELFMAG0 &&
|
||||
ELFHeader->e_ident[EI_MAG1] == ELFMAG1 &&
|
||||
ELFHeader->e_ident[EI_MAG2] == ELFMAG2 &&
|
||||
ELFHeader->e_ident[EI_MAG3] == ELFMAG3)
|
||||
if (ELFHeader.e_ident[EI_MAG0] == ELFMAG0 &&
|
||||
ELFHeader.e_ident[EI_MAG1] == ELFMAG1 &&
|
||||
ELFHeader.e_ident[EI_MAG2] == ELFMAG2 &&
|
||||
ELFHeader.e_ident[EI_MAG3] == ELFMAG3)
|
||||
{
|
||||
debug("Image - ELF");
|
||||
Type = BinaryType::BinTypeELF;
|
||||
goto Success;
|
||||
}
|
||||
|
||||
/* Check MZ header. */
|
||||
else if (MZHeader->e_magic == IMAGE_DOS_SIGNATURE)
|
||||
if (MachHeader.magic == MH_MAGIC || MachHeader.magic == MH_CIGAM)
|
||||
{
|
||||
fd->seek(MZHeader->e_lfanew, SEEK_SET);
|
||||
fd->read(sh, 512);
|
||||
IMAGE_NT_HEADERS *PEHeader =
|
||||
(IMAGE_NT_HEADERS *)(((char *)sh.Get()) +
|
||||
MZHeader->e_lfanew);
|
||||
debug("Image - Mach-O");
|
||||
Type = BinaryType::BinTypeMachO;
|
||||
goto Success;
|
||||
}
|
||||
|
||||
IMAGE_OS2_HEADER *NEHeader =
|
||||
(IMAGE_OS2_HEADER *)(((char *)sh.Get()) +
|
||||
MZHeader->e_lfanew);
|
||||
/* Check MZ header. */
|
||||
else if (MZHeader.e_magic == IMAGE_DOS_SIGNATURE)
|
||||
{
|
||||
IMAGE_NT_HEADERS PEHeader;
|
||||
Node->Read(&PEHeader, sizeof(IMAGE_NT_HEADERS), MZHeader.e_lfanew);
|
||||
|
||||
IMAGE_OS2_HEADER NEHeader;
|
||||
Node->Read(&NEHeader, sizeof(IMAGE_OS2_HEADER), MZHeader.e_lfanew);
|
||||
|
||||
/* TODO: LE, EDOS */
|
||||
if (PEHeader->Signature == IMAGE_NT_SIGNATURE)
|
||||
if (PEHeader.Signature == IMAGE_NT_SIGNATURE)
|
||||
{
|
||||
debug("Image - PE");
|
||||
Type = BinaryType::BinTypePE;
|
||||
goto Success;
|
||||
}
|
||||
else if (NEHeader->ne_magic == IMAGE_OS2_SIGNATURE)
|
||||
else if (NEHeader.ne_magic == IMAGE_OS2_SIGNATURE)
|
||||
{
|
||||
debug("Image - NE");
|
||||
Type = BinaryType::BinTypeNE;
|
||||
@ -92,7 +94,12 @@ namespace Execute
|
||||
|
||||
Type = BinaryType::BinTypeUnknown;
|
||||
Success:
|
||||
delete fd;
|
||||
return Type;
|
||||
}
|
||||
|
||||
BinaryType GetBinaryType(std::string Path)
|
||||
{
|
||||
FileNode *node = fs->GetByPath(Path.c_str(), nullptr);
|
||||
return GetBinaryType(node);
|
||||
}
|
||||
}
|
||||
|
@ -33,15 +33,16 @@ using namespace vfs;
|
||||
namespace Execute
|
||||
{
|
||||
void ELFObject::GenerateAuxiliaryVector_x86_32(Memory::VirtualMemoryArea *vma,
|
||||
vfs::RefNode *fd,
|
||||
FileNode *fd,
|
||||
Elf32_Ehdr ELFHeader,
|
||||
uint32_t EntryPoint,
|
||||
uint32_t BaseAddress)
|
||||
{
|
||||
assert(!"Function not implemented");
|
||||
}
|
||||
|
||||
void ELFObject::GenerateAuxiliaryVector_x86_64(Memory::VirtualMemoryArea *vma,
|
||||
vfs::RefNode *fd,
|
||||
FileNode *fd,
|
||||
Elf64_Ehdr ELFHeader,
|
||||
uint64_t EntryPoint,
|
||||
uint64_t BaseAddress)
|
||||
@ -50,8 +51,8 @@ namespace Execute
|
||||
char *aux_platform = (char *)vma->RequestPages(1, true); /* TODO: 4KiB is too much for this */
|
||||
strcpy(aux_platform, "x86_64");
|
||||
|
||||
void *execfn_str = vma->RequestPages(TO_PAGES(strlen(fd->node->FullPath) + 1), true);
|
||||
strcpy((char *)execfn_str, fd->node->FullPath);
|
||||
void *execfn_str = vma->RequestPages(TO_PAGES(fd->Path.size() + 1), true);
|
||||
strcpy((char *)execfn_str, fd->Path.c_str());
|
||||
void *at_random = vma->RequestPages(1, true);
|
||||
*(uint64_t *)at_random = Random::rand16();
|
||||
|
||||
@ -93,22 +94,21 @@ namespace Execute
|
||||
#endif
|
||||
}
|
||||
|
||||
void ELFObject::LoadExec_x86_32(vfs::RefNode *, PCB *)
|
||||
void ELFObject::LoadExec_x86_32(FileNode *, PCB *)
|
||||
{
|
||||
stub;
|
||||
assert(!"Function not implemented");
|
||||
}
|
||||
|
||||
void ELFObject::LoadExec_x86_64(vfs::RefNode *fd, PCB *TargetProcess)
|
||||
void ELFObject::LoadExec_x86_64(FileNode *fd, PCB *TargetProcess)
|
||||
{
|
||||
#if defined(a64)
|
||||
std::vector<Elf64_Phdr> PhdrINTERP = ELFGetSymbolType_x86_64(fd, PT_INTERP);
|
||||
foreach (auto Interp in PhdrINTERP)
|
||||
{
|
||||
Memory::SmartHeap InterpreterPath = Memory::SmartHeap(256);
|
||||
fd->seek(Interp.p_offset, SEEK_SET);
|
||||
fd->read(InterpreterPath, 256);
|
||||
fd->Read(InterpreterPath, 256, Interp.p_offset);
|
||||
|
||||
vfs::RefNode *ifd = fs->Open((const char *)InterpreterPath.Get());
|
||||
FileNode *ifd = fs->GetByPath((const char *)InterpreterPath.Get(), TargetProcess->Info.RootNode);
|
||||
if (ifd == nullptr)
|
||||
{
|
||||
warn("Failed to open interpreter file: %s",
|
||||
@ -121,7 +121,6 @@ namespace Execute
|
||||
{
|
||||
warn("Interpreter %s is not an ELF file",
|
||||
(const char *)InterpreterPath.Get());
|
||||
delete ifd;
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -130,15 +129,13 @@ namespace Execute
|
||||
/* FIXME: specify argv[1] as the location for the interpreter */
|
||||
|
||||
debug("Interpreter loaded successfully");
|
||||
delete ifd;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Elf64_Ehdr ELFHeader;
|
||||
fd->seek(0, SEEK_SET);
|
||||
fd->read((uint8_t *)&ELFHeader, sizeof(Elf64_Ehdr));
|
||||
Elf64_Ehdr ELFHeader{};
|
||||
fd->Read(&ELFHeader, sizeof(Elf64_Ehdr), 0);
|
||||
uintptr_t EntryPoint = ELFHeader.e_entry;
|
||||
debug("Entry point is %#lx", EntryPoint);
|
||||
|
||||
@ -152,8 +149,7 @@ namespace Execute
|
||||
Elf64_Phdr ProgramHeader;
|
||||
for (Elf64_Half i = 0; i < ELFHeader.e_phnum; i++)
|
||||
{
|
||||
fd->seek(ELFHeader.e_phoff + (i * sizeof(Elf64_Phdr)), SEEK_SET);
|
||||
fd->read((uint8_t *)&ProgramHeader, sizeof(Elf64_Phdr));
|
||||
fd->Read(&ProgramHeader, sizeof(Elf64_Phdr), ELFHeader.e_phoff + (i * sizeof(Elf64_Phdr)));
|
||||
switch (ProgramHeader.p_type)
|
||||
{
|
||||
case PT_LOAD:
|
||||
@ -182,10 +178,8 @@ namespace Execute
|
||||
|
||||
if (ProgramHeader.p_filesz > 0)
|
||||
{
|
||||
debug("%d %#lx %d", ProgramHeader.p_offset,
|
||||
(uint8_t *)pAddr + SegDestOffset, ProgramHeader.p_filesz);
|
||||
fd->seek(ProgramHeader.p_offset, SEEK_SET);
|
||||
fd->read((uint8_t *)pAddr + SegDestOffset, ProgramHeader.p_filesz);
|
||||
debug("%d %#lx %d", ProgramHeader.p_offset, (uint8_t *)pAddr + SegDestOffset, ProgramHeader.p_filesz);
|
||||
fd->Read((uint8_t *)pAddr + SegDestOffset, ProgramHeader.p_filesz, ProgramHeader.p_offset);
|
||||
}
|
||||
|
||||
if (ProgramHeader.p_memsz - ProgramHeader.p_filesz > 0)
|
||||
@ -203,40 +197,35 @@ namespace Execute
|
||||
case PT_NOTE:
|
||||
{
|
||||
Elf64_Nhdr NoteHeader;
|
||||
fd->seek(ProgramHeader.p_offset, SEEK_SET);
|
||||
fd->read((uint8_t *)&NoteHeader, sizeof(Elf64_Nhdr));
|
||||
fd->Read(&NoteHeader, sizeof(Elf64_Nhdr), ProgramHeader.p_offset);
|
||||
|
||||
switch (NoteHeader.n_type)
|
||||
{
|
||||
case NT_PRSTATUS:
|
||||
{
|
||||
Elf64_Prstatus prstatus;
|
||||
fd->seek(ProgramHeader.p_offset + sizeof(Elf64_Nhdr), SEEK_SET);
|
||||
fd->read((uint8_t *)&prstatus, sizeof(Elf64_Prstatus));
|
||||
fd->Read(&prstatus, sizeof(Elf64_Prstatus), ProgramHeader.p_offset + sizeof(Elf64_Nhdr));
|
||||
debug("PRSTATUS: %#lx", prstatus.pr_reg[0]);
|
||||
break;
|
||||
}
|
||||
case NT_PRPSINFO:
|
||||
{
|
||||
Elf64_Prpsinfo prpsinfo;
|
||||
fd->seek(ProgramHeader.p_offset + sizeof(Elf64_Nhdr), SEEK_SET);
|
||||
fd->read((uint8_t *)&prpsinfo, sizeof(Elf64_Prpsinfo));
|
||||
fd->Read(&prpsinfo, sizeof(Elf64_Prpsinfo), ProgramHeader.p_offset + sizeof(Elf64_Nhdr));
|
||||
debug("PRPSINFO: %s", prpsinfo.pr_fname);
|
||||
break;
|
||||
}
|
||||
case NT_PLATFORM:
|
||||
{
|
||||
char platform[256];
|
||||
fd->seek(ProgramHeader.p_offset + sizeof(Elf64_Nhdr), SEEK_SET);
|
||||
fd->read((uint8_t *)&platform, 256);
|
||||
fd->Read(&platform, sizeof(platform), ProgramHeader.p_offset + sizeof(Elf64_Nhdr));
|
||||
debug("PLATFORM: %s", platform);
|
||||
break;
|
||||
}
|
||||
case NT_AUXV:
|
||||
{
|
||||
Elf64_auxv_t auxv;
|
||||
fd->seek(ProgramHeader.p_offset + sizeof(Elf64_Nhdr), SEEK_SET);
|
||||
fd->read((uint8_t *)&auxv, sizeof(Elf64_auxv_t));
|
||||
fd->Read(&auxv, sizeof(Elf64_auxv_t), ProgramHeader.p_offset + sizeof(Elf64_Nhdr));
|
||||
debug("AUXV: %#lx", auxv.a_un.a_val);
|
||||
break;
|
||||
}
|
||||
@ -254,8 +243,7 @@ namespace Execute
|
||||
debug("TLS Size: %ld (%ld pages)",
|
||||
tlsSize, TO_PAGES(tlsSize));
|
||||
void *tlsMemory = vma->RequestPages(TO_PAGES(tlsSize));
|
||||
fd->seek(ProgramHeader.p_offset, SEEK_SET);
|
||||
fd->read((uint8_t *)tlsMemory, tlsSize);
|
||||
fd->Read(tlsMemory, tlsSize, ProgramHeader.p_offset);
|
||||
TargetProcess->TLS = {
|
||||
.pBase = uintptr_t(tlsMemory),
|
||||
.vBase = ProgramHeader.p_vaddr,
|
||||
@ -323,23 +311,22 @@ namespace Execute
|
||||
#endif
|
||||
}
|
||||
|
||||
void ELFObject::LoadDyn_x86_32(vfs::RefNode *, PCB *)
|
||||
void ELFObject::LoadDyn_x86_32(FileNode *, PCB *)
|
||||
{
|
||||
stub;
|
||||
assert(!"Function not implemented");
|
||||
}
|
||||
|
||||
void ELFObject::LoadDyn_x86_64(vfs::RefNode *fd, PCB *TargetProcess)
|
||||
void ELFObject::LoadDyn_x86_64(FileNode *fd, PCB *TargetProcess)
|
||||
{
|
||||
#if defined(a64)
|
||||
std::vector<Elf64_Phdr> PhdrINTERP = ELFGetSymbolType_x86_64(fd, PT_INTERP);
|
||||
foreach (auto Interp in PhdrINTERP)
|
||||
{
|
||||
Memory::SmartHeap InterpreterPath = Memory::SmartHeap(256);
|
||||
fd->seek(Interp.p_offset, SEEK_SET);
|
||||
fd->read(InterpreterPath, 256);
|
||||
fd->Read(InterpreterPath, 256, Interp.p_offset);
|
||||
InterpreterPath = InterpreterPath;
|
||||
|
||||
vfs::RefNode *ifd = fs->Open((const char *)InterpreterPath.Get());
|
||||
FileNode *ifd = fs->GetByPath((const char *)InterpreterPath.Get(), TargetProcess->Info.RootNode);
|
||||
if (ifd == nullptr)
|
||||
{
|
||||
warn("Failed to open interpreter file: %s",
|
||||
@ -352,22 +339,19 @@ namespace Execute
|
||||
{
|
||||
warn("Interpreter %s is not an ELF file",
|
||||
(const char *)InterpreterPath.Get());
|
||||
delete ifd;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (LoadInterpreter(ifd, TargetProcess))
|
||||
{
|
||||
debug("Interpreter loaded successfully");
|
||||
delete ifd;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Elf64_Ehdr ELFHeader;
|
||||
fd->seek(0, SEEK_SET);
|
||||
fd->read((uint8_t *)&ELFHeader, sizeof(Elf64_Ehdr));
|
||||
fd->Read(&ELFHeader, sizeof(Elf64_Ehdr), 0);
|
||||
uintptr_t EntryPoint = ELFHeader.e_entry;
|
||||
debug("Entry point is %#lx", EntryPoint);
|
||||
|
||||
@ -383,8 +367,7 @@ namespace Execute
|
||||
size_t SegmentsSize = 0;
|
||||
for (Elf64_Half i = 0; i < ELFHeader.e_phnum; i++)
|
||||
{
|
||||
fd->seek(ELFHeader.e_phoff + (i * sizeof(Elf64_Phdr)), SEEK_SET);
|
||||
fd->read((uint8_t *)&ProgramHeader, sizeof(Elf64_Phdr));
|
||||
fd->Read(&ProgramHeader, sizeof(Elf64_Phdr), ELFHeader.e_phoff + (i * sizeof(Elf64_Phdr)));
|
||||
|
||||
if (ProgramHeader.p_type == PT_LOAD ||
|
||||
ProgramHeader.p_type == PT_DYNAMIC)
|
||||
@ -408,8 +391,7 @@ namespace Execute
|
||||
|
||||
for (Elf64_Half i = 0; i < ELFHeader.e_phnum; i++)
|
||||
{
|
||||
fd->seek(ELFHeader.e_phoff + (i * sizeof(Elf64_Phdr)), SEEK_SET);
|
||||
fd->read((uint8_t *)&ProgramHeader, sizeof(Elf64_Phdr));
|
||||
fd->Read(&ProgramHeader, sizeof(Elf64_Phdr), ELFHeader.e_phoff + (i * sizeof(Elf64_Phdr)));
|
||||
|
||||
switch (ProgramHeader.p_type)
|
||||
{
|
||||
@ -428,8 +410,7 @@ namespace Execute
|
||||
|
||||
if (ProgramHeader.p_filesz > 0)
|
||||
{
|
||||
fd->seek(ProgramHeader.p_offset, SEEK_SET);
|
||||
fd->read((uint8_t *)SegmentDestination, ProgramHeader.p_filesz);
|
||||
fd->Read(SegmentDestination, ProgramHeader.p_filesz, ProgramHeader.p_offset);
|
||||
}
|
||||
|
||||
if (ProgramHeader.p_memsz - ProgramHeader.p_filesz > 0)
|
||||
@ -455,8 +436,7 @@ namespace Execute
|
||||
|
||||
if (ProgramHeader.p_filesz > 0)
|
||||
{
|
||||
fd->seek(ProgramHeader.p_offset, SEEK_SET);
|
||||
fd->read((uint8_t *)DynamicSegmentDestination, ProgramHeader.p_filesz);
|
||||
fd->Read(DynamicSegmentDestination, ProgramHeader.p_filesz, ProgramHeader.p_offset);
|
||||
}
|
||||
|
||||
if (ProgramHeader.p_memsz - ProgramHeader.p_filesz > 0)
|
||||
@ -559,14 +539,11 @@ namespace Execute
|
||||
// Elf64_Shdr shdr;
|
||||
// for (Elf64_Half i = 0; i < ELFHeader.e_shnum; i++)
|
||||
// {
|
||||
// fd->seek(ELFHeader.e_shoff + i * sizeof(Elf64_Shdr), SEEK_SET);
|
||||
// fd->read((uint8_t *)&shdr, sizeof(Elf64_Shdr));
|
||||
// fd->Read(&shdr, sizeof(Elf64_Shdr), ELFHeader.e_shoff + i * sizeof(Elf64_Shdr));
|
||||
// char sectionName[32];
|
||||
// Elf64_Shdr n_shdr;
|
||||
// fd->seek(ELFHeader.e_shoff + ELFHeader.e_shstrndx * sizeof(Elf64_Shdr), SEEK_SET);
|
||||
// fd->read((uint8_t *)&n_shdr, sizeof(Elf64_Shdr));
|
||||
// fd->seek(n_shdr.sh_offset + shdr.sh_name, SEEK_SET);
|
||||
// fd->read((uint8_t *)sectionName, 32);
|
||||
// fd->Read(&n_shdr, sizeof(Elf64_Shdr), ELFHeader.e_shoff + ELFHeader.e_shstrndx * sizeof(Elf64_Shdr));
|
||||
// fd->Read(sectionName, sizeof(sectionName), n_shdr.sh_offset + shdr.sh_name);
|
||||
// debug("shdr: %s", sectionName);
|
||||
// if (strcmp(sectionName, ".rela.plt") == 0)
|
||||
// {
|
||||
@ -692,8 +669,7 @@ namespace Execute
|
||||
// // STT_OBJECT
|
||||
// Elf64_Xword numEntries = shdr.sh_size / shdr.sh_entsize;
|
||||
// Elf64_Sym *SymArray = new Elf64_Sym[numEntries];
|
||||
// fd->seek(shdr.sh_offset, SEEK_SET);
|
||||
// fd->read((uint8_t *)SymArray, shdr.sh_size);
|
||||
// fd->Read(SymArray, shdr.sh_size, shdr.sh_offset);
|
||||
// debug("start %#lx (off %#lx), entries %ld",
|
||||
// SymArray, shdr.sh_addr, numEntries);
|
||||
// for (Elf64_Xword j = 0; j < numEntries; j++)
|
||||
@ -734,10 +710,10 @@ namespace Execute
|
||||
#endif
|
||||
}
|
||||
|
||||
bool ELFObject::LoadInterpreter(vfs::RefNode *fd, PCB *TargetProcess)
|
||||
bool ELFObject::LoadInterpreter(FileNode *fd, PCB *TargetProcess)
|
||||
{
|
||||
Elf32_Ehdr ELFHeader;
|
||||
fd->read((uint8_t *)&ELFHeader, sizeof(Elf32_Ehdr));
|
||||
fd->Read(&ELFHeader, sizeof(Elf32_Ehdr), 0);
|
||||
|
||||
switch (ELFHeader.e_type)
|
||||
{
|
||||
@ -805,24 +781,24 @@ namespace Execute
|
||||
return false;
|
||||
}
|
||||
|
||||
ELFObject::ELFObject(char *AbsolutePath,
|
||||
ELFObject::ELFObject(std::string AbsolutePath,
|
||||
PCB *TargetProcess,
|
||||
const char **argv,
|
||||
const char **envp)
|
||||
{
|
||||
if (GetBinaryType(AbsolutePath) != BinaryType::BinTypeELF)
|
||||
{
|
||||
error("%s is not an ELF file or is invalid.", AbsolutePath);
|
||||
error("%s is not an ELF file or is invalid.", AbsolutePath.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
vfs::RefNode *fd = fs->Open(AbsolutePath);
|
||||
FileNode *fd = fs->GetByPath(AbsolutePath.c_str(), TargetProcess->Info.RootNode);
|
||||
if (fd == nullptr)
|
||||
{
|
||||
error("Failed to open %s, errno: %d", AbsolutePath, fd);
|
||||
error("Failed to open %s, errno: %d", AbsolutePath.c_str(), fd);
|
||||
return;
|
||||
}
|
||||
debug("Opened %s", AbsolutePath);
|
||||
debug("Opened %s", AbsolutePath.c_str());
|
||||
|
||||
int argc = 0;
|
||||
int envc = 0;
|
||||
@ -833,17 +809,15 @@ namespace Execute
|
||||
envc++;
|
||||
|
||||
Elf32_Ehdr ELFHeader;
|
||||
fd->read((uint8_t *)&ELFHeader, sizeof(Elf32_Ehdr));
|
||||
fd->Read(&ELFHeader, sizeof(Elf32_Ehdr), 0);
|
||||
|
||||
std::vector<Elf64_Phdr> PhdrINTERP = ELFGetSymbolType_x86_64(fd, PT_INTERP);
|
||||
const char *ElfInterpPath = nullptr;
|
||||
if (!PhdrINTERP.empty() && ELFHeader.e_type == ET_DYN)
|
||||
{
|
||||
fd->seek(PhdrINTERP.front().p_offset, SEEK_SET);
|
||||
ElfInterpPath = new char[256];
|
||||
fd->read((uint8_t *)ElfInterpPath, 256);
|
||||
fd->Read(ElfInterpPath, 256, PhdrINTERP.front().p_offset);
|
||||
debug("Interpreter: %s", ElfInterpPath);
|
||||
fd->seek(0, SEEK_SET);
|
||||
argc++;
|
||||
}
|
||||
|
||||
@ -945,8 +919,6 @@ namespace Execute
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
delete fd;
|
||||
}
|
||||
|
||||
ELFObject::~ELFObject()
|
||||
|
@ -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 {};
|
||||
}
|
||||
|
@ -21,16 +21,14 @@
|
||||
|
||||
namespace Execute
|
||||
{
|
||||
std::vector<Elf64_Dyn> ELFGetDynamicTag_x86_64(vfs::RefNode *fd,
|
||||
std::vector<Elf64_Dyn> ELFGetDynamicTag_x86_64(FileNode *fd,
|
||||
DynamicArrayTags Tag)
|
||||
{
|
||||
#if defined(a64) || defined(aa64)
|
||||
off_t OldOffset = fd->seek(0, SEEK_CUR);
|
||||
std::vector<Elf64_Dyn> Ret;
|
||||
|
||||
Elf64_Ehdr ELFHeader;
|
||||
fd->seek(0, SEEK_SET);
|
||||
fd->read((uint8_t *)&ELFHeader, sizeof(Elf64_Ehdr));
|
||||
Elf64_Ehdr ELFHeader{};
|
||||
fd->Read(&ELFHeader, sizeof(Elf64_Ehdr), 0);
|
||||
|
||||
std::vector<Elf64_Phdr> DYNAMICPhdrs = ELFGetSymbolType_x86_64(fd, PT_DYNAMIC);
|
||||
|
||||
@ -42,11 +40,10 @@ namespace Execute
|
||||
|
||||
foreach (auto Phdr in DYNAMICPhdrs)
|
||||
{
|
||||
Elf64_Dyn Dynamic;
|
||||
Elf64_Dyn Dynamic{};
|
||||
for (size_t i = 0; i < Phdr.p_filesz / sizeof(Elf64_Dyn); i++)
|
||||
{
|
||||
fd->seek(Phdr.p_offset + (i * sizeof(Elf64_Dyn)), SEEK_SET);
|
||||
fd->read((uint8_t *)&Dynamic, sizeof(Elf64_Dyn));
|
||||
fd->Read(&Dynamic, sizeof(Elf64_Dyn), Phdr.p_offset + (i * sizeof(Elf64_Dyn)));
|
||||
|
||||
if (Dynamic.d_tag != Tag)
|
||||
continue;
|
||||
@ -57,7 +54,6 @@ namespace Execute
|
||||
}
|
||||
}
|
||||
|
||||
fd->seek(OldOffset, SEEK_SET);
|
||||
return Ret;
|
||||
#elif defined(a32)
|
||||
return {};
|
||||
|
@ -21,24 +21,20 @@
|
||||
|
||||
namespace Execute
|
||||
{
|
||||
std::vector<Elf64_Shdr> ELFGetSections_x86_64(vfs::RefNode *fd,
|
||||
std::vector<Elf64_Shdr> ELFGetSections_x86_64(FileNode *fd,
|
||||
const char *SectionName)
|
||||
{
|
||||
#if defined(a64) || defined(aa64)
|
||||
off_t OldOffset = fd->seek(0, SEEK_CUR);
|
||||
std::vector<Elf64_Shdr> Ret;
|
||||
|
||||
Elf64_Ehdr ELFHeader;
|
||||
fd->seek(0, SEEK_SET);
|
||||
fd->read((uint8_t *)&ELFHeader, sizeof(Elf64_Ehdr));
|
||||
Elf64_Ehdr ELFHeader{};
|
||||
fd->Read(&ELFHeader, sizeof(Elf64_Ehdr), 0);
|
||||
|
||||
Elf64_Shdr *SectionHeaders = new Elf64_Shdr[ELFHeader.e_shnum];
|
||||
fd->seek(ELFHeader.e_shoff, SEEK_SET);
|
||||
fd->read((uint8_t *)SectionHeaders, sizeof(Elf64_Shdr) * ELFHeader.e_shnum);
|
||||
fd->Read(SectionHeaders, sizeof(Elf64_Shdr) * ELFHeader.e_shnum, ELFHeader.e_shoff);
|
||||
|
||||
char *SectionNames = new char[SectionHeaders[ELFHeader.e_shstrndx].sh_size];
|
||||
fd->seek(SectionHeaders[ELFHeader.e_shstrndx].sh_offset, SEEK_SET);
|
||||
fd->read((uint8_t *)SectionNames, SectionHeaders[ELFHeader.e_shstrndx].sh_size);
|
||||
fd->Read(SectionNames, SectionHeaders[ELFHeader.e_shstrndx].sh_size, SectionHeaders[ELFHeader.e_shstrndx].sh_offset);
|
||||
|
||||
for (Elf64_Half i = 0; i < ELFHeader.e_shnum; ++i)
|
||||
{
|
||||
@ -47,7 +43,6 @@ namespace Execute
|
||||
Ret.push_back(SectionHeaders[i]);
|
||||
}
|
||||
|
||||
fd->seek(OldOffset, SEEK_SET);
|
||||
delete[] SectionHeaders;
|
||||
delete[] SectionNames;
|
||||
return Ret;
|
||||
|
@ -21,31 +21,28 @@
|
||||
|
||||
namespace Execute
|
||||
{
|
||||
std::vector<Elf64_Phdr> ELFGetSymbolType_x86_64(vfs::RefNode *fd,
|
||||
std::vector<Elf64_Phdr> ELFGetSymbolType_x86_64(FileNode *fd,
|
||||
SegmentTypes Tag)
|
||||
{
|
||||
#if defined(a64) || defined(aa64)
|
||||
off_t OldOffset = fd->seek(0, SEEK_CUR);
|
||||
std::vector<Elf64_Phdr> Ret;
|
||||
|
||||
Elf64_Ehdr ELFHeader;
|
||||
fd->seek(0, SEEK_SET);
|
||||
fd->read((uint8_t *)&ELFHeader, sizeof(Elf64_Ehdr));
|
||||
Elf64_Ehdr ELFHeader{};
|
||||
fd->Read(&ELFHeader, sizeof(Elf64_Ehdr), 0);
|
||||
|
||||
Elf64_Phdr ProgramHeaders;
|
||||
fd->seek(ELFHeader.e_phoff, SEEK_SET);
|
||||
fd->read((uint8_t *)&ProgramHeaders, sizeof(Elf64_Phdr));
|
||||
Elf64_Phdr ProgramHeaders{};
|
||||
fd->Read(&ProgramHeaders, sizeof(Elf64_Phdr), ELFHeader.e_phoff);
|
||||
|
||||
off_t currentOffset = ELFHeader.e_phoff;
|
||||
for (Elf64_Half i = 0; i < ELFHeader.e_phnum; i++)
|
||||
{
|
||||
if (ProgramHeaders.p_type == Tag)
|
||||
Ret.push_back(ProgramHeaders);
|
||||
|
||||
fd->seek(sizeof(Elf64_Phdr), SEEK_CUR);
|
||||
fd->read((uint8_t *)&ProgramHeaders, sizeof(Elf64_Phdr));
|
||||
currentOffset += sizeof(Elf64_Phdr);
|
||||
fd->Read(&ProgramHeaders, sizeof(Elf64_Phdr), currentOffset);
|
||||
}
|
||||
|
||||
fd->seek(OldOffset, SEEK_SET);
|
||||
return Ret;
|
||||
#elif defined(a32)
|
||||
return {};
|
||||
|
@ -35,15 +35,12 @@ namespace Execute
|
||||
Tasking::TaskCompatibility Compatibility,
|
||||
bool Critical)
|
||||
{
|
||||
vfs::RefNode *fd = fs->Open(Path);
|
||||
FileNode *fd = fs->GetByPath(Path, nullptr);
|
||||
if (fd == nullptr)
|
||||
return -ENOENT;
|
||||
|
||||
if (fd->node->Type == vfs::NodeType::DIRECTORY)
|
||||
{
|
||||
delete fd;
|
||||
return -EISDIR;
|
||||
}
|
||||
if (!fd->IsRegularFile())
|
||||
return -ENOEXEC;
|
||||
|
||||
switch (GetBinaryType(Path))
|
||||
{
|
||||
@ -53,7 +50,7 @@ namespace Execute
|
||||
const char *BaseName;
|
||||
cwk_path_get_basename(Path, &BaseName, nullptr);
|
||||
Elf32_Ehdr ELFHeader;
|
||||
fd->read((uint8_t *)&ELFHeader, sizeof(Elf32_Ehdr));
|
||||
fd->Read(&ELFHeader, sizeof(Elf32_Ehdr), 0);
|
||||
|
||||
switch (ELFHeader.e_machine)
|
||||
{
|
||||
@ -119,22 +116,20 @@ namespace Execute
|
||||
if (Parent == nullptr)
|
||||
Parent = thisProcess;
|
||||
|
||||
Process = TaskManager->CreateProcess(Parent,
|
||||
BaseName,
|
||||
Process = TaskManager->CreateProcess(Parent, BaseName,
|
||||
TaskExecutionMode::User,
|
||||
false, 0, 0);
|
||||
Process->Info.Compatibility = Compatibility;
|
||||
Process->Info.Architecture = Arch;
|
||||
}
|
||||
|
||||
Process->SetWorkingDirectory(fs->GetNodeFromPath(Path)->Parent);
|
||||
Process->SetWorkingDirectory(fs->GetByPath(Path, nullptr)->Parent);
|
||||
Process->SetExe(Path);
|
||||
|
||||
ELFObject *obj = new ELFObject(Path, Process, argv, envp);
|
||||
if (!obj->IsValid)
|
||||
{
|
||||
error("Failed to load ELF object");
|
||||
delete fd;
|
||||
delete Process;
|
||||
return -ENOEXEC;
|
||||
}
|
||||
@ -142,23 +137,20 @@ namespace Execute
|
||||
vfs::FileDescriptorTable *pfdt = Parent->FileDescriptors;
|
||||
vfs::FileDescriptorTable *fdt = Process->FileDescriptors;
|
||||
|
||||
auto ForkStdio = [pfdt, fdt](Node *SearchNode)
|
||||
auto ForkStdio = [pfdt, fdt](FileNode *SearchNode)
|
||||
{
|
||||
if (unlikely(SearchNode == nullptr))
|
||||
return false;
|
||||
|
||||
std::vector<FileDescriptorTable::Fildes>
|
||||
pfds = pfdt->GetFileDescriptors();
|
||||
|
||||
foreach (auto ffd in pfds)
|
||||
foreach (const auto &ffd in pfdt->FileMap)
|
||||
{
|
||||
if (ffd.Flags & O_CLOEXEC)
|
||||
if (ffd.second.Flags & O_CLOEXEC)
|
||||
continue;
|
||||
|
||||
if (ffd.Handle->node == SearchNode)
|
||||
if (ffd.second.Node == SearchNode)
|
||||
{
|
||||
fdt->_open(ffd.Handle->node->FullPath,
|
||||
ffd.Flags, ffd.Mode);
|
||||
fdt->usr_open(ffd.second.Node->Path.c_str(),
|
||||
ffd.second.Flags, ffd.second.Mode);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -166,37 +158,31 @@ namespace Execute
|
||||
};
|
||||
|
||||
if (!ForkStdio(Parent->stdin))
|
||||
fdt->_open("/dev/kcon", O_RDWR, 0666);
|
||||
fdt->usr_open("/dev/kcon", O_RDWR, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
|
||||
|
||||
if (!ForkStdio(Parent->stdout))
|
||||
fdt->_open("/dev/kcon", O_RDWR, 0666);
|
||||
fdt->usr_open("/dev/kcon", O_RDWR, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
|
||||
|
||||
if (!ForkStdio(Parent->stderr))
|
||||
fdt->_open("/dev/kcon", O_RDWR, 0666);
|
||||
fdt->usr_open("/dev/kcon", O_RDWR, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
|
||||
|
||||
TCB *Thread = nullptr;
|
||||
{
|
||||
CriticalSection cs;
|
||||
Thread = TaskManager->CreateThread(Process,
|
||||
obj->InstructionPointer,
|
||||
Thread = TaskManager->CreateThread(Process, obj->InstructionPointer,
|
||||
obj->argv, obj->envp, obj->auxv,
|
||||
Arch,
|
||||
Compatibility);
|
||||
Arch, Compatibility);
|
||||
Thread->SetCritical(Critical);
|
||||
}
|
||||
delete fd;
|
||||
return Thread->ID;
|
||||
}
|
||||
default:
|
||||
{
|
||||
debug("Unknown binary type: %d",
|
||||
GetBinaryType(Path));
|
||||
delete fd;
|
||||
debug("Unknown binary type: %d", GetBinaryType(Path));
|
||||
return -ENOEXEC;
|
||||
}
|
||||
}
|
||||
|
||||
delete fd;
|
||||
return -ENOEXEC;
|
||||
}
|
||||
}
|
||||
|
@ -15,25 +15,31 @@
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <syscalls.hpp>
|
||||
#ifndef __FENNIX_KERNEL_CIRCULAR_BUFFER_H__
|
||||
#define __FENNIX_KERNEL_CIRCULAR_BUFFER_H__
|
||||
|
||||
#include <memory.hpp>
|
||||
#include <types.h>
|
||||
#include <lock.hpp>
|
||||
#include <exec.hpp>
|
||||
#include <errno.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include "../../syscalls.h"
|
||||
#include "../../kernel.h"
|
||||
|
||||
using Tasking::PCB;
|
||||
|
||||
/* https://pubs.opengroup.org/onlinepubs/009604499/functions/lseek.html */
|
||||
off_t sys_lseek(SysFrm *, int fildes,
|
||||
off_t offset, int whence)
|
||||
class CircularBuffer
|
||||
{
|
||||
function("%d, %d, %d", fildes, offset, whence);
|
||||
PCB *pcb = thisProcess;
|
||||
vfs::FileDescriptorTable *fdt = pcb->FileDescriptors;
|
||||
return fdt->_lseek(fildes, offset, whence);
|
||||
}
|
||||
private:
|
||||
spin_lock Lock;
|
||||
uint8_t *Buffer;
|
||||
size_t BufferSize;
|
||||
size_t BufferCount;
|
||||
|
||||
size_t Head;
|
||||
size_t Tail;
|
||||
|
||||
public:
|
||||
CircularBuffer(size_t Size);
|
||||
~CircularBuffer();
|
||||
size_t Write(const uint8_t *Data, size_t Size);
|
||||
size_t Read(uint8_t *Data, size_t Size);
|
||||
size_t Peek(uint8_t *Data, size_t Size);
|
||||
size_t Count();
|
||||
size_t Free();
|
||||
};
|
||||
|
||||
#endif // !__FENNIX_KERNEL_CIRCULAR_BUFFER_H__
|
@ -17,6 +17,7 @@
|
||||
|
||||
#pragma once
|
||||
#include <types.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
@ -31,11 +32,7 @@ extern "C"
|
||||
|
||||
#define NAN (__builtin_nanf(""))
|
||||
|
||||
int isdigit(int c);
|
||||
int isspace(int c);
|
||||
int isempty(char *str);
|
||||
int isalpha(int c);
|
||||
int isupper(int c);
|
||||
unsigned int isdelim(char c, const char *delim);
|
||||
long abs(long i);
|
||||
void swap(char *x, char *y);
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2020 Leonard Iklé
|
||||
Copyright (c) 2024 Leonard Iklé
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
@ -27,7 +27,8 @@ SOFTWARE.
|
||||
#ifndef CWK_LIBRARY_H
|
||||
#define CWK_LIBRARY_H
|
||||
|
||||
#include <types.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#if defined(_WIN32) || defined(__CYGWIN__)
|
||||
#define CWK_EXPORT __declspec(dllexport)
|
||||
@ -344,9 +345,10 @@ CWK_PUBLIC size_t cwk_path_change_extension(const char *path,
|
||||
* This function creates a normalized version of the path within the specified
|
||||
* buffer. This function will not write out more than the specified buffer can
|
||||
* contain. However, the generated string is always null-terminated - even if
|
||||
* not the whole path is written out. The function returns the total number of
|
||||
* characters the complete buffer would have, even if it was not written out
|
||||
* completely. The path may be the same memory address as the buffer.
|
||||
* not the whole path is written out. The returned value is the amount of
|
||||
* characters which the resulting path would take if it was not truncated
|
||||
* (excluding the null-terminating character). The path may be the same memory
|
||||
* address as the buffer.
|
||||
*
|
||||
* The following will be true for the normalized path:
|
||||
* 1) "../" will be resolved.
|
||||
@ -518,4 +520,4 @@ CWK_PUBLIC enum cwk_path_style cwk_path_get_style(void);
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
@ -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__)
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include <memory.hpp>
|
||||
#include <debug.h>
|
||||
#include <cstring>
|
||||
#include <vector>
|
||||
|
||||
extern uintptr_t _binary_files_tamsyn_font_1_11_Tamsyn10x20b_psf_end;
|
||||
extern uintptr_t _binary_files_tamsyn_font_1_11_Tamsyn10x20b_psf_size;
|
||||
|
@ -38,111 +38,6 @@ namespace Driver
|
||||
char GetScanCode(uint8_t ScanCode, bool Upper);
|
||||
bool IsValidChar(uint8_t ScanCode);
|
||||
|
||||
class SlaveDeviceFile : public vfs::Node
|
||||
{
|
||||
private:
|
||||
int /* DeviceDriverType */ DeviceType;
|
||||
|
||||
std::list<uint8_t> KeyQueue;
|
||||
|
||||
public:
|
||||
typedef int (*drvOpen_t)(dev_t, dev_t, int, mode_t);
|
||||
typedef int (*drvClose_t)(dev_t, dev_t);
|
||||
typedef size_t (*drvRead_t)(dev_t, dev_t, uint8_t *, size_t, off_t);
|
||||
typedef size_t (*drvWrite_t)(dev_t, dev_t, uint8_t *, size_t, off_t);
|
||||
typedef int (*drvIoctl_t)(dev_t, dev_t, unsigned long, void *);
|
||||
|
||||
drvOpen_t Open;
|
||||
drvClose_t Close;
|
||||
drvRead_t Read;
|
||||
drvWrite_t Write;
|
||||
drvIoctl_t Ioctl;
|
||||
|
||||
int open(int Flags, mode_t Mode) final;
|
||||
int close() final;
|
||||
size_t read(uint8_t *Buffer,
|
||||
size_t Size,
|
||||
off_t Offset) final;
|
||||
size_t write(uint8_t *Buffer,
|
||||
size_t Size,
|
||||
off_t Offset) final;
|
||||
int ioctl(unsigned long Request,
|
||||
void *Argp) final;
|
||||
|
||||
void ClearBuffers();
|
||||
|
||||
int ReportKeyEvent(uint8_t ScanCode);
|
||||
|
||||
SlaveDeviceFile(const char *Name, vfs::Node *Parent, int Type, vfs::NodeType NType);
|
||||
~SlaveDeviceFile();
|
||||
};
|
||||
|
||||
class MasterDeviceFile : private vfs::Node
|
||||
{
|
||||
private:
|
||||
typedef dev_t maj_t;
|
||||
typedef dev_t min_t;
|
||||
char SlaveName[16];
|
||||
vfs::Node *SlaveParent;
|
||||
int /* DeviceDriverType */ DeviceType;
|
||||
min_t SlaveIDCounter = 0;
|
||||
|
||||
typedef std::unordered_map<min_t, SlaveDeviceFile *> *Slaves;
|
||||
std::unordered_map<maj_t, Slaves> SlavesMap;
|
||||
|
||||
std::list<uint8_t> RawKeyQueue;
|
||||
std::list<uint8_t> KeyQueue;
|
||||
bool UpperCase = false;
|
||||
bool CapsLock = false;
|
||||
|
||||
public:
|
||||
typedef int (*drvOpen_t)(dev_t, dev_t, int, mode_t);
|
||||
typedef int (*drvClose_t)(dev_t, dev_t);
|
||||
typedef size_t (*drvRead_t)(dev_t, dev_t, uint8_t *, size_t, off_t);
|
||||
typedef size_t (*drvWrite_t)(dev_t, dev_t, uint8_t *, size_t, off_t);
|
||||
typedef int (*drvIoctl_t)(dev_t, dev_t, unsigned long, void *);
|
||||
|
||||
int open(int Flags, mode_t Mode) final;
|
||||
int close() final;
|
||||
size_t read(uint8_t *Buffer,
|
||||
size_t Size,
|
||||
off_t Offset) final;
|
||||
size_t write(uint8_t *Buffer,
|
||||
size_t Size,
|
||||
off_t Offset) final;
|
||||
int ioctl(unsigned long Request,
|
||||
void *Argp) final;
|
||||
|
||||
void ClearBuffers();
|
||||
|
||||
int ReportKeyEvent(maj_t ID, min_t MinorID, uint8_t ScanCode);
|
||||
int ReportMouseEvent(maj_t ID, min_t MinorID,
|
||||
bool LeftButton, bool RightButton, bool MiddleButton,
|
||||
bool Button4, bool Button5, bool Button6,
|
||||
bool Button7, bool Button8,
|
||||
uintptr_t X, uintptr_t Y, int8_t Z, bool Relative);
|
||||
|
||||
int ReportNetworkPacket(maj_t ID, min_t MinorID, void *Buffer, size_t Size);
|
||||
|
||||
int NewBlock(maj_t ID, min_t MinorID, drvOpen_t Open, drvClose_t Close,
|
||||
drvRead_t Read, drvWrite_t Write, drvIoctl_t Ioctl);
|
||||
|
||||
int NewAudio(maj_t ID, min_t MinorID, drvOpen_t Open, drvClose_t Close,
|
||||
drvRead_t Read, drvWrite_t Write, drvIoctl_t Ioctl);
|
||||
|
||||
int NewNet(maj_t ID, min_t MinorID, drvOpen_t Open, drvClose_t Close,
|
||||
drvRead_t Read, drvWrite_t Write, drvIoctl_t Ioctl);
|
||||
|
||||
dev_t Register(maj_t ID);
|
||||
int Unregister(maj_t ID, min_t MinorID);
|
||||
|
||||
MasterDeviceFile(const char *MasterName,
|
||||
const char *SlaveName,
|
||||
vfs::Node *Parent,
|
||||
int Type);
|
||||
~MasterDeviceFile();
|
||||
};
|
||||
|
||||
struct DriverObject
|
||||
{
|
||||
uintptr_t BaseAddress = 0;
|
||||
@ -150,7 +45,7 @@ namespace Driver
|
||||
Memory::VirtualMemoryArea *vma = nullptr;
|
||||
|
||||
/* Path has the same pointer as in the Node */
|
||||
const char *Path = nullptr;
|
||||
std::string Path;
|
||||
std::unordered_map<uint8_t, void *> *InterruptHandlers;
|
||||
|
||||
char Name[32] = {'\0'};
|
||||
@ -172,28 +67,18 @@ namespace Driver
|
||||
private:
|
||||
NewLock(ModuleInitLock);
|
||||
std::unordered_map<dev_t, DriverObject> Drivers;
|
||||
dev_t MajorIDCounter = 0;
|
||||
dev_t DriverIDCounter = 0;
|
||||
|
||||
int LoadDriverFile(uintptr_t &EntryPoint,
|
||||
uintptr_t &BaseAddress,
|
||||
Memory::VirtualMemoryArea *dVma,
|
||||
vfs::RefNode *rDrv);
|
||||
FileNode *rDrv);
|
||||
|
||||
public:
|
||||
MasterDeviceFile *InputMouseDev = nullptr;
|
||||
MasterDeviceFile *InputKeyboardDev = nullptr;
|
||||
|
||||
MasterDeviceFile *BlockSATADev = nullptr;
|
||||
MasterDeviceFile *BlockHDDev = nullptr;
|
||||
MasterDeviceFile *BlockNVMeDev = nullptr;
|
||||
|
||||
MasterDeviceFile *AudioDev = nullptr;
|
||||
|
||||
MasterDeviceFile *NetDev = nullptr;
|
||||
|
||||
std::unordered_map<dev_t, DriverObject> &
|
||||
GetDrivers() { return Drivers; }
|
||||
|
||||
void PreloadDrivers();
|
||||
void LoadAllDrivers();
|
||||
void UnloadAllDrivers();
|
||||
void Panic();
|
||||
|
@ -22,7 +22,6 @@
|
||||
|
||||
#include <filesystem.hpp>
|
||||
#include <task.hpp>
|
||||
#include <std.hpp>
|
||||
#include <errno.h>
|
||||
#include <vector>
|
||||
#include <elf.h>
|
||||
@ -36,6 +35,7 @@ namespace Execute
|
||||
BinTypePE,
|
||||
BinTypeNE,
|
||||
BinTypeMZ,
|
||||
BinTypeMachO,
|
||||
BinTypeUnknown
|
||||
};
|
||||
|
||||
@ -67,20 +67,20 @@ namespace Execute
|
||||
void *ELFProgramHeaders;
|
||||
|
||||
void GenerateAuxiliaryVector_x86_32(Memory::VirtualMemoryArea *vma,
|
||||
vfs::RefNode *fd, Elf32_Ehdr ELFHeader,
|
||||
FileNode *fd, Elf32_Ehdr ELFHeader,
|
||||
uint32_t EntryPoint,
|
||||
uint32_t BaseAddress);
|
||||
|
||||
void GenerateAuxiliaryVector_x86_64(Memory::VirtualMemoryArea *vma,
|
||||
vfs::RefNode *fd, Elf64_Ehdr ELFHeader,
|
||||
FileNode *fd, Elf64_Ehdr ELFHeader,
|
||||
uint64_t EntryPoint,
|
||||
uint64_t BaseAddress);
|
||||
|
||||
void LoadExec_x86_32(vfs::RefNode *fd, Tasking::PCB *TargetProcess);
|
||||
void LoadExec_x86_64(vfs::RefNode *fd, Tasking::PCB *TargetProcess);
|
||||
void LoadDyn_x86_32(vfs::RefNode *fd, Tasking::PCB *TargetProcess);
|
||||
void LoadDyn_x86_64(vfs::RefNode *fd, Tasking::PCB *TargetProcess);
|
||||
bool LoadInterpreter(vfs::RefNode *fd, Tasking::PCB *TargetProcess);
|
||||
void LoadExec_x86_32(FileNode *fd, Tasking::PCB *TargetProcess);
|
||||
void LoadExec_x86_64(FileNode *fd, Tasking::PCB *TargetProcess);
|
||||
void LoadDyn_x86_32(FileNode *fd, Tasking::PCB *TargetProcess);
|
||||
void LoadDyn_x86_64(FileNode *fd, Tasking::PCB *TargetProcess);
|
||||
bool LoadInterpreter(FileNode *fd, Tasking::PCB *TargetProcess);
|
||||
|
||||
public:
|
||||
decltype(IsElfValid) &IsValid = IsElfValid;
|
||||
@ -89,14 +89,15 @@ namespace Execute
|
||||
decltype(ELFenvp) &envp = ELFenvp;
|
||||
decltype(Elfauxv) &auxv = Elfauxv;
|
||||
|
||||
ELFObject(char *AbsolutePath,
|
||||
ELFObject(std::string AbsolutePath,
|
||||
Tasking::PCB *TargetProcess,
|
||||
const char **argv,
|
||||
const char **envp);
|
||||
~ELFObject();
|
||||
};
|
||||
|
||||
BinaryType GetBinaryType(const char *Path);
|
||||
BinaryType GetBinaryType(FileNode *Path);
|
||||
BinaryType GetBinaryType(std::string Path);
|
||||
|
||||
int Spawn(char *Path, const char **argv, const char **envp,
|
||||
Tasking::PCB *Parent = nullptr, bool Fork = false,
|
||||
@ -108,18 +109,18 @@ namespace Execute
|
||||
Elf64_Shdr *GetELFSection(Elf64_Ehdr *Header, uint64_t Index);
|
||||
char *GetELFStringTable(Elf64_Ehdr *Header);
|
||||
char *ELFLookupString(Elf64_Ehdr *Header, uintptr_t Offset);
|
||||
Elf64_Sym *ELFLookupSymbol(Elf64_Ehdr *Header, const char *Name);
|
||||
Elf64_Sym ELFLookupSymbol(vfs::RefNode *fd, const char *Name);
|
||||
Elf64_Sym *ELFLookupSymbol(Elf64_Ehdr *Header, std::string Name);
|
||||
Elf64_Sym ELFLookupSymbol(FileNode *fd, std::string Name);
|
||||
uintptr_t ELFGetSymbolValue(Elf64_Ehdr *Header, uint64_t Table, uint64_t Index);
|
||||
|
||||
std::vector<Elf64_Phdr> ELFGetSymbolType_x86_64(vfs::RefNode *fd, SegmentTypes Tag);
|
||||
std::vector<Elf32_Phdr> ELFGetSymbolType_x86_32(vfs::RefNode *fd, SegmentTypes Tag);
|
||||
std::vector<Elf64_Phdr> ELFGetSymbolType_x86_64(FileNode *fd, SegmentTypes Tag);
|
||||
std::vector<Elf32_Phdr> ELFGetSymbolType_x86_32(FileNode *fd, SegmentTypes Tag);
|
||||
|
||||
std::vector<Elf64_Shdr> ELFGetSections_x86_64(vfs::RefNode *fd, const char *SectionName);
|
||||
std::vector<Elf32_Shdr> ELFGetSections_x86_32(vfs::RefNode *fd, const char *SectionName);
|
||||
std::vector<Elf64_Shdr> ELFGetSections_x86_64(FileNode *fd, std::string SectionName);
|
||||
std::vector<Elf32_Shdr> ELFGetSections_x86_32(FileNode *fd, std::string SectionName);
|
||||
|
||||
std::vector<Elf64_Dyn> ELFGetDynamicTag_x86_64(vfs::RefNode *fd, DynamicArrayTags Tag);
|
||||
std::vector<Elf32_Dyn> ELFGetDynamicTag_x86_32(vfs::RefNode *fd, DynamicArrayTags Tag);
|
||||
std::vector<Elf64_Dyn> ELFGetDynamicTag_x86_64(FileNode *fd, DynamicArrayTags Tag);
|
||||
std::vector<Elf32_Dyn> ELFGetDynamicTag_x86_32(FileNode *fd, DynamicArrayTags Tag);
|
||||
}
|
||||
|
||||
#endif // !__FENNIX_KERNEL_FILE_EXECUTE_H__
|
||||
|
@ -20,309 +20,136 @@
|
||||
|
||||
#include <types.h>
|
||||
|
||||
#include <smart_ptr.hpp>
|
||||
#include <interface/fs.h>
|
||||
#include <unordered_map>
|
||||
#include <lock.hpp>
|
||||
#include <errno.h>
|
||||
#include <vector>
|
||||
#include <atomic>
|
||||
#include <string>
|
||||
#include <list>
|
||||
|
||||
#define SEEK_SET 0
|
||||
#define SEEK_CUR 1
|
||||
#define SEEK_END 2
|
||||
static_assert(DTTOIF(DT_FIFO) == S_IFIFO);
|
||||
static_assert(IFTODT(S_IFCHR) == DT_CHR);
|
||||
|
||||
/** Other users have execute permission. */
|
||||
#define S_IXOTH 0001
|
||||
/** Other users have write permission. */
|
||||
#define S_IWOTH 0002
|
||||
/** Other users have read permission. */
|
||||
#define S_IROTH 0004
|
||||
/** Other users have read, write, and execute permissions. */
|
||||
#define S_IRWXO 0007
|
||||
/** Group members have execute permission. */
|
||||
#define S_IXGRP 0010
|
||||
/** Group members have write permission. */
|
||||
#define S_IWGRP 0020
|
||||
/** Group members have read permission. */
|
||||
#define S_IRGRP 0040
|
||||
/** Group members have read, write, and execute permissions. */
|
||||
#define S_IRWXG 0070
|
||||
/** The file owner has execute permission. */
|
||||
#define S_IXUSR 0100
|
||||
/** The file owner has write permission. */
|
||||
#define S_IWUSR 0200
|
||||
/** The file owner has read permission. */
|
||||
#define S_IRUSR 0400
|
||||
/** The file owner has read, write,
|
||||
* and execute permissions. */
|
||||
#define S_IRWXU 0700
|
||||
#define __check_op(op, ...) \
|
||||
if (fsi->Ops.op == nullptr) \
|
||||
return -ENOTSUP; \
|
||||
else \
|
||||
return fsi->Ops.op(this->Node, ##__VA_ARGS__)
|
||||
|
||||
#define O_RDONLY 00
|
||||
#define O_WRONLY 01
|
||||
#define O_RDWR 02
|
||||
#define O_CREAT 0100
|
||||
#define O_EXCL 0200
|
||||
#define O_TRUNC 01000
|
||||
#define O_APPEND 02000
|
||||
#define O_CLOEXEC 02000000
|
||||
|
||||
#define S_IFIFO 0010000
|
||||
#define S_IFCHR 0020000
|
||||
#define S_IFDIR 0040000
|
||||
#define S_IFBLK 0060000
|
||||
#define S_IFREG 0100000
|
||||
#define S_IFLNK 0120000
|
||||
#define S_IFSOCK 0140000
|
||||
|
||||
#define S_IFMT 0170000
|
||||
|
||||
#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
|
||||
#define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR)
|
||||
#define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK)
|
||||
#define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
|
||||
#define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO)
|
||||
#define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK)
|
||||
#define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK)
|
||||
|
||||
struct kstat
|
||||
class FileNode
|
||||
{
|
||||
/** Device ID of the file. */
|
||||
dev_t st_dev;
|
||||
/** Inode number. */
|
||||
ino_t st_ino;
|
||||
/** File type and mode. */
|
||||
mode_t st_mode;
|
||||
/** Number of hard links. */
|
||||
nlink_t st_nlink;
|
||||
/** User ID of the file's owner. */
|
||||
uid_t st_uid;
|
||||
/** Group ID of the file's owner. */
|
||||
gid_t st_gid;
|
||||
/** Device ID for special files. */
|
||||
dev_t st_rdev;
|
||||
/** Size of the file in bytes. */
|
||||
off_t st_size;
|
||||
/** Time of last access. */
|
||||
time_t st_atime;
|
||||
/** Time of last modification. */
|
||||
time_t st_mtime;
|
||||
/** Time of last status change. */
|
||||
time_t st_ctime;
|
||||
/** Optimal I/O block size. */
|
||||
blksize_t st_blksize;
|
||||
/** Number of blocks allocated. */
|
||||
blkcnt_t st_blocks;
|
||||
/** Additional file attributes. */
|
||||
mode_t st_attr;
|
||||
public:
|
||||
std::string Name, Path;
|
||||
FileNode *Parent;
|
||||
std::vector<FileNode *> Children;
|
||||
Inode *Node;
|
||||
FileSystemInfo *fsi;
|
||||
|
||||
bool IsDirectory() { return S_ISDIR(Node->Mode); }
|
||||
bool IsCharacterDevice() { return S_ISCHR(Node->Mode); }
|
||||
bool IsBlockDevice() { return S_ISBLK(Node->Mode); }
|
||||
bool IsRegularFile() { return S_ISREG(Node->Mode); }
|
||||
bool IsFIFO() { return S_ISFIFO(Node->Mode); }
|
||||
bool IsSymbolicLink() { return S_ISLNK(Node->Mode); }
|
||||
bool IsSocket() { return S_ISSOCK(Node->Mode); }
|
||||
|
||||
int Lookup(const char *Name, Inode **Node) { __check_op(Lookup, Name, Node); }
|
||||
int Create(const char *Name, mode_t Mode, Inode **Node) { __check_op(Create, Name, Mode, Node); }
|
||||
int Remove(const char *Name) { __check_op(Remove, Name); }
|
||||
int Rename(const char *OldName, const char *NewName) { __check_op(Rename, OldName, NewName); }
|
||||
ssize_t Read(auto Buffer, size_t Size, off_t Offset) { __check_op(Read, (void *)Buffer, Size, Offset); }
|
||||
ssize_t Write(const auto Buffer, size_t Size, off_t Offset) { __check_op(Write, (const void *)Buffer, Size, Offset); }
|
||||
int Truncate(off_t Size) { __check_op(Truncate, Size); }
|
||||
int Open(int Flags, mode_t Mode) { __check_op(Open, Flags, Mode); }
|
||||
int Close() { __check_op(Close); }
|
||||
int Ioctl(unsigned long Request, void *Argp) { __check_op(Ioctl, Request, Argp); }
|
||||
ssize_t ReadDir(struct kdirent *Buffer, size_t Size, off_t Offset, off_t Entries) { __check_op(ReadDir, Buffer, Size, Offset, Entries); }
|
||||
int MkDir(const char *Name, mode_t Mode, struct Inode **Result) { __check_op(MkDir, Name, Mode, Result); }
|
||||
int RmDir(const char *Name) { __check_op(RmDir, Name); }
|
||||
int SymLink(const char *Name, const char *Target, struct Inode **Result) { __check_op(SymLink, Name, Target, Result); }
|
||||
ssize_t ReadLink(auto Buffer, size_t Size) { __check_op(ReadLink, (char *)Buffer, Size); }
|
||||
off_t Seek(off_t Offset) { __check_op(Seek, Offset); }
|
||||
int Stat(struct kstat *Stat) { __check_op(Stat, Stat); }
|
||||
|
||||
~FileNode() = delete;
|
||||
};
|
||||
|
||||
static inline int ConvertFileFlags(const char *Mode)
|
||||
{
|
||||
int Flags = 0;
|
||||
|
||||
if (strchr(Mode, '+'))
|
||||
Flags |= O_RDWR;
|
||||
else if (*Mode == 'r')
|
||||
Flags |= O_RDONLY;
|
||||
else
|
||||
Flags |= O_WRONLY;
|
||||
|
||||
if (strchr(Mode, 'x'))
|
||||
Flags |= O_EXCL;
|
||||
|
||||
if (strchr(Mode, 'e'))
|
||||
Flags |= O_CLOEXEC;
|
||||
|
||||
if (*Mode != 'r')
|
||||
Flags |= O_CREAT;
|
||||
|
||||
if (*Mode == 'w')
|
||||
Flags |= O_TRUNC;
|
||||
|
||||
if (*Mode == 'a')
|
||||
Flags |= O_APPEND;
|
||||
|
||||
return Flags;
|
||||
}
|
||||
#undef __check_op
|
||||
|
||||
namespace vfs
|
||||
{
|
||||
enum NodeType : mode_t
|
||||
struct vfsInode
|
||||
{
|
||||
NODE_TYPE_NONE = 0x0,
|
||||
FILE = S_IFREG,
|
||||
DIRECTORY = S_IFDIR,
|
||||
CHARDEVICE = S_IFCHR,
|
||||
BLOCKDEVICE = S_IFBLK,
|
||||
PIPE = S_IFIFO,
|
||||
SYMLINK = S_IFLNK,
|
||||
MOUNTPOINT = S_IFDIR
|
||||
};
|
||||
|
||||
class RefNode;
|
||||
|
||||
/**
|
||||
* Virtual filesystem node
|
||||
*
|
||||
* @note https://isocpp.org/wiki/faq/freestore-mgmt#delete-this
|
||||
*/
|
||||
class Node
|
||||
{
|
||||
private:
|
||||
NewLock(NodeLock);
|
||||
|
||||
public:
|
||||
virtual int open(int Flags, mode_t Mode);
|
||||
virtual int close();
|
||||
virtual size_t read(uint8_t *Buffer, size_t Size, off_t Offset);
|
||||
virtual size_t write(uint8_t *Buffer, size_t Size, off_t Offset);
|
||||
virtual int ioctl(unsigned long Request, void *Argp);
|
||||
// virtual int stat(struct kstat *Stat);
|
||||
// virtual int lstat(struct kstat *Stat);
|
||||
// virtual int fstat(struct kstat *Stat);
|
||||
// virtual int unlink();
|
||||
// virtual int mkdir(mode_t Mode);
|
||||
// virtual int rmdir();
|
||||
// virtual int rename(const char *NewName);
|
||||
// virtual int chmod(mode_t Mode);
|
||||
// virtual int chown(uid_t User, gid_t Group);
|
||||
// virtual int truncate(off_t Size);
|
||||
// virtual int symlink(const char *Target);
|
||||
// virtual int readlink(char *Buffer, size_t Size);
|
||||
// virtual int mount(Node *Target);
|
||||
// virtual int umount();
|
||||
|
||||
typedef int (*open_t)(int, mode_t);
|
||||
typedef int (*close_t)();
|
||||
typedef size_t (*read_t)(uint8_t *, size_t, off_t);
|
||||
typedef size_t (*write_t)(uint8_t *, size_t, off_t);
|
||||
typedef int (*ioctl_t)(unsigned long, void *);
|
||||
|
||||
open_t open_ptr = nullptr;
|
||||
close_t close_ptr = nullptr;
|
||||
read_t read_ptr = nullptr;
|
||||
write_t write_ptr = nullptr;
|
||||
ioctl_t ioctl_ptr = nullptr;
|
||||
|
||||
class Virtual *vFS = nullptr;
|
||||
Node *Parent = nullptr;
|
||||
const char *Name;
|
||||
const char *FullPath;
|
||||
NodeType Type;
|
||||
ino_t IndexNode;
|
||||
|
||||
const char *Symlink;
|
||||
Node *SymlinkTarget;
|
||||
|
||||
mode_t Mode;
|
||||
uid_t UserIdentifier;
|
||||
gid_t GroupIdentifier;
|
||||
|
||||
dev_t DeviceMajor;
|
||||
dev_t DeviceMinor;
|
||||
|
||||
time_t AccessTime;
|
||||
time_t ModifyTime;
|
||||
time_t ChangeTime;
|
||||
|
||||
off_t Size;
|
||||
std::vector<Node *> Children;
|
||||
|
||||
std::vector<RefNode *> References;
|
||||
RefNode *CreateReference();
|
||||
void RemoveReference(RefNode *Reference);
|
||||
|
||||
/**
|
||||
* Create a new node
|
||||
*
|
||||
* @param Parent The parent node
|
||||
* @param Name The name of the node
|
||||
* @param Type The type of the node
|
||||
* @param NoParent If true, the Parent will
|
||||
* be used as a hint for the parent node, but it
|
||||
* won't be set as the parent node.
|
||||
* @param fs The virtual filesystem (only if
|
||||
* NoParent is set)
|
||||
* @param Err If not nullptr, the function will
|
||||
* write the error code to the given address.
|
||||
*/
|
||||
Node(Node *Parent,
|
||||
const char *Name,
|
||||
NodeType Type,
|
||||
bool NoParent = false,
|
||||
Virtual *fs = nullptr,
|
||||
int *Err = nullptr);
|
||||
|
||||
virtual ~Node();
|
||||
};
|
||||
|
||||
class RefNode
|
||||
{
|
||||
private:
|
||||
std::atomic_int64_t FileOffset = 0;
|
||||
off_t FileSize = 0;
|
||||
Node *n;
|
||||
RefNode *SymlinkTo;
|
||||
|
||||
public:
|
||||
void *SpecialData;
|
||||
|
||||
decltype(FileSize) &Size = FileSize;
|
||||
decltype(n) &node = n;
|
||||
|
||||
size_t read(uint8_t *Buffer, size_t Size);
|
||||
size_t write(uint8_t *Buffer, size_t Size);
|
||||
off_t seek(off_t Offset, int Whence);
|
||||
int ioctl(unsigned long Request, void *Argp);
|
||||
|
||||
RefNode(Node *node);
|
||||
~RefNode();
|
||||
|
||||
friend class Virtual;
|
||||
friend class FileDescriptorTable;
|
||||
Inode Node;
|
||||
std::string Name;
|
||||
std::vector<Inode *> Children;
|
||||
};
|
||||
|
||||
class Virtual
|
||||
{
|
||||
private:
|
||||
Node *FileSystemRoot = nullptr;
|
||||
NewLock(VirtualLock);
|
||||
|
||||
Node *GetParent(const char *Path, Node *Parent);
|
||||
/** @note This function is NOT thread safe */
|
||||
Node *GetNodeFromPath_Unsafe(const char *Path, Node *Parent = nullptr);
|
||||
struct FSMountInfo
|
||||
{
|
||||
FileSystemInfo *fsi;
|
||||
Inode *Root;
|
||||
};
|
||||
|
||||
struct CacheNode
|
||||
{
|
||||
FileNode *fn;
|
||||
std::atomic_int References;
|
||||
};
|
||||
|
||||
std::unordered_map<dev_t, FSMountInfo> DeviceMap;
|
||||
std::atomic_bool RegisterLock = false;
|
||||
|
||||
FileNode *__CacheRecursiveSearch(FileNode *, const char *, bool);
|
||||
FileNode *CacheLookup(const char *Path);
|
||||
FileNode *CreateCacheNode(FileNode *Parent, Inode *Node, const char *Name, mode_t Mode);
|
||||
|
||||
int RemoveCacheNode(FileNode *Node);
|
||||
|
||||
public:
|
||||
Node *nRoot = nullptr;
|
||||
Node *GetNodeFromPath(const char *Path, Node *Parent = nullptr);
|
||||
vfsInode *FileSystemRoots = nullptr;
|
||||
|
||||
bool PathIsRelative(const char *Path);
|
||||
|
||||
Node *GetRootNode() { return FileSystemRoot; }
|
||||
|
||||
const char *NormalizePath(const char *Path, Node *Parent = nullptr);
|
||||
bool PathExists(const char *Path, Node *Parent = nullptr);
|
||||
|
||||
Node *Create(const char *Path, NodeType Type, Node *Parent = nullptr);
|
||||
Node *CreateLink(const char *Path, const char *Target, Node *Parent);
|
||||
|
||||
int Delete(const char *Path, bool Recursive = false, Node *Parent = nullptr);
|
||||
int Delete(Node *Path, bool Recursive = false, Node *Parent = nullptr);
|
||||
bool PathIsAbsolute(const char *Path) { return !PathIsRelative(Path); }
|
||||
|
||||
/**
|
||||
* Open a file
|
||||
* @param Path The path to the file, relative or absolute. The buffer shouldn't be modified while the function is running.
|
||||
* @param Parent Pointer to the parent node, if nullptr, the root node will be used.
|
||||
* @return A pointer to the vfs::ReferenceNode, or nullptr if the file doesn't exist.
|
||||
* Reserve a device number for a filesystem
|
||||
*
|
||||
* @note After this function is called, the filesystem must
|
||||
* call LateRegisterFileSystem to release the lock
|
||||
*/
|
||||
RefNode *Open(const char *Path, Node *Parent = nullptr);
|
||||
dev_t EarlyReserveDevice();
|
||||
|
||||
Node *CreateIfNotExists(const char *Path, NodeType Type, Node *Parent = nullptr);
|
||||
/**
|
||||
* Register a filesystem after the device number has been reserved
|
||||
*/
|
||||
int LateRegisterFileSystem(dev_t Device, FileSystemInfo *fsi, Inode *Root);
|
||||
|
||||
dev_t RegisterFileSystem(FileSystemInfo *fsi, Inode *Root);
|
||||
int UnregisterFileSystem(dev_t Device);
|
||||
|
||||
void AddRoot(Inode *Root);
|
||||
FileNode *GetRoot(size_t Index);
|
||||
|
||||
FileNode *Create(FileNode *Parent, const char *Name, mode_t Mode);
|
||||
FileNode *ForceCreate(FileNode *Parent, const char *Name, mode_t Mode);
|
||||
|
||||
FileNode *GetByPath(const char *Path, FileNode *Parent);
|
||||
FileNode *CreateLink(const char *Path, FileNode *Parent, const char *Target);
|
||||
FileNode *CreateLink(const char *Path, FileNode *Parent, FileNode *Target);
|
||||
bool PathExists(const char *Path, FileNode *Parent);
|
||||
|
||||
int Remove(FileNode *Node);
|
||||
|
||||
void Initialize();
|
||||
Virtual();
|
||||
~Virtual();
|
||||
|
||||
friend class Node;
|
||||
};
|
||||
|
||||
class FileDescriptorTable
|
||||
@ -330,63 +157,59 @@ namespace vfs
|
||||
public:
|
||||
struct Fildes
|
||||
{
|
||||
RefNode *Handle = nullptr;
|
||||
enum FildesType
|
||||
{
|
||||
FD_INODE,
|
||||
FD_PIPE,
|
||||
FD_SOCKET,
|
||||
} Type;
|
||||
mode_t Mode = 0;
|
||||
int Flags = 0;
|
||||
int Descriptor = -1;
|
||||
FileNode *Node = nullptr;
|
||||
int References = 0;
|
||||
off_t Offset = 0;
|
||||
|
||||
int operator==(const Fildes &other)
|
||||
{
|
||||
return this->Handle == other.Handle &&
|
||||
this->Mode == other.Mode &&
|
||||
this->Flags == other.Flags &&
|
||||
this->Descriptor == other.Descriptor;
|
||||
return Type == other.Type &&
|
||||
Mode == other.Mode &&
|
||||
Flags == other.Flags &&
|
||||
Node == other.Node &&
|
||||
References == other.References &&
|
||||
Offset == other.Offset;
|
||||
}
|
||||
|
||||
int operator!=(const Fildes &other)
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
} __attribute__((packed)) nullfd;
|
||||
};
|
||||
|
||||
private:
|
||||
std::vector<Fildes> FileDescriptors;
|
||||
std::vector<Fildes> FildesDuplicates;
|
||||
vfs::Node *fdDir = nullptr;
|
||||
FileNode *fdDir = nullptr;
|
||||
void *Owner;
|
||||
|
||||
Fildes &GetFileDescriptor(int FileDescriptor);
|
||||
FileDescriptorTable::Fildes &GetDupFildes(int FileDescriptor);
|
||||
|
||||
int ProbeMode(mode_t Mode, int Flags);
|
||||
int AddFileDescriptor(const char *AbsolutePath, mode_t Mode, int Flags);
|
||||
int RemoveFileDescriptor(int FileDescriptor);
|
||||
int GetFreeFileDescriptor();
|
||||
|
||||
public:
|
||||
Fildes &GetDescriptor(int FileDescriptor);
|
||||
const char *GetAbsolutePath(int FileDescriptor);
|
||||
std::vector<Fildes> &GetFileDescriptors() { return FileDescriptors; }
|
||||
std::vector<Fildes> &GetFileDescriptorsDuplicates() { return FildesDuplicates; }
|
||||
RefNode *GetRefNode(int FileDescriptor);
|
||||
std::unordered_map<int, Fildes> FileMap;
|
||||
|
||||
int GetFlags(int FileDescriptor);
|
||||
int SetFlags(int FileDescriptor, int Flags);
|
||||
void Fork(FileDescriptorTable *Parent);
|
||||
|
||||
int _open(const char *pathname, int flags, mode_t mode);
|
||||
int _creat(const char *pathname, mode_t mode);
|
||||
ssize_t _read(int fd, void *buf, size_t count);
|
||||
ssize_t _write(int fd, const void *buf, size_t count);
|
||||
int _close(int fd);
|
||||
off_t _lseek(int fd, off_t offset, int whence);
|
||||
int _stat(const char *pathname, struct kstat *statbuf);
|
||||
int _fstat(int fd, struct kstat *statbuf);
|
||||
int _lstat(const char *pathname, struct kstat *statbuf);
|
||||
int _dup(int oldfd);
|
||||
int _dup2(int oldfd, int newfd);
|
||||
int _ioctl(int fd, unsigned long request, void *argp);
|
||||
int usr_open(const char *pathname, int flags, mode_t mode);
|
||||
int usr_creat(const char *pathname, mode_t mode);
|
||||
ssize_t usr_read(int fd, void *buf, size_t count);
|
||||
ssize_t usr_write(int fd, const void *buf, size_t count);
|
||||
int usr_close(int fd);
|
||||
off_t usr_lseek(int fd, off_t offset, int whence);
|
||||
int usr_stat(const char *pathname, struct kstat *statbuf);
|
||||
int usr_fstat(int fd, struct kstat *statbuf);
|
||||
int usr_lstat(const char *pathname, struct kstat *statbuf);
|
||||
int usr_dup(int oldfd);
|
||||
int usr_dup2(int oldfd, int newfd);
|
||||
int usr_ioctl(int fd, unsigned long request, void *argp);
|
||||
|
||||
FileDescriptorTable(void *Owner);
|
||||
~FileDescriptorTable();
|
||||
~FileDescriptorTable() = default;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -1,117 +0,0 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __FENNIX_KERNEL_FILESYSTEM_FAT_H__
|
||||
#define __FENNIX_KERNEL_FILESYSTEM_FAT_H__
|
||||
|
||||
#include <types.h>
|
||||
|
||||
#include <filesystem.hpp>
|
||||
|
||||
namespace vfs
|
||||
{
|
||||
class FAT
|
||||
{
|
||||
public:
|
||||
enum FatType
|
||||
{
|
||||
Unknown,
|
||||
FAT12,
|
||||
FAT16,
|
||||
FAT32
|
||||
};
|
||||
|
||||
/* https://wiki.osdev.org/FAT */
|
||||
struct BIOSParameterBlock
|
||||
{
|
||||
/** The first three bytes EB 3C 90 disassemble to JMP SHORT 3C NOP.
|
||||
* (The 3C value may be different.) The reason for this is to jump
|
||||
* over the disk format information (the BPB and EBPB). Since the
|
||||
* first sector of the disk is loaded into ram at location
|
||||
* 0x0000:0x7c00 and executed, without this jump, the processor
|
||||
* would attempt to execute data that isn't code. Even for
|
||||
* non-bootable volumes, code matching this pattern (or using the
|
||||
* E9 jump opcode) is required to be present by both Windows and
|
||||
* OS X. To fulfil this requirement, an infinite loop can be placed
|
||||
* here with the bytes EB FE 90. */
|
||||
uint8_t JumpBoot[3];
|
||||
|
||||
/** OEM identifier. The first 8 Bytes (3 - 10) is the version of DOS
|
||||
* being used. The next eight Bytes 29 3A 63 7E 2D 49 48 and 43 read
|
||||
* out the name of the version. The official FAT Specification from
|
||||
* Microsoft says that this field is really meaningless and is ignored
|
||||
* by MS FAT Modules, however it does recommend the value "MSWIN4.1"
|
||||
* as some 3rd party drivers supposedly check it and expect it to
|
||||
* have that value. Older versions of dos also report MSDOS5.1,
|
||||
* linux-formatted floppy will likely to carry "mkdosfs" here, and
|
||||
* FreeDOS formatted disks have been observed to have "FRDOS5.1" here.
|
||||
* If the string is less than 8 bytes, it is padded with spaces. */
|
||||
uint8_t OEM[8];
|
||||
|
||||
/** The number of Bytes per sector (remember, all numbers are in the
|
||||
* little-endian format). */
|
||||
uint16_t BytesPerSector;
|
||||
|
||||
/** Number of sectors per cluster. */
|
||||
uint8_t SectorsPerCluster;
|
||||
|
||||
/** Number of reserved sectors. The boot record sectors are included
|
||||
* in this value. */
|
||||
uint16_t ReservedSectors;
|
||||
|
||||
/** Number of File Allocation Tables (FAT's) on the storage media.
|
||||
* Often this value is 2. */
|
||||
uint8_t NumberOfFATs;
|
||||
|
||||
/** Number of root directory entries (must be set so that the root
|
||||
* directory occupies entire sectors). */
|
||||
uint16_t RootDirectoryEntries;
|
||||
|
||||
/** The total sectors in the logical volume. If this value is 0, it
|
||||
* means there are more than 65535 sectors in the volume, and the
|
||||
* actual count is stored in the Large Sector Count entry at 0x20. */
|
||||
uint16_t Sectors16;
|
||||
|
||||
/** This Byte indicates the media descriptor type. */
|
||||
uint8_t Media;
|
||||
|
||||
/** Number of sectors per FAT. FAT12/FAT16 only. */
|
||||
uint16_t SectorsPerFAT;
|
||||
|
||||
/** Number of sectors per track. */
|
||||
uint16_t SectorsPerTrack;
|
||||
|
||||
/** Number of heads or sides on the storage media. */
|
||||
uint16_t NumberOfHeads;
|
||||
|
||||
/** Number of hidden sectors. (i.e. the LBA of the beginning of
|
||||
* the partition). */
|
||||
uint32_t HiddenSectors;
|
||||
|
||||
/** Large sector count. This field is set if there are more than
|
||||
* 65535 sectors in the volume, resulting in a value which does not
|
||||
* fit in the Number of Sectors entry at 0x13. */
|
||||
uint32_t Sectors32;
|
||||
} __packed;
|
||||
|
||||
FatType GetFATType(BIOSParameterBlock *bpb);
|
||||
FAT(void *partition);
|
||||
~FAT();
|
||||
};
|
||||
}
|
||||
|
||||
#endif // !__FENNIX_KERNEL_FILESYSTEM_FAT_H__
|
@ -20,7 +20,7 @@
|
||||
|
||||
#include <types.h>
|
||||
#include <stropts.h>
|
||||
#include <filesystem/termios.hpp>
|
||||
#include <termios.h>
|
||||
|
||||
#define _IOC_NRBITS 8
|
||||
#define _IOC_TYPEBITS 8
|
||||
|
@ -20,184 +20,53 @@
|
||||
|
||||
#include <types.h>
|
||||
|
||||
#include <filesystem/termios.hpp>
|
||||
#include <filesystem.hpp>
|
||||
#include <bitmap.hpp>
|
||||
#include <task.hpp>
|
||||
#include <termios.h>
|
||||
#include <lock.hpp>
|
||||
#include <vector>
|
||||
|
||||
namespace vfs
|
||||
{
|
||||
class vfsRoot : public Node
|
||||
{
|
||||
public:
|
||||
vfsRoot(const char *Name, Virtual *vfs_ctx);
|
||||
~vfsRoot() {}
|
||||
};
|
||||
|
||||
class NullDevice : public Node
|
||||
{
|
||||
public:
|
||||
size_t read(uint8_t *Buffer,
|
||||
size_t Size,
|
||||
off_t Offset) final;
|
||||
size_t write(uint8_t *Buffer,
|
||||
size_t Size,
|
||||
off_t Offset) final;
|
||||
|
||||
NullDevice();
|
||||
~NullDevice();
|
||||
};
|
||||
|
||||
class RandomDevice : public Node
|
||||
{
|
||||
public:
|
||||
size_t read(uint8_t *Buffer,
|
||||
size_t Size,
|
||||
off_t Offset) final;
|
||||
size_t write(uint8_t *Buffer,
|
||||
size_t Size,
|
||||
off_t Offset) final;
|
||||
|
||||
RandomDevice();
|
||||
~RandomDevice();
|
||||
};
|
||||
|
||||
class ZeroDevice : public Node
|
||||
{
|
||||
public:
|
||||
size_t read(uint8_t *Buffer,
|
||||
size_t Size,
|
||||
off_t Offset) final;
|
||||
size_t write(uint8_t *Buffer,
|
||||
size_t Size,
|
||||
off_t Offset) final;
|
||||
|
||||
ZeroDevice();
|
||||
~ZeroDevice();
|
||||
};
|
||||
|
||||
class KConDevice : public Node
|
||||
{
|
||||
public:
|
||||
size_t read(uint8_t *Buffer,
|
||||
size_t Size,
|
||||
off_t Offset) final;
|
||||
size_t write(uint8_t *Buffer,
|
||||
size_t Size,
|
||||
off_t Offset) final;
|
||||
int ioctl(unsigned long Request,
|
||||
void *Argp) final;
|
||||
|
||||
termios term{};
|
||||
winsize termSize{};
|
||||
|
||||
KConDevice();
|
||||
~KConDevice();
|
||||
};
|
||||
|
||||
class TTYDevice : public Node
|
||||
{
|
||||
public:
|
||||
size_t write(uint8_t *Buffer,
|
||||
size_t Size,
|
||||
off_t Offset) final;
|
||||
int ioctl(unsigned long Request,
|
||||
void *Argp) final;
|
||||
|
||||
TTYDevice();
|
||||
~TTYDevice();
|
||||
};
|
||||
|
||||
class MasterPTY
|
||||
{
|
||||
NewLock(PTYLock);
|
||||
|
||||
public:
|
||||
size_t read(uint8_t *Buffer,
|
||||
size_t Size,
|
||||
off_t Offset);
|
||||
size_t write(uint8_t *Buffer,
|
||||
size_t Size,
|
||||
off_t Offset);
|
||||
|
||||
MasterPTY();
|
||||
~MasterPTY();
|
||||
};
|
||||
|
||||
class SlavePTY
|
||||
{
|
||||
NewLock(PTYLock);
|
||||
|
||||
public:
|
||||
size_t read(uint8_t *Buffer,
|
||||
size_t Size,
|
||||
off_t Offset);
|
||||
size_t write(uint8_t *Buffer,
|
||||
size_t Size,
|
||||
off_t Offset);
|
||||
|
||||
SlavePTY();
|
||||
~SlavePTY();
|
||||
};
|
||||
|
||||
class PTYDevice : public Node
|
||||
class PTYDevice
|
||||
{
|
||||
private:
|
||||
Node *pts;
|
||||
Inode *pts;
|
||||
int id;
|
||||
int fildes;
|
||||
bool isMaster;
|
||||
termios term{};
|
||||
winsize termSize{};
|
||||
|
||||
MasterPTY *MasterDev;
|
||||
SlavePTY *SlaveDev;
|
||||
class PTYSlave
|
||||
{
|
||||
};
|
||||
|
||||
class PTYMaster
|
||||
{
|
||||
};
|
||||
|
||||
public:
|
||||
decltype(id) &ptyId = id;
|
||||
decltype(fildes) &fd = fildes;
|
||||
|
||||
int open(int Flags, mode_t Mode) final;
|
||||
int close() final;
|
||||
size_t read(uint8_t *Buffer,
|
||||
size_t Size,
|
||||
off_t Offset) final;
|
||||
size_t write(uint8_t *Buffer,
|
||||
size_t Size,
|
||||
off_t Offset) final;
|
||||
int ioctl(unsigned long Request,
|
||||
void *Argp) final;
|
||||
ssize_t Read(struct Inode *Node, void *Buffer, size_t Size, off_t Offset);
|
||||
ssize_t Write(struct Inode *Node, const void *Buffer, size_t Size, off_t Offset);
|
||||
int Ioctl(struct Inode *Node, unsigned long Request, void *Argp);
|
||||
|
||||
int OpenMaster(int Flags, mode_t Mode);
|
||||
|
||||
PTYDevice(Node *pts, int id);
|
||||
PTYDevice(Inode *pts, int id);
|
||||
~PTYDevice();
|
||||
};
|
||||
|
||||
class PTMXDevice : public Node
|
||||
class PTMXDevice
|
||||
{
|
||||
private:
|
||||
NewLock(PTMXLock);
|
||||
Node *pts;
|
||||
FileNode *ptmx;
|
||||
FileNode *pts;
|
||||
Bitmap ptysId;
|
||||
std::vector<PTYDevice *> ptysList;
|
||||
std::unordered_map<size_t, PTYDevice *> ptysList;
|
||||
|
||||
public:
|
||||
int open(int Flags, mode_t Mode) final;
|
||||
|
||||
/**
|
||||
* Remove a PTY from the list
|
||||
*
|
||||
* @param fd The file descriptor of the PTY
|
||||
* @param pcb The process that owns the PTY
|
||||
*
|
||||
* @note if pcb is nullptr, the current process
|
||||
* will be used.
|
||||
*
|
||||
*/
|
||||
void RemovePTY(int fd, Tasking::PCB *pcb = nullptr);
|
||||
int Open(struct Inode *Node, int Flags, mode_t Mode, struct Inode *Result);
|
||||
int Close(struct Inode *Node);
|
||||
|
||||
PTMXDevice();
|
||||
~PTMXDevice();
|
||||
|
@ -18,38 +18,40 @@
|
||||
#ifndef __FENNIX_KERNEL_FILESYSTEM_USTAR_H__
|
||||
#define __FENNIX_KERNEL_FILESYSTEM_USTAR_H__
|
||||
|
||||
#include <types.h>
|
||||
|
||||
#include <filesystem.hpp>
|
||||
|
||||
namespace vfs
|
||||
{
|
||||
class USTARNode : public Node
|
||||
{
|
||||
private:
|
||||
uintptr_t Address;
|
||||
|
||||
public:
|
||||
size_t read(uint8_t *Buffer, size_t Size, off_t Offset) final;
|
||||
|
||||
USTARNode(uintptr_t Address, const char *Name, NodeType Type,
|
||||
Virtual *vfs_ctx);
|
||||
|
||||
~USTARNode();
|
||||
};
|
||||
|
||||
class USTAR
|
||||
{
|
||||
|
||||
enum FileType
|
||||
public:
|
||||
enum TypeFlag
|
||||
{
|
||||
REGULAR_FILE = '0',
|
||||
HARDLINK = '1',
|
||||
SYMLINK = '2',
|
||||
CHARDEV = '3',
|
||||
BLOCKDEV = '4',
|
||||
DIRECTORY = '5',
|
||||
FIFO = '6'
|
||||
AREGTYPE = '\0',
|
||||
REGTYPE = '0',
|
||||
LNKTYPE = '1',
|
||||
SYMTYPE = '2',
|
||||
CHRTYPE = '3',
|
||||
BLKTYPE = '4',
|
||||
DIRTYPE = '5',
|
||||
FIFOTYPE = '6',
|
||||
CONTTYPE = '7'
|
||||
};
|
||||
|
||||
enum ModeFlag
|
||||
{
|
||||
TSUID = 04000,
|
||||
TSGID = 02000,
|
||||
TSVTX = 01000,
|
||||
TUREAD = 00400,
|
||||
TUWRITE = 00200,
|
||||
TUEXEC = 00100,
|
||||
TGREAD = 00040,
|
||||
TGWRITE = 00020,
|
||||
TGEXEC = 00010,
|
||||
TOREAD = 00004,
|
||||
TOWRITE = 00002,
|
||||
TOEXEC = 00001,
|
||||
};
|
||||
|
||||
struct FileHeader
|
||||
@ -73,7 +75,23 @@ namespace vfs
|
||||
char pad[12];
|
||||
};
|
||||
|
||||
constexpr static int INODE_CHECKSUM = 0x7757A4;
|
||||
|
||||
struct USTARInode
|
||||
{
|
||||
struct Inode Node;
|
||||
FileHeader *Header;
|
||||
USTARInode *Parent;
|
||||
std::string Name;
|
||||
std::string Path;
|
||||
std::vector<USTARInode *> Children;
|
||||
bool Deleted;
|
||||
int Checksum;
|
||||
};
|
||||
|
||||
private:
|
||||
std::unordered_map<ino_t, USTARInode *> Files;
|
||||
|
||||
inline uint32_t GetSize(const char *String)
|
||||
{
|
||||
uint32_t ret = 0;
|
||||
@ -95,11 +113,25 @@ namespace vfs
|
||||
}
|
||||
|
||||
public:
|
||||
dev_t DeviceID = -1;
|
||||
ino_t NextInode = 0;
|
||||
|
||||
int Lookup(struct Inode *Parent, const char *Name, struct Inode **Result);
|
||||
int Create(struct Inode *Parent, const char *Name, mode_t Mode, struct Inode **Result);
|
||||
ssize_t Read(struct Inode *Node, void *Buffer, size_t Size, off_t Offset);
|
||||
ssize_t ReadDir(struct Inode *Node, struct kdirent *Buffer, size_t Size, off_t Offset, off_t Entries);
|
||||
int SymLink(struct Inode *Node, const char *Name, const char *Target, struct Inode **Result);
|
||||
ssize_t ReadLink(struct Inode *Node, char *Buffer, size_t Size);
|
||||
int Stat(struct Inode *Node, struct kstat *Stat);
|
||||
|
||||
bool TestArchive(uintptr_t Address);
|
||||
void ReadArchive(uintptr_t Address, Virtual *vfs_ctx);
|
||||
USTAR();
|
||||
~USTAR();
|
||||
void ReadArchive(uintptr_t Address, size_t Size);
|
||||
|
||||
USTAR(){};
|
||||
~USTAR(){};
|
||||
};
|
||||
}
|
||||
|
||||
bool TestAndInitializeUSTAR(uintptr_t Address, size_t Size);
|
||||
|
||||
#endif // !__FENNIX_KERNEL_FILESYSTEM_USTAR_H__
|
||||
|
@ -194,40 +194,22 @@ typedef enum
|
||||
|
||||
typedef enum
|
||||
{
|
||||
ddt_Keyboard,
|
||||
ddt_Mouse,
|
||||
ddt_Joystick,
|
||||
ddt_Gamepad,
|
||||
ddt_Touchpad,
|
||||
ddt_Touchscreen,
|
||||
IOCTL_AUDIO_GET_VOLUME = 0,
|
||||
IOCTL_AUDIO_SET_VOLUME = 1,
|
||||
|
||||
ddt_SATA,
|
||||
ddt_ATA,
|
||||
ddt_NVMe,
|
||||
IOCTL_AUDIO_GET_MUTE = 2,
|
||||
IOCTL_AUDIO_SET_MUTE = 3,
|
||||
|
||||
ddt_Audio,
|
||||
IOCTL_AUDIO_GET_SAMPLE_RATE = 4,
|
||||
IOCTL_AUDIO_SET_SAMPLE_RATE = 5,
|
||||
|
||||
ddt_Network,
|
||||
} DeviceDriverType;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
IOCTL_AUDIO_GET_VOLUME,
|
||||
IOCTL_AUDIO_SET_VOLUME,
|
||||
|
||||
IOCTL_AUDIO_GET_MUTE,
|
||||
IOCTL_AUDIO_SET_MUTE,
|
||||
|
||||
IOCTL_AUDIO_GET_SAMPLE_RATE,
|
||||
IOCTL_AUDIO_SET_SAMPLE_RATE,
|
||||
|
||||
IOCTL_AUDIO_GET_CHANNELS,
|
||||
IOCTL_AUDIO_SET_CHANNELS,
|
||||
IOCTL_AUDIO_GET_CHANNELS = 6,
|
||||
IOCTL_AUDIO_SET_CHANNELS = 7,
|
||||
} AudioIoctl;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
IOCTL_NET_GET_MAC,
|
||||
IOCTL_NET_GET_MAC = 0,
|
||||
} NetIoctl;
|
||||
|
||||
typedef enum
|
||||
@ -261,25 +243,9 @@ typedef struct
|
||||
int (*UnregisterInterruptHandler)(dev_t MajorID, uint8_t IRQ, void *Handler);
|
||||
int (*UnregisterAllInterruptHandlers)(dev_t MajorID, void *Handler);
|
||||
|
||||
/* Input */
|
||||
dev_t (*RegisterInputDevice)(dev_t MajorID, DeviceDriverType Type);
|
||||
int (*UnregisterInputDevice)(dev_t MajorID, dev_t MinorID, DeviceDriverType Type);
|
||||
int (*ReportKeyboardEvent)(dev_t MajorID, dev_t MinorID, uint8_t ScanCode);
|
||||
int (*ReportRelativeMouseEvent)(dev_t MajorID, dev_t MinorID, __MouseButtons Button, int X, int Y, int8_t Z);
|
||||
int (*ReportAbsoluteMouseEvent)(dev_t MajorID, dev_t MinorID, __MouseButtons Button, uintptr_t X, uintptr_t Y, int8_t Z);
|
||||
|
||||
/* Storage */
|
||||
dev_t (*RegisterBlockDevice)(dev_t MajorID, DeviceDriverType Type, void *Open, void *Close, void *Read, void *Write, void *Ioctl);
|
||||
int (*UnregisterBlockDevice)(dev_t MajorID, dev_t MinorID, DeviceDriverType Type);
|
||||
|
||||
/* Audio */
|
||||
dev_t (*RegisterAudioDevice)(dev_t MajorID, DeviceDriverType Type, void *Open, void *Close, void *Read, void *Write, void *Ioctl);
|
||||
int (*UnregisterAudioDevice)(dev_t MajorID, dev_t MinorID, DeviceDriverType Type);
|
||||
|
||||
/* Network */
|
||||
dev_t (*RegisterNetDevice)(dev_t MajorID, DeviceDriverType Type, void *Open, void *Close, void *Read, void *Write, void *Ioctl);
|
||||
int (*UnregisterNetDevice)(dev_t MajorID, dev_t MinorID, DeviceDriverType Type);
|
||||
int (*ReportNetworkPacket)(dev_t MajorID, dev_t MinorID, void *Buffer, size_t Size);
|
||||
/* /dev/... */
|
||||
dev_t (*RegisterDevice)(dev_t MajorID, char Prefix[8], void *Open, void *Close, void *Read, void *Write, void *Ioctl);
|
||||
int (*UnregisterDevice)(dev_t MajorID, dev_t MinorID);
|
||||
|
||||
/* Logging */
|
||||
void (*KPrint)(dev_t MajorID, const char *Format, va_list args);
|
604
include/interface/errno.h
Normal file
604
include/interface/errno.h
Normal file
@ -0,0 +1,604 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __FENNIX_KERNEL_ERRNO_H__
|
||||
#define __FENNIX_KERNEL_ERRNO_H__
|
||||
|
||||
/**
|
||||
* The documentation for these error codes are from:
|
||||
* https://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html
|
||||
*
|
||||
* Full list:
|
||||
* https://pubs.opengroup.org/onlinepubs/9699919799.2018edition/basedefs/errno.h.html
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
/**
|
||||
* No Error
|
||||
*/
|
||||
EOK = 0,
|
||||
|
||||
/**
|
||||
* Argument list too long. The sum of the number of bytes used by the
|
||||
* new process image's argument list and environment list is greater
|
||||
* than the system-imposed limit of {ARG_MAX} bytes.
|
||||
* or:
|
||||
* Lack of space in an output buffer.
|
||||
* or:
|
||||
* Argument is greater than the system-imposed maximum.
|
||||
*/
|
||||
E2BIG = 1,
|
||||
|
||||
/**
|
||||
* Permission denied. An attempt was made to access a file in a way
|
||||
* forbidden by its file access permissions.
|
||||
*/
|
||||
EACCES = 2,
|
||||
|
||||
/**
|
||||
* Address in use. The specified address is in use.
|
||||
*/
|
||||
EADDRINUSE = 3,
|
||||
|
||||
/**
|
||||
* Address not available. The specified address is not available from
|
||||
* the local system.
|
||||
*/
|
||||
EADDRNOTAVAIL = 4,
|
||||
|
||||
/**
|
||||
* Address family not supported. The implementation does not support
|
||||
* the specified address family, or the specified address is not a
|
||||
* valid address for the address family of the specified socket.
|
||||
*/
|
||||
EAFNOSUPPORT = 5,
|
||||
|
||||
/**
|
||||
* Resource temporarily unavailable. This is a temporary condition
|
||||
* and later calls to the same routine may complete normally.
|
||||
*/
|
||||
EAGAIN = 6,
|
||||
|
||||
/**
|
||||
* Connection already in progress. A connection request is already in
|
||||
* progress for the specified socket.
|
||||
*/
|
||||
EALREADY = 7,
|
||||
|
||||
/**
|
||||
* Bad file descriptor. A file descriptor argument is out of range,
|
||||
* refers to no open file, or a read (write) request is made to a
|
||||
* file that is only open for writing (reading).
|
||||
*/
|
||||
EBADF = 8,
|
||||
|
||||
/**
|
||||
* Bad message. During a read(), getmsg(), getpmsg(), or ioctl()
|
||||
* I_RECVFD request to a STREAMS device, a message arrived at the
|
||||
* head of the STREAM that is inappropriate for the function
|
||||
* receiving the message.
|
||||
* read()
|
||||
* Message waiting to be read on a STREAM is not a data message.
|
||||
* getmsg() or getpmsg()
|
||||
* A file descriptor was received instead of a control message.
|
||||
* ioctl()
|
||||
* Control or data information was received instead of a file
|
||||
* descriptor when I_RECVFD was specified.
|
||||
*/
|
||||
EBADMSG = 9,
|
||||
|
||||
/**
|
||||
* Resource busy. An attempt was made to make use of a system
|
||||
* resource that is not currently available, as it is being
|
||||
* used by another process in a manner that would have
|
||||
* conflicted with the request being made by this process.
|
||||
*/
|
||||
EBUSY = 10,
|
||||
|
||||
/**
|
||||
* Operation canceled. The associated asynchronous operation was
|
||||
* canceled before completion.
|
||||
*/
|
||||
ECANCELED = 11,
|
||||
|
||||
/**
|
||||
* No child process. A wait(), waitid(), or waitpid() function was
|
||||
* executed by a process that had no existing or unwaited-for
|
||||
* child process.
|
||||
*/
|
||||
ECHILD = 12,
|
||||
|
||||
/**
|
||||
* Connection aborted. The connection has been aborted.
|
||||
*/
|
||||
ECONNABORTED = 13,
|
||||
|
||||
/**
|
||||
* Connection refused. An attempt to connect to a socket was refused
|
||||
* because there was no process listening or because the queue of
|
||||
* connection requests was full and the underlying protocol does not
|
||||
* support retransmissions.
|
||||
*/
|
||||
ECONNREFUSED = 14,
|
||||
|
||||
/**
|
||||
* Connection reset. The connection was forcibly closed by the peer.
|
||||
*/
|
||||
ECONNRESET = 15,
|
||||
|
||||
/**
|
||||
* Resource deadlock would occur. An attempt was made to lock a system
|
||||
* resource that would have resulted in a deadlock situation.
|
||||
*/
|
||||
EDEADLK = 16,
|
||||
|
||||
/**
|
||||
* Destination address required. No bind address was established.
|
||||
*/
|
||||
EDESTADDRREQ = 17,
|
||||
|
||||
/**
|
||||
* Domain error. An input argument is outside the defined domain of the
|
||||
* mathematical function (defined in the ISO C standard).
|
||||
*/
|
||||
EDOM = 18,
|
||||
|
||||
/**
|
||||
* Reserved.
|
||||
*/
|
||||
EDQUOT = 19,
|
||||
|
||||
/**
|
||||
* File exists. An existing file was mentioned in an inappropriate
|
||||
* context; for example, as a new link name in the link() function.
|
||||
*/
|
||||
EEXIST = 20,
|
||||
|
||||
/**
|
||||
* Bad address. The system detected an invalid address in attempting
|
||||
* to use an argument of a call. The reliable detection of this error
|
||||
* cannot be guaranteed, and when not detected may result in the
|
||||
* generation of a signal, indicating an address violation, which is
|
||||
* sent to the process.
|
||||
*/
|
||||
EFAULT = 21,
|
||||
|
||||
/**
|
||||
* File too large. The size of a file would exceed the maximum file
|
||||
* size of an implementation or offset maximum established in the
|
||||
* corresponding file description.
|
||||
*/
|
||||
EFBIG = 22,
|
||||
|
||||
/**
|
||||
* Host is unreachable. The destination host cannot be reached
|
||||
* (probably because the host is down or a remote router cannot
|
||||
* reach it).
|
||||
*/
|
||||
EHOSTUNREACH = 23,
|
||||
|
||||
/**
|
||||
* Identifier removed. Returned during XSI interprocess communication
|
||||
* if an identifier has been removed from the system.
|
||||
*/
|
||||
EIDRM = 24,
|
||||
|
||||
/**
|
||||
* Illegal byte sequence. A wide-character code has been detected that
|
||||
* does not correspond to a valid character, or a byte sequence does
|
||||
* not form a valid wide-character code (defined in the ISO C standard).
|
||||
*/
|
||||
EILSEQ = 25,
|
||||
|
||||
/**
|
||||
* Operation in progress. This code is used to indicate that an
|
||||
* asynchronous operation has not yet completed.
|
||||
* or:
|
||||
* O_NONBLOCK is set for the socket file descriptor and the connection
|
||||
* cannot be immediately established.
|
||||
*/
|
||||
EINPROGRESS = 26,
|
||||
|
||||
/**
|
||||
* Interrupted function call. An asynchronous signal was caught by the
|
||||
* process during the execution of an interruptible function. If the
|
||||
* signal handler performs a normal return, the interrupted function
|
||||
* call may return this condition (see the Base Definitions volume
|
||||
* of POSIX.1-2017, <signal.h>).
|
||||
*/
|
||||
EINTR = 27,
|
||||
|
||||
/**
|
||||
* Invalid argument. Some invalid argument was supplied; for example,
|
||||
* specifying an undefined signal in a signal() function or a
|
||||
* kill() function.
|
||||
*/
|
||||
EINVAL = 28,
|
||||
|
||||
/**
|
||||
* Input/output error. Some physical input or output error has occurred.
|
||||
* This error may be reported on a subsequent operation on the same
|
||||
* file descriptor. Any other error-causing operation on the same file
|
||||
* descriptor may cause the [EIO] error indication to be lost.
|
||||
*/
|
||||
EIO = 29,
|
||||
|
||||
/**
|
||||
* Socket is connected. The specified socket is already connected.
|
||||
*/
|
||||
EISCONN = 30,
|
||||
|
||||
/**
|
||||
* Is a directory. An attempt was made to open a directory with write
|
||||
* mode specified.
|
||||
*/
|
||||
EISDIR = 31,
|
||||
|
||||
/**
|
||||
* Symbolic link loop. A loop exists in symbolic links encountered
|
||||
* during pathname resolution. This error may also be returned if
|
||||
* more than {SYMLOOP_MAX} symbolic links are encountered during
|
||||
* pathname resolution.
|
||||
*/
|
||||
ELOOP = 32,
|
||||
|
||||
/**
|
||||
* File descriptor value too large or too many open streams. An
|
||||
* attempt was made to open a file descriptor with a value greater
|
||||
* than or equal to {OPEN_MAX}, or an attempt was made to open more
|
||||
* than the maximum number of streams allowed in the process.
|
||||
*/
|
||||
EMFILE = 33,
|
||||
|
||||
/**
|
||||
* Too many links. An attempt was made to have the link count of a
|
||||
* single file exceed {LINK_MAX}.
|
||||
*/
|
||||
EMLINK = 34,
|
||||
|
||||
/**
|
||||
* Message too large. A message sent on a transport provider was
|
||||
* larger than an internal message buffer or some other network limit.
|
||||
* or:
|
||||
* Inappropriate message buffer length.
|
||||
*/
|
||||
EMSGSIZE = 35,
|
||||
|
||||
/**
|
||||
* Reserved.
|
||||
*/
|
||||
EMULTIHOP = 36,
|
||||
|
||||
/**
|
||||
* Filename too long. The length of a pathname exceeds {PATH_MAX} and
|
||||
* the implementation considers this to be an error, or a pathname
|
||||
* component is longer than {NAME_MAX}. This error may also occur
|
||||
* when pathname substitution, as a result of encountering a
|
||||
* symbolic link during pathname resolution, results in a pathname
|
||||
* string the size of which exceeds {PATH_MAX}.
|
||||
*/
|
||||
ENAMETOOLONG = 37,
|
||||
|
||||
/**
|
||||
* Network is down. The local network interface used to reach the
|
||||
* destination is down.
|
||||
*/
|
||||
ENETDOWN = 38,
|
||||
|
||||
/**
|
||||
* The connection was aborted by the network.
|
||||
*/
|
||||
ENETRESET = 39,
|
||||
|
||||
/**
|
||||
* Network unreachable. No route to the network is present.
|
||||
*/
|
||||
ENETUNREACH = 40,
|
||||
|
||||
/**
|
||||
* Too many files open in system. Too many files are currently open
|
||||
* in the system. The system has reached its predefined limit for
|
||||
* simultaneously open files and temporarily cannot accept requests
|
||||
* to open another one.
|
||||
*/
|
||||
ENFILE = 41,
|
||||
|
||||
/**
|
||||
* No buffer space available. Insufficient buffer resources were
|
||||
* available in the system to perform the socket operation.
|
||||
*/
|
||||
ENOBUFS = 42,
|
||||
|
||||
/**
|
||||
* No message available. No message is available on the STREAM head
|
||||
* read queue.
|
||||
*/
|
||||
ENODATA = 43,
|
||||
|
||||
/**
|
||||
* No such device. An attempt was made to apply an inappropriate
|
||||
* function to a device; for example, trying to read a write-only
|
||||
* device such as a printer.
|
||||
*/
|
||||
ENODEV = 44,
|
||||
|
||||
/**
|
||||
* No such file or directory. A component of a specified pathname
|
||||
* does not exist, or the pathname is an empty string.
|
||||
*/
|
||||
ENOENT = 45,
|
||||
|
||||
/**
|
||||
* Executable file format error. A request is made to execute a file
|
||||
* that, although it has appropriate privileges, is not in the
|
||||
* format required by the implementation for executable files.
|
||||
*/
|
||||
ENOEXEC = 46,
|
||||
|
||||
/**
|
||||
* No locks available. A system-imposed limit on the number of
|
||||
* simultaneous file and record locks has been reached and no more
|
||||
* are currently available.
|
||||
*/
|
||||
ENOLCK = 47,
|
||||
|
||||
/**
|
||||
* Reserved.
|
||||
*/
|
||||
ENOLINK = 48,
|
||||
|
||||
/**
|
||||
* Not enough space. The new process image requires more memory than
|
||||
* is allowed by the hardware or system-imposed memory management
|
||||
* constraints.
|
||||
*/
|
||||
ENOMEM = 49,
|
||||
|
||||
/**
|
||||
* No message of the desired type. The message queue does not contain
|
||||
* a message of the required type during XSI interprocess communication.
|
||||
*/
|
||||
ENOMSG = 50,
|
||||
|
||||
/**
|
||||
* Protocol not available. The protocol option specified to
|
||||
* setsockopt() is not supported by the implementation.
|
||||
*/
|
||||
ENOPROTOOPT = 51,
|
||||
|
||||
/**
|
||||
* No space left on a device. During the write() function on a
|
||||
* regular file or when extending a directory, there is no free
|
||||
* space left on the device.
|
||||
*/
|
||||
ENOSPC = 52,
|
||||
|
||||
/**
|
||||
* No STREAM resources. Insufficient STREAMS memory resources are
|
||||
* available to perform a STREAMS-related function. This is a
|
||||
* temporary condition; it may be recovered from if other
|
||||
* processes release resources.
|
||||
*/
|
||||
ENOSR = 53,
|
||||
|
||||
/**
|
||||
* Not a STREAM. A STREAM function was attempted on a file descriptor
|
||||
* that was not associated with a STREAMS device.
|
||||
*/
|
||||
ENOSTR = 54,
|
||||
|
||||
/**
|
||||
* Functionality not supported. An attempt was made to use optional
|
||||
* functionality that is not supported in this implementation.
|
||||
*/
|
||||
ENOSYS = 55,
|
||||
|
||||
/**
|
||||
* Socket not connected. The socket is not connected.
|
||||
*/
|
||||
ENOTCONN = 56,
|
||||
|
||||
/**
|
||||
* Not a directory. A component of the specified pathname exists, but
|
||||
* it is not a directory, when a directory was expected; or an
|
||||
* attempt was made to create a non-directory file, and the specified
|
||||
* pathname contains at least one non- <slash> character and ends
|
||||
* with one or more trailing <slash> characters.
|
||||
*/
|
||||
ENOTDIR = 57,
|
||||
|
||||
/**
|
||||
* Directory not empty. A directory other than an empty directory
|
||||
* was supplied when an empty directory was expected.
|
||||
*/
|
||||
ENOTEMPTY = 58,
|
||||
|
||||
/**
|
||||
* State not recoverable. The state protected by a robust mutex
|
||||
* is not recoverable.
|
||||
*/
|
||||
ENOTRECOVERABLE = 59,
|
||||
|
||||
/**
|
||||
* Not a socket. The file descriptor does not refer to a socket.
|
||||
*/
|
||||
ENOTSOCK = 60,
|
||||
|
||||
/**
|
||||
* Not supported. The implementation does not support the requested
|
||||
* feature or value.
|
||||
*/
|
||||
ENOTSUP = 61,
|
||||
|
||||
/**
|
||||
* Inappropriate I/O control operation. A control function has been
|
||||
* attempted for a file or special file for which the operation
|
||||
* is inappropriate.
|
||||
*/
|
||||
ENOTTY = 62,
|
||||
|
||||
/**
|
||||
* No such device or address. Input or output on a special file
|
||||
* refers to a device that does not exist, or makes a request
|
||||
* beyond the capabilities of the device. It may also occur when,
|
||||
* for example, a tape drive is not on-line.
|
||||
*/
|
||||
ENXIO = 63,
|
||||
|
||||
/**
|
||||
* Operation not supported on socket. The type of socket (address
|
||||
* family or protocol) does not support the requested operation.
|
||||
*/
|
||||
EOPNOTSUPP = 64,
|
||||
|
||||
/**
|
||||
* Value too large to be stored in data type. An operation was
|
||||
* attempted which would generate a value that is outside the
|
||||
* range of values that can be represented in the relevant data
|
||||
* type or that are allowed for a given data item.
|
||||
*/
|
||||
EOVERFLOW = 65,
|
||||
|
||||
/**
|
||||
* Previous owner died. The owner of a robust mutex terminated
|
||||
* while holding the mutex lock.
|
||||
*/
|
||||
EOWNERDEAD = 66,
|
||||
|
||||
/**
|
||||
* Operation not permitted. An attempt was made to perform an
|
||||
* operation limited to processes with appropriate privileges or
|
||||
* to the owner of a file or other resource.
|
||||
*/
|
||||
EPERM = 67,
|
||||
|
||||
/**
|
||||
* Broken pipe. A write was attempted on a socket, pipe, or FIFO
|
||||
* for which there is no process to read the data.
|
||||
*/
|
||||
EPIPE = 68,
|
||||
|
||||
/**
|
||||
* Protocol error. Some protocol error occurred. This error is
|
||||
* device-specific, but is generally not related to a
|
||||
* hardware failure.
|
||||
*/
|
||||
EPROTO = 69,
|
||||
|
||||
/**
|
||||
* Protocol not supported. The protocol is not supported by the
|
||||
* address family, or the protocol is not supported by
|
||||
* the implementation.
|
||||
*/
|
||||
EPROTONOSUPPORT = 70,
|
||||
|
||||
/**
|
||||
* Protocol wrong type for socket. The socket type is not
|
||||
* supported by the protocol.
|
||||
*/
|
||||
EPROTOTYPE = 71,
|
||||
|
||||
/**
|
||||
* Result too large or too small. The result of the function
|
||||
* is too large (overflow) or too small (underflow) to be
|
||||
* represented in the available space.
|
||||
*/
|
||||
ERANGE = 72,
|
||||
|
||||
/**
|
||||
* Read-only file system. An attempt was made to modify a file
|
||||
* or directory on a file system that is read-only.
|
||||
*/
|
||||
EROFS = 73,
|
||||
|
||||
/**
|
||||
* Invalid seek. An attempt was made to access the file offset
|
||||
* associated with a pipe or FIFO.
|
||||
*/
|
||||
ESPIPE = 74,
|
||||
|
||||
/**
|
||||
* No such process. No process can be found corresponding to that
|
||||
* specified by the given process ID.
|
||||
*/
|
||||
ESRCH = 75,
|
||||
|
||||
/**
|
||||
* Reserved.
|
||||
*/
|
||||
ESTALE = 76,
|
||||
|
||||
/**
|
||||
* STREAM ioctl() timeout. The timer set for a STREAMS ioctl() call
|
||||
* has expired. The cause of this error is device-specific and could
|
||||
* indicate either a hardware or software failure, or a timeout
|
||||
* value that is too short for the specific operation. The status
|
||||
* of the ioctl() operation is unspecified.
|
||||
*/
|
||||
ETIME = 77,
|
||||
|
||||
/**
|
||||
* Connection timed out. The connection to a remote machine has
|
||||
* timed out.
|
||||
* If the connection timed out during execution of the function that
|
||||
* reported this error (as opposed to timing out prior to the
|
||||
* function being called), it is unspecified whether the function
|
||||
* has completed some or all of the documented behavior associated
|
||||
* with a successful completion of the function.
|
||||
* or:
|
||||
* Operation timed out. The time limit associated with the operation
|
||||
* was exceeded before the operation completed.
|
||||
*/
|
||||
ETIMEDOUT = 78,
|
||||
|
||||
/**
|
||||
* Text file busy. An attempt was made to execute a pure-procedure
|
||||
* program that is currently open for writing, or an attempt has
|
||||
* been made to open for writing a pure-procedure program that
|
||||
* is being executed.
|
||||
*/
|
||||
ETXTBSY = 79,
|
||||
|
||||
/**
|
||||
* Operation would block. An operation on a socket marked as
|
||||
* non-blocking has encountered a situation such as no data available
|
||||
* that otherwise would have caused the function to suspend execution.
|
||||
*/
|
||||
EWOULDBLOCK = 80,
|
||||
|
||||
/**
|
||||
* Improper link. A link to a file on another file system was attempted.
|
||||
*/
|
||||
EXDEV = 81,
|
||||
|
||||
__ERRNO_MAX
|
||||
} KernelErrors;
|
||||
|
||||
#include <types.h>
|
||||
EXTERNC int *__errno_location(void) __attribute__((const));
|
||||
#define errno (*__errno_location())
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
char *strerror(int errnum);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // !__FENNIX_KERNEL_ERRNO_H__
|
378
include/interface/fs.h
Normal file
378
include/interface/fs.h
Normal file
@ -0,0 +1,378 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __FENNIX_API_FILESYSTEM_H__
|
||||
#define __FENNIX_API_FILESYSTEM_H__
|
||||
|
||||
#ifdef __kernel__
|
||||
#include <types.h>
|
||||
#endif
|
||||
|
||||
#define SEEK_SET 0
|
||||
#define SEEK_CUR 1
|
||||
#define SEEK_END 2
|
||||
|
||||
/**
|
||||
* File type mask for the upper 32 bits of mode_t.
|
||||
*
|
||||
* @note Maybe it will be used in the future.
|
||||
*/
|
||||
#define S_IFMT32 037777600000
|
||||
|
||||
/**
|
||||
* File type mask.
|
||||
*
|
||||
* This mask is used to extract the file type
|
||||
* from the mode field of a stat structure.
|
||||
*
|
||||
* Doing bitwise AND with this mask will return
|
||||
* the file type.
|
||||
* Example: st_mode & S_IFMT
|
||||
*
|
||||
* Doing bitwise negation and AND with this mask
|
||||
* will return the permissions.
|
||||
* Example: st_mode & ~S_IFMT
|
||||
*/
|
||||
#define S_IFMT 0170000
|
||||
|
||||
/* Whiteout */
|
||||
#define S_IFWHT 0160000
|
||||
/* Socket */
|
||||
#define S_IFSOCK 0140000
|
||||
/* Symbolic link */
|
||||
#define S_IFLNK 0120000
|
||||
/* Regular file */
|
||||
#define S_IFREG 0100000
|
||||
/* Block device */
|
||||
#define S_IFBLK 0060000
|
||||
/* Directory */
|
||||
#define S_IFDIR 0040000
|
||||
/* Character device */
|
||||
#define S_IFCHR 0020000
|
||||
/* FIFO */
|
||||
#define S_IFIFO 0010000
|
||||
|
||||
#define S_ISUID 04000
|
||||
#define S_ISGID 02000
|
||||
#define S_ISVTX 01000
|
||||
|
||||
/** Owner: RWX */
|
||||
#define S_IRWXU 0700
|
||||
/** Owner: R */
|
||||
#define S_IRUSR 0400
|
||||
/** Owner: W */
|
||||
#define S_IWUSR 0200
|
||||
/** Owner: X */
|
||||
#define S_IXUSR 0100
|
||||
|
||||
/** Group: RWX */
|
||||
#define S_IRWXG 0070
|
||||
/** Group: R */
|
||||
#define S_IRGRP 0040
|
||||
/** Group: W */
|
||||
#define S_IWGRP 0020
|
||||
/** Group: X */
|
||||
#define S_IXGRP 0010
|
||||
|
||||
/** Other: RWX */
|
||||
#define S_IRWXO 0007
|
||||
/** Other: R */
|
||||
#define S_IROTH 0004
|
||||
/** Other: W */
|
||||
#define S_IWOTH 0002
|
||||
/** Other: X */
|
||||
#define S_IXOTH 0001
|
||||
|
||||
#define O_RDONLY 00
|
||||
#define O_WRONLY 01
|
||||
#define O_RDWR 02
|
||||
#define O_CREAT 0100
|
||||
#define O_EXCL 0200
|
||||
#define O_TRUNC 01000
|
||||
#define O_APPEND 02000
|
||||
#define O_NOFOLLOW 0400000
|
||||
#define O_CLOEXEC 02000000
|
||||
|
||||
#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
|
||||
#define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR)
|
||||
#define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK)
|
||||
#define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
|
||||
#define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO)
|
||||
#define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK)
|
||||
#define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK)
|
||||
|
||||
#define DT_UNKNOWN 0x0
|
||||
#define DT_FIFO 0x1
|
||||
#define DT_CHR 0x2
|
||||
#define DT_DIR 0x4
|
||||
#define DT_BLK 0x6
|
||||
#define DT_REG 0x8
|
||||
#define DT_LNK 0xA
|
||||
#define DT_SOCK 0xC
|
||||
#define DT_WHT 0xE
|
||||
|
||||
#define IFTODT(x) ((x) >> 12 & 0xF)
|
||||
#define DTTOIF(x) ((x) << 12)
|
||||
|
||||
#define SYMLOOP_MAX 40
|
||||
|
||||
#ifndef __cplusplus
|
||||
#define static_assert _Static_assert
|
||||
#endif
|
||||
|
||||
#ifdef __LP64__
|
||||
static_assert(sizeof(dev_t) == 8, "dev_t must be 64 bits");
|
||||
static_assert(sizeof(ino_t) == 8, "ino_t must be 64 bits");
|
||||
static_assert(sizeof(mode_t) == 4, "mode_t must be 32 bits");
|
||||
static_assert(sizeof(nlink_t) == 4, "nlink_t must be 32 bits");
|
||||
static_assert(sizeof(uid_t) == 4, "uid_t must be 32 bits");
|
||||
static_assert(sizeof(gid_t) == 4, "gid_t must be 32 bits");
|
||||
static_assert(sizeof(off_t) == 8, "off_t must be 64 bits");
|
||||
static_assert(sizeof(time_t) == 8, "time_t must be 64 bits");
|
||||
static_assert(sizeof(blksize_t) == 8, "blksize_t must be 64 bits");
|
||||
static_assert(sizeof(blkcnt_t) == 8, "blkcnt_t must be 64 bits");
|
||||
#else
|
||||
static_assert(sizeof(dev_t) == 4, "dev_t must be 32 bits");
|
||||
static_assert(sizeof(ino_t) == 4, "ino_t must be 32 bits");
|
||||
static_assert(sizeof(mode_t) == 2, "mode_t must be 16 bits");
|
||||
static_assert(sizeof(nlink_t) == 2, "nlink_t must be 16 bits");
|
||||
static_assert(sizeof(uid_t) == 2, "uid_t must be 16 bits");
|
||||
static_assert(sizeof(gid_t) == 2, "gid_t must be 16 bits");
|
||||
static_assert(sizeof(off_t) == 4, "off_t must be 32 bits");
|
||||
static_assert(sizeof(time_t) == 4, "time_t must be 32 bits");
|
||||
static_assert(sizeof(blksize_t) == 4, "blksize_t must be 32 bits");
|
||||
static_assert(sizeof(blkcnt_t) == 4, "blkcnt_t must be 32 bits");
|
||||
#endif
|
||||
|
||||
#undef static_assert
|
||||
|
||||
struct kstat
|
||||
{
|
||||
/** Device ID of the file. */
|
||||
dev_t Device;
|
||||
|
||||
/** Inode number. */
|
||||
ino_t Index;
|
||||
|
||||
/** File type and mode. */
|
||||
mode_t Mode;
|
||||
|
||||
/** Number of hard links. */
|
||||
nlink_t HardLinks;
|
||||
|
||||
/** User ID of the file's owner. */
|
||||
uid_t UserID;
|
||||
|
||||
/** Group ID of the file's owner. */
|
||||
gid_t GroupID;
|
||||
|
||||
/** Device ID for special files. */
|
||||
dev_t RawDevice;
|
||||
|
||||
/** Size of the file in bytes. */
|
||||
off_t Size;
|
||||
|
||||
/** Time of last access. */
|
||||
time_t AccessTime;
|
||||
|
||||
/** Time of last modification. */
|
||||
time_t ModifyTime;
|
||||
|
||||
/** Time of last status change. */
|
||||
time_t ChangeTime;
|
||||
|
||||
/** Optimal I/O block size. */
|
||||
blksize_t BlockSize;
|
||||
|
||||
/** Number of blocks allocated. */
|
||||
blkcnt_t Blocks;
|
||||
|
||||
/** Additional file attributes. */
|
||||
mode_t Attribute;
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
dev_t MakeDevice(int Major, int Minor)
|
||||
{
|
||||
return ((Major & 0xFFF) << 8) |
|
||||
(Minor & 0xFF);
|
||||
}
|
||||
|
||||
int GetMajor()
|
||||
{
|
||||
return ((unsigned int)(Device) >> 8) & 0xFFF;
|
||||
}
|
||||
|
||||
int GetMinor()
|
||||
{
|
||||
return Device & 0xFF;
|
||||
}
|
||||
|
||||
void SetFileType(mode_t Type)
|
||||
{
|
||||
Mode = (Mode & ~S_IFMT) |
|
||||
(Type & S_IFMT);
|
||||
}
|
||||
|
||||
mode_t GetFileType() { return Mode & S_IFMT; }
|
||||
void ClearFileType() { Mode = Mode & ~S_IFMT; }
|
||||
bool IsType(mode_t Type) { return (Mode & S_IFMT) == Type; }
|
||||
|
||||
void SetPermissions(mode_t Permissions)
|
||||
{
|
||||
Mode = (Mode & S_IFMT) |
|
||||
(Permissions & ~S_IFMT);
|
||||
}
|
||||
|
||||
mode_t GetPermissions() { return Mode & ~S_IFMT; }
|
||||
void ClearPermissions() { Mode = Mode & S_IFMT; }
|
||||
|
||||
#endif // __cplusplus
|
||||
};
|
||||
|
||||
struct kdirent
|
||||
{
|
||||
ino_t d_ino;
|
||||
off_t d_off;
|
||||
unsigned short d_reclen;
|
||||
unsigned char d_type;
|
||||
char d_name[];
|
||||
};
|
||||
|
||||
struct InodeOperations
|
||||
{
|
||||
int (*Lookup)(struct Inode *Parent, const char *Name, struct Inode **Result);
|
||||
int (*Create)(struct Inode *Parent, const char *Name, mode_t Mode, struct Inode **Result);
|
||||
int (*Remove)(struct Inode *Parent, const char *Name);
|
||||
int (*Rename)(struct Inode *Parent, const char *OldName, const char *NewName);
|
||||
ssize_t (*Read)(struct Inode *Node, void *Buffer, size_t Size, off_t Offset);
|
||||
ssize_t (*Write)(struct Inode *Node, const void *Buffer, size_t Size, off_t Offset);
|
||||
int (*Truncate)(struct Inode *Node, off_t Size);
|
||||
int (*Open)(struct Inode *Node, int Flags, mode_t Mode);
|
||||
int (*Close)(struct Inode *Node);
|
||||
int (*Ioctl)(struct Inode *Node, unsigned long Request, void *Argp);
|
||||
ssize_t (*ReadDir)(struct Inode *Node, struct kdirent *Buffer, size_t Size, off_t Offset, off_t Entries);
|
||||
int (*MkDir)(struct Inode *Parent, const char *Name, mode_t Mode, struct Inode **Result);
|
||||
int (*RmDir)(struct Inode *Parent, const char *Name);
|
||||
int (*SymLink)(struct Inode *Parent, const char *Name, const char *Target, struct Inode **Result);
|
||||
ssize_t (*ReadLink)(struct Inode *Node, char *Buffer, size_t Size);
|
||||
off_t (*Seek)(struct Inode *Node, off_t Offset);
|
||||
int (*Stat)(struct Inode *Node, struct kstat *Stat);
|
||||
} __attribute__((packed));
|
||||
|
||||
#define I_FLAG_MOUNTPOINT 0x1
|
||||
#define I_FLAG_CACHE_KEEP 0x2
|
||||
|
||||
struct Inode
|
||||
{
|
||||
dev_t Device, RawDevice;
|
||||
ino_t Index;
|
||||
mode_t Mode;
|
||||
uint32_t Flags;
|
||||
off_t Offset;
|
||||
|
||||
void *PrivateData;
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
/* ... */
|
||||
|
||||
void SetDevice(int Major, int Minor)
|
||||
{
|
||||
this->RawDevice = ((Major & 0xFFF) << 8) |
|
||||
(Minor & 0xFF);
|
||||
}
|
||||
|
||||
int GetMajor()
|
||||
{
|
||||
return ((unsigned int)(this->RawDevice) >> 8) & 0xFFF;
|
||||
}
|
||||
|
||||
int GetMinor()
|
||||
{
|
||||
return this->RawDevice & 0xFF;
|
||||
}
|
||||
|
||||
Inode()
|
||||
{
|
||||
Index = 0;
|
||||
Mode = 0;
|
||||
Device = 0;
|
||||
RawDevice = 0;
|
||||
Flags = 0;
|
||||
PrivateData = nullptr;
|
||||
}
|
||||
|
||||
~Inode() = default;
|
||||
|
||||
#else // __cplusplus
|
||||
|
||||
#define INODE_MAKEDEV(major, minor) \
|
||||
((dev_t)(((major & 0xFFF) << 8) | \
|
||||
(minor & 0xFF)))
|
||||
|
||||
#define INODE_MAJOR(rdev) \
|
||||
((int)(((rdev) >> 8) & 0xFFF))
|
||||
|
||||
#define INODE_MINOR(rdev) \
|
||||
((int)((rdev) & 0xFF))
|
||||
|
||||
#endif // __cplusplus
|
||||
};
|
||||
|
||||
struct SuperBlockOperations
|
||||
{
|
||||
int (*AllocateInode)(struct FileSystemInfo *Info, struct Inode **Result);
|
||||
int (*DeleteInode)(struct FileSystemInfo *Info, struct Inode *Node);
|
||||
|
||||
/**
|
||||
* Synchronize the filesystem.
|
||||
*
|
||||
* Write all pending changes to the disk.
|
||||
*
|
||||
* @param Info Inode to synchronize. If NULL, synchronize all inodes.
|
||||
*
|
||||
* @return Zero on success, otherwise an error code.
|
||||
*/
|
||||
int (*Synchronize)(struct FileSystemInfo *Info, struct Inode *Node);
|
||||
|
||||
/**
|
||||
* Destroy the filesystem.
|
||||
*
|
||||
* Unregister the filesystem and free all resources.
|
||||
*
|
||||
* @param Info Filesystem to destroy.
|
||||
*
|
||||
* @return Zero on success, otherwise an error code.
|
||||
*/
|
||||
int (*Destroy)(FileSystemInfo *Info);
|
||||
} __attribute__((packed));
|
||||
|
||||
struct FileSystemInfo
|
||||
{
|
||||
const char *Name;
|
||||
int Flags;
|
||||
struct SuperBlockOperations SuperOps;
|
||||
struct InodeOperations Ops;
|
||||
|
||||
void *PrivateData;
|
||||
} __attribute__((packed));
|
||||
|
||||
dev_t RegisterFileSystem(FileSystemInfo *Info, struct Inode *Root);
|
||||
int UnregisterFileSystem(dev_t Device);
|
||||
|
||||
#endif // !__FENNIX_API_FILESYSTEM_H__
|
111
include/interface/syscalls.h
Normal file
111
include/interface/syscalls.h
Normal file
@ -0,0 +1,111 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __FENNIX_API_SYSCALLS_LIST_H__
|
||||
#define __FENNIX_API_SYSCALLS_LIST_H__
|
||||
|
||||
#ifndef syscall0
|
||||
static inline long syscall0(long syscall)
|
||||
{
|
||||
long ret;
|
||||
__asm__ __volatile__("syscall"
|
||||
: "=a"(ret)
|
||||
: "a"(syscall)
|
||||
: "rcx", "r11", "memory");
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef syscall1
|
||||
static inline long syscall1(long syscall, long arg1)
|
||||
{
|
||||
long ret;
|
||||
__asm__ __volatile__("syscall"
|
||||
: "=a"(ret)
|
||||
: "a"(syscall), "D"(arg1)
|
||||
: "rcx", "r11", "memory");
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef syscall2
|
||||
static inline long syscall2(long syscall, long arg1, long arg2)
|
||||
{
|
||||
long ret;
|
||||
__asm__ __volatile__("syscall"
|
||||
: "=a"(ret)
|
||||
: "a"(syscall), "D"(arg1), "S"(arg2)
|
||||
: "rcx", "r11", "memory");
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef syscall3
|
||||
static inline long syscall3(long syscall, long arg1, long arg2, long arg3)
|
||||
{
|
||||
long ret;
|
||||
__asm__ __volatile__("syscall"
|
||||
: "=a"(ret)
|
||||
: "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3)
|
||||
: "rcx", "r11", "memory");
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef syscall4
|
||||
static inline long syscall4(long syscall, long arg1, long arg2, long arg3, long arg4)
|
||||
{
|
||||
long ret;
|
||||
register long r10 __asm__("r10") = arg4;
|
||||
__asm__ __volatile__("syscall"
|
||||
: "=a"(ret)
|
||||
: "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3), "r"(r10)
|
||||
: "rcx", "r11", "memory");
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef syscall5
|
||||
static inline long syscall5(long syscall, long arg1, long arg2, long arg3, long arg4, long arg5)
|
||||
{
|
||||
long ret;
|
||||
register long r10 __asm__("r10") = arg4;
|
||||
register long r8 __asm__("r8") = arg5;
|
||||
__asm__ __volatile__("syscall"
|
||||
: "=a"(ret)
|
||||
: "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3), "r"(r10), "r"(r8)
|
||||
: "rcx", "r11", "memory");
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef syscall6
|
||||
static inline long syscall6(long syscall, long arg1, long arg2, long arg3, long arg4, long arg5, long arg6)
|
||||
{
|
||||
long ret;
|
||||
register long r10 __asm__("r10") = arg4;
|
||||
register long r8 __asm__("r8") = arg5;
|
||||
register long r9 __asm__("r9") = arg6;
|
||||
__asm__ __volatile__("syscall"
|
||||
: "=a"(ret)
|
||||
: "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3), "r"(r10), "r"(r8), "r"(r9)
|
||||
: "rcx", "r11", "memory");
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // !__FENNIX_API_SYSCALLS_LIST_H__
|
29
include/kcon.hpp
Normal file
29
include/kcon.hpp
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __FENNIX_KERNEL_KERNEL_CONSOLE_H__
|
||||
#define __FENNIX_KERNEL_KERNEL_CONSOLE_H__
|
||||
|
||||
#include <termios.h>
|
||||
|
||||
namespace KernelConsole
|
||||
{
|
||||
void EarlyInit();
|
||||
void LateInit();
|
||||
}
|
||||
|
||||
#endif // !__FENNIX_KERNEL_KERNEL_CONSOLE_H__
|
@ -19,7 +19,7 @@
|
||||
#define __FENNIX_KERNEL_CXXABI_H__
|
||||
|
||||
#include <types.h>
|
||||
#include <unwind.h>
|
||||
#include <kexcept/unwind.h>
|
||||
#include <typeinfo>
|
||||
|
||||
namespace __cxxabiv1
|
||||
@ -37,33 +37,82 @@ namespace __cxxabiv1
|
||||
|
||||
struct __cxa_exception
|
||||
{
|
||||
#ifdef __LP64__
|
||||
char __padding[8];
|
||||
uintptr_t referenceCount;
|
||||
#endif
|
||||
std::type_info *exceptionType;
|
||||
void (*exceptionDestructor)(void *);
|
||||
std::terminate_handler unexpectedHandler;
|
||||
std::terminate_handler terminateHandler;
|
||||
__cxa_exception *nextException;
|
||||
int handlerCount;
|
||||
#ifdef __ARM_EABI_UNWINDER__
|
||||
#ifdef __arm__
|
||||
__cxa_exception *nextPropagatingException;
|
||||
int propagationCount;
|
||||
#else
|
||||
int handlerSwitchValue;
|
||||
const unsigned char *actionRecord;
|
||||
const unsigned char *languageSpecificData;
|
||||
_Unwind_Ptr catchTemp;
|
||||
void *catchTemp;
|
||||
void *adjustedPtr;
|
||||
#endif
|
||||
#ifndef __LP64__
|
||||
uintptr_t referenceCount;
|
||||
#endif
|
||||
_Unwind_Exception unwindHeader;
|
||||
};
|
||||
|
||||
struct __cxa_dependent_exception
|
||||
{
|
||||
#ifdef __LP64__
|
||||
char __padding[8];
|
||||
void *primaryException;
|
||||
#endif
|
||||
std::type_info *exceptionType;
|
||||
void (*exceptionDestructor)(void *);
|
||||
std::unexpected_handler unexpectedHandler;
|
||||
std::terminate_handler terminateHandler;
|
||||
__cxa_exception *nextException;
|
||||
int handlerCount;
|
||||
#ifdef __arm__
|
||||
_Unwind_Exception *nextCleanup;
|
||||
int cleanupCount;
|
||||
#endif
|
||||
int handlerSwitchValue;
|
||||
const char *actionRecord;
|
||||
const char *languageSpecificData;
|
||||
void *catchTemp;
|
||||
void *adjustedPtr;
|
||||
#ifndef __LP64__
|
||||
void *primaryException;
|
||||
#endif
|
||||
_Unwind_Exception unwindHeader;
|
||||
};
|
||||
|
||||
struct __cxa_eh_globals
|
||||
{
|
||||
__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__
|
@ -20,7 +20,7 @@
|
||||
|
||||
#include <types.h>
|
||||
|
||||
enum _Unwind_Reason_Code
|
||||
typedef enum
|
||||
{
|
||||
_URC_NO_REASON = 0,
|
||||
_URC_FOREIGN_EXCEPTION_CAUGHT = 1,
|
||||
@ -31,7 +31,7 @@ enum _Unwind_Reason_Code
|
||||
_URC_HANDLER_FOUND = 6,
|
||||
_URC_INSTALL_CONTEXT = 7,
|
||||
_URC_CONTINUE_UNWIND = 8
|
||||
};
|
||||
} _Unwind_Reason_Code;
|
||||
|
||||
typedef void *_Unwind_Context_Reg_Val;
|
||||
typedef unsigned _Unwind_Exception_Class __attribute__((__mode__(__DI__)));
|
||||
@ -40,20 +40,15 @@ typedef unsigned _Unwind_Word __attribute__((__mode__(__unwind_word__)));
|
||||
typedef signed _Unwind_Sword __attribute__((__mode__(__unwind_word__)));
|
||||
typedef int _Unwind_Action;
|
||||
|
||||
enum _UA : _Unwind_Action
|
||||
{
|
||||
_UA_SEARCH_PHASE = 1,
|
||||
_UA_CLEANUP_PHASE = 2,
|
||||
_UA_HANDLER_FRAME = 4,
|
||||
_UA_FORCE_UNWIND = 8,
|
||||
_UA_END_OF_STACK = 16
|
||||
};
|
||||
#define _UA_SEARCH_PHASE 1
|
||||
#define _UA_CLEANUP_PHASE 2
|
||||
#define _UA_HANDLER_FRAME 4
|
||||
#define _UA_FORCE_UNWIND 8
|
||||
#define _UA_END_OF_STACK 16
|
||||
|
||||
typedef void (*_Unwind_Exception_Cleanup_Fn)(_Unwind_Reason_Code,
|
||||
struct _Unwind_Exception *);
|
||||
typedef void (*_Unwind_Exception_Cleanup_Fn)(_Unwind_Reason_Code, struct _Unwind_Exception *);
|
||||
|
||||
typedef _Unwind_Reason_Code (*_Unwind_Personality_Fn)(int,
|
||||
_Unwind_Action,
|
||||
typedef _Unwind_Reason_Code (*_Unwind_Personality_Fn)(int, _Unwind_Action,
|
||||
_Unwind_Exception_Class,
|
||||
struct _Unwind_Exception *,
|
||||
struct _Unwind_Context *);
|
||||
@ -66,13 +61,14 @@ struct _Unwind_Exception
|
||||
_Unwind_Word private_2;
|
||||
} __attribute__((__aligned__));
|
||||
|
||||
struct _Unwind_Context;
|
||||
struct _Unwind_Context
|
||||
{
|
||||
int __stub;
|
||||
};
|
||||
|
||||
struct _Unwind_FrameState
|
||||
{
|
||||
_Unwind_Personality_Fn personality;
|
||||
};
|
||||
|
||||
EXTERNC _Unwind_Reason_Code _Unwind_RaiseException(_Unwind_Exception *Exception);
|
||||
|
||||
#endif // !__FENNIX_KERNEL_UNWIND_H__
|
@ -94,6 +94,25 @@ public:
|
||||
~spin_lock() = default;
|
||||
};
|
||||
|
||||
class __sl_guard
|
||||
{
|
||||
private:
|
||||
spin_lock &sl;
|
||||
|
||||
public:
|
||||
__sl_guard(spin_lock &sl, const char *FunctionName) : sl(sl)
|
||||
{
|
||||
this->sl.lock(FunctionName);
|
||||
}
|
||||
|
||||
~__sl_guard()
|
||||
{
|
||||
this->sl.unlock();
|
||||
}
|
||||
};
|
||||
|
||||
#define sl_guard(sl) __sl_guard CONCAT(sl_guard_, __COUNTER__)(sl, __FUNCTION__)
|
||||
|
||||
/** @brief Please use this macro to create a new smart lock. */
|
||||
class SmartLockClass
|
||||
{
|
||||
|
76
include/macho.h
Normal file
76
include/macho.h
Normal file
@ -0,0 +1,76 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __FENNIX_KERNEL_MACH_O_H__
|
||||
#define __FENNIX_KERNEL_MACH_O_H__
|
||||
|
||||
#include <types.h>
|
||||
|
||||
#define MH_MAGIC 0xfeedface
|
||||
#define MH_CIGAM 0xcefaedfe
|
||||
|
||||
#define CPU_TYPE_ANY ((cpu_type_t) - 1)
|
||||
|
||||
#define CPU_TYPE_VAX ((cpu_type_t)1)
|
||||
#define CPU_TYPE_ROMP ((cpu_type_t)2)
|
||||
#define CPU_TYPE_NS32032 ((cpu_type_t)4)
|
||||
#define CPU_TYPE_NS32332 ((cpu_type_t)5)
|
||||
#define CPU_TYPE_MC680x0 ((cpu_type_t)6)
|
||||
#define CPU_TYPE_I386 ((cpu_type_t)7)
|
||||
#define CPU_TYPE_X86_64 ((cpu_type_t)(CPU_TYPE_I386 | CPU_ARCH_ABI64))
|
||||
#define CPU_TYPE_MIPS ((cpu_type_t)8)
|
||||
#define CPU_TYPE_NS32532 ((cpu_type_t)9)
|
||||
#define CPU_TYPE_HPPA ((cpu_type_t)11)
|
||||
#define CPU_TYPE_ARM ((cpu_type_t)12)
|
||||
#define CPU_TYPE_MC88000 ((cpu_type_t)13)
|
||||
#define CPU_TYPE_SPARC ((cpu_type_t)14)
|
||||
#define CPU_TYPE_I860 ((cpu_type_t)15)
|
||||
#define CPU_TYPE_I860_LITTLE ((cpu_type_t)16)
|
||||
#define CPU_TYPE_RS6000 ((cpu_type_t)17)
|
||||
#define CPU_TYPE_MC98000 ((cpu_type_t)18)
|
||||
#define CPU_TYPE_POWERPC ((cpu_type_t)18)
|
||||
#define CPU_ARCH_ABI64 0x1000000
|
||||
#define CPU_TYPE_POWERPC64 ((cpu_type_t)(CPU_TYPE_POWERPC | CPU_ARCH_ABI64))
|
||||
#define CPU_TYPE_VEO ((cpu_type_t)255)
|
||||
|
||||
typedef int cpu_type_t;
|
||||
typedef int cpu_subtype_t;
|
||||
|
||||
struct mach_header
|
||||
{
|
||||
uint32_t magic;
|
||||
cpu_type_t cputype;
|
||||
cpu_subtype_t cpusubtype;
|
||||
uint32_t filetype;
|
||||
uint32_t ncmds;
|
||||
uint32_t sizeofcmds;
|
||||
uint32_t flags;
|
||||
};
|
||||
|
||||
struct mach_header_64
|
||||
{
|
||||
uint32_t magic;
|
||||
cpu_type_t cputype;
|
||||
cpu_subtype_t cpusubtype;
|
||||
uint32_t filetype;
|
||||
uint32_t ncmds;
|
||||
uint32_t sizeofcmds;
|
||||
uint32_t flags;
|
||||
uint32_t reserved;
|
||||
};
|
||||
|
||||
#endif // !__FENNIX_KERNEL_MACH_O_H__
|
@ -23,9 +23,9 @@
|
||||
#include <boot/binfo.h>
|
||||
#include <bitmap.hpp>
|
||||
#include <lock.hpp>
|
||||
#include <std.hpp>
|
||||
#include <atomic>
|
||||
#include <cstddef>
|
||||
#include <atomic>
|
||||
#include <new>
|
||||
#endif // __cplusplus
|
||||
#include <types.h>
|
||||
|
||||
@ -53,7 +53,7 @@ namespace Memory
|
||||
|
||||
/**
|
||||
* @warning Not working as expected.
|
||||
*
|
||||
*
|
||||
* FIXME: This allocator is not working as expected.
|
||||
*/
|
||||
rpmalloc_,
|
||||
@ -73,24 +73,20 @@ namespace Memory
|
||||
void InitializeMemoryManagement();
|
||||
void CreatePageTable(Memory::PageTable *pt);
|
||||
|
||||
void *operator new(std::size_t Size);
|
||||
void *operator new[](std::size_t Size);
|
||||
void *operator new(std::size_t Size, std::align_val_t Alignment);
|
||||
void operator delete(void *Pointer);
|
||||
void operator delete[](void *Pointer);
|
||||
void operator delete(void *Pointer, long unsigned int Size);
|
||||
void operator delete[](void *Pointer, long unsigned int Size);
|
||||
|
||||
extern Memory::Physical KernelAllocator;
|
||||
extern Memory::PageTable *KernelPageTable;
|
||||
|
||||
#endif // __cplusplus
|
||||
|
||||
#ifndef __FENNIX_KERNEL_STDLIB_H__
|
||||
|
||||
EXTERNC void *malloc(size_t Size);
|
||||
EXTERNC void *calloc(size_t n, size_t Size);
|
||||
EXTERNC void *realloc(void *Address, size_t Size);
|
||||
EXTERNC void free(void *Address);
|
||||
|
||||
#endif // !__FENNIX_KERNEL_STDLIB_H__
|
||||
|
||||
#define kmalloc(Size) malloc(Size)
|
||||
#define kcalloc(n, Size) calloc(n, Size)
|
||||
#define krealloc(Address, Size) realloc(Address, Size)
|
||||
|
@ -44,7 +44,7 @@ namespace Memory
|
||||
|
||||
void InitBrk(uintptr_t Address)
|
||||
{
|
||||
function("%#lx", Address);
|
||||
func("%#lx", Address);
|
||||
HeapStart = Address;
|
||||
Break = Address;
|
||||
}
|
||||
|
@ -128,7 +128,7 @@ namespace NetworkIPv4
|
||||
UNUSED(DestinationIP);
|
||||
UNUSED(Data);
|
||||
UNUSED(Length);
|
||||
warn("Not implemented.");
|
||||
warn("Not implemented");
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
@ -53,7 +53,7 @@ namespace NetworkUDP
|
||||
UNUSED(Socket);
|
||||
UNUSED(Data);
|
||||
UNUSED(Length);
|
||||
warn("Not implemented.");
|
||||
warn("Not implemented");
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -58,12 +58,12 @@ namespace Tasking::Scheduler
|
||||
assert(!"GetProcessByID not implemented");
|
||||
}
|
||||
|
||||
virtual TCB *GetThreadByID(TID ID, PCB* Parent)
|
||||
virtual TCB *GetThreadByID(TID ID, PCB *Parent)
|
||||
{
|
||||
assert(!"GetThreadByID not implemented");
|
||||
}
|
||||
|
||||
virtual std::list<PCB *> &GetProcessList()
|
||||
virtual std::vector<PCB *> &GetProcessList()
|
||||
{
|
||||
assert(!"GetProcessList not implemented");
|
||||
}
|
||||
@ -111,7 +111,7 @@ namespace Tasking::Scheduler
|
||||
NewLock(SchedulerLock);
|
||||
|
||||
public:
|
||||
std::list<PCB *> ProcessList;
|
||||
std::vector<PCB *> ProcessList;
|
||||
|
||||
PCB *IdleProcess = nullptr;
|
||||
TCB *IdleThread = nullptr;
|
||||
@ -119,8 +119,8 @@ namespace Tasking::Scheduler
|
||||
bool RemoveThread(TCB *tcb) final;
|
||||
bool RemoveProcess(PCB *pcb) final;
|
||||
PCB *GetProcessByID(TID ID) final;
|
||||
TCB *GetThreadByID(TID ID, PCB* Parent) final;
|
||||
std::list<PCB *> &GetProcessList() final;
|
||||
TCB *GetThreadByID(TID ID, PCB *Parent) final;
|
||||
std::vector<PCB *> &GetProcessList() final;
|
||||
void StartIdleProcess() final;
|
||||
void StartScheduler() final;
|
||||
void Yield() final;
|
||||
|
@ -19,7 +19,7 @@
|
||||
#define __FENNIX_KERNEL_SMP_H__
|
||||
|
||||
#include <task.hpp>
|
||||
#include <cxxabi.h>
|
||||
#include <kexcept/cxxabi.h>
|
||||
#include <types.h>
|
||||
#include <atomic>
|
||||
|
||||
@ -39,31 +39,31 @@ struct CPUArchData
|
||||
|
||||
struct CPUData
|
||||
{
|
||||
/** @brief Used by CPU */
|
||||
/** Used by CPU */
|
||||
uintptr_t Stack;
|
||||
|
||||
/** @brief CPU ID. */
|
||||
/** CPU ID. */
|
||||
int ID;
|
||||
|
||||
/** @brief Local CPU error code. */
|
||||
/** Local CPU error code. */
|
||||
long ErrorCode;
|
||||
|
||||
/** @brief Current running process */
|
||||
/** Current running process */
|
||||
std::atomic<Tasking::PCB *> CurrentProcess;
|
||||
|
||||
/** @brief Current running thread */
|
||||
/** Current running thread */
|
||||
std::atomic<Tasking::TCB *> CurrentThread;
|
||||
|
||||
/** @brief Unwind data */
|
||||
__cxa_eh_globals EHGlobals;
|
||||
/** Exception information. */
|
||||
ExceptionInfo Exception;
|
||||
|
||||
/** @brief Architecture-specific data. */
|
||||
/** Architecture-specific data. */
|
||||
CPUArchData Data;
|
||||
|
||||
/** @brief Checksum. Used to verify the integrity of the data. Must be equal to CPU_DATA_CHECKSUM (0xC0FFEE). */
|
||||
/** Checksum. Used to verify the integrity of the data. Must be equal to CPU_DATA_CHECKSUM (0xC0FFEE). */
|
||||
int Checksum;
|
||||
|
||||
/** @brief Is CPU online? */
|
||||
/** Is CPU online? */
|
||||
bool IsActive;
|
||||
} __aligned(16);
|
||||
|
||||
|
@ -15,36 +15,30 @@
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <filesystem/mounts.hpp>
|
||||
#include <filesystem/ioctl.hpp>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <initializer_list>
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
|
||||
#include "../../../kernel.h"
|
||||
|
||||
namespace vfs
|
||||
template <typename T, std::size_t N>
|
||||
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<T> 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; }
|
||||
};
|
@ -20,174 +20,178 @@
|
||||
|
||||
#include <types.h>
|
||||
|
||||
#define ARCH_SET_GS 0x1001
|
||||
#define ARCH_SET_FS 0x1002
|
||||
#define ARCH_GET_FS 0x1003
|
||||
#define ARCH_GET_GS 0x1004
|
||||
#define linux_SEEK_SET 0
|
||||
#define linux_SEEK_CUR 1
|
||||
#define linux_SEEK_END 2
|
||||
|
||||
#define ARCH_GET_CPUID 0x1011
|
||||
#define ARCH_SET_CPUID 0x1012
|
||||
#define linux_ARCH_SET_GS 0x1001
|
||||
#define linux_ARCH_SET_FS 0x1002
|
||||
#define linux_ARCH_GET_FS 0x1003
|
||||
#define linux_ARCH_GET_GS 0x1004
|
||||
|
||||
#define ARCH_GET_XCOMP_SUPP 0x1021
|
||||
#define ARCH_GET_XCOMP_PERM 0x1022
|
||||
#define ARCH_REQ_XCOMP_PERM 0x1023
|
||||
#define ARCH_GET_XCOMP_GUEST_PERM 0x1024
|
||||
#define ARCH_REQ_XCOMP_GUEST_PERM 0x1025
|
||||
#define linux_ARCH_GET_CPUID 0x1011
|
||||
#define linux_ARCH_SET_CPUID 0x1012
|
||||
|
||||
#define ARCH_XCOMP_TILECFG 17
|
||||
#define ARCH_XCOMP_TILEDATA 18
|
||||
#define linux_ARCH_GET_XCOMP_SUPP 0x1021
|
||||
#define linux_ARCH_GET_XCOMP_PERM 0x1022
|
||||
#define linux_ARCH_REQ_XCOMP_PERM 0x1023
|
||||
#define linux_ARCH_GET_XCOMP_GUEST_PERM 0x1024
|
||||
#define linux_ARCH_REQ_XCOMP_GUEST_PERM 0x1025
|
||||
|
||||
#define ARCH_MAP_VDSO_X32 0x2001
|
||||
#define ARCH_MAP_VDSO_32 0x2002
|
||||
#define ARCH_MAP_VDSO_64 0x2003
|
||||
#define linux_ARCH_XCOMP_TILECFG 17
|
||||
#define linux_ARCH_XCOMP_TILEDATA 18
|
||||
|
||||
#define ARCH_GET_UNTAG_MASK 0x4001
|
||||
#define ARCH_ENABLE_TAGGED_ADDR 0x4002
|
||||
#define ARCH_GET_MAX_TAG_BITS 0x4003
|
||||
#define ARCH_FORCE_TAGGED_SVA 0x4004
|
||||
#define linux_ARCH_MAP_VDSO_X32 0x2001
|
||||
#define linux_ARCH_MAP_VDSO_32 0x2002
|
||||
#define linux_ARCH_MAP_VDSO_64 0x2003
|
||||
|
||||
#define PROT_NONE 0
|
||||
#define PROT_READ 1
|
||||
#define PROT_WRITE 2
|
||||
#define PROT_EXEC 4
|
||||
#define PROT_GROWSDOWN 0x01000000
|
||||
#define PROT_GROWSUP 0x02000000
|
||||
#define linux_ARCH_GET_UNTAG_MASK 0x4001
|
||||
#define linux_ARCH_ENABLE_TAGGED_ADDR 0x4002
|
||||
#define linux_ARCH_GET_MAX_TAG_BITS 0x4003
|
||||
#define linux_ARCH_FORCE_TAGGED_SVA 0x4004
|
||||
|
||||
#define MAP_TYPE 0x0f
|
||||
#define linux_PROT_NONE 0
|
||||
#define linux_PROT_READ 1
|
||||
#define linux_PROT_WRITE 2
|
||||
#define linux_PROT_EXEC 4
|
||||
#define linux_PROT_GROWSDOWN 0x01000000
|
||||
#define linux_PROT_GROWSUP 0x02000000
|
||||
|
||||
#define MAP_FILE 0
|
||||
#define MAP_SHARED 0x01
|
||||
#define MAP_PRIVATE 0x02
|
||||
#define MAP_SHARED_VALIDATE 0x03
|
||||
#define MAP_FIXED 0x10
|
||||
#define MAP_ANONYMOUS 0x20
|
||||
#define MAP_NORESERVE 0x4000
|
||||
#define MAP_GROWSDOWN 0x0100
|
||||
#define MAP_DENYWRITE 0x0800
|
||||
#define MAP_EXECUTABLE 0x1000
|
||||
#define MAP_LOCKED 0x2000
|
||||
#define MAP_POPULATE 0x8000
|
||||
#define MAP_NONBLOCK 0x10000
|
||||
#define MAP_STACK 0x20000
|
||||
#define MAP_HUGETLB 0x40000
|
||||
#define MAP_SYNC 0x80000
|
||||
#define MAP_FIXED_NOREPLACE 0x100000
|
||||
#define linux_MAP_TYPE 0x0f
|
||||
|
||||
#define CLOCK_REALTIME 0
|
||||
#define CLOCK_MONOTONIC 1
|
||||
#define CLOCK_PROCESS_CPUTIME_ID 2
|
||||
#define CLOCK_THREAD_CPUTIME_ID 3
|
||||
#define CLOCK_MONOTONIC_RAW 4
|
||||
#define CLOCK_REALTIME_COARSE 5
|
||||
#define CLOCK_MONOTONIC_COARSE 6
|
||||
#define CLOCK_BOOTTIME 7
|
||||
#define CLOCK_REALTIME_ALARM 8
|
||||
#define CLOCK_BOOTTIME_ALARM 9
|
||||
#define CLOCK_SGI_CYCLE 10
|
||||
#define CLOCK_TAI 11
|
||||
#define linux_MAP_FILE 0
|
||||
#define linux_MAP_SHARED 0x01
|
||||
#define linux_MAP_PRIVATE 0x02
|
||||
#define linux_MAP_SHARED_VALIDATE 0x03
|
||||
#define linux_MAP_FIXED 0x10
|
||||
#define linux_MAP_ANONYMOUS 0x20
|
||||
#define linux_MAP_NORESERVE 0x4000
|
||||
#define linux_MAP_GROWSDOWN 0x0100
|
||||
#define linux_MAP_DENYWRITE 0x0800
|
||||
#define linux_MAP_EXECUTABLE 0x1000
|
||||
#define linux_MAP_LOCKED 0x2000
|
||||
#define linux_MAP_POPULATE 0x8000
|
||||
#define linux_MAP_NONBLOCK 0x10000
|
||||
#define linux_MAP_STACK 0x20000
|
||||
#define linux_MAP_HUGETLB 0x40000
|
||||
#define linux_MAP_SYNC 0x80000
|
||||
#define linux_MAP_FIXED_NOREPLACE 0x100000
|
||||
|
||||
#define GRND_NONBLOCK 0x1
|
||||
#define GRND_RANDOM 0x2
|
||||
#define GRND_INSECURE 0x4
|
||||
#define linux_CLOCK_REALTIME 0
|
||||
#define linux_CLOCK_MONOTONIC 1
|
||||
#define linux_CLOCK_PROCESS_CPUTIME_ID 2
|
||||
#define linux_CLOCK_THREAD_CPUTIME_ID 3
|
||||
#define linux_CLOCK_MONOTONIC_RAW 4
|
||||
#define linux_CLOCK_REALTIME_COARSE 5
|
||||
#define linux_CLOCK_MONOTONIC_COARSE 6
|
||||
#define linux_CLOCK_BOOTTIME 7
|
||||
#define linux_CLOCK_REALTIME_ALARM 8
|
||||
#define linux_CLOCK_BOOTTIME_ALARM 9
|
||||
#define linux_CLOCK_SGI_CYCLE 10
|
||||
#define linux_CLOCK_TAI 11
|
||||
|
||||
#define RLIMIT_CPU 0
|
||||
#define RLIMIT_FSIZE 1
|
||||
#define RLIMIT_DATA 2
|
||||
#define RLIMIT_STACK 3
|
||||
#define RLIMIT_CORE 4
|
||||
#define RLIMIT_RSS 5
|
||||
#define RLIMIT_NPROC 6
|
||||
#define RLIMIT_NOFILE 7
|
||||
#define RLIMIT_MEMLOCK 8
|
||||
#define RLIMIT_AS 9
|
||||
#define RLIMIT_LOCKS 10
|
||||
#define RLIMIT_SIGPENDING 11
|
||||
#define RLIMIT_MSGQUEUE 12
|
||||
#define RLIMIT_NICE 13
|
||||
#define RLIMIT_RTPRIO 14
|
||||
#define RLIMIT_RTTIME 15
|
||||
#define RLIMIT_NLIMITS 16
|
||||
#define linux_GRND_NONBLOCK 0x1
|
||||
#define linux_GRND_RANDOM 0x2
|
||||
#define linux_GRND_INSECURE 0x4
|
||||
|
||||
#define F_DUPFD 0
|
||||
#define F_GETFD 1
|
||||
#define F_SETFD 2
|
||||
#define F_GETFL 3
|
||||
#define F_SETFL 4
|
||||
#define linux_RLIMIT_CPU 0
|
||||
#define linux_RLIMIT_FSIZE 1
|
||||
#define linux_RLIMIT_DATA 2
|
||||
#define linux_RLIMIT_STACK 3
|
||||
#define linux_RLIMIT_CORE 4
|
||||
#define linux_RLIMIT_RSS 5
|
||||
#define linux_RLIMIT_NPROC 6
|
||||
#define linux_RLIMIT_NOFILE 7
|
||||
#define linux_RLIMIT_MEMLOCK 8
|
||||
#define linux_RLIMIT_AS 9
|
||||
#define linux_RLIMIT_LOCKS 10
|
||||
#define linux_RLIMIT_SIGPENDING 11
|
||||
#define linux_RLIMIT_MSGQUEUE 12
|
||||
#define linux_RLIMIT_NICE 13
|
||||
#define linux_RLIMIT_RTPRIO 14
|
||||
#define linux_RLIMIT_RTTIME 15
|
||||
#define linux_RLIMIT_NLIMITS 16
|
||||
|
||||
#define F_SETOWN 8
|
||||
#define F_GETOWN 9
|
||||
#define F_SETSIG 10
|
||||
#define F_GETSIG 11
|
||||
#define linux_F_DUPFD 0
|
||||
#define linux_F_GETFD 1
|
||||
#define linux_F_SETFD 2
|
||||
#define linux_F_GETFL 3
|
||||
#define linux_F_SETFL 4
|
||||
|
||||
#define linux_F_SETOWN 8
|
||||
#define linux_F_GETOWN 9
|
||||
#define linux_F_SETSIG 10
|
||||
#define linux_F_GETSIG 11
|
||||
|
||||
#if __LONG_MAX == 0x7fffffffL
|
||||
#define F_GETLK 12
|
||||
#define F_SETLK 13
|
||||
#define F_SETLKW 14
|
||||
#define linux_F_GETLK 12
|
||||
#define linux_F_SETLK 13
|
||||
#define linux_F_SETLKW 14
|
||||
#else
|
||||
#define F_GETLK 5
|
||||
#define F_SETLK 6
|
||||
#define F_SETLKW 7
|
||||
#define linux_F_GETLK 5
|
||||
#define linux_F_SETLK 6
|
||||
#define linux_F_SETLKW 7
|
||||
#endif
|
||||
|
||||
#define F_SETOWN_EX 15
|
||||
#define F_GETOWN_EX 16
|
||||
#define F_GETOWNER_UIDS 17
|
||||
#define linux_F_SETOWN_EX 15
|
||||
#define linux_F_GETOWN_EX 16
|
||||
#define linux_F_GETOWNER_UIDS 17
|
||||
|
||||
#define F_OFD_GETLK 36
|
||||
#define F_OFD_SETLK 37
|
||||
#define F_OFD_SETLKW 38
|
||||
#define linux_F_OFD_GETLK 36
|
||||
#define linux_F_OFD_SETLK 37
|
||||
#define linux_F_OFD_SETLKW 38
|
||||
|
||||
#define F_DUPFD_CLOEXEC 1030
|
||||
#define linux_F_DUPFD_CLOEXEC 1030
|
||||
|
||||
#define FD_CLOEXEC 1
|
||||
#define linux_FD_CLOEXEC 1
|
||||
|
||||
#define DT_UNKNOWN 0
|
||||
#define DT_FIFO 1
|
||||
#define DT_CHR 2
|
||||
#define DT_DIR 4
|
||||
#define DT_BLK 6
|
||||
#define DT_REG 8
|
||||
#define DT_LNK 10
|
||||
#define DT_SOCK 12
|
||||
#define DT_WHT 14
|
||||
#define linux_DT_UNKNOWN 0
|
||||
#define linux_DT_FIFO 1
|
||||
#define linux_DT_CHR 2
|
||||
#define linux_DT_DIR 4
|
||||
#define linux_DT_BLK 6
|
||||
#define linux_DT_REG 8
|
||||
#define linux_DT_LNK 10
|
||||
#define linux_DT_SOCK 12
|
||||
#define linux_DT_WHT 14
|
||||
|
||||
#define AT_FDCWD (-100)
|
||||
#define AT_SYMLINK_NOFOLLOW 0x100
|
||||
#define AT_REMOVEDIR 0x200
|
||||
#define AT_SYMLINK_FOLLOW 0x400
|
||||
#define AT_EACCESS 0x200
|
||||
#define AT_NO_AUTOMOUNT 0x800
|
||||
#define AT_EMPTY_PATH 0x1000
|
||||
#define AT_STATX_SYNC_TYPE 0x6000
|
||||
#define AT_STATX_SYNC_AS_STAT 0x0000
|
||||
#define AT_STATX_FORCE_SYNC 0x2000
|
||||
#define AT_STATX_DONT_SYNC 0x4000
|
||||
#define AT_RECURSIVE 0x8000
|
||||
#define linux_AT_FDCWD (-100)
|
||||
#define linux_AT_SYMLINK_NOFOLLOW 0x100
|
||||
#define linux_AT_REMOVEDIR 0x200
|
||||
#define linux_AT_SYMLINK_FOLLOW 0x400
|
||||
#define linux_AT_EACCESS 0x200
|
||||
#define linux_AT_NO_AUTOMOUNT 0x800
|
||||
#define linux_AT_EMPTY_PATH 0x1000
|
||||
#define linux_AT_STATX_SYNC_TYPE 0x6000
|
||||
#define linux_AT_STATX_SYNC_AS_STAT 0x0000
|
||||
#define linux_AT_STATX_FORCE_SYNC 0x2000
|
||||
#define linux_AT_STATX_DONT_SYNC 0x4000
|
||||
#define linux_AT_RECURSIVE 0x8000
|
||||
|
||||
#define LINUX_REBOOT_MAGIC1 0xfee1dead
|
||||
#define LINUX_REBOOT_MAGIC2 0x28121969
|
||||
#define LINUX_REBOOT_MAGIC2A 0x05121996
|
||||
#define LINUX_REBOOT_MAGIC2B 0x16041998
|
||||
#define LINUX_REBOOT_MAGIC2C 0x20112000
|
||||
#define linux_LINUX_REBOOT_MAGIC1 0xfee1dead
|
||||
#define linux_LINUX_REBOOT_MAGIC2 0x28121969
|
||||
#define linux_LINUX_REBOOT_MAGIC2A 0x05121996
|
||||
#define linux_LINUX_REBOOT_MAGIC2B 0x16041998
|
||||
#define linux_LINUX_REBOOT_MAGIC2C 0x20112000
|
||||
|
||||
#define LINUX_REBOOT_CMD_RESTART 0x01234567
|
||||
#define LINUX_REBOOT_CMD_HALT 0xCDEF0123
|
||||
#define LINUX_REBOOT_CMD_CAD_ON 0x89ABCDEF
|
||||
#define LINUX_REBOOT_CMD_CAD_OFF 0x00000000
|
||||
#define LINUX_REBOOT_CMD_POWER_OFF 0x4321FEDC
|
||||
#define LINUX_REBOOT_CMD_RESTART2 0xA1B2C3D4
|
||||
#define LINUX_REBOOT_CMD_SW_SUSPEND 0xD000FCE2
|
||||
#define LINUX_REBOOT_CMD_KEXEC 0x45584543
|
||||
#define linux_LINUX_REBOOT_CMD_RESTART 0x01234567
|
||||
#define linux_LINUX_REBOOT_CMD_HALT 0xCDEF0123
|
||||
#define linux_LINUX_REBOOT_CMD_CAD_ON 0x89ABCDEF
|
||||
#define linux_LINUX_REBOOT_CMD_CAD_OFF 0x00000000
|
||||
#define linux_LINUX_REBOOT_CMD_POWER_OFF 0x4321FEDC
|
||||
#define linux_LINUX_REBOOT_CMD_RESTART2 0xA1B2C3D4
|
||||
#define linux_LINUX_REBOOT_CMD_SW_SUSPEND 0xD000FCE2
|
||||
#define linux_LINUX_REBOOT_CMD_KEXEC 0x45584543
|
||||
|
||||
#define SA_IMMUTABLE 0x00800000
|
||||
#define linux_SA_IMMUTABLE 0x00800000
|
||||
|
||||
#define ITIMER_REAL 0
|
||||
#define ITIMER_VIRTUAL 1
|
||||
#define ITIMER_PROF 2
|
||||
#define linux_ITIMER_REAL 0
|
||||
#define linux_ITIMER_VIRTUAL 1
|
||||
#define linux_ITIMER_PROF 2
|
||||
|
||||
#define RUSAGE_SELF 0
|
||||
#define RUSAGE_CHILDREN (-1)
|
||||
#define RUSAGE_THREAD 1
|
||||
#define linux_RUSAGE_SELF 0
|
||||
#define linux_RUSAGE_CHILDREN (-1)
|
||||
#define linux_RUSAGE_THREAD 1
|
||||
|
||||
typedef long __kernel_long_t;
|
||||
typedef unsigned long __kernel_ulong_t;
|
||||
@ -249,19 +253,24 @@ struct rusage
|
||||
|
||||
struct linux_dirent
|
||||
{
|
||||
unsigned long d_ino; /* Inode number */
|
||||
unsigned long d_off; /* Offset to next linux_dirent */
|
||||
unsigned short d_reclen; /* Length of this linux_dirent */
|
||||
char d_name[]; /* Filename (null-terminated) */
|
||||
unsigned long d_ino;
|
||||
unsigned long d_off;
|
||||
unsigned short d_reclen;
|
||||
char d_name[];
|
||||
/**
|
||||
* Getting d_type is not the same as linux_dirent64:
|
||||
* https://github.com/torvalds/linux/blob/bfa8f18691ed2e978e4dd51190569c434f93e268/fs/readdir.c#L296
|
||||
* "man 2 getdents" also is helpful
|
||||
*/
|
||||
};
|
||||
|
||||
struct linux_dirent64
|
||||
{
|
||||
ino64_t d_ino; /* 64-bit inode number */
|
||||
off64_t d_off; /* 64-bit offset to next structure */
|
||||
unsigned short d_reclen; /* Size of this dirent */
|
||||
unsigned char d_type; /* File type */
|
||||
char d_name[]; /* Filename (null-terminated) */
|
||||
uint64_t d_ino;
|
||||
int64_t d_off;
|
||||
unsigned short d_reclen;
|
||||
unsigned char d_type;
|
||||
char d_name[];
|
||||
};
|
||||
|
||||
struct linux_kstat
|
||||
|
408
include/syscall/linux/errno.h
Normal file
408
include/syscall/linux/errno.h
Normal file
@ -0,0 +1,408 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __FENNIX_KERNEL_LINUX_ERRNO_H__
|
||||
#define __FENNIX_KERNEL_LINUX_ERRNO_H__
|
||||
|
||||
/** Operation not permitted */
|
||||
#define linux_EPERM 1
|
||||
|
||||
/** No such file or directory */
|
||||
#define linux_ENOENT 2
|
||||
|
||||
/** No such process */
|
||||
#define linux_ESRCH 3
|
||||
|
||||
/** Interrupted system call */
|
||||
#define linux_EINTR 4
|
||||
|
||||
/** I/O error */
|
||||
#define linux_EIO 5
|
||||
|
||||
/** No such device or address */
|
||||
#define linux_ENXIO 6
|
||||
|
||||
/** Argument list too long */
|
||||
#define linux_E2BIG 7
|
||||
|
||||
/** Exec format error */
|
||||
#define linux_ENOEXEC 8
|
||||
|
||||
/** Bad file number */
|
||||
#define linux_EBADF 9
|
||||
|
||||
/** No child processes */
|
||||
#define linux_ECHILD 10
|
||||
|
||||
/** Try again */
|
||||
#define linux_EAGAIN 11
|
||||
|
||||
/** Out of memory */
|
||||
#define linux_ENOMEM 12
|
||||
|
||||
/** Permission denied */
|
||||
#define linux_EACCES 13
|
||||
|
||||
/** Bad address */
|
||||
#define linux_EFAULT 14
|
||||
|
||||
/** Block device required */
|
||||
#define linux_ENOTBLK 15
|
||||
|
||||
/** Device or resource busy */
|
||||
#define linux_EBUSY 16
|
||||
|
||||
/** File exists */
|
||||
#define linux_EEXIST 17
|
||||
|
||||
/** Cross-device link */
|
||||
#define linux_EXDEV 18
|
||||
|
||||
/** No such device */
|
||||
#define linux_ENODEV 19
|
||||
|
||||
/** Not a directory */
|
||||
#define linux_ENOTDIR 20
|
||||
|
||||
/** Is a directory */
|
||||
#define linux_EISDIR 21
|
||||
|
||||
/** Invalid argument */
|
||||
#define linux_EINVAL 22
|
||||
|
||||
/** File table overflow */
|
||||
#define linux_ENFILE 23
|
||||
|
||||
/** Too many open files */
|
||||
#define linux_EMFILE 24
|
||||
|
||||
/** Not a typewriter */
|
||||
#define linux_ENOTTY 25
|
||||
|
||||
/** Text file busy */
|
||||
#define linux_ETXTBSY 26
|
||||
|
||||
/** File too large */
|
||||
#define linux_EFBIG 27
|
||||
|
||||
/** No space left on device */
|
||||
#define linux_ENOSPC 28
|
||||
|
||||
/** Illegal seek */
|
||||
#define linux_ESPIPE 29
|
||||
|
||||
/** Read-only file system */
|
||||
#define linux_EROFS 30
|
||||
|
||||
/** Too many links */
|
||||
#define linux_EMLINK 31
|
||||
|
||||
/** Broken pipe */
|
||||
#define linux_EPIPE 32
|
||||
|
||||
/** Math argument out of domain of func */
|
||||
#define linux_EDOM 33
|
||||
|
||||
/** Math result not representable */
|
||||
#define linux_ERANGE 34
|
||||
|
||||
/** Resource deadlock would occur */
|
||||
#define linux_EDEADLK 35
|
||||
|
||||
/** File name too long */
|
||||
#define linux_ENAMETOOLONG 36
|
||||
|
||||
/** No record locks available */
|
||||
#define linux_ENOLCK 37
|
||||
|
||||
/** Function not implemented */
|
||||
#define linux_ENOSYS 38
|
||||
|
||||
/** Directory not empty */
|
||||
#define linux_ENOTEMPTY 39
|
||||
|
||||
/** Too many symbolic links encountered */
|
||||
#define linux_ELOOP 40
|
||||
|
||||
/** No message of desired type */
|
||||
#define linux_ENOMSG 42
|
||||
|
||||
/** Identifier removed */
|
||||
#define linux_EIDRM 43
|
||||
|
||||
/** Channel number out of range */
|
||||
#define linux_ECHRNG 44
|
||||
|
||||
/** Level 2 not synchronized */
|
||||
#define linux_EL2NSYNC 45
|
||||
|
||||
/** Level 3 halted */
|
||||
#define linux_EL3HLT 46
|
||||
|
||||
/** Level 3 reset */
|
||||
#define linux_EL3RST 47
|
||||
|
||||
/** Link number out of range */
|
||||
#define linux_ELNRNG 48
|
||||
|
||||
/** Protocol driver not attached */
|
||||
#define linux_EUNATCH 49
|
||||
|
||||
/** No CSI structure available */
|
||||
#define linux_ENOCSI 50
|
||||
|
||||
/** Level 2 halted */
|
||||
#define linux_EL2HLT 51
|
||||
|
||||
/** Invalid exchange */
|
||||
#define linux_EBADE 52
|
||||
|
||||
/** Invalid request descriptor */
|
||||
#define linux_EBADR 53
|
||||
|
||||
/** Exchange full */
|
||||
#define linux_EXFULL 54
|
||||
|
||||
/** No anode */
|
||||
#define linux_ENOANO 55
|
||||
|
||||
/** Invalid request code */
|
||||
#define linux_EBADRQC 56
|
||||
|
||||
/** Invalid slot */
|
||||
#define linux_EBADSLT 57
|
||||
|
||||
/** Bad font file format */
|
||||
#define linux_EBFONT 59
|
||||
|
||||
/** Device not a stream */
|
||||
#define linux_ENOSTR 60
|
||||
|
||||
/** No data available */
|
||||
#define linux_ENODATA 61
|
||||
|
||||
/** Timer expired */
|
||||
#define linux_ETIME 62
|
||||
|
||||
/** Out of streams resources */
|
||||
#define linux_ENOSR 63
|
||||
|
||||
/** Machine is not on the network */
|
||||
#define linux_ENONET 64
|
||||
|
||||
/** Package not installed */
|
||||
#define linux_ENOPKG 65
|
||||
|
||||
/** Object is remote */
|
||||
#define linux_EREMOTE 66
|
||||
|
||||
/** Link has been severed */
|
||||
#define linux_ENOLINK 67
|
||||
|
||||
/** Advertise error */
|
||||
#define linux_EADV 68
|
||||
|
||||
/** Srmount error */
|
||||
#define linux_ESRMNT 69
|
||||
|
||||
/** Communication error on send */
|
||||
#define linux_ECOMM 70
|
||||
|
||||
/** Protocol error */
|
||||
#define linux_EPROTO 71
|
||||
|
||||
/** Multihop attempted */
|
||||
#define linux_EMULTIHOP 72
|
||||
|
||||
/** RFS specific error */
|
||||
#define linux_EDOTDOT 73
|
||||
|
||||
/** Not a data message */
|
||||
#define linux_EBADMSG 74
|
||||
|
||||
/** Value too large for defined data type */
|
||||
#define linux_EOVERFLOW 75
|
||||
|
||||
/** Name not unique on network */
|
||||
#define linux_ENOTUNIQ 76
|
||||
|
||||
/** File descriptor in bad state */
|
||||
#define linux_EBADFD 77
|
||||
|
||||
/** Remote address changed */
|
||||
#define linux_EREMCHG 78
|
||||
|
||||
/** Can not access a needed shared library */
|
||||
#define linux_ELIBACC 79
|
||||
|
||||
/** Accessing a corrupted shared library */
|
||||
#define linux_ELIBBAD 80
|
||||
|
||||
/** .lib section in a.out corrupted */
|
||||
#define linux_ELIBSCN 81
|
||||
|
||||
/** Attempting to link in too many shared libraries */
|
||||
#define linux_ELIBMAX 82
|
||||
|
||||
/** Cannot exec a shared library directly */
|
||||
#define linux_ELIBEXEC 83
|
||||
|
||||
/** Illegal byte sequence */
|
||||
#define linux_EILSEQ 84
|
||||
|
||||
/** Interrupted system call should be restarted */
|
||||
#define linux_ERESTART 85
|
||||
|
||||
/** Streams pipe error */
|
||||
#define linux_ESTRPIPE 86
|
||||
|
||||
/** Too many users */
|
||||
#define linux_EUSERS 87
|
||||
|
||||
/** Socket operation on non-socket */
|
||||
#define linux_ENOTSOCK 88
|
||||
|
||||
/** Destination address required */
|
||||
#define linux_EDESTADDRREQ 89
|
||||
|
||||
/** Message too long */
|
||||
#define linux_EMSGSIZE 90
|
||||
|
||||
/** Protocol wrong type for socket */
|
||||
#define linux_EPROTOTYPE 91
|
||||
|
||||
/** Protocol not available */
|
||||
#define linux_ENOPROTOOPT 92
|
||||
|
||||
/** Protocol not supported */
|
||||
#define linux_EPROTONOSUPPORT 93
|
||||
|
||||
/** Socket type not supported */
|
||||
#define linux_ESOCKTNOSUPPORT 94
|
||||
|
||||
/** Operation not supported on transport endpoint */
|
||||
#define linux_EOPNOTSUPP 95
|
||||
|
||||
/** Protocol family not supported */
|
||||
#define linux_EPFNOSUPPORT 96
|
||||
|
||||
/** Address family not supported by protocol */
|
||||
#define linux_EAFNOSUPPORT 97
|
||||
|
||||
/** Address already in use */
|
||||
#define linux_EADDRINUSE 98
|
||||
|
||||
/** Cannot assign requested address */
|
||||
#define linux_EADDRNOTAVAIL 99
|
||||
|
||||
/** Network is down */
|
||||
#define linux_ENETDOWN 100
|
||||
|
||||
/** Network is unreachable */
|
||||
#define linux_ENETUNREACH 101
|
||||
|
||||
/** Network dropped connection because of reset */
|
||||
#define linux_ENETRESET 102
|
||||
|
||||
/** Software caused connection abort */
|
||||
#define linux_ECONNABORTED 103
|
||||
|
||||
/** Connection reset by peer */
|
||||
#define linux_ECONNRESET 104
|
||||
|
||||
/** No buffer space available */
|
||||
#define linux_ENOBUFS 105
|
||||
|
||||
/** Transport endpoint is already connected */
|
||||
#define linux_EISCONN 106
|
||||
|
||||
/** Transport endpoint is not connected */
|
||||
#define linux_ENOTCONN 107
|
||||
|
||||
/** Cannot send after transport endpoint shutdown */
|
||||
#define linux_ESHUTDOWN 108
|
||||
|
||||
/** Too many references: cannot splice */
|
||||
#define linux_ETOOMANYREFS 109
|
||||
|
||||
/** Connection timed out */
|
||||
#define linux_ETIMEDOUT 110
|
||||
|
||||
/** Connection refused */
|
||||
#define linux_ECONNREFUSED 111
|
||||
|
||||
/** Host is down */
|
||||
#define linux_EHOSTDOWN 112
|
||||
|
||||
/** No route to host */
|
||||
#define linux_EHOSTUNREACH 113
|
||||
|
||||
/** Operation already in progress */
|
||||
#define linux_EALREADY 114
|
||||
|
||||
/** Operation now in progress */
|
||||
#define linux_EINPROGRESS 115
|
||||
|
||||
/** Stale NFS file handle */
|
||||
#define linux_ESTALE 116
|
||||
|
||||
/** Structure needs cleaning */
|
||||
#define linux_EUCLEAN 117
|
||||
|
||||
/** Not a XENIX named type file */
|
||||
#define linux_ENOTNAM 118
|
||||
|
||||
/** No XENIX semaphores available */
|
||||
#define linux_ENAVAIL 119
|
||||
|
||||
/** Is a named type file */
|
||||
#define linux_EISNAM 120
|
||||
|
||||
/** Remote I/O error */
|
||||
#define linux_EREMOTEIO 121
|
||||
|
||||
/** Quota exceeded */
|
||||
#define linux_EDQUOT 122
|
||||
|
||||
/** No medium found */
|
||||
#define linux_ENOMEDIUM 123
|
||||
|
||||
/** Wrong medium type */
|
||||
#define linux_EMEDIUMTYPE 124
|
||||
|
||||
/** Operation Canceled */
|
||||
#define linux_ECANCELED 125
|
||||
|
||||
/** Required key not available */
|
||||
#define linux_ENOKEY 126
|
||||
|
||||
/** Key has expired */
|
||||
#define linux_EKEYEXPIRED 127
|
||||
|
||||
/** Key has been revoked */
|
||||
#define linux_EKEYREVOKED 128
|
||||
|
||||
/** Key was rejected by service */
|
||||
#define linux_EKEYREJECTED 129
|
||||
|
||||
/** Owner died */
|
||||
#define linux_EOWNERDEAD 130
|
||||
|
||||
/** State not recoverable */
|
||||
#define linux_ENOTRECOVERABLE 131
|
||||
|
||||
#endif // !__FENNIX_KERNEL_LINUX_ERRNO_H__
|
@ -26,12 +26,13 @@
|
||||
#include <memory.hpp>
|
||||
#include <signal.hpp>
|
||||
#include <ints.hpp>
|
||||
#include <kexcept/cxxabi.h>
|
||||
#include <debug.h>
|
||||
#include <cwalk.h>
|
||||
#include <vector>
|
||||
#include <atomic>
|
||||
#include <vector>
|
||||
#include <abi.h>
|
||||
#include <list>
|
||||
|
||||
#define RLIM_INFINITY (~0ULL)
|
||||
|
||||
@ -45,7 +46,6 @@ struct rlimit
|
||||
namespace Tasking
|
||||
{
|
||||
using vfs::FileDescriptorTable;
|
||||
using vfs::Node;
|
||||
|
||||
/** Instruction Pointer */
|
||||
typedef __UINTPTR_TYPE__ IP;
|
||||
@ -212,6 +212,7 @@ namespace Tasking
|
||||
TaskArchitecture Architecture = TaskArchitecture::UnknownArchitecture;
|
||||
TaskCompatibility Compatibility = TaskCompatibility::UnknownPlatform;
|
||||
cwk_path_style PathStyle = CWK_STYLE_UNIX;
|
||||
FileNode *RootNode = nullptr;
|
||||
};
|
||||
|
||||
struct ThreadLocalStorage
|
||||
@ -334,7 +335,7 @@ namespace Tasking
|
||||
class PCB *Parent = nullptr;
|
||||
IP EntryPoint = 0;
|
||||
|
||||
/* Statuses */
|
||||
/* Status */
|
||||
std::atomic_int ExitCode;
|
||||
std::atomic<TaskState> State = TaskState::Waiting;
|
||||
int ErrorNumber;
|
||||
@ -377,6 +378,9 @@ namespace Tasking
|
||||
pid_t tgid = 0;
|
||||
} Linux{};
|
||||
|
||||
/* Kernel Exceptions */
|
||||
ExceptionInfo KernelException{};
|
||||
|
||||
int SendSignal(int sig);
|
||||
void SetState(TaskState state);
|
||||
void SetExitCode(int code);
|
||||
@ -411,7 +415,7 @@ namespace Tasking
|
||||
~TCB();
|
||||
};
|
||||
|
||||
class PCB : public vfs::Node
|
||||
class PCB
|
||||
{
|
||||
private:
|
||||
class Task *ctx = nullptr;
|
||||
@ -434,6 +438,7 @@ namespace Tasking
|
||||
PID ID = -1;
|
||||
const char *Name = nullptr;
|
||||
PCB *Parent = nullptr;
|
||||
FileNode *ProcDirectory = nullptr;
|
||||
|
||||
/* Statuses */
|
||||
std::atomic_int ExitCode;
|
||||
@ -464,14 +469,14 @@ namespace Tasking
|
||||
ThreadLocalStorage TLS{};
|
||||
|
||||
/* Filesystem */
|
||||
Node *CurrentWorkingDirectory;
|
||||
Node *Executable;
|
||||
FileNode *CWD;
|
||||
FileNode *Executable;
|
||||
FileDescriptorTable *FileDescriptors;
|
||||
|
||||
/* stdio */
|
||||
Node *stdin;
|
||||
Node *stdout;
|
||||
Node *stderr;
|
||||
FileNode *stdin;
|
||||
FileNode *stdout;
|
||||
FileNode *stderr;
|
||||
|
||||
/* Memory */
|
||||
Memory::PageTable *PageTable;
|
||||
@ -480,12 +485,13 @@ namespace Tasking
|
||||
|
||||
/* Other */
|
||||
Signal Signals;
|
||||
mode_t FileCreationMask = S_IRUSR | S_IWUSR | S_IRGRP |
|
||||
S_IWGRP | S_IROTH | S_IWOTH;
|
||||
mode_t FileCreationMask = S_IRUSR | S_IWUSR |
|
||||
S_IRGRP | S_IWGRP |
|
||||
S_IROTH | S_IWOTH;
|
||||
|
||||
/* Threads & Children */
|
||||
std::list<TCB *> Threads;
|
||||
std::list<PCB *> Children;
|
||||
std::vector<TCB *> Threads;
|
||||
std::vector<PCB *> Children;
|
||||
|
||||
public:
|
||||
class Task *GetContext() { return ctx; }
|
||||
@ -494,7 +500,7 @@ namespace Tasking
|
||||
void SetState(TaskState state);
|
||||
void SetExitCode(int code);
|
||||
void Rename(const char *name);
|
||||
void SetWorkingDirectory(Node *node);
|
||||
void SetWorkingDirectory(FileNode *node);
|
||||
void SetExe(const char *path);
|
||||
size_t GetSize();
|
||||
TCB *GetThread(TID ID);
|
||||
@ -538,7 +544,7 @@ namespace Tasking
|
||||
public:
|
||||
void *GetScheduler() { return Scheduler; }
|
||||
PCB *GetKernelProcess() { return KernelProcess; }
|
||||
std::list<PCB *> GetProcessList();
|
||||
std::vector<PCB *> GetProcessList();
|
||||
void Panic();
|
||||
bool IsPanic();
|
||||
|
||||
|
@ -18,6 +18,8 @@
|
||||
#ifndef __FENNIX_KERNEL_TYPES_H__
|
||||
#define __FENNIX_KERNEL_TYPES_H__
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define EXTERNC extern "C"
|
||||
#define START_EXTERNC \
|
||||
@ -35,15 +37,11 @@
|
||||
#define NULL 0
|
||||
#else // __cplusplus
|
||||
#define NULL ((void *)0)
|
||||
#define bool _Bool
|
||||
#endif // __cplusplus
|
||||
|
||||
#define asm __asm__
|
||||
#define asmv __asm__ volatile
|
||||
|
||||
#define true 1
|
||||
#define false 0
|
||||
|
||||
#define inf_loop while (1)
|
||||
#define ilp inf_loop; /* Used for debugging */
|
||||
|
||||
@ -64,11 +62,6 @@
|
||||
#define UNUSED(x) (void)(x)
|
||||
#define CONCAT(x, y) x##y
|
||||
|
||||
#ifndef __cplusplus /* This conflicts with std */
|
||||
#define toupper(c) ((c)-0x20 * (((c) >= 'a') && ((c) <= 'z')))
|
||||
#define tolower(c) ((c) + 0x20 * (((c) >= 'A') && ((c) <= 'Z')))
|
||||
#endif
|
||||
|
||||
#ifndef __va_list__
|
||||
typedef __builtin_va_list va_list;
|
||||
#endif
|
||||
@ -77,8 +70,8 @@ typedef __builtin_va_list va_list;
|
||||
#define va_end(v) __builtin_va_end(v)
|
||||
#define va_arg(v, l) __builtin_va_arg(v, l)
|
||||
|
||||
#define ALIGN_UP(x, align) ((__typeof__(x))(((uintptr_t)(x) + ((align)-1)) & (~((align)-1))))
|
||||
#define ALIGN_DOWN(x, align) ((__typeof__(x))((x) & (~((align)-1))))
|
||||
#define ALIGN_UP(x, align) ((__typeof__(x))(((uintptr_t)(x) + ((align) - 1)) & (~((align) - 1))))
|
||||
#define ALIGN_DOWN(x, align) ((__typeof__(x))((x) & (~((align) - 1))))
|
||||
|
||||
#define offsetof(type, member) __builtin_offsetof(type, member)
|
||||
|
||||
@ -96,8 +89,8 @@ typedef __builtin_va_list va_list;
|
||||
_a < _b ? _a : _b; \
|
||||
})
|
||||
|
||||
#define ROUND_UP(x, y) (((x) + (y)-1) & ~((y)-1))
|
||||
#define ROUND_DOWN(x, y) ((x) & ~((y)-1))
|
||||
#define ROUND_UP(x, y) (((x) + (y) - 1) & ~((y) - 1))
|
||||
#define ROUND_DOWN(x, y) ((x) & ~((y) - 1))
|
||||
|
||||
#define VPOKE(type, address) (*((volatile type *)(address)))
|
||||
#define POKE(type, address) (*((type *)(address)))
|
||||
@ -399,21 +392,53 @@ typedef uint48_t uint_fast48_t;
|
||||
(((x) & 0xff0000000000) >> 40)))
|
||||
#define b64(x) __builtin_bswap64(x)
|
||||
|
||||
/* https://gcc.gnu.org/onlinedocs/gcc-9.5.0/gnat_ugn/Optimization-Levels.html */
|
||||
/* https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html */
|
||||
|
||||
/** @brief No optimization (the default); generates unoptimized code but has the fastest compilation time. */
|
||||
/** No optimization (the default); generates
|
||||
* unoptimized code but has the fastest compilation time.
|
||||
*/
|
||||
#define O0 __attribute__((optimize("O0")))
|
||||
/** @brief Moderate optimization; optimizes reasonably well but does not degrade compilation time significantly. */
|
||||
|
||||
/** Moderate optimization;
|
||||
* optimizes reasonably well but does not degrade
|
||||
* compilation time significantly. */
|
||||
#define O1 __attribute__((optimize("O1")))
|
||||
/** @brief Full optimization; generates highly optimized code and has the slowest compilation time. */
|
||||
|
||||
/** Full optimization; generates highly
|
||||
* optimized code and has the slowest compilation time.
|
||||
*/
|
||||
#define O2 __attribute__((optimize("O2")))
|
||||
/** @brief Full optimization as in -O2; also uses more aggressive automatic inlining of subprograms within a unit (Inlining of Subprograms) and attempts to vectorize loops. */
|
||||
|
||||
/** Full optimization as in -O2;
|
||||
* also uses more aggressive automatic inlining of
|
||||
* subprograms within a unit (Inlining of Subprograms)
|
||||
* and attempts to vectorize loops. */
|
||||
#define O3 __attribute__((optimize("O3")))
|
||||
/** @brief Optimize space usage (code and data) of resulting program. */
|
||||
|
||||
/** Optimize space usage (code and data)
|
||||
* of resulting program.
|
||||
*/
|
||||
#define Os __attribute__((optimize("Os")))
|
||||
/** @brief Disregard strict standards compliance. -Ofast enables all -O3 optimizations. It also enables optimizations that are not valid for all standard-compliant programs. */
|
||||
|
||||
/** Disregard strict standards compliance.
|
||||
* -Ofast enables all -O3 optimizations.
|
||||
* It also enables optimizations that are not valid for
|
||||
* all standard-compliant programs.
|
||||
*/
|
||||
#define Ofast __attribute__((optimize("Ofast")))
|
||||
|
||||
/** Optimize for size.
|
||||
* -Oz enables all -Os optimizations that do not typically
|
||||
* increase code size.
|
||||
*/
|
||||
#define Oz __attribute__((optimize("Oz")))
|
||||
|
||||
/** Optimize for debugging.
|
||||
* -Og enables optimizations that do not interfere with
|
||||
* debugging.
|
||||
*/
|
||||
#define Og __attribute__((optimize("Og")))
|
||||
|
||||
#define __unused __attribute__((unused))
|
||||
#define __packed __attribute__((packed))
|
||||
#define __naked __attribute__((naked))
|
||||
@ -457,8 +482,6 @@ typedef uint48_t uint_fast48_t;
|
||||
// sanitizer
|
||||
#define __no_sanitize(x) __attribute__((no_sanitize(x)))
|
||||
#define __no_sanitize_address __attribute__((no_sanitize_address))
|
||||
/** @brief The no_address_safety_analysis is a deprecated alias of the no_sanitize_address attribute, new code should use no_sanitize_address. */
|
||||
#define __no_address_safety_analysis __attribute__((no_address_safety_analysis))
|
||||
#define __no_sanitize_thread __attribute__((no_sanitize_thread))
|
||||
#define __no_sanitize_undefined __attribute__((no_sanitize_undefined))
|
||||
#define __no_sanitize_coverage __attribute__((no_sanitize_coverage))
|
||||
@ -471,10 +494,7 @@ typedef uint48_t uint_fast48_t;
|
||||
#define likely(x) __builtin_expect(!!(x), 1)
|
||||
#define unlikely(x) __builtin_expect(!!(x), 0)
|
||||
|
||||
#define PUBLIC __visibility("default")
|
||||
#define PRIVATE __visibility("hidden")
|
||||
|
||||
#define NoSecurityAnalysis __no_stack_protector __no_sanitize_address __no_sanitize_undefined __no_address_safety_analysis __no_sanitize_thread
|
||||
#define NoSecurityAnalysis __no_stack_protector __no_sanitize_address __no_sanitize_undefined __no_sanitize_thread
|
||||
#define nsa NoSecurityAnalysis
|
||||
|
||||
#define NIF __no_instrument_function
|
||||
@ -486,9 +506,16 @@ typedef uint48_t uint_fast48_t;
|
||||
: "memory")
|
||||
|
||||
#define StackPush(stack, type, value) \
|
||||
*((type *)--stack) = value;
|
||||
*((type *)--stack) = value
|
||||
|
||||
#define StackPop(stack, type) \
|
||||
*((type *)stack++)
|
||||
|
||||
#define ReturnLogError(ret, Format, ...) \
|
||||
{ \
|
||||
trace(Format, ##__VA_ARGS__); \
|
||||
return ret; \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
#endif // !__FENNIX_KERNEL_TYPES_H__
|
||||
|
@ -42,12 +42,31 @@ namespace std
|
||||
return d_last;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void swap(T &a, T &b)
|
||||
template <typename InputIt, typename OutputIt, typename UnaryOperation>
|
||||
OutputIt transform(InputIt first, InputIt last, OutputIt result, UnaryOperation op)
|
||||
{
|
||||
T temp = move(a);
|
||||
a = move(b);
|
||||
b = move(temp);
|
||||
while (first != last)
|
||||
{
|
||||
*result = op(*first);
|
||||
++first;
|
||||
++result;
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
void swap(T &a, T &b) noexcept(std::is_nothrow_move_constructible<T>::value && std::is_nothrow_move_assignable<T>::value)
|
||||
{
|
||||
T temp = std::move(a);
|
||||
a = std::move(b);
|
||||
b = std::move(temp);
|
||||
}
|
||||
|
||||
template <class T2, std::size_t N>
|
||||
void swap(T2 (&a)[N], T2 (&b)[N]) noexcept(std::is_nothrow_swappable_v<T2>)
|
||||
{
|
||||
for (std::size_t i = 0; i < N; ++i)
|
||||
std::swap(a[i], b[i]);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@ -193,4 +212,116 @@ namespace std
|
||||
}
|
||||
return first;
|
||||
}
|
||||
|
||||
template <class InputIt1, class InputIt2>
|
||||
constexpr bool equal(InputIt1 first1, InputIt1 last1, InputIt2 first2)
|
||||
{
|
||||
while (first1 != last1)
|
||||
{
|
||||
if (!(*first1 == *first2))
|
||||
return false;
|
||||
|
||||
++first1;
|
||||
++first2;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class ExecutionPolicy, class ForwardIt1, class ForwardIt2>
|
||||
bool equal(ExecutionPolicy &&policy, ForwardIt1 first1, ForwardIt1 last1, ForwardIt2 first2)
|
||||
{
|
||||
while (first1 != last1)
|
||||
{
|
||||
if (!(*first1 == *first2))
|
||||
return false;
|
||||
|
||||
++first1;
|
||||
++first2;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class InputIt1, class InputIt2, class BinaryPred>
|
||||
constexpr bool equal(InputIt1 first1, InputIt1 last1, InputIt2 first2, BinaryPred p)
|
||||
{
|
||||
while (first1 != last1)
|
||||
{
|
||||
if (!p(*first1, *first2))
|
||||
return false;
|
||||
|
||||
++first1;
|
||||
++first2;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class ExecutionPolicy, class ForwardIt1, class ForwardIt2, class BinaryPred>
|
||||
bool equal(ExecutionPolicy &&policy, ForwardIt1 first1, ForwardIt1 last1, ForwardIt2 first2, BinaryPred p)
|
||||
{
|
||||
while (first1 != last1)
|
||||
{
|
||||
if (!p(*first1, *first2))
|
||||
return false;
|
||||
|
||||
++first1;
|
||||
++first2;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class InputIt1, class InputIt2>
|
||||
constexpr bool equal(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2)
|
||||
{
|
||||
while (first1 != last1)
|
||||
{
|
||||
if (!(*first1 == *first2))
|
||||
return false;
|
||||
|
||||
++first1;
|
||||
++first2;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class ExecutionPolicy, class ForwardIt1, class ForwardIt2>
|
||||
bool equal(ExecutionPolicy &&policy, ForwardIt1 first1, ForwardIt1 last1, ForwardIt2 first2, ForwardIt2 last2)
|
||||
{
|
||||
while (first1 != last1)
|
||||
{
|
||||
if (!(*first1 == *first2))
|
||||
return false;
|
||||
|
||||
++first1;
|
||||
++first2;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class InputIt1, class InputIt2, class BinaryPred>
|
||||
constexpr bool equal(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2, BinaryPred p)
|
||||
{
|
||||
while (first1 != last1)
|
||||
{
|
||||
if (!p(*first1, *first2))
|
||||
return false;
|
||||
|
||||
++first1;
|
||||
++first2;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class ExecutionPolicy, class ForwardIt1, class ForwardIt2, class BinaryPred>
|
||||
bool equal(ExecutionPolicy &&policy, ForwardIt1 first1, ForwardIt1 last1, ForwardIt2 first2, ForwardIt2 last2, BinaryPred p)
|
||||
{
|
||||
while (first1 != last1)
|
||||
{
|
||||
if (!p(*first1, *first2))
|
||||
return false;
|
||||
|
||||
++first1;
|
||||
++first2;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -15,18 +15,23 @@
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <filesystem/mounts.hpp>
|
||||
#pragma once
|
||||
|
||||
#include "../../kernel.h"
|
||||
|
||||
namespace 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;
|
||||
}
|
||||
}
|
@ -17,9 +17,12 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cfloat>
|
||||
#include <type_traits>
|
||||
|
||||
namespace std
|
||||
{
|
||||
double sin(double x)
|
||||
constexpr double sin(double x)
|
||||
{
|
||||
const int NUM_TERMS = 10;
|
||||
|
||||
@ -35,7 +38,7 @@ namespace std
|
||||
return result;
|
||||
}
|
||||
|
||||
float powf(float base, float exp)
|
||||
constexpr float powf(float base, float exp)
|
||||
{
|
||||
float result = 1.0;
|
||||
for (int i = 0; i < (int)exp; ++i)
|
||||
@ -43,7 +46,7 @@ namespace std
|
||||
return result;
|
||||
}
|
||||
|
||||
double pow(double base, double exp)
|
||||
constexpr double pow(double base, double exp)
|
||||
{
|
||||
double result = 1.0;
|
||||
for (int i = 0; i < (int)exp; ++i)
|
||||
@ -51,7 +54,7 @@ namespace std
|
||||
return result;
|
||||
}
|
||||
|
||||
long double powl(long double base, long double exp)
|
||||
constexpr long double powl(long double base, long double exp)
|
||||
{
|
||||
long double result = 1.0;
|
||||
for (long i = 0; i < (long)exp; ++i)
|
||||
@ -59,24 +62,121 @@ namespace std
|
||||
return result;
|
||||
}
|
||||
|
||||
float fabsf(float num)
|
||||
constexpr float fabsf(float num)
|
||||
{
|
||||
if (num < 0)
|
||||
return -num;
|
||||
return num;
|
||||
}
|
||||
|
||||
double fabs(double num)
|
||||
constexpr double fabs(double num)
|
||||
{
|
||||
if (num < 0)
|
||||
return -num;
|
||||
return num;
|
||||
}
|
||||
|
||||
long double fabsl(long double num)
|
||||
constexpr long double fabsl(long double num)
|
||||
{
|
||||
if (num < 0)
|
||||
return -num;
|
||||
return num;
|
||||
}
|
||||
|
||||
template <class Integer>
|
||||
constexpr bool isinf(Integer num)
|
||||
{
|
||||
union
|
||||
{
|
||||
unsigned long u;
|
||||
double f;
|
||||
} ieee754;
|
||||
ieee754.f = num;
|
||||
|
||||
bool a = ((unsigned)(ieee754.u >> 32) & 0x7fffffff) == 0x7ff00000;
|
||||
bool b = ((unsigned)ieee754.u == 0);
|
||||
return a && b;
|
||||
}
|
||||
|
||||
template <class Integer>
|
||||
constexpr bool isnan(Integer num)
|
||||
{
|
||||
return num != num;
|
||||
}
|
||||
|
||||
template <class Integer>
|
||||
constexpr double fabs(Integer num)
|
||||
{
|
||||
return num < 0 ? -num : num;
|
||||
}
|
||||
|
||||
template <class Integer>
|
||||
constexpr double remainder(Integer x, Integer y)
|
||||
{
|
||||
return x - (int)(x / y) * y;
|
||||
}
|
||||
|
||||
template <class Integer>
|
||||
constexpr double copysign(Integer mag, Integer sgn)
|
||||
{
|
||||
return (sgn < 0) ? -mag : mag;
|
||||
}
|
||||
|
||||
template <class Integer>
|
||||
constexpr bool signbit(Integer num)
|
||||
{
|
||||
return num < 0;
|
||||
}
|
||||
|
||||
template <class Integer>
|
||||
constexpr double fmod(Integer x, Integer y)
|
||||
{
|
||||
#pragma STDC FENV_ACCESS ON
|
||||
double result = std::remainder(std::fabs(x), y = std::fabs(y));
|
||||
if (std::signbit(result))
|
||||
result += (double)y;
|
||||
return std::copysign(result, x);
|
||||
}
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wfloat-equal"
|
||||
|
||||
template <class Integer>
|
||||
constexpr double ceil(Integer num)
|
||||
{
|
||||
// int i = (int)num;
|
||||
// return i + (i < num);
|
||||
|
||||
double remainder = std::fmod((double)num, 1.0);
|
||||
return num >= 0 ? (remainder == 0 ? num : num + 1 - remainder) : num - remainder;
|
||||
}
|
||||
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
template <class Integer>
|
||||
constexpr double trunc(Integer num)
|
||||
{
|
||||
if (std::isinf(num))
|
||||
return num;
|
||||
|
||||
if (std::isnan(num))
|
||||
return num;
|
||||
|
||||
return static_cast<int>(num);
|
||||
}
|
||||
|
||||
template <class Integer>
|
||||
constexpr double exp(Integer num)
|
||||
{
|
||||
double result = 1.0;
|
||||
double term = 1.0;
|
||||
|
||||
for (int i = 1; i <= 10; ++i)
|
||||
{
|
||||
term *= static_cast<double>(num) / i;
|
||||
result += term;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
@ -15,5 +15,7 @@
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <std/smart_ptr.hpp>
|
||||
namespace std
|
||||
{
|
||||
/* FIXME: Implement */
|
||||
}
|
@ -15,35 +15,37 @@
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __FENNIX_KERNEL_TERMIOS_H__
|
||||
#define __FENNIX_KERNEL_TERMIOS_H__
|
||||
#ifndef __FENNIX_KERNEL_C_TYPE_H__
|
||||
#define __FENNIX_KERNEL_C_TYPE_H__
|
||||
|
||||
#include <types.h>
|
||||
#include <filesystem/termios-bits.hpp>
|
||||
|
||||
typedef unsigned char cc_t;
|
||||
typedef unsigned int speed_t;
|
||||
typedef unsigned int tcflag_t;
|
||||
START_EXTERNC
|
||||
|
||||
#define NCCS 32
|
||||
struct termios
|
||||
{
|
||||
tcflag_t c_iflag;
|
||||
tcflag_t c_oflag;
|
||||
tcflag_t c_cflag;
|
||||
tcflag_t c_lflag;
|
||||
cc_t c_line;
|
||||
cc_t c_cc[NCCS];
|
||||
speed_t c_ispeed;
|
||||
speed_t c_ospeed;
|
||||
};
|
||||
int isalnum(int);
|
||||
int isalpha(int);
|
||||
int isascii(int);
|
||||
|
||||
struct winsize
|
||||
{
|
||||
unsigned short ws_row;
|
||||
unsigned short ws_col;
|
||||
unsigned short ws_xpixel;
|
||||
unsigned short ws_ypixel;
|
||||
};
|
||||
int isblank(int);
|
||||
int iscntrl(int);
|
||||
int isdigit(int);
|
||||
int isgraph(int);
|
||||
int islower(int);
|
||||
int isprint(int);
|
||||
int ispunct(int);
|
||||
int isspace(int);
|
||||
int isupper(int);
|
||||
int isxdigit(int);
|
||||
|
||||
#endif // !__FENNIX_KERNEL_TERMIOS_H__
|
||||
int toascii(int);
|
||||
int tolower(int);
|
||||
int toupper(int);
|
||||
|
||||
#ifndef __cplusplus /* This conflicts with std */
|
||||
#define _toupper(c) ((c) - 0x20 * (((c) >= 'a') && ((c) <= 'z')))
|
||||
#define _tolower(c) ((c) + 0x20 * (((c) >= 'A') && ((c) <= 'Z')))
|
||||
#endif
|
||||
|
||||
END_EXTERNC
|
||||
|
||||
#endif // !__FENNIX_KERNEL_C_TYPE_H__
|
@ -15,7 +15,17 @@
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _DLFCN_H
|
||||
#define _DLFCN_H
|
||||
#ifndef __FENNIX_KERNEL_DLFCN_H__
|
||||
#define __FENNIX_KERNEL_DLFCN_H__
|
||||
|
||||
#endif // !_DLFCN_H
|
||||
#include <types.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const char *dli_fname;
|
||||
void *dli_fbase;
|
||||
const char *dli_sname;
|
||||
void *dli_saddr;
|
||||
} Dl_info;
|
||||
|
||||
#endif // !__FENNIX_KERNEL_DLFCN_H__
|
||||
|
@ -15,407 +15,9 @@
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _ERRNO_H
|
||||
#define _ERRNO_H
|
||||
#ifndef __FENNIX_KERNEL_STD_ERRNO_H__
|
||||
#define __FENNIX_KERNEL_STD_ERRNO_H__
|
||||
|
||||
/** Operation not permitted */
|
||||
#define EPERM 1
|
||||
#include <interface/errno.h>
|
||||
|
||||
/** No such file or directory */
|
||||
#define ENOENT 2
|
||||
|
||||
/** No such process */
|
||||
#define ESRCH 3
|
||||
|
||||
/** Interrupted system call */
|
||||
#define EINTR 4
|
||||
|
||||
/** I/O error */
|
||||
#define EIO 5
|
||||
|
||||
/** No such device or address */
|
||||
#define ENXIO 6
|
||||
|
||||
/** Argument list too long */
|
||||
#define E2BIG 7
|
||||
|
||||
/** Exec format error */
|
||||
#define ENOEXEC 8
|
||||
|
||||
/** Bad file number */
|
||||
#define EBADF 9
|
||||
|
||||
/** No child processes */
|
||||
#define ECHILD 10
|
||||
|
||||
/** Try again */
|
||||
#define EAGAIN 11
|
||||
|
||||
/** Out of memory */
|
||||
#define ENOMEM 12
|
||||
|
||||
/** Permission denied */
|
||||
#define EACCES 13
|
||||
|
||||
/** Bad address */
|
||||
#define EFAULT 14
|
||||
|
||||
/** Block device required */
|
||||
#define ENOTBLK 15
|
||||
|
||||
/** Device or resource busy */
|
||||
#define EBUSY 16
|
||||
|
||||
/** File exists */
|
||||
#define EEXIST 17
|
||||
|
||||
/** Cross-device link */
|
||||
#define EXDEV 18
|
||||
|
||||
/** No such device */
|
||||
#define ENODEV 19
|
||||
|
||||
/** Not a directory */
|
||||
#define ENOTDIR 20
|
||||
|
||||
/** Is a directory */
|
||||
#define EISDIR 21
|
||||
|
||||
/** Invalid argument */
|
||||
#define EINVAL 22
|
||||
|
||||
/** File table overflow */
|
||||
#define ENFILE 23
|
||||
|
||||
/** Too many open files */
|
||||
#define EMFILE 24
|
||||
|
||||
/** Not a typewriter */
|
||||
#define ENOTTY 25
|
||||
|
||||
/** Text file busy */
|
||||
#define ETXTBSY 26
|
||||
|
||||
/** File too large */
|
||||
#define EFBIG 27
|
||||
|
||||
/** No space left on device */
|
||||
#define ENOSPC 28
|
||||
|
||||
/** Illegal seek */
|
||||
#define ESPIPE 29
|
||||
|
||||
/** Read-only file system */
|
||||
#define EROFS 30
|
||||
|
||||
/** Too many links */
|
||||
#define EMLINK 31
|
||||
|
||||
/** Broken pipe */
|
||||
#define EPIPE 32
|
||||
|
||||
/** Math argument out of domain of func */
|
||||
#define EDOM 33
|
||||
|
||||
/** Math result not representable */
|
||||
#define ERANGE 34
|
||||
|
||||
/** Resource deadlock would occur */
|
||||
#define EDEADLK 35
|
||||
|
||||
/** File name too long */
|
||||
#define ENAMETOOLONG 36
|
||||
|
||||
/** No record locks available */
|
||||
#define ENOLCK 37
|
||||
|
||||
/** Function not implemented */
|
||||
#define ENOSYS 38
|
||||
|
||||
/** Directory not empty */
|
||||
#define ENOTEMPTY 39
|
||||
|
||||
/** Too many symbolic links encountered */
|
||||
#define ELOOP 40
|
||||
|
||||
/** No message of desired type */
|
||||
#define ENOMSG 42
|
||||
|
||||
/** Identifier removed */
|
||||
#define EIDRM 43
|
||||
|
||||
/** Channel number out of range */
|
||||
#define ECHRNG 44
|
||||
|
||||
/** Level 2 not synchronized */
|
||||
#define EL2NSYNC 45
|
||||
|
||||
/** Level 3 halted */
|
||||
#define EL3HLT 46
|
||||
|
||||
/** Level 3 reset */
|
||||
#define EL3RST 47
|
||||
|
||||
/** Link number out of range */
|
||||
#define ELNRNG 48
|
||||
|
||||
/** Protocol driver not attached */
|
||||
#define EUNATCH 49
|
||||
|
||||
/** No CSI structure available */
|
||||
#define ENOCSI 50
|
||||
|
||||
/** Level 2 halted */
|
||||
#define EL2HLT 51
|
||||
|
||||
/** Invalid exchange */
|
||||
#define EBADE 52
|
||||
|
||||
/** Invalid request descriptor */
|
||||
#define EBADR 53
|
||||
|
||||
/** Exchange full */
|
||||
#define EXFULL 54
|
||||
|
||||
/** No anode */
|
||||
#define ENOANO 55
|
||||
|
||||
/** Invalid request code */
|
||||
#define EBADRQC 56
|
||||
|
||||
/** Invalid slot */
|
||||
#define EBADSLT 57
|
||||
|
||||
/** Bad font file format */
|
||||
#define EBFONT 59
|
||||
|
||||
/** Device not a stream */
|
||||
#define ENOSTR 60
|
||||
|
||||
/** No data available */
|
||||
#define ENODATA 61
|
||||
|
||||
/** Timer expired */
|
||||
#define ETIME 62
|
||||
|
||||
/** Out of streams resources */
|
||||
#define ENOSR 63
|
||||
|
||||
/** Machine is not on the network */
|
||||
#define ENONET 64
|
||||
|
||||
/** Package not installed */
|
||||
#define ENOPKG 65
|
||||
|
||||
/** Object is remote */
|
||||
#define EREMOTE 66
|
||||
|
||||
/** Link has been severed */
|
||||
#define ENOLINK 67
|
||||
|
||||
/** Advertise error */
|
||||
#define EADV 68
|
||||
|
||||
/** Srmount error */
|
||||
#define ESRMNT 69
|
||||
|
||||
/** Communication error on send */
|
||||
#define ECOMM 70
|
||||
|
||||
/** Protocol error */
|
||||
#define EPROTO 71
|
||||
|
||||
/** Multihop attempted */
|
||||
#define EMULTIHOP 72
|
||||
|
||||
/** RFS specific error */
|
||||
#define EDOTDOT 73
|
||||
|
||||
/** Not a data message */
|
||||
#define EBADMSG 74
|
||||
|
||||
/** Value too large for defined data type */
|
||||
#define EOVERFLOW 75
|
||||
|
||||
/** Name not unique on network */
|
||||
#define ENOTUNIQ 76
|
||||
|
||||
/** File descriptor in bad state */
|
||||
#define EBADFD 77
|
||||
|
||||
/** Remote address changed */
|
||||
#define EREMCHG 78
|
||||
|
||||
/** Can not access a needed shared library */
|
||||
#define ELIBACC 79
|
||||
|
||||
/** Accessing a corrupted shared library */
|
||||
#define ELIBBAD 80
|
||||
|
||||
/** .lib section in a.out corrupted */
|
||||
#define ELIBSCN 81
|
||||
|
||||
/** Attempting to link in too many shared libraries */
|
||||
#define ELIBMAX 82
|
||||
|
||||
/** Cannot exec a shared library directly */
|
||||
#define ELIBEXEC 83
|
||||
|
||||
/** Illegal byte sequence */
|
||||
#define EILSEQ 84
|
||||
|
||||
/** Interrupted system call should be restarted */
|
||||
#define ERESTART 85
|
||||
|
||||
/** Streams pipe error */
|
||||
#define ESTRPIPE 86
|
||||
|
||||
/** Too many users */
|
||||
#define EUSERS 87
|
||||
|
||||
/** Socket operation on non-socket */
|
||||
#define ENOTSOCK 88
|
||||
|
||||
/** Destination address required */
|
||||
#define EDESTADDRREQ 89
|
||||
|
||||
/** Message too long */
|
||||
#define EMSGSIZE 90
|
||||
|
||||
/** Protocol wrong type for socket */
|
||||
#define EPROTOTYPE 91
|
||||
|
||||
/** Protocol not available */
|
||||
#define ENOPROTOOPT 92
|
||||
|
||||
/** Protocol not supported */
|
||||
#define EPROTONOSUPPORT 93
|
||||
|
||||
/** Socket type not supported */
|
||||
#define ESOCKTNOSUPPORT 94
|
||||
|
||||
/** Operation not supported on transport endpoint */
|
||||
#define EOPNOTSUPP 95
|
||||
|
||||
/** Protocol family not supported */
|
||||
#define EPFNOSUPPORT 96
|
||||
|
||||
/** Address family not supported by protocol */
|
||||
#define EAFNOSUPPORT 97
|
||||
|
||||
/** Address already in use */
|
||||
#define EADDRINUSE 98
|
||||
|
||||
/** Cannot assign requested address */
|
||||
#define EADDRNOTAVAIL 99
|
||||
|
||||
/** Network is down */
|
||||
#define ENETDOWN 100
|
||||
|
||||
/** Network is unreachable */
|
||||
#define ENETUNREACH 101
|
||||
|
||||
/** Network dropped connection because of reset */
|
||||
#define ENETRESET 102
|
||||
|
||||
/** Software caused connection abort */
|
||||
#define ECONNABORTED 103
|
||||
|
||||
/** Connection reset by peer */
|
||||
#define ECONNRESET 104
|
||||
|
||||
/** No buffer space available */
|
||||
#define ENOBUFS 105
|
||||
|
||||
/** Transport endpoint is already connected */
|
||||
#define EISCONN 106
|
||||
|
||||
/** Transport endpoint is not connected */
|
||||
#define ENOTCONN 107
|
||||
|
||||
/** Cannot send after transport endpoint shutdown */
|
||||
#define ESHUTDOWN 108
|
||||
|
||||
/** Too many references: cannot splice */
|
||||
#define ETOOMANYREFS 109
|
||||
|
||||
/** Connection timed out */
|
||||
#define ETIMEDOUT 110
|
||||
|
||||
/** Connection refused */
|
||||
#define ECONNREFUSED 111
|
||||
|
||||
/** Host is down */
|
||||
#define EHOSTDOWN 112
|
||||
|
||||
/** No route to host */
|
||||
#define EHOSTUNREACH 113
|
||||
|
||||
/** Operation already in progress */
|
||||
#define EALREADY 114
|
||||
|
||||
/** Operation now in progress */
|
||||
#define EINPROGRESS 115
|
||||
|
||||
/** Stale NFS file handle */
|
||||
#define ESTALE 116
|
||||
|
||||
/** Structure needs cleaning */
|
||||
#define EUCLEAN 117
|
||||
|
||||
/** Not a XENIX named type file */
|
||||
#define ENOTNAM 118
|
||||
|
||||
/** No XENIX semaphores available */
|
||||
#define ENAVAIL 119
|
||||
|
||||
/** Is a named type file */
|
||||
#define EISNAM 120
|
||||
|
||||
/** Remote I/O error */
|
||||
#define EREMOTEIO 121
|
||||
|
||||
/** Quota exceeded */
|
||||
#define EDQUOT 122
|
||||
|
||||
/** No medium found */
|
||||
#define ENOMEDIUM 123
|
||||
|
||||
/** Wrong medium type */
|
||||
#define EMEDIUMTYPE 124
|
||||
|
||||
/** Operation Canceled */
|
||||
#define ECANCELED 125
|
||||
|
||||
/** Required key not available */
|
||||
#define ENOKEY 126
|
||||
|
||||
/** Key has expired */
|
||||
#define EKEYEXPIRED 127
|
||||
|
||||
/** Key has been revoked */
|
||||
#define EKEYREVOKED 128
|
||||
|
||||
/** Key was rejected by service */
|
||||
#define EKEYREJECTED 129
|
||||
|
||||
/** Owner died */
|
||||
#define EOWNERDEAD 130
|
||||
|
||||
/** State not recoverable */
|
||||
#define ENOTRECOVERABLE 131
|
||||
|
||||
#include <types.h>
|
||||
EXTERNC int *__errno_location(void) __attribute__((const));
|
||||
#define errno (*__errno_location())
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
const char *strerror(int errnum);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // !_ERRNO_H
|
||||
#endif // !__FENNIX_KERNEL_STD_ERRNO_H__
|
||||
|
@ -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__
|
||||
|
@ -17,9 +17,13 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <types.h>
|
||||
#include <algorithm>
|
||||
#include <typeinfo>
|
||||
|
||||
namespace std
|
||||
{
|
||||
template <typename T>
|
||||
template <typename T = void>
|
||||
struct equal_to
|
||||
{
|
||||
bool operator()(const T &lhs, const T &rhs) const
|
||||
@ -58,4 +62,193 @@ namespace std
|
||||
return static_cast<size_t>(hash);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class reference_wrapper;
|
||||
|
||||
template <class>
|
||||
class function; /* undefined */
|
||||
|
||||
template <class R, class... Args>
|
||||
class function<R(Args...)>
|
||||
{
|
||||
private:
|
||||
class impl_base
|
||||
{
|
||||
public:
|
||||
virtual ~impl_base() = default;
|
||||
virtual R invoke(Args...) const = 0;
|
||||
#ifdef __GXX_RTTI
|
||||
virtual const std::type_info &target_type() const noexcept = 0;
|
||||
#endif
|
||||
virtual impl_base *clone() const = 0;
|
||||
};
|
||||
|
||||
template <class F>
|
||||
class impl : public impl_base
|
||||
{
|
||||
public:
|
||||
F _f;
|
||||
|
||||
template <class G>
|
||||
impl(G &&f)
|
||||
: _f(std::forward<G>(f))
|
||||
{
|
||||
}
|
||||
|
||||
R invoke(Args... args) const override
|
||||
{
|
||||
return _f(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
#ifdef __GXX_RTTI
|
||||
const std::type_info &target_type() const noexcept override
|
||||
{
|
||||
return typeid(F);
|
||||
}
|
||||
#endif
|
||||
|
||||
impl_base *clone() const override
|
||||
{
|
||||
return new impl<F>(_f);
|
||||
}
|
||||
};
|
||||
|
||||
impl_base *_ptr;
|
||||
|
||||
public:
|
||||
using result_type = R;
|
||||
|
||||
function() noexcept
|
||||
: _ptr(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
function(std::nullptr_t) noexcept
|
||||
: _ptr(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
function(const function &other)
|
||||
: _ptr(other._ptr)
|
||||
{
|
||||
}
|
||||
|
||||
function(function &&other) noexcept
|
||||
: _ptr(other._ptr)
|
||||
{
|
||||
other._ptr = nullptr;
|
||||
}
|
||||
|
||||
template <class F>
|
||||
function(F &&f)
|
||||
: _ptr(new impl<F>(std::forward<F>(f)))
|
||||
{
|
||||
}
|
||||
|
||||
~function()
|
||||
{
|
||||
delete _ptr;
|
||||
}
|
||||
|
||||
function &operator=(const function &other)
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
delete _ptr;
|
||||
_ptr = other._ptr ? other._ptr->clone() : nullptr;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
function &operator=(function &&other)
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
delete _ptr;
|
||||
_ptr = other._ptr;
|
||||
other._ptr = nullptr;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
function &operator=(std::nullptr_t) noexcept
|
||||
{
|
||||
delete _ptr;
|
||||
_ptr = nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class F>
|
||||
function &operator=(F &&f)
|
||||
{
|
||||
delete _ptr;
|
||||
_ptr = new impl<F>(std::forward<F>(f));
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class F>
|
||||
function &operator=(std::reference_wrapper<F> f) noexcept
|
||||
{
|
||||
delete _ptr;
|
||||
_ptr = new impl<std::reference_wrapper<F>>(f);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void swap(function &other) noexcept
|
||||
{
|
||||
std::swap(_ptr, other._ptr);
|
||||
}
|
||||
|
||||
explicit operator bool() const noexcept
|
||||
{
|
||||
return _ptr != nullptr;
|
||||
}
|
||||
|
||||
R operator()(Args... args) const
|
||||
{
|
||||
return _ptr->invoke(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
#ifdef __GXX_RTTI
|
||||
const std::type_info &target_type() const noexcept
|
||||
{
|
||||
return _ptr ? _ptr->target_type() : typeid(void);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
T *target() noexcept
|
||||
{
|
||||
return _ptr && _ptr->target_type() == typeid(T) ? &static_cast<impl<T> *>(_ptr)->_f : nullptr;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
const T *target() const noexcept
|
||||
{
|
||||
return _ptr && _ptr->target_type() == typeid(T) ? &static_cast<impl<T> *>(_ptr)->_f : nullptr;
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
template <class R, class... Args>
|
||||
void swap(std::function<R(Args...)> &lhs, std::function<R(Args...)> &rhs) noexcept
|
||||
{
|
||||
lhs.swap(rhs);
|
||||
}
|
||||
|
||||
template <class R, class... ArgTypes>
|
||||
|
||||
bool operator==(const std::function<R(ArgTypes...)> &f, std::nullptr_t) noexcept
|
||||
{
|
||||
return !f;
|
||||
}
|
||||
|
||||
template <class T = void>
|
||||
struct less
|
||||
{
|
||||
constexpr bool operator()(const T &lhs, const T &rhs) const
|
||||
{
|
||||
return lhs < rhs;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -21,28 +21,41 @@
|
||||
|
||||
namespace std
|
||||
{
|
||||
template <typename T>
|
||||
template <typename _E>
|
||||
class initializer_list
|
||||
{
|
||||
public:
|
||||
typedef _E value_type;
|
||||
typedef const _E &reference;
|
||||
typedef const _E &const_reference;
|
||||
typedef size_t size_type;
|
||||
typedef const _E *iterator;
|
||||
typedef const _E *const_iterator;
|
||||
|
||||
private:
|
||||
const T *array;
|
||||
size_t len;
|
||||
iterator array;
|
||||
size_type len;
|
||||
|
||||
public:
|
||||
initializer_list() : array(nullptr), len(0) {}
|
||||
size_t size() const { return len; }
|
||||
const T *begin() const { return array; }
|
||||
const T *end() const { return begin() + size(); }
|
||||
constexpr initializer_list(const_iterator a, size_type l)
|
||||
: array(a), len(l) {}
|
||||
|
||||
constexpr initializer_list()
|
||||
: array(nullptr), len(0) {}
|
||||
|
||||
constexpr size_type size() const { return len; }
|
||||
constexpr const_iterator begin() const { return array; }
|
||||
constexpr const_iterator end() const { return begin() + size(); }
|
||||
};
|
||||
|
||||
template <class E>
|
||||
const E *begin(std::initializer_list<E> il)
|
||||
constexpr const E *begin(initializer_list<E> il)
|
||||
{
|
||||
return il.begin();
|
||||
}
|
||||
|
||||
template <class E>
|
||||
constexpr const E *end(std::initializer_list<E> il)
|
||||
constexpr const E *end(initializer_list<E> il)
|
||||
{
|
||||
return il.end();
|
||||
}
|
||||
|
23
include_std/inttypes.h
Normal file
23
include_std/inttypes.h
Normal file
@ -0,0 +1,23 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __FENNIX_KERNEL_INTTYPES_H__
|
||||
#define __FENNIX_KERNEL_INTTYPES_H__
|
||||
|
||||
#include <types.h>
|
||||
|
||||
#endif // !__FENNIX_KERNEL_INTTYPES_H__
|
286
include_std/ios
Normal file
286
include_std/ios
Normal file
@ -0,0 +1,286 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <system_error>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <locale>
|
||||
|
||||
#ifdef in
|
||||
#undef in
|
||||
#endif /* deprecated macro in */
|
||||
|
||||
namespace std
|
||||
{
|
||||
enum class io_errc
|
||||
{
|
||||
stream = 1,
|
||||
};
|
||||
|
||||
typedef long long streamsize;
|
||||
|
||||
class ios_base
|
||||
{
|
||||
public:
|
||||
#pragma region Member types and constants
|
||||
|
||||
typedef int openmode;
|
||||
static constexpr openmode app = 1;
|
||||
static constexpr openmode binary = 2;
|
||||
static constexpr openmode in = 4;
|
||||
static constexpr openmode out = 8;
|
||||
static constexpr openmode trunc = 16;
|
||||
static constexpr openmode ate = 32;
|
||||
static constexpr openmode noreplace = 64;
|
||||
|
||||
typedef int fmtflags;
|
||||
static constexpr fmtflags dec = 1;
|
||||
static constexpr fmtflags oct = 2;
|
||||
static constexpr fmtflags hex = 4;
|
||||
static constexpr fmtflags basefield = dec | oct | hex;
|
||||
|
||||
static constexpr fmtflags left = 1;
|
||||
static constexpr fmtflags right = 2;
|
||||
static constexpr fmtflags internal = 4;
|
||||
static constexpr fmtflags adjustfield = left | right | internal;
|
||||
|
||||
static constexpr fmtflags scientific = 1;
|
||||
static constexpr fmtflags fixed = 2;
|
||||
static constexpr fmtflags floatfield = scientific | fixed;
|
||||
|
||||
static constexpr fmtflags boolalpha = 1;
|
||||
static constexpr fmtflags showbase = 2;
|
||||
static constexpr fmtflags showpoint = 4;
|
||||
static constexpr fmtflags showpos = 8;
|
||||
static constexpr fmtflags skipws = 16;
|
||||
static constexpr fmtflags unitbuf = 32;
|
||||
static constexpr fmtflags uppercase = 64;
|
||||
|
||||
typedef int iostate;
|
||||
static constexpr iostate goodbit = 0;
|
||||
static constexpr iostate badbit = 1;
|
||||
static constexpr iostate failbit = 2;
|
||||
static constexpr iostate eofbit = 4;
|
||||
|
||||
typedef int seekdir;
|
||||
static constexpr seekdir beg = 0;
|
||||
static constexpr seekdir end = 1;
|
||||
static constexpr seekdir cur = 2;
|
||||
|
||||
enum event
|
||||
{
|
||||
erase_event,
|
||||
imbue_event,
|
||||
copyfmt_event
|
||||
};
|
||||
|
||||
typedef void (*event_callback)(event type, ios_base &ios, int index);
|
||||
|
||||
#pragma endregion Member types and constants
|
||||
|
||||
#pragma region Member Functions
|
||||
|
||||
protected:
|
||||
ios_base();
|
||||
|
||||
public:
|
||||
ios_base(const ios_base &) = delete;
|
||||
virtual ~ios_base() = default;
|
||||
ios_base &operator=(const ios_base &) = delete;
|
||||
|
||||
#pragma endregion Member Functions
|
||||
|
||||
#pragma region Formatting
|
||||
|
||||
fmtflags flags() const
|
||||
{
|
||||
return _flags;
|
||||
}
|
||||
|
||||
fmtflags flags(fmtflags flags)
|
||||
{
|
||||
fmtflags old = _flags;
|
||||
_flags = flags;
|
||||
return old;
|
||||
}
|
||||
|
||||
fmtflags setf(fmtflags flags)
|
||||
{
|
||||
fmtflags old = _flags;
|
||||
_flags |= flags;
|
||||
return old;
|
||||
}
|
||||
|
||||
fmtflags setf(fmtflags flags, fmtflags mask)
|
||||
{
|
||||
fmtflags old = _flags;
|
||||
_flags &= ~mask;
|
||||
_flags |= flags;
|
||||
return old;
|
||||
}
|
||||
|
||||
void unsetf(fmtflags flags)
|
||||
{
|
||||
_flags &= ~flags;
|
||||
}
|
||||
|
||||
streamsize precision() const
|
||||
{
|
||||
return _precision;
|
||||
}
|
||||
|
||||
streamsize precision(streamsize new_precision)
|
||||
{
|
||||
streamsize old = _precision;
|
||||
_precision = new_precision;
|
||||
return old;
|
||||
}
|
||||
|
||||
streamsize width() const
|
||||
{
|
||||
return _width;
|
||||
}
|
||||
|
||||
streamsize width(streamsize new_width)
|
||||
{
|
||||
streamsize old = _width;
|
||||
_width = new_width;
|
||||
return old;
|
||||
}
|
||||
|
||||
#pragma endregion Formatting
|
||||
|
||||
#pragma region Locales
|
||||
|
||||
std::locale imbue(const std::locale &loc)
|
||||
{
|
||||
std::locale old = _loc;
|
||||
_loc = loc;
|
||||
__call_event(imbue_event, *this, 0);
|
||||
return old;
|
||||
}
|
||||
|
||||
std::locale getloc() const
|
||||
{
|
||||
return _loc;
|
||||
}
|
||||
|
||||
#pragma endregion Locales
|
||||
|
||||
#pragma region Internal Extensible Array
|
||||
|
||||
static int xalloc()
|
||||
{
|
||||
static int index = 0;
|
||||
return index++;
|
||||
}
|
||||
|
||||
long &iword(int index)
|
||||
{
|
||||
static std::vector<long> iwords;
|
||||
if ((size_t)index >= iwords.size())
|
||||
iwords.resize(index + 1);
|
||||
return iwords[index];
|
||||
}
|
||||
|
||||
void *&pword(int index)
|
||||
{
|
||||
static std::vector<void *> pwords;
|
||||
if ((size_t)index >= pwords.size())
|
||||
pwords.resize(index + 1);
|
||||
return pwords[index];
|
||||
}
|
||||
|
||||
#pragma endregion Internal Extensible Array
|
||||
|
||||
#pragma region Miscellaneous
|
||||
|
||||
void register_callback(event_callback function, int index)
|
||||
{
|
||||
_event_callback = function;
|
||||
__call_event(imbue_event, *this, index);
|
||||
}
|
||||
|
||||
static bool sync_with_stdio(bool sync = true)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
#pragma endregion Miscellaneous
|
||||
|
||||
#pragma region Member Classes
|
||||
|
||||
class failure
|
||||
{
|
||||
public:
|
||||
explicit failure(const std::string &message, const std::error_code &ec = std::io_errc::stream)
|
||||
{
|
||||
}
|
||||
|
||||
explicit failure(const char *message, const std::error_code &ec = std::io_errc::stream)
|
||||
{
|
||||
}
|
||||
|
||||
failure(const failure &other) noexcept
|
||||
{
|
||||
}
|
||||
|
||||
failure &operator=(const failure &other) noexcept
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
virtual const char *what() const noexcept
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
class Init
|
||||
{
|
||||
public:
|
||||
Init() = default;
|
||||
~Init() = default;
|
||||
};
|
||||
|
||||
#pragma endregion Member Classes
|
||||
|
||||
private:
|
||||
fmtflags _flags = skipws;
|
||||
streamsize _precision = 6;
|
||||
streamsize _width = 0;
|
||||
std::locale _loc = std::locale::classic();
|
||||
|
||||
static event_callback _event_callback;
|
||||
|
||||
static void __call_event(event type, ios_base &ios, int index)
|
||||
{
|
||||
if (_event_callback)
|
||||
_event_callback(type, ios, index);
|
||||
}
|
||||
};
|
||||
|
||||
template <class CharT, class Traits = std::char_traits<CharT>>
|
||||
class basic_ios : public std::ios_base
|
||||
{
|
||||
};
|
||||
|
||||
typedef basic_ios<char> ios;
|
||||
typedef basic_ios<wchar_t> wios;
|
||||
}
|
@ -15,23 +15,22 @@
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <filesystem/mounts.hpp>
|
||||
#include <errno.h>
|
||||
#pragma once
|
||||
|
||||
#include "../../kernel.h"
|
||||
#include <ostream>
|
||||
#include <istream>
|
||||
|
||||
namespace vfs
|
||||
namespace std
|
||||
{
|
||||
size_t NullDevice::read(uint8_t *Buffer, size_t Size, off_t Offset)
|
||||
{
|
||||
return Size;
|
||||
}
|
||||
extern std::istream cin;
|
||||
extern std::wistream wcin;
|
||||
|
||||
size_t NullDevice::write(uint8_t *Buffer, size_t Size, off_t Offset)
|
||||
{
|
||||
return Size;
|
||||
}
|
||||
extern std::ostream cout;
|
||||
extern std::wostream wcout;
|
||||
|
||||
NullDevice::NullDevice() : Node(DevFS, "null", CHARDEVICE) {}
|
||||
NullDevice::~NullDevice() {}
|
||||
extern std::ostream cerr;
|
||||
extern std::wostream wcerr;
|
||||
|
||||
extern std::ostream clog;
|
||||
extern std::wostream wclog;
|
||||
}
|
79
include_std/istream
Normal file
79
include_std/istream
Normal file
@ -0,0 +1,79 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <streambuf>
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
#include <ios>
|
||||
|
||||
namespace std
|
||||
{
|
||||
template <class CharT, class Traits = std::char_traits<CharT>>
|
||||
class basic_istream : virtual public std::basic_ios<CharT, Traits>
|
||||
{
|
||||
};
|
||||
|
||||
template <class CharT, class Traits = std::char_traits<CharT>>
|
||||
class basic_iostream : public basic_istream<CharT, Traits>, public basic_ostream<CharT, Traits>
|
||||
{
|
||||
private:
|
||||
void init(std::basic_streambuf<CharT, Traits> *sb)
|
||||
{
|
||||
this->basic_istream<CharT, Traits>::rdbuf(sb);
|
||||
this->basic_ostream<CharT, Traits>::rdbuf(sb);
|
||||
}
|
||||
|
||||
public:
|
||||
typedef CharT char_type;
|
||||
typedef Traits::char_type traits_type;
|
||||
typedef Traits::int_type int_type;
|
||||
typedef Traits::pos_type pos_type;
|
||||
typedef Traits::off_type off_type;
|
||||
|
||||
explicit basic_iostream(std::basic_streambuf<CharT, Traits> *sb)
|
||||
{
|
||||
this->init(sb);
|
||||
}
|
||||
|
||||
basic_iostream(const basic_iostream &other) = delete;
|
||||
virtual ~basic_iostream() = default;
|
||||
|
||||
basic_iostream &operator=(const basic_iostream &other) = delete;
|
||||
|
||||
protected:
|
||||
basic_iostream(basic_iostream &&other)
|
||||
{
|
||||
this->rdbuf(other.rdbuf());
|
||||
other.rdbuf(nullptr);
|
||||
}
|
||||
|
||||
basic_iostream &operator=(basic_iostream &&other);
|
||||
|
||||
void swap(basic_iostream &other)
|
||||
{
|
||||
std::swap(this->rdbuf(), other.rdbuf());
|
||||
}
|
||||
};
|
||||
|
||||
typedef basic_istream<char> istream;
|
||||
typedef basic_istream<wchar_t> wistream;
|
||||
|
||||
typedef basic_iostream<char> iostream;
|
||||
typedef basic_iostream<wchar_t> wiostream;
|
||||
}
|
@ -43,26 +43,21 @@ namespace std
|
||||
{
|
||||
};
|
||||
|
||||
template <class Iter>
|
||||
class reverse_iterator
|
||||
{
|
||||
public:
|
||||
/* FIXME: missing implementation */
|
||||
};
|
||||
|
||||
template <class Iter>
|
||||
struct iterator_traits
|
||||
{
|
||||
public:
|
||||
typedef Iter::difference_type difference_type;
|
||||
|
||||
/* FIXME: missing implementation */
|
||||
using difference_type = typename Iter::difference_type;
|
||||
using value_type = typename Iter::value_type;
|
||||
using pointer = typename Iter::pointer;
|
||||
using reference = typename Iter::reference;
|
||||
using iterator_category = typename Iter::iterator_category;
|
||||
};
|
||||
|
||||
template <class It>
|
||||
constexpr typename std::iterator_traits<It>::difference_type __do_distance(It first, It last, std::input_iterator_tag)
|
||||
template <class InputIt>
|
||||
constexpr typename std::iterator_traits<InputIt>::difference_type __do_distance(InputIt first, InputIt last, std::input_iterator_tag)
|
||||
{
|
||||
typename std::iterator_traits<It>::difference_type result = 0;
|
||||
typename std::iterator_traits<InputIt>::difference_type result = 0;
|
||||
while (first != last)
|
||||
{
|
||||
++first;
|
||||
@ -71,8 +66,8 @@ namespace std
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class It>
|
||||
constexpr typename std::iterator_traits<It>::difference_type __do_distance(It first, It last, std::random_access_iterator_tag)
|
||||
template <class InputIt>
|
||||
constexpr typename std::iterator_traits<InputIt>::difference_type __do_distance(InputIt first, InputIt last, std::random_access_iterator_tag)
|
||||
{
|
||||
return last - first;
|
||||
}
|
||||
@ -82,4 +77,56 @@ namespace std
|
||||
{
|
||||
return __do_distance(first, last, typename std::iterator_traits<InputIt>::iterator_category());
|
||||
}
|
||||
|
||||
template <class InputIt>
|
||||
void __do_advance(InputIt &it, typename std::iterator_traits<InputIt>::difference_type n, std::input_iterator_tag)
|
||||
{
|
||||
while (n > 0)
|
||||
{
|
||||
--n;
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
template <class InputIt>
|
||||
void __do_advance(InputIt &it, typename std::iterator_traits<InputIt>::difference_type n, std::bidirectional_iterator_tag)
|
||||
{
|
||||
while (n > 0)
|
||||
{
|
||||
--n;
|
||||
++it;
|
||||
}
|
||||
while (n < 0)
|
||||
{
|
||||
++n;
|
||||
--it;
|
||||
}
|
||||
}
|
||||
|
||||
template <class InputIt>
|
||||
void __do_advance(InputIt &it, typename std::iterator_traits<InputIt>::difference_type n, std::random_access_iterator_tag)
|
||||
{
|
||||
it += n;
|
||||
}
|
||||
|
||||
template <class InputIt, class Distance>
|
||||
constexpr void advance(InputIt &it, Distance n)
|
||||
{
|
||||
__do_advance(it, typename std::iterator_traits<InputIt>::difference_type(n),
|
||||
typename std::iterator_traits<InputIt>::iterator_category());
|
||||
}
|
||||
|
||||
template <class BidirIt>
|
||||
constexpr BidirIt prev(BidirIt it, typename std::iterator_traits<BidirIt>::difference_type n = 1)
|
||||
{
|
||||
std::advance(it, -n);
|
||||
return it;
|
||||
}
|
||||
|
||||
template <class InputIt>
|
||||
constexpr InputIt next(InputIt it, typename std::iterator_traits<InputIt>::difference_type n = 1)
|
||||
{
|
||||
std::advance(it, n);
|
||||
return it;
|
||||
}
|
||||
}
|
||||
|
987
include_std/list
987
include_std/list
File diff suppressed because it is too large
Load Diff
159
include_std/locale
Normal file
159
include_std/locale
Normal file
@ -0,0 +1,159 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <cassert>
|
||||
#include <string>
|
||||
|
||||
namespace std
|
||||
{
|
||||
class locale
|
||||
{
|
||||
public:
|
||||
#pragma region Member Types
|
||||
|
||||
class id
|
||||
{
|
||||
public:
|
||||
id() = default;
|
||||
id(const id &) = delete;
|
||||
};
|
||||
|
||||
class facet
|
||||
{
|
||||
private:
|
||||
std::size_t refs;
|
||||
|
||||
public:
|
||||
explicit facet(std::size_t refs = 0)
|
||||
{
|
||||
this->refs = refs;
|
||||
}
|
||||
|
||||
facet(const facet &) = delete;
|
||||
|
||||
protected:
|
||||
virtual ~facet() = default;
|
||||
};
|
||||
|
||||
typedef int category;
|
||||
|
||||
#pragma endregion Member Types
|
||||
|
||||
#pragma region Member Objects
|
||||
|
||||
static const category none = 0;
|
||||
static const category collate = 1;
|
||||
static const category ctype = 2;
|
||||
static const category monetary = 4;
|
||||
static const category numeric = 8;
|
||||
static const category time = 16;
|
||||
static const category messages = 32;
|
||||
static const category all = collate | ctype | monetary | numeric | time | messages;
|
||||
|
||||
#pragma endregion Member Objects
|
||||
|
||||
#pragma region Member Functions
|
||||
|
||||
locale() noexcept
|
||||
{
|
||||
assert(!"Function not implemented");
|
||||
}
|
||||
|
||||
locale(const locale &other) noexcept
|
||||
{
|
||||
assert(!"Function not implemented");
|
||||
}
|
||||
|
||||
explicit locale(const char *std_name)
|
||||
{
|
||||
assert(!"Function not implemented");
|
||||
}
|
||||
|
||||
explicit locale(const std::string &std_name)
|
||||
{
|
||||
assert(!"Function not implemented");
|
||||
}
|
||||
|
||||
locale(const locale &other, const char *std_name, category cats)
|
||||
{
|
||||
assert(!"Function not implemented");
|
||||
}
|
||||
|
||||
locale(const locale &other, const std::string &std_name, category cats)
|
||||
{
|
||||
assert(!"Function not implemented");
|
||||
}
|
||||
|
||||
template <class Facet>
|
||||
locale(const locale &other, Facet *f)
|
||||
{
|
||||
assert(!"Function not implemented");
|
||||
}
|
||||
|
||||
locale(const locale &other, const locale &one, category cats)
|
||||
{
|
||||
assert(!"Function not implemented");
|
||||
}
|
||||
|
||||
~locale()
|
||||
{
|
||||
assert(!"Function not implemented");
|
||||
}
|
||||
|
||||
const locale &operator=(const locale &other) noexcept
|
||||
{
|
||||
assert(!"Function not implemented");
|
||||
}
|
||||
|
||||
template <class Facet>
|
||||
locale combine(const locale &other) const
|
||||
{
|
||||
assert(!"Function not implemented");
|
||||
}
|
||||
|
||||
std::string name() const
|
||||
{
|
||||
assert(!"Function not implemented");
|
||||
}
|
||||
|
||||
bool operator==(const locale &other) const
|
||||
{
|
||||
assert(!"Function not implemented");
|
||||
}
|
||||
|
||||
template <class CharT, class Traits, class Alloc>
|
||||
bool operator()(const basic_string<CharT, Traits, Alloc> &s1, const basic_string<CharT, Traits, Alloc> &s2) const
|
||||
{
|
||||
assert(!"Function not implemented");
|
||||
}
|
||||
|
||||
static locale global(const locale &loc)
|
||||
{
|
||||
assert(!"Function not implemented");
|
||||
}
|
||||
|
||||
static const locale &classic()
|
||||
{
|
||||
assert(!"Function not implemented");
|
||||
}
|
||||
|
||||
#pragma endregion Member Functions
|
||||
};
|
||||
}
|
@ -18,12 +18,136 @@
|
||||
#pragma once
|
||||
|
||||
#include <type_traits>
|
||||
#include <functional>
|
||||
#include <cstddef>
|
||||
#include <utility>
|
||||
#include <limits>
|
||||
#include <new>
|
||||
|
||||
#include <debug.h>
|
||||
|
||||
namespace std
|
||||
{
|
||||
namespace __memory__detail
|
||||
{
|
||||
template <class>
|
||||
constexpr bool is_unbounded_array_v = false;
|
||||
template <class T>
|
||||
constexpr bool is_unbounded_array_v<T[]> = true;
|
||||
|
||||
template <class>
|
||||
constexpr bool is_bounded_array_v = false;
|
||||
template <class T, std::size_t N>
|
||||
constexpr bool is_bounded_array_v<T[N]> = true;
|
||||
}
|
||||
|
||||
template <class T, class... Args>
|
||||
constexpr T *construct_at(T *p, Args &&...args)
|
||||
{
|
||||
return ::new (static_cast<void *>(p)) T(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
constexpr void destroy_at(T *p)
|
||||
{
|
||||
p->~T();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
T *addressof(T &arg)
|
||||
{
|
||||
return reinterpret_cast<T *>(&const_cast<char &>(reinterpret_cast<const volatile char &>(arg)));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
const T *addressof(const T &&) = delete;
|
||||
|
||||
template <class InputIt, class Size, class NoThrowForwardIt>
|
||||
NoThrowForwardIt uninitialized_copy_n(InputIt first, Size count, NoThrowForwardIt d_first)
|
||||
{
|
||||
using ValueType = typename std::iterator_traits<NoThrowForwardIt>::value_type;
|
||||
NoThrowForwardIt current = d_first;
|
||||
try
|
||||
{
|
||||
for (Size i = 0; i < count; ++i, (void)++current, ++first)
|
||||
{
|
||||
::new (static_cast<void *>(std::addressof(*current))) ValueType(*first);
|
||||
}
|
||||
return current;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
for (; d_first != current; ++d_first)
|
||||
{
|
||||
d_first->~ValueType();
|
||||
}
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
template <class ExecutionPolicy, class ForwardIt, class Size, class NoThrowForwardIt>
|
||||
NoThrowForwardIt uninitialized_copy_n(ExecutionPolicy &&policy, ForwardIt first, Size count, NoThrowForwardIt d_first)
|
||||
{
|
||||
return uninitialized_copy_n(first, count, d_first);
|
||||
}
|
||||
|
||||
template <class ForwardIt, class Size, class T>
|
||||
ForwardIt uninitialized_fill_n(ForwardIt first, Size count, const T &value)
|
||||
{
|
||||
using V = typename std::iterator_traits<ForwardIt>::value_type;
|
||||
ForwardIt current = first;
|
||||
try
|
||||
{
|
||||
for (; count > 0; ++current, (void)--count)
|
||||
::new (static_cast<void *>(std::addressof(*current))) V(value);
|
||||
return current;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
for (; first != current; ++first)
|
||||
first->~V();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
template <class ExecutionPolicy, class ForwardIt, class Size, class T>
|
||||
ForwardIt uninitialized_fill_n(ExecutionPolicy &&policy, ForwardIt first, Size count, const T &value)
|
||||
{
|
||||
return uninitialized_fill_n(first, count, value);
|
||||
}
|
||||
|
||||
template <class Ptr>
|
||||
struct pointer_traits
|
||||
{
|
||||
using pointer = Ptr;
|
||||
using element_type = typename Ptr::element_type;
|
||||
using difference_type = typename Ptr::difference_type;
|
||||
|
||||
template <class U>
|
||||
using rebind = typename Ptr::template rebind<U>;
|
||||
|
||||
static pointer pointer_to(element_type &r) noexcept
|
||||
{
|
||||
return Ptr::pointer_to(r);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct pointer_traits<T *>
|
||||
{
|
||||
using pointer = T *;
|
||||
using element_type = T;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
|
||||
template <class U>
|
||||
using rebind = U *;
|
||||
|
||||
static pointer pointer_to(element_type &r) noexcept
|
||||
{
|
||||
return std::addressof(r);
|
||||
}
|
||||
};
|
||||
|
||||
template <class Pointer, class SizeType = std::size_t>
|
||||
struct allocation_result
|
||||
{
|
||||
@ -31,6 +155,73 @@ namespace std
|
||||
SizeType count;
|
||||
};
|
||||
|
||||
template <class Alloc>
|
||||
struct allocator_traits
|
||||
{
|
||||
typedef Alloc allocator_type;
|
||||
typedef typename Alloc::value_type value_type;
|
||||
typedef typename Alloc::pointer pointer;
|
||||
typedef typename Alloc::const_pointer const_pointer;
|
||||
// typedef typename Alloc::void_pointer void_pointer;
|
||||
// typedef typename Alloc::const_void_pointer const_void_pointer;
|
||||
// typedef typename std::pointer_traits<pointer>::rebind<void> void_pointer;
|
||||
// typedef typename std::pointer_traits<pointer>::rebind<const void> const_void_pointer;
|
||||
typedef typename Alloc::difference_type difference_type;
|
||||
typedef typename Alloc::size_type size_type;
|
||||
// typedef typename Alloc::propagate_on_container_copy_assignment propagate_on_container_copy_assignment;
|
||||
typedef typename std::false_type propagate_on_container_copy_assignment;
|
||||
typedef typename Alloc::propagate_on_container_move_assignment propagate_on_container_move_assignment;
|
||||
typedef typename std::false_type propagate_on_container_swap;
|
||||
typedef typename Alloc::is_always_equal is_always_equal;
|
||||
|
||||
template <class T>
|
||||
using rebind_alloc = typename Alloc::template rebind<T>::other;
|
||||
template <class T>
|
||||
using rebind_traits = allocator_traits<rebind_alloc<T>>;
|
||||
|
||||
[[nodiscard]] static constexpr pointer allocate(Alloc &a, size_type n)
|
||||
{
|
||||
return a.allocate(n);
|
||||
}
|
||||
|
||||
// [[nodiscard]] static constexpr pointer allocate(Alloc &a, size_type n, const_void_pointer hint)
|
||||
// {
|
||||
// return a.allocate(n, hint);
|
||||
// }
|
||||
|
||||
[[nodiscard]] static constexpr std::allocation_result<pointer, size_type> allocate_at_least(Alloc &a, size_type n)
|
||||
{
|
||||
return a.allocate_at_least(n);
|
||||
}
|
||||
|
||||
static constexpr void deallocate(Alloc &a, pointer p, size_type n)
|
||||
{
|
||||
a.deallocate(p, n);
|
||||
}
|
||||
|
||||
template <class T, class... Args>
|
||||
static constexpr void construct(Alloc &a, T *p, Args &&...args)
|
||||
{
|
||||
std::construct_at(p, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static constexpr void destroy(Alloc &a, T *p)
|
||||
{
|
||||
std::destroy_at(p);
|
||||
}
|
||||
|
||||
static constexpr size_type max_size(const Alloc &a)
|
||||
{
|
||||
return a.max_size();
|
||||
}
|
||||
|
||||
static constexpr Alloc select_on_container_copy_construction(const Alloc &a)
|
||||
{
|
||||
return a;
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct allocator
|
||||
{
|
||||
@ -64,9 +255,7 @@ namespace std
|
||||
|
||||
std::allocation_result<T *, std::size_t> allocate_at_least(std::size_t n)
|
||||
{
|
||||
if (n > max_size())
|
||||
return {nullptr, 0};
|
||||
return {allocate(n), n};
|
||||
return {static_cast<T *>(::operator new(n * sizeof(T))), n};
|
||||
}
|
||||
|
||||
void deallocate(T *p, std::size_t n)
|
||||
@ -74,35 +263,344 @@ namespace std
|
||||
::operator delete(p);
|
||||
}
|
||||
|
||||
size_type max_size() const
|
||||
{
|
||||
return std::numeric_limits<size_type>::max() / sizeof(T);
|
||||
}
|
||||
|
||||
void construct(pointer p, const_reference val)
|
||||
{
|
||||
::new ((void *)p) T(val);
|
||||
}
|
||||
|
||||
template <class U, class... Args>
|
||||
void construct(U *p, Args &&...args)
|
||||
{
|
||||
::new ((void *)p) U(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
void destroy(pointer p) { p->~T(); }
|
||||
template <class U>
|
||||
void destroy(U *p) { p->~U(); }
|
||||
pointer address(reference x) const { return &x; }
|
||||
const_pointer address(const_reference x) const { return &x; }
|
||||
};
|
||||
|
||||
template <class T>
|
||||
T *addressof(T &arg)
|
||||
struct default_delete
|
||||
{
|
||||
return reinterpret_cast<T *>(&const_cast<char &>(reinterpret_cast<const volatile char &>(arg)));
|
||||
constexpr default_delete() noexcept = default;
|
||||
|
||||
template <class U>
|
||||
constexpr default_delete(const default_delete<U> &d) noexcept {}
|
||||
|
||||
constexpr void operator()(T *ptr) const { delete ptr; }
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct default_delete<T[]>
|
||||
{
|
||||
constexpr default_delete() noexcept = default;
|
||||
|
||||
template <class U>
|
||||
constexpr default_delete(const default_delete<U[]> &d) noexcept {}
|
||||
|
||||
template <class U>
|
||||
constexpr void operator()(U *ptr) const { delete[] ptr; }
|
||||
};
|
||||
|
||||
template <class T, class Deleter = std::default_delete<T>>
|
||||
class unique_ptr
|
||||
{
|
||||
public:
|
||||
using pointer = T *; // std::remove_reference<Deleter>::type::pointer;
|
||||
using element_type = T;
|
||||
using deleter_type = Deleter;
|
||||
|
||||
private:
|
||||
pointer _ptr;
|
||||
|
||||
public:
|
||||
#pragma region Member Functions
|
||||
|
||||
constexpr unique_ptr() noexcept : _ptr(nullptr) {}
|
||||
|
||||
constexpr unique_ptr(std::nullptr_t) noexcept : _ptr(nullptr) {}
|
||||
|
||||
constexpr explicit unique_ptr(pointer p) noexcept : _ptr(p) {}
|
||||
|
||||
// constexpr unique_ptr(pointer p, /* TODO */ d1) noexcept : _ptr(p) {}
|
||||
|
||||
// constexpr unique_ptr(pointer p, /* TODO */ d2) noexcept : _ptr(p) {}
|
||||
|
||||
constexpr unique_ptr(unique_ptr &&u) noexcept : _ptr(u.release()) {}
|
||||
|
||||
template <class U, class E>
|
||||
constexpr unique_ptr(unique_ptr<U, E> &&u) noexcept : _ptr(u.release()) {}
|
||||
|
||||
unique_ptr(const unique_ptr &) = delete;
|
||||
|
||||
~unique_ptr()
|
||||
{
|
||||
if (_ptr == nullptr)
|
||||
return;
|
||||
Deleter d;
|
||||
d(_ptr);
|
||||
}
|
||||
|
||||
constexpr unique_ptr &operator=(unique_ptr &&r) noexcept
|
||||
{
|
||||
reset(r.release());
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class U, class E>
|
||||
constexpr unique_ptr &operator=(unique_ptr<U, E> &&r) noexcept
|
||||
{
|
||||
reset(r.release());
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr unique_ptr &operator=(std::nullptr_t) noexcept
|
||||
{
|
||||
reset();
|
||||
return *this;
|
||||
}
|
||||
|
||||
unique_ptr &operator=(const unique_ptr &) = delete;
|
||||
|
||||
#pragma endregion Member Functions
|
||||
|
||||
#pragma region Modifiers
|
||||
|
||||
constexpr pointer release() noexcept
|
||||
{
|
||||
pointer p = _ptr;
|
||||
_ptr = nullptr;
|
||||
return p;
|
||||
}
|
||||
|
||||
constexpr void reset(pointer ptr = pointer()) noexcept
|
||||
{
|
||||
Deleter d;
|
||||
d(_ptr);
|
||||
_ptr = ptr;
|
||||
}
|
||||
|
||||
void swap(unique_ptr &other) noexcept
|
||||
{
|
||||
pointer tmp = _ptr;
|
||||
_ptr = other._ptr;
|
||||
other._ptr = tmp;
|
||||
}
|
||||
|
||||
#pragma endregion Modifiers
|
||||
|
||||
#pragma region Observers
|
||||
|
||||
constexpr pointer get() const noexcept { return _ptr; }
|
||||
constexpr Deleter &get_deleter() noexcept { return _ptr; }
|
||||
constexpr const Deleter &get_deleter() const noexcept { return _ptr; }
|
||||
constexpr explicit operator bool() const noexcept { return get() != nullptr; }
|
||||
|
||||
#pragma endregion Observers
|
||||
|
||||
#pragma region Element Access
|
||||
|
||||
constexpr typename std::add_lvalue_reference<T>::type operator*() const noexcept(noexcept(*std::declval<pointer>())) { return *_ptr; }
|
||||
constexpr pointer operator->() const noexcept { return _ptr; }
|
||||
|
||||
#pragma endregion Element Access
|
||||
};
|
||||
|
||||
template <class T, class Deleter>
|
||||
class unique_ptr<T[], Deleter>
|
||||
{
|
||||
public:
|
||||
using pointer = T *; // std::remove_reference<Deleter>::type::pointer;
|
||||
using element_type = T;
|
||||
using deleter_type = Deleter;
|
||||
|
||||
private:
|
||||
pointer _ptr;
|
||||
|
||||
public:
|
||||
#pragma region Member Functions
|
||||
|
||||
constexpr unique_ptr() noexcept : _ptr(nullptr) {}
|
||||
|
||||
constexpr unique_ptr(std::nullptr_t) noexcept : _ptr(nullptr) {}
|
||||
|
||||
template <class U>
|
||||
constexpr explicit unique_ptr(U p) noexcept : _ptr(p) {}
|
||||
|
||||
// template <class U>
|
||||
// constexpr unique_ptr(U p, /* TODO */ d1) noexcept : _ptr(p) {}
|
||||
|
||||
// template <class U>
|
||||
// constexpr unique_ptr(U p, /* TODO */ d2) noexcept : _ptr(p) {}
|
||||
|
||||
constexpr unique_ptr(unique_ptr &&u) noexcept : _ptr(u.release()) {}
|
||||
|
||||
template <class U, class E>
|
||||
constexpr unique_ptr(unique_ptr<U, E> &&u) noexcept : _ptr(u.release()) {}
|
||||
|
||||
unique_ptr(const unique_ptr &) = delete;
|
||||
|
||||
~unique_ptr()
|
||||
{
|
||||
if (_ptr == nullptr)
|
||||
return;
|
||||
Deleter d;
|
||||
d(_ptr);
|
||||
}
|
||||
|
||||
constexpr unique_ptr &operator=(unique_ptr &&r) noexcept
|
||||
{
|
||||
reset(r.release());
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class U, class E>
|
||||
constexpr unique_ptr &operator=(unique_ptr<U, E> &&r) noexcept
|
||||
{
|
||||
reset(r.release());
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr unique_ptr &operator=(std::nullptr_t) noexcept
|
||||
{
|
||||
reset();
|
||||
return *this;
|
||||
}
|
||||
|
||||
unique_ptr &operator=(const unique_ptr &) = delete;
|
||||
|
||||
#pragma endregion Member Functions
|
||||
|
||||
#pragma region Modifiers
|
||||
|
||||
constexpr pointer release() noexcept
|
||||
{
|
||||
pointer p = _ptr;
|
||||
_ptr = nullptr;
|
||||
return p;
|
||||
}
|
||||
|
||||
template <class U>
|
||||
constexpr void reset(U ptr) noexcept
|
||||
{
|
||||
Deleter d;
|
||||
d(_ptr);
|
||||
_ptr = ptr;
|
||||
}
|
||||
|
||||
constexpr void reset(std::nullptr_t = nullptr) noexcept
|
||||
{
|
||||
Deleter d;
|
||||
d(_ptr);
|
||||
_ptr = nullptr;
|
||||
}
|
||||
|
||||
void swap(unique_ptr &other) noexcept
|
||||
{
|
||||
pointer tmp = _ptr;
|
||||
_ptr = other._ptr;
|
||||
other._ptr = tmp;
|
||||
}
|
||||
|
||||
#pragma endregion Modifiers
|
||||
|
||||
#pragma region Observers
|
||||
|
||||
constexpr pointer get() const noexcept { return _ptr; }
|
||||
constexpr Deleter &get_deleter() noexcept { return _ptr; }
|
||||
constexpr const Deleter &get_deleter() const noexcept { return _ptr; }
|
||||
constexpr explicit operator bool() const noexcept { return get() != nullptr; }
|
||||
|
||||
#pragma endregion Observers
|
||||
|
||||
#pragma region Element Access
|
||||
|
||||
constexpr T &operator[](std::size_t i) const { return _ptr[i]; }
|
||||
|
||||
#pragma endregion Element Access
|
||||
};
|
||||
|
||||
template <class T, class... Args>
|
||||
std::enable_if_t<!std::is_array<T>::value, std::unique_ptr<T>>
|
||||
make_unique(Args &&...args)
|
||||
{
|
||||
return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
const T *addressof(const T &&) = delete;
|
||||
std::enable_if_t<__memory__detail::is_unbounded_array_v<T>, std::unique_ptr<T>>
|
||||
make_unique(std::size_t n)
|
||||
{
|
||||
return std::unique_ptr<T>(new std::remove_extent_t<T>[n]());
|
||||
}
|
||||
|
||||
template <class T, class... Args>
|
||||
std::enable_if_t<__memory__detail::is_bounded_array_v<T>> make_unique(Args &&...) = delete;
|
||||
|
||||
template <class T>
|
||||
requires(!std::is_array_v<T>)
|
||||
std::unique_ptr<T> make_unique_for_overwrite()
|
||||
{
|
||||
return std::unique_ptr<T>(new T);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
requires std::is_unbounded_array_v<T>
|
||||
std::unique_ptr<T> make_unique_for_overwrite(std::size_t n)
|
||||
{
|
||||
return std::unique_ptr<T>(new std::remove_extent_t<T>[n]);
|
||||
}
|
||||
|
||||
template <class T, class... Args>
|
||||
requires std::is_bounded_array_v<T>
|
||||
void make_unique_for_overwrite(Args &&...) = delete;
|
||||
|
||||
template <class T1, class D1, class T2, class D2>
|
||||
constexpr bool operator==(const unique_ptr<T1, D1> &x, const unique_ptr<T2, D2> &y) { return x.get() == y.get(); }
|
||||
|
||||
template <class T1, class D1, class T2, class D2>
|
||||
bool operator<(const unique_ptr<T1, D1> &x, const unique_ptr<T2, D2> &y)
|
||||
{
|
||||
return std::less<typename std::common_type<typename unique_ptr<T1, D1>::pointer, typename unique_ptr<T2, D2>::pointer>::type>()(x.get(), y.get());
|
||||
}
|
||||
|
||||
template <class T1, class D1, class T2, class D2>
|
||||
bool operator<=(const unique_ptr<T1, D1> &x, const unique_ptr<T2, D2> &y) { return !(y < x); }
|
||||
|
||||
template <class T1, class D1, class T2, class D2>
|
||||
bool operator>(const unique_ptr<T1, D1> &x, const unique_ptr<T2, D2> &y) { return y < x; }
|
||||
|
||||
template <class T1, class D1, class T2, class D2>
|
||||
bool operator>=(const unique_ptr<T1, D1> &x, const unique_ptr<T2, D2> &y) { return !(x < y); }
|
||||
|
||||
// operator<=>(const unique_ptr<T1, D1> &x, const unique_ptr<T2, D2> &y);
|
||||
|
||||
template <class T, class D>
|
||||
constexpr bool operator==(const unique_ptr<T, D> &x, std::nullptr_t) noexcept { return !x; }
|
||||
|
||||
template <class T, class D>
|
||||
constexpr bool operator<(const unique_ptr<T, D> &x, std::nullptr_t) { return std::less<typename unique_ptr<T, D>::pointer>()(x.get(), nullptr); }
|
||||
|
||||
template <class T, class D>
|
||||
constexpr bool operator<(std::nullptr_t, const unique_ptr<T, D> &y) { return std::less<typename unique_ptr<T, D>::pointer>()(nullptr, y.get()); }
|
||||
|
||||
template <class T, class D>
|
||||
constexpr bool operator<=(const unique_ptr<T, D> &x, std::nullptr_t) { return !(nullptr < x); }
|
||||
|
||||
template <class T, class D>
|
||||
constexpr bool operator<=(std::nullptr_t, const unique_ptr<T, D> &y) { return !(y < nullptr); }
|
||||
|
||||
template <class T, class D>
|
||||
constexpr bool operator>(const unique_ptr<T, D> &x, std::nullptr_t) { return nullptr < x; }
|
||||
|
||||
template <class T, class D>
|
||||
constexpr bool operator>(std::nullptr_t, const unique_ptr<T, D> &y) { return y < nullptr; }
|
||||
|
||||
template <class T, class D>
|
||||
constexpr bool operator>=(const unique_ptr<T, D> &x, std::nullptr_t) { return !(x < nullptr); }
|
||||
|
||||
template <class T, class D>
|
||||
constexpr bool operator>=(std::nullptr_t, const unique_ptr<T, D> &y) { return !(nullptr < y); }
|
||||
|
||||
// operator<=>(const unique_ptr<T, D> &x, std::nullptr_t);
|
||||
|
||||
// template <class CharT, class Traits, class Y, class D>
|
||||
// std::basic_ostream<CharT, Traits> &operator<<(std::basic_ostream<CharT, Traits> &os, const std::unique_ptr<Y, D> &p)
|
||||
// {
|
||||
// return os << p.get();
|
||||
// }
|
||||
|
||||
template <class T, class D>
|
||||
void swap(std::unique_ptr<T, D> &lhs, std::unique_ptr<T, D> &rhs) noexcept
|
||||
{
|
||||
lhs.swap(rhs);
|
||||
}
|
||||
}
|
||||
|
23
include_std/memory.h
Normal file
23
include_std/memory.h
Normal file
@ -0,0 +1,23 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __FENNIX_KERNEL_STD_MEMORY_H__
|
||||
#define __FENNIX_KERNEL_STD_MEMORY_H__
|
||||
|
||||
#include <convert.h>
|
||||
|
||||
#endif // !__FENNIX_KERNEL_STD_MEMORY_H__
|
143
include_std/new
Normal file
143
include_std/new
Normal file
@ -0,0 +1,143 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <exception>
|
||||
|
||||
namespace std
|
||||
{
|
||||
enum class align_val_t : std::size_t
|
||||
{
|
||||
};
|
||||
|
||||
struct nothrow_t
|
||||
{
|
||||
explicit nothrow_t() = default;
|
||||
};
|
||||
|
||||
extern const std::nothrow_t nothrow;
|
||||
|
||||
struct destroying_delete_t
|
||||
{
|
||||
explicit destroying_delete_t() = default;
|
||||
};
|
||||
|
||||
inline constexpr destroying_delete_t destroying_delete{};
|
||||
|
||||
typedef void (*new_handler)();
|
||||
std::new_handler set_new_handler(std::new_handler new_p) noexcept;
|
||||
std::new_handler get_new_handler() noexcept;
|
||||
|
||||
class bad_alloc : public exception
|
||||
{
|
||||
public:
|
||||
bad_alloc() noexcept = default;
|
||||
bad_alloc(const bad_alloc &other) noexcept = default;
|
||||
|
||||
bad_alloc &operator=(const bad_alloc &other) noexcept = default;
|
||||
|
||||
virtual const char *what() const noexcept
|
||||
{
|
||||
return "bad_alloc";
|
||||
}
|
||||
};
|
||||
|
||||
class bad_array_new_length : public bad_alloc
|
||||
{
|
||||
public:
|
||||
bad_array_new_length() noexcept = default;
|
||||
bad_array_new_length(const bad_array_new_length &other) noexcept = default;
|
||||
virtual ~bad_array_new_length() = default;
|
||||
|
||||
bad_array_new_length &operator=(const bad_array_new_length &other) noexcept
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
virtual const char *what() const noexcept
|
||||
{
|
||||
return "bad_array_new_length";
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
[[nodiscard]] void *operator new(std::size_t count);
|
||||
[[nodiscard]] void *operator new[](std::size_t count);
|
||||
// [[nodiscard]] void *operator new(std::size_t count, std::align_val_t al);
|
||||
// [[nodiscard]] void *operator new[](std::size_t count, std::align_val_t al);
|
||||
|
||||
// [[nodiscard]] void *operator new(std::size_t count, const std::nothrow_t &tag) noexcept;
|
||||
// [[nodiscard]] void *operator new[](std::size_t count, const std::nothrow_t &tag) noexcept;
|
||||
// [[nodiscard]] void *operator new(std::size_t count, std::align_val_t al, const std::nothrow_t &) noexcept;
|
||||
// [[nodiscard]] void *operator new[](std::size_t count, std::align_val_t al, const std::nothrow_t &) noexcept;
|
||||
|
||||
[[nodiscard]] void *operator new(std::size_t count, void *ptr) noexcept;
|
||||
[[nodiscard]] void *operator new[](std::size_t count, void *ptr) noexcept;
|
||||
|
||||
// void *operator new(std::size_t count, ...);
|
||||
// void *operator new[](std::size_t count, ...);
|
||||
// void *operator new(std::size_t count, std::align_val_t al, ...);
|
||||
// void *operator new[](std::size_t count, std::align_val_t al, ...);
|
||||
|
||||
// void *T::operator new(std::size_t count);
|
||||
// void *T::operator new[](std::size_t count);
|
||||
// void *T::operator new(std::size_t count, std::align_val_t al);
|
||||
// void *T::operator new[](std::size_t count, std::align_val_t al);
|
||||
|
||||
// void *T::operator new(std::size_t count, ...);
|
||||
// void *T::operator new[](std::size_t count, ...);
|
||||
// void *T::operator new(std::size_t count, std::align_val_t al, ...);
|
||||
// void *T::operator new[](std::size_t count, std::align_val_t al, ...);
|
||||
|
||||
void operator delete(void *ptr) noexcept;
|
||||
void operator delete[](void *ptr) noexcept;
|
||||
// void operator delete(void *ptr, std::align_val_t al) noexcept;
|
||||
// void operator delete[](void *ptr, std::align_val_t al) noexcept;
|
||||
void operator delete(void *ptr, std::size_t sz) noexcept;
|
||||
// void operator delete[](void *ptr, std::size_t sz) noexcept;
|
||||
// void operator delete(void *ptr, std::size_t sz, std::align_val_t al) noexcept;
|
||||
// void operator delete[](void *ptr, std::size_t sz, std::align_val_t al) noexcept;
|
||||
|
||||
// void operator delete(void *ptr, const std::nothrow_t &tag) noexcept;
|
||||
// void operator delete[](void *ptr, const std::nothrow_t &tag) noexcept;
|
||||
// void operator delete(void *ptr, std::align_val_t al, const std::nothrow_t &tag) noexcept;
|
||||
// void operator delete[](void *ptr, std::align_val_t al, const std::nothrow_t &tag) noexcept;
|
||||
|
||||
// void operator delete(void *ptr, void *place) noexcept;
|
||||
// void operator delete[](void *ptr, void *place) noexcept;
|
||||
|
||||
// void operator delete(void *ptr, ...);
|
||||
// void operator delete[](void *ptr, ...);
|
||||
|
||||
// void T::operator delete(void *ptr);
|
||||
// void T::operator delete[](void *ptr);
|
||||
// void T::operator delete(void *ptr, std::align_val_t al);
|
||||
// void T::operator delete[](void *ptr, std::align_val_t al);
|
||||
// void T::operator delete(void *ptr, std::size_t sz);
|
||||
// void T::operator delete[](void *ptr, std::size_t sz);
|
||||
// void T::operator delete(void *ptr, std::size_t sz, std::align_val_t al);
|
||||
// void T::operator delete[](void *ptr, std::size_t sz, std::align_val_t al);
|
||||
|
||||
// void T::operator delete(void *ptr, args...);
|
||||
// void T::operator delete[](void *ptr, args...);
|
||||
|
||||
// void T::operator delete(T *ptr, std::destroying_delete_t);
|
||||
// void T::operator delete(T *ptr, std::destroying_delete_t, std::align_val_t al);
|
||||
// void T::operator delete(T *ptr, std::destroying_delete_t, std::size_t sz);
|
||||
// void T::operator delete(T *ptr, std::destroying_delete_t, std::size_t sz, std::align_val_t al);
|
@ -15,29 +15,26 @@
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <filesystem/mounts.hpp>
|
||||
#include <errno.h>
|
||||
#pragma once
|
||||
|
||||
#include "../../kernel.h"
|
||||
#include <string>
|
||||
#include <ios>
|
||||
|
||||
using namespace vfs;
|
||||
|
||||
namespace vfs
|
||||
namespace std
|
||||
{
|
||||
size_t ZeroDevice::read(uint8_t *Buffer, size_t Size, off_t Offset)
|
||||
template <class CharT, class Traits = std::char_traits<CharT>>
|
||||
class basic_ostream : virtual public std::basic_ios<CharT, Traits>
|
||||
{
|
||||
if (Size <= 0)
|
||||
return 0;
|
||||
};
|
||||
|
||||
memset(Buffer, 0, Size);
|
||||
return Size;
|
||||
template <class CharT, class Traits>
|
||||
std::basic_ostream<CharT, Traits> &endl(std::basic_ostream<CharT, Traits> &os)
|
||||
{
|
||||
os.put(os.widen('\n'));
|
||||
os.flush();
|
||||
return os;
|
||||
}
|
||||
|
||||
size_t ZeroDevice::write(uint8_t *Buffer, size_t Size, off_t Offset)
|
||||
{
|
||||
return Size;
|
||||
}
|
||||
|
||||
ZeroDevice::ZeroDevice() : Node(DevFS, "zero", CHARDEVICE) {}
|
||||
ZeroDevice::~ZeroDevice() {}
|
||||
typedef basic_ostream<char> ostream;
|
||||
typedef basic_ostream<wchar_t> wostream;
|
||||
}
|
23
include_std/signal.h
Normal file
23
include_std/signal.h
Normal file
@ -0,0 +1,23 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __FENNIX_KERNEL_STD_SIGNAL_H__
|
||||
#define __FENNIX_KERNEL_STD_SIGNAL_H__
|
||||
|
||||
#include <types.h>
|
||||
|
||||
#endif // !__FENNIX_KERNEL_STD_SIGNAL_H__
|
@ -1,68 +0,0 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* This function includes all the standard headers and defines some useful macros.
|
||||
* Note: This std implementation is not complete.
|
||||
*/
|
||||
#ifndef __FENNIX_KERNEL_STD_H__
|
||||
#define __FENNIX_KERNEL_STD_H__
|
||||
|
||||
#include <types.h>
|
||||
|
||||
/**
|
||||
* @brief // stub namespace for std::align_val_t and new operator
|
||||
* @note // Found on https://gcc.gnu.org/legacy-ml/gcc-patches/2016-09/msg00628.html for "_ZnwmSt11align_val_t" compiler error
|
||||
*/
|
||||
namespace std
|
||||
{
|
||||
typedef __SIZE_TYPE__ size_t;
|
||||
static const size_t npos = -1;
|
||||
|
||||
enum class align_val_t : std::size_t
|
||||
{
|
||||
};
|
||||
|
||||
template <typename InputIt, typename OutputIt, typename UnaryOperation>
|
||||
OutputIt transform(InputIt first, InputIt last, OutputIt result, UnaryOperation op)
|
||||
{
|
||||
while (first != last)
|
||||
{
|
||||
*result = op(*first);
|
||||
++first;
|
||||
++result;
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
inline __always_inline int tolower(int c)
|
||||
{
|
||||
if (c >= 'A' && c <= 'Z')
|
||||
return c + ('a' - 'A');
|
||||
else
|
||||
return c;
|
||||
}
|
||||
|
||||
inline __always_inline int toupper(int c)
|
||||
{
|
||||
if (c >= 'a' && c <= 'z')
|
||||
return c - ('a' - 'A');
|
||||
else
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // !__FENNIX_KERNEL_STD_H__
|
@ -1,266 +0,0 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __FENNIX_KERNEL_STD_SMART_POINTER_H__
|
||||
#define __FENNIX_KERNEL_STD_SMART_POINTER_H__
|
||||
|
||||
#include <types.h>
|
||||
|
||||
#include <type_traits>
|
||||
#include <debug.h>
|
||||
|
||||
// show debug messages
|
||||
// #define DEBUG_SMARTPOINTERS 1
|
||||
|
||||
#ifdef DEBUG_SMARTPOINTERS
|
||||
#define spdbg(m, ...) debug(m, ##__VA_ARGS__)
|
||||
#else
|
||||
#define spdbg(m, ...)
|
||||
#endif
|
||||
|
||||
namespace std
|
||||
{
|
||||
/**
|
||||
* @brief A smart pointer class
|
||||
*
|
||||
* This class is a smart pointer class. It is used to manage the lifetime of
|
||||
* objects. It is a reference counted pointer, so when the last reference to
|
||||
* the object is removed, the object is deleted.
|
||||
*
|
||||
* Basic Usage:
|
||||
* smart_ptr<char> pointer(new char());
|
||||
* *pointer = 'a';
|
||||
* printf("%c", *pointer); // Prints "a"
|
||||
*/
|
||||
template <class T>
|
||||
class smart_ptr
|
||||
{
|
||||
T *RealPointer;
|
||||
|
||||
public:
|
||||
explicit smart_ptr(T *Pointer = nullptr)
|
||||
{
|
||||
spdbg("Smart pointer created (%#lx)", this->RealPointer);
|
||||
this->RealPointer = Pointer;
|
||||
}
|
||||
|
||||
~smart_ptr()
|
||||
{
|
||||
spdbg("Smart pointer deleted (%#lx)", this->RealPointer);
|
||||
delete this->RealPointer, this->RealPointer = nullptr;
|
||||
}
|
||||
|
||||
T &operator*()
|
||||
{
|
||||
spdbg("Smart pointer dereferenced (%#lx)", this->RealPointer);
|
||||
return *this->RealPointer;
|
||||
}
|
||||
|
||||
T *operator->()
|
||||
{
|
||||
spdbg("Smart pointer dereferenced (%#lx)", this->RealPointer);
|
||||
return this->RealPointer;
|
||||
}
|
||||
|
||||
T *get()
|
||||
{
|
||||
spdbg("Smart pointer returned (%#lx)", this->RealPointer);
|
||||
return this->RealPointer;
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class auto_ptr
|
||||
{
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class unique_ptr
|
||||
{
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class weak_ptr
|
||||
{
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class shared_ptr
|
||||
{
|
||||
private:
|
||||
class counter
|
||||
{
|
||||
private:
|
||||
unsigned int RefCount{};
|
||||
|
||||
public:
|
||||
counter() : RefCount(0) { spdbg("Counter %#lx created", this); };
|
||||
counter(const counter &) = delete;
|
||||
counter &operator=(const counter &) = delete;
|
||||
~counter() { spdbg("Counter %#lx deleted", this); }
|
||||
void reset()
|
||||
{
|
||||
this->RefCount = 0;
|
||||
spdbg("reset");
|
||||
}
|
||||
|
||||
unsigned int get()
|
||||
{
|
||||
return this->RefCount;
|
||||
spdbg("return");
|
||||
}
|
||||
|
||||
void operator++()
|
||||
{
|
||||
this->RefCount++;
|
||||
spdbg("increment");
|
||||
}
|
||||
|
||||
void operator++(int)
|
||||
{
|
||||
this->RefCount++;
|
||||
spdbg("increment");
|
||||
}
|
||||
|
||||
void operator--()
|
||||
{
|
||||
this->RefCount--;
|
||||
spdbg("decrement");
|
||||
}
|
||||
|
||||
void operator--(int)
|
||||
{
|
||||
this->RefCount--;
|
||||
spdbg("decrement");
|
||||
}
|
||||
};
|
||||
|
||||
counter *ReferenceCounter;
|
||||
T *RealPointer;
|
||||
|
||||
public:
|
||||
explicit shared_ptr(T *Pointer = nullptr)
|
||||
{
|
||||
this->RealPointer = Pointer;
|
||||
this->ReferenceCounter = new counter();
|
||||
spdbg("[%#lx] Shared pointer created (ptr=%#lx, ref=%#lx)", this, Pointer, this->ReferenceCounter);
|
||||
if (Pointer)
|
||||
(*this->ReferenceCounter)++;
|
||||
}
|
||||
|
||||
shared_ptr(shared_ptr<T> &SPtr)
|
||||
{
|
||||
spdbg("[%#lx] Shared pointer copied (ptr=%#lx, ref=%#lx)", this, SPtr.RealPointer, SPtr.ReferenceCounter);
|
||||
this->RealPointer = SPtr.RealPointer;
|
||||
this->ReferenceCounter = SPtr.ReferenceCounter;
|
||||
(*this->ReferenceCounter)++;
|
||||
}
|
||||
|
||||
~shared_ptr()
|
||||
{
|
||||
spdbg("[%#lx] Shared pointer destructor called", this);
|
||||
(*this->ReferenceCounter)--;
|
||||
if (this->ReferenceCounter->get() == 0)
|
||||
{
|
||||
spdbg("[%#lx] Shared pointer deleted (ptr=%#lx, ref=%#lx)", this, this->RealPointer, this->ReferenceCounter);
|
||||
delete this->ReferenceCounter, this->ReferenceCounter = nullptr;
|
||||
delete this->RealPointer, this->RealPointer = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int get_count()
|
||||
{
|
||||
spdbg("[%#lx] Shared pointer count (%d)", this, this->ReferenceCounter->get());
|
||||
return this->ReferenceCounter->get();
|
||||
}
|
||||
|
||||
T *get()
|
||||
{
|
||||
spdbg("[%#lx] Shared pointer get (%#lx)", this, this->RealPointer);
|
||||
return this->RealPointer;
|
||||
}
|
||||
|
||||
T &operator*()
|
||||
{
|
||||
spdbg("[%#lx] Shared pointer dereference (ptr*=%#lx)", this, *this->RealPointer);
|
||||
return *this->RealPointer;
|
||||
}
|
||||
|
||||
T *operator->()
|
||||
{
|
||||
spdbg("[%#lx] Shared pointer dereference (ptr->%#lx)", this, this->RealPointer);
|
||||
return this->RealPointer;
|
||||
}
|
||||
|
||||
void reset(T *Pointer = nullptr)
|
||||
{
|
||||
if (this->RealPointer == Pointer)
|
||||
return;
|
||||
spdbg("[%#lx] Shared pointer reset (ptr=%#lx, ref=%#lx)", this, Pointer, this->ReferenceCounter);
|
||||
(*this->ReferenceCounter)--;
|
||||
if (this->ReferenceCounter->get() == 0)
|
||||
{
|
||||
delete this->RealPointer;
|
||||
delete this->ReferenceCounter;
|
||||
}
|
||||
this->RealPointer = Pointer;
|
||||
this->ReferenceCounter = new counter();
|
||||
if (Pointer)
|
||||
(*this->ReferenceCounter)++;
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
spdbg("[%#lx] Shared pointer reset (ptr=%#lx, ref=%#lx)", this, this->RealPointer, this->ReferenceCounter);
|
||||
if (this->ReferenceCounter->get() == 1)
|
||||
{
|
||||
delete this->RealPointer, this->RealPointer = nullptr;
|
||||
delete this->ReferenceCounter, this->ReferenceCounter = nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
(*this->ReferenceCounter)--;
|
||||
}
|
||||
}
|
||||
|
||||
void swap(shared_ptr<T> &Other)
|
||||
{
|
||||
spdbg("[%#lx] Shared pointer swap (ptr=%#lx, ref=%#lx <=> ptr=%#lx, ref=%#lx)",
|
||||
this, this->RealPointer, this->ReferenceCounter, Other.RealPointer, Other.ReferenceCounter);
|
||||
T *tempRealPointer = this->RealPointer;
|
||||
counter *tempReferenceCounter = this->ReferenceCounter;
|
||||
this->RealPointer = Other.RealPointer;
|
||||
this->ReferenceCounter = Other.ReferenceCounter;
|
||||
Other.RealPointer = tempRealPointer;
|
||||
Other.ReferenceCounter = tempReferenceCounter;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, typename... Args>
|
||||
shared_ptr<T> make_shared(Args &&...args)
|
||||
{
|
||||
return shared_ptr<T>(new T(forward<Args>(args)...));
|
||||
};
|
||||
|
||||
template <typename T, typename... Args>
|
||||
smart_ptr<T> make_smart(Args &&...args)
|
||||
{
|
||||
return smart_ptr<T>(new T(forward<Args>(args)...));
|
||||
};
|
||||
}
|
||||
|
||||
#endif // !__FENNIX_KERNEL_STD_SMART_POINTER_H__
|
35
include_std/stdbool.h
Normal file
35
include_std/stdbool.h
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __FENNIX_KERNEL_header_H__
|
||||
#define __FENNIX_KERNEL_header_H__
|
||||
|
||||
#include <types.h>
|
||||
|
||||
#ifndef __cplusplus
|
||||
|
||||
#define bool _Bool
|
||||
#define true 1
|
||||
#define false 0
|
||||
|
||||
#else
|
||||
|
||||
#define _Bool bool
|
||||
|
||||
#endif // !__cplusplus
|
||||
|
||||
#endif // !__FENNIX_KERNEL_header_H__
|
@ -17,27 +17,103 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <assert.h>
|
||||
#include <convert.h>
|
||||
#include <cassert>
|
||||
#include <new>
|
||||
|
||||
namespace std
|
||||
{
|
||||
class runtime_error
|
||||
class __simple_string
|
||||
{
|
||||
private:
|
||||
const char *m_what;
|
||||
char *data;
|
||||
size_t size;
|
||||
|
||||
public:
|
||||
runtime_error(const char *what_arg) : m_what(what_arg) {}
|
||||
const char *what() const { return this->m_what; }
|
||||
};
|
||||
|
||||
class out_of_range
|
||||
{
|
||||
public:
|
||||
out_of_range(const char *what_arg)
|
||||
__simple_string()
|
||||
: data(nullptr),
|
||||
size(0)
|
||||
{
|
||||
/* FIXME: This is a temporary assert */
|
||||
assert(what_arg != nullptr);
|
||||
}
|
||||
|
||||
__simple_string(const char *str)
|
||||
: data(nullptr),
|
||||
size(0)
|
||||
{
|
||||
size = strlen(str);
|
||||
data = new char[size + 1];
|
||||
assert(data != nullptr);
|
||||
memcpy(data, str, size);
|
||||
data[size] = '\0';
|
||||
}
|
||||
|
||||
__simple_string(const __simple_string &other)
|
||||
: data(nullptr),
|
||||
size(0)
|
||||
{
|
||||
size = other.size;
|
||||
data = new char[size + 1];
|
||||
assert(data != nullptr);
|
||||
memcpy(data, other.data, size);
|
||||
data[size] = '\0';
|
||||
}
|
||||
|
||||
~__simple_string()
|
||||
{
|
||||
if (data)
|
||||
delete[] data;
|
||||
}
|
||||
|
||||
const char *c_str() const { return data; }
|
||||
|
||||
__simple_string &operator=(const __simple_string &other)
|
||||
{
|
||||
if (data)
|
||||
delete[] data;
|
||||
|
||||
size = other.size;
|
||||
data = new char[size + 1];
|
||||
assert(data != nullptr);
|
||||
memcpy(data, other.data, size);
|
||||
data[size] = '\0';
|
||||
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
class runtime_error : public exception
|
||||
{
|
||||
};
|
||||
|
||||
class logic_error : public exception
|
||||
{
|
||||
private:
|
||||
__simple_string msg;
|
||||
|
||||
public:
|
||||
logic_error(const char *what_arg) : msg(what_arg) {}
|
||||
logic_error(const logic_error &other) : msg(other.msg) {}
|
||||
|
||||
logic_error &operator=(const logic_error &other) noexcept
|
||||
{
|
||||
msg = other.msg;
|
||||
return *this;
|
||||
}
|
||||
|
||||
virtual const char *what() const noexcept
|
||||
{
|
||||
return msg.c_str();
|
||||
}
|
||||
};
|
||||
|
||||
class out_of_range : public logic_error
|
||||
{
|
||||
public:
|
||||
out_of_range(const char *what_arg) : logic_error(what_arg) {}
|
||||
out_of_range(const out_of_range &other) = default;
|
||||
out_of_range &operator=(const out_of_range &) = default;
|
||||
out_of_range(out_of_range &&) = default;
|
||||
out_of_range &operator=(out_of_range &&) = default;
|
||||
virtual ~out_of_range() = default;
|
||||
};
|
||||
}
|
||||
|
@ -15,7 +15,42 @@
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _STDIO_H
|
||||
#define _STDIO_H
|
||||
#ifndef __FENNIX_KERNEL_STDIO_H__
|
||||
#define __FENNIX_KERNEL_STDIO_H__
|
||||
|
||||
#endif // !_STDIO_H
|
||||
#include <types.h>
|
||||
|
||||
START_EXTERNC
|
||||
|
||||
#define FILENAME_MAX 4096
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int st;
|
||||
} FILE;
|
||||
|
||||
extern FILE *stdin;
|
||||
extern FILE *stdout;
|
||||
extern FILE *stderr;
|
||||
|
||||
#define stdin stdin
|
||||
#define stdout stdout
|
||||
#define stderr stderr
|
||||
|
||||
int printf(const char *format, ...) __attribute__((format(__printf__, (1), (2))));
|
||||
int vprintf(const char *format, va_list arg) __attribute__((format(__printf__, ((1)), (0))));
|
||||
int sprintf(char *s, const char *format, ...) __attribute__((format(__printf__, (2), (3))));
|
||||
int vsprintf(char *s, const char *format, va_list arg) __attribute__((format(__printf__, ((2)), (0))));
|
||||
int snprintf(char *s, size_t count, const char *format, ...) __attribute__((format(__printf__, (3), (4))));
|
||||
int vsnprintf(char *s, size_t count, const char *format, va_list arg) __attribute__((format(__printf__, ((3)), (0))));
|
||||
|
||||
int asprintf(char **strp, const char *fmt, ...) __attribute__((format(__printf__, (2), (3))));
|
||||
int vasprintf(char **strp, const char *fmt, va_list ap) __attribute__((format(__printf__, ((2)), (0))));
|
||||
|
||||
int fprintf(FILE *stream, const char *format, ...) __attribute__((format(__printf__, (2), (3))));
|
||||
|
||||
int fputs(const char *s, FILE *stream);
|
||||
|
||||
END_EXTERNC
|
||||
|
||||
#endif // !__FENNIX_KERNEL_STDIO_H__
|
||||
|
@ -15,7 +15,27 @@
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _STDLIB_H
|
||||
#define _STDLIB_H
|
||||
#ifndef __FENNIX_KERNEL_STDLIB_H__
|
||||
#define __FENNIX_KERNEL_STDLIB_H__
|
||||
|
||||
#endif // !_STDLIB_H
|
||||
#include <types.h>
|
||||
|
||||
START_EXTERNC
|
||||
|
||||
#ifndef __FENNIX_KERNEL_INTERNAL_MEMORY_H__
|
||||
|
||||
void *malloc(size_t Size);
|
||||
void *calloc(size_t n, size_t Size);
|
||||
void *realloc(void *Address, size_t Size);
|
||||
void free(void *Address);
|
||||
|
||||
#endif // !__FENNIX_KERNEL_INTERNAL_MEMORY_H__
|
||||
|
||||
void abort();
|
||||
|
||||
#define EXIT_FAILURE 1
|
||||
#define EXIT_SUCCESS 0
|
||||
|
||||
END_EXTERNC
|
||||
|
||||
#endif // !__FENNIX_KERNEL_STDLIB_H__
|
||||
|
312
include_std/streambuf
Normal file
312
include_std/streambuf
Normal file
@ -0,0 +1,312 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <locale>
|
||||
#include <ios>
|
||||
|
||||
namespace std
|
||||
{
|
||||
template <class CharT, class Traits = std::char_traits<CharT>>
|
||||
class basic_streambuf
|
||||
{
|
||||
public:
|
||||
typedef CharT char_type;
|
||||
typedef Traits::char_type traits_type;
|
||||
typedef Traits::int_type int_type;
|
||||
typedef Traits::pos_type pos_type;
|
||||
typedef Traits::off_type off_type;
|
||||
|
||||
private:
|
||||
char_type *_eback;
|
||||
char_type *_gptr;
|
||||
char_type *_egptr;
|
||||
char_type *_pbase;
|
||||
char_type *_pptr;
|
||||
char_type *_epptr;
|
||||
|
||||
public:
|
||||
virtual ~basic_streambuf();
|
||||
|
||||
#pragma region Locales
|
||||
|
||||
std::locale pubimbue(const std::locale &loc)
|
||||
{
|
||||
return imbue(loc);
|
||||
}
|
||||
|
||||
std::locale getloc() const
|
||||
{
|
||||
return imbue(std::locale());
|
||||
}
|
||||
|
||||
#pragma endregion Locales
|
||||
|
||||
#pragma region Positioning
|
||||
|
||||
basic_streambuf<CharT, Traits> *pubsetbuf(char_type *s, std::streamsize n)
|
||||
{
|
||||
return setbuf(s, n);
|
||||
}
|
||||
|
||||
pos_type pubseekoff(off_type off, std::ios_base::seekdir dir, std::ios_base::openmode which = ios_base::in | ios_base::out)
|
||||
{
|
||||
return seekoff(off, dir, which);
|
||||
}
|
||||
|
||||
pos_type pubseekpos(pos_type pos, std::ios_base::openmode which = std::ios_base::in | std::ios_base::out)
|
||||
{
|
||||
return seekpos(pos, which);
|
||||
}
|
||||
|
||||
int pubsync()
|
||||
{
|
||||
return sync();
|
||||
}
|
||||
|
||||
#pragma endregion Positioning
|
||||
|
||||
#pragma region Get Area
|
||||
|
||||
std::streamsize in_avail()
|
||||
{
|
||||
return egptr() - gptr();
|
||||
}
|
||||
|
||||
int_type snextc()
|
||||
{
|
||||
return gptr() == egptr() ? Traits::eof() : Traits::to_int_type(*gptr());
|
||||
}
|
||||
|
||||
int_type sgetc()
|
||||
{
|
||||
return gptr() == egptr() ? underflow() : Traits::to_int_type(*gptr());
|
||||
}
|
||||
|
||||
std::streamsize sgetn(char_type *s, std::streamsize count)
|
||||
{
|
||||
std::streamsize copied = 0;
|
||||
while (copied < count)
|
||||
{
|
||||
if (gptr() == egptr())
|
||||
{
|
||||
if (underflow() == Traits::eof())
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
*s++ = *gptr();
|
||||
++copied;
|
||||
}
|
||||
return copied;
|
||||
}
|
||||
|
||||
#pragma endregion Get Area
|
||||
|
||||
#pragma region Put Area
|
||||
|
||||
int_type sputc(char_type ch)
|
||||
{
|
||||
if (pptr() == epptr())
|
||||
{
|
||||
if (overflow(Traits::to_int_type(ch)) == Traits::eof())
|
||||
{
|
||||
return Traits::eof();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
*pptr() = ch;
|
||||
pbump(1);
|
||||
}
|
||||
return Traits::to_int_type(ch);
|
||||
}
|
||||
|
||||
std::streamsize sputn(const char_type *s, std::streamsize count)
|
||||
{
|
||||
return xsputn(s, count);
|
||||
}
|
||||
|
||||
#pragma endregion Put Area
|
||||
|
||||
#pragma region Putback
|
||||
|
||||
int_type sputbackc(char_type c)
|
||||
{
|
||||
if (gptr() == eback() || !Traits::eq(c, gptr()[-1]))
|
||||
{
|
||||
return Traits::eof();
|
||||
}
|
||||
gbump(-1);
|
||||
return Traits::to_int_type(c);
|
||||
}
|
||||
|
||||
int_type sungetc()
|
||||
{
|
||||
if (gptr() == eback())
|
||||
{
|
||||
return Traits::eof();
|
||||
}
|
||||
gbump(-1);
|
||||
return Traits::to_int_type(*gptr());
|
||||
}
|
||||
|
||||
#pragma endregion Putback
|
||||
|
||||
protected:
|
||||
basic_streambuf()
|
||||
: _eback(nullptr),
|
||||
_gptr(nullptr),
|
||||
_egptr(nullptr),
|
||||
_pbase(nullptr),
|
||||
_pptr(nullptr),
|
||||
_epptr(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
basic_streambuf(const basic_streambuf &rhs)
|
||||
: _eback(rhs._eback),
|
||||
_gptr(rhs._gptr),
|
||||
_egptr(rhs._egptr),
|
||||
_pbase(rhs._pbase),
|
||||
_pptr(rhs._pptr),
|
||||
_epptr(rhs._epptr)
|
||||
{
|
||||
}
|
||||
|
||||
basic_streambuf &operator=(const basic_streambuf &other)
|
||||
{
|
||||
if (this == &other)
|
||||
return *this;
|
||||
|
||||
_eback = other._eback;
|
||||
_gptr = other._gptr;
|
||||
_egptr = other._egptr;
|
||||
_pbase = other._pbase;
|
||||
_pptr = other._pptr;
|
||||
_epptr = other._epptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void swap(basic_streambuf &other)
|
||||
{
|
||||
std::swap(_eback, other._eback);
|
||||
std::swap(_gptr, other._gptr);
|
||||
std::swap(_egptr, other._egptr);
|
||||
std::swap(_pbase, other._pbase);
|
||||
std::swap(_pptr, other._pptr);
|
||||
std::swap(_epptr, other._epptr);
|
||||
}
|
||||
|
||||
#pragma region Locales
|
||||
|
||||
virtual void imbue(const std::locale &loc) = 0;
|
||||
|
||||
#pragma endregion Locales
|
||||
|
||||
#pragma region Positioning
|
||||
|
||||
virtual basic_streambuf<CharT, Traits> *setbuf(char_type *s, std::streamsize n) = 0;
|
||||
virtual pos_type seekoff(off_type off, std::ios_base::seekdir dir, std::ios_base::openmode which = ios_base::in | ios_base::out) = 0;
|
||||
virtual pos_type seekpos(pos_type pos, std::ios_base::openmode which = std::ios_base::in | std::ios_base::out) = 0;
|
||||
virtual int sync() = 0;
|
||||
|
||||
#pragma endregion Positioning
|
||||
|
||||
#pragma region Get Area
|
||||
|
||||
virtual std::streamsize showmanyc() = 0;
|
||||
virtual int_type underflow() = 0;
|
||||
virtual int_type uflow() = 0;
|
||||
virtual std::streamsize xsgetn(char_type *s, std::streamsize count) = 0;
|
||||
|
||||
char_type *eback() const
|
||||
{
|
||||
return _eback;
|
||||
}
|
||||
|
||||
char_type *gptr() const
|
||||
{
|
||||
return _gptr;
|
||||
}
|
||||
|
||||
char_type *egptr() const
|
||||
{
|
||||
return _egptr;
|
||||
}
|
||||
|
||||
void gbump(int count)
|
||||
{
|
||||
_gptr += count;
|
||||
}
|
||||
|
||||
void setg(char_type *gbeg, char_type *gcurr, char_type *gend)
|
||||
{
|
||||
_eback = gbeg;
|
||||
_gptr = gcurr;
|
||||
_egptr = gend;
|
||||
}
|
||||
|
||||
#pragma endregion Get Area
|
||||
|
||||
#pragma region Put Area
|
||||
|
||||
virtual std::streamsize xsputn(const char_type *s, std::streamsize count) = 0;
|
||||
virtual int_type overflow(int_type ch = Traits::eof()) = 0;
|
||||
|
||||
char_type *pbase() const
|
||||
{
|
||||
return _pbase;
|
||||
}
|
||||
|
||||
char_type *pptr() const
|
||||
{
|
||||
return _pptr;
|
||||
}
|
||||
|
||||
char_type *epptr() const
|
||||
{
|
||||
return _epptr;
|
||||
}
|
||||
|
||||
void pbump(int count)
|
||||
{
|
||||
_pptr += count;
|
||||
}
|
||||
|
||||
void setp(char_type *pbeg, char_type *pend)
|
||||
{
|
||||
_pbase = pbeg;
|
||||
_pptr = pbeg;
|
||||
_epptr = pend;
|
||||
}
|
||||
|
||||
#pragma endregion Put Area
|
||||
|
||||
#pragma region Putback
|
||||
|
||||
virtual int_type pbackfail(int_type c = Traits::eof()) = 0;
|
||||
|
||||
#pragma endregion Putback
|
||||
};
|
||||
|
||||
typedef basic_streambuf<char> streambuf;
|
||||
typedef basic_streambuf<wchar_t> wstreambuf;
|
||||
}
|
3055
include_std/string
3055
include_std/string
File diff suppressed because it is too large
Load Diff
62
include_std/string_view
Normal file
62
include_std/string_view
Normal file
@ -0,0 +1,62 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <ostream>
|
||||
|
||||
namespace std
|
||||
{
|
||||
typedef basic_string_view<char> string_view;
|
||||
typedef basic_string_view<wchar_t> wstring_view;
|
||||
typedef basic_string_view<char8_t> u8string_view;
|
||||
typedef basic_string_view<char16_t> u16string_view;
|
||||
typedef basic_string_view<char32_t> u32string_view;
|
||||
|
||||
template <class CharT, class Traits>
|
||||
std::basic_ostream<CharT, Traits> &operator<<(std::basic_ostream<CharT, Traits> &os, std::basic_string_view<CharT, Traits> v)
|
||||
{
|
||||
os.write(v.data(), v.size());
|
||||
return os;
|
||||
}
|
||||
|
||||
constexpr std::string_view operator""sv(const char *str, std::size_t len) noexcept
|
||||
{
|
||||
return std::string_view{str, len};
|
||||
}
|
||||
|
||||
constexpr std::u8string_view operator""sv(const char8_t *str, std::size_t len) noexcept
|
||||
{
|
||||
return std::u8string_view{str, len};
|
||||
}
|
||||
|
||||
constexpr std::u16string_view operator""sv(const char16_t *str, std::size_t len) noexcept
|
||||
{
|
||||
return std::u16string_view{str, len};
|
||||
}
|
||||
|
||||
constexpr std::u32string_view operator""sv(const char32_t *str, std::size_t len) noexcept
|
||||
{
|
||||
return std::u32string_view{str, len};
|
||||
}
|
||||
|
||||
constexpr std::wstring_view operator""sv(const wchar_t *str, std::size_t len) noexcept
|
||||
{
|
||||
return std::wstring_view{str, len};
|
||||
}
|
||||
}
|
@ -18,7 +18,7 @@
|
||||
#pragma once
|
||||
#include <types.h>
|
||||
|
||||
/* stubs */
|
||||
/* stubs for rpmalloc.c */
|
||||
|
||||
#ifndef MAP_PRIVATE
|
||||
#define MAP_PRIVATE 0x0
|
||||
|
58
include_std/system_error
Normal file
58
include_std/system_error
Normal file
@ -0,0 +1,58 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace std
|
||||
{
|
||||
class error_category
|
||||
{
|
||||
/* https://en.cppreference.com/w/cpp/error/error_category */
|
||||
};
|
||||
|
||||
class error_code
|
||||
{
|
||||
public:
|
||||
error_code() noexcept
|
||||
{
|
||||
}
|
||||
|
||||
error_code(int ec, const error_category &ecat) noexcept
|
||||
{
|
||||
}
|
||||
|
||||
template <class ErrorCodeEnum>
|
||||
error_code(ErrorCodeEnum e) noexcept
|
||||
{
|
||||
}
|
||||
|
||||
error_code(const error_code &other) = default;
|
||||
error_code(error_code &&other) = default;
|
||||
|
||||
template <class ErrorCodeEnum>
|
||||
error_code &operator=(ErrorCodeEnum e) noexcept
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
error_code &operator=(const error_code &other) = default;
|
||||
|
||||
error_code &operator=(error_code &&other) = default;
|
||||
|
||||
/* https://en.cppreference.com/w/cpp/error/error_code */
|
||||
};
|
||||
}
|
@ -15,8 +15,10 @@
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __FENNIX_KERNEL_TERMIOS_BITS_H__
|
||||
#define __FENNIX_KERNEL_TERMIOS_BITS_H__
|
||||
#ifndef __FENNIX_KERNEL_TERMIOS_H__
|
||||
#define __FENNIX_KERNEL_TERMIOS_H__
|
||||
|
||||
#include <types.h>
|
||||
|
||||
/* c_cc */
|
||||
#define VINTR 0
|
||||
@ -157,4 +159,29 @@
|
||||
#define CMSPAR 010000000000
|
||||
#define CRTSCTS 020000000000
|
||||
|
||||
#endif // !__FENNIX_KERNEL_TERMIOS_BITS_H__
|
||||
typedef unsigned char cc_t;
|
||||
typedef unsigned int speed_t;
|
||||
typedef unsigned int tcflag_t;
|
||||
|
||||
#define NCCS 32
|
||||
struct termios
|
||||
{
|
||||
tcflag_t c_iflag;
|
||||
tcflag_t c_oflag;
|
||||
tcflag_t c_cflag;
|
||||
tcflag_t c_lflag;
|
||||
cc_t c_line;
|
||||
cc_t c_cc[NCCS];
|
||||
speed_t c_ispeed;
|
||||
speed_t c_ospeed;
|
||||
};
|
||||
|
||||
struct winsize
|
||||
{
|
||||
unsigned short ws_row;
|
||||
unsigned short ws_col;
|
||||
unsigned short ws_xpixel;
|
||||
unsigned short ws_ypixel;
|
||||
};
|
||||
|
||||
#endif // !__FENNIX_KERNEL_TERMIOS_H__
|
27
include_std/tuple
Normal file
27
include_std/tuple
Normal file
@ -0,0 +1,27 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <type_traits>
|
||||
#include <cstddef>
|
||||
|
||||
namespace std
|
||||
{
|
||||
template <class... Types>
|
||||
class tuple;
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user