Compare commits

...

47 Commits

Author SHA1 Message Date
abb7899a9d
fix(kernel/std): improve capacity growth strategy in std::vector operations
Some checks failed
Build OS / Build Cross-Compiler & Toolchain (push) Has been cancelled
Build OS / Analyze (c-cpp) (push) Has been cancelled
Build OS / Build OS (push) Has been cancelled
2025-04-15 16:48:23 +00:00
8c4c8d36de
fix(kernel/std): ensure null termination after removing elements in std::string::erase 2025-04-15 15:38:20 +00:00
0fffc6c914
build: fix "limine.h: No such file or directory" error 2025-04-14 01:29:25 +00:00
34e24df7c9
build: add __ci-prepare-archive 2025-04-14 01:27:20 +00:00
550e98e87c
ci: fix job names 2025-04-14 01:26:18 +00:00
4ff6790072
ci: add separate build steps in workflow 2025-04-14 01:20:57 +00:00
205ddb1e49
ci: ensure artifact upload occurs regardless of previous steps 2025-04-13 13:50:02 +00:00
0735743f44
build: fix kernel build on different architectures
Userspace still fails to compile on non-x86!!!
2025-04-13 13:47:59 +00:00
33eee9c628
feat(kernel/syscalls): implement stub linux_poll 2025-04-13 10:18:15 +00:00
ef5d61df9d
build(kernel/tty): fix vtable linking error 2025-04-13 10:08:49 +00:00
11d326b693
feat(kernel/tty): implement processing control characters (^C, ^D, etc) 2025-04-13 09:49:09 +00:00
5293bb2039
feat(kernel/tty): implement blinking cursor 2025-04-12 10:55:01 +00:00
bc84c406d9
build: update Linux Subsystem boot configuration to use compressed rootfs 2025-04-12 04:39:30 +00:00
ed1f4f3c1b
test: reduce debug qemu memory allocation for amd64 architecture 2025-04-12 04:38:24 +00:00
ec04e5abe9
build: update rootfs tar command to use gzip compression 2025-04-12 04:37:48 +00:00
5ecfffc049
build: create mnt directory in root filesystem setup 2025-04-12 04:37:23 +00:00
c7d501b466
build: add support for quiet build mode in CMakeLists 2025-04-12 04:36:16 +00:00
1f646d6826
fix(kernel): improve error message for failed init program startup 2025-04-12 04:33:10 +00:00
3315d79742
fix(kernel/vfs): support multiple roots 2025-04-08 05:04:04 +00:00
a1b58bacd8
refactor(kernel): remove unused assert_allow_continue macro 2025-04-08 03:37:32 +00:00
69122746de
refactor(kernel): change NIF to nif 2025-04-08 03:25:38 +00:00
764dfe67a5
refactor(kernel): replace manual sorting with std::sort 2025-04-08 02:37:22 +00:00
3d87345a51
fix(kernel/memory): correct bitmap address calculation 2025-04-08 02:31:40 +00:00
eb89b060f6
fix(kernel/vfs): accessing null pointer 2025-04-07 07:42:27 +00:00
25713e0f13
refactor(kernel): improve code readability and formatting 2025-04-07 07:30:48 +00:00
03147b532c
fix(kernel/memory): correct loop control in ReservePages function 2025-04-07 07:25:11 +00:00
d8cd27196d
feat(kernel/std): add std::sort implementations 2025-04-07 06:32:25 +00:00
832833a56f
fix(kernel/vfs): forgot ';' inside ramfs.hpp 2025-04-07 05:38:24 +00:00
a4e5f4785c
refactor(kernel): clean up KPrint formatting and fix memory reporting 2025-04-07 05:37:45 +00:00
a268f8dc2f
feat(kernel/vfs): implement RAMFS filesystem 2025-04-07 05:37:23 +00:00
a16a88b5f9
fix(kernel): validate symbol entries to prevent processing of invalid symbols 2025-04-07 05:35:17 +00:00
2d2d28689c
fix(kernel/vfs): correct root assignment logic in filesystem 2025-04-07 05:31:13 +00:00
d4346202ca
refactor(kernel): ramfs loading 2025-04-07 05:04:23 +00:00
b1a30059ed
feat(kernel): add initial subsystem implementation files 2025-04-07 04:51:05 +00:00
58accf8acf
feat(kernel): add initial security implementation files 2025-04-07 04:02:02 +00:00
24c0848797
refactor(workspace): remove useless settings in vscode workspaces 2025-04-05 17:20:34 +00:00
b232dc6b40
feat(kernel/vfs): add AddRootAt, SetRootAt, RemoveRoot & RootExists functions
Signed-off-by: EnderIce2 <enderice2@protonmail.com>
2025-04-04 11:51:47 +00:00
120d67fb1a
refactor(kernel): remove unnecessary type casting in Execute::Spawn call
Signed-off-by: EnderIce2 <enderice2@protonmail.com>
2025-04-04 11:01:40 +00:00
f6eb4bd3dc
test(kernel/std): add <array> header tests
Signed-off-by: EnderIce2 <enderice2@protonmail.com>
2025-04-04 10:58:13 +00:00
7e7e475dac
feat(kernel/std): implement <array> header
Signed-off-by: EnderIce2 <enderice2@protonmail.com>
2025-04-04 10:57:40 +00:00
23d0056098
feat(kernel/std): implement std::is_pointer_v
Signed-off-by: EnderIce2 <enderice2@protonmail.com>
2025-04-04 10:57:10 +00:00
3edb4b4761
feat(kernel/std): implement std::reverse_iterator
Signed-off-by: EnderIce2 <enderice2@protonmail.com>
2025-04-04 10:56:46 +00:00
fd24431eea
feat(kernel/std): implement std::runtime_error and std::length_error
Signed-off-by: EnderIce2 <enderice2@protonmail.com>
2025-04-04 10:55:44 +00:00
5c1c26b135
refactor(kernel): use default constructor for std::exception class
Signed-off-by: EnderIce2 <enderice2@protonmail.com>
2025-04-04 10:54:33 +00:00
a333d8aa7c
refactor(kernel): change Spawn function parameter type from char* to const char*
Signed-off-by: EnderIce2 <enderice2@protonmail.com>
2025-04-04 10:53:40 +00:00
f054e9976a
build: increase qemu debug RAM to 1GB
Signed-off-by: EnderIce2 <enderice2@protonmail.com>
2025-04-04 10:50:39 +00:00
f87c3d7e11
feat(kernel/tty): add TCSETS
Signed-off-by: EnderIce2 <enderice2@protonmail.com>
2025-04-04 04:14:19 +00:00
86 changed files with 2736 additions and 732 deletions

View File

@ -138,13 +138,71 @@ jobs:
sudo touch /run/user/1000/pulse/native
echo "XAUTHORITY=/tmp/.Xauthority" >> $GITHUB_ENV
- name: Run make ci-build in dev container
- name: Build AMD64 Debug
if: always()
uses: devcontainers/ci@v0.3
with:
push: never
runCmd: /usr/bin/make ci-build
runCmd: /usr/bin/make __ci-amd64-debug
- name: Build AMD64 Release
if: always()
uses: devcontainers/ci@v0.3
with:
push: never
runCmd: /usr/bin/make __ci-amd64-release
- name: Build i386 Debug
if: always()
uses: devcontainers/ci@v0.3
with:
push: never
runCmd: /usr/bin/make __ci-i386-debug
- name: Build i386 Release
if: always()
uses: devcontainers/ci@v0.3
with:
push: never
runCmd: /usr/bin/make __ci-i386-release
- name: Build ARM Debug
if: always()
uses: devcontainers/ci@v0.3
with:
push: never
runCmd: /usr/bin/make __ci-arm-debug
- name: Build ARM Release
if: always()
uses: devcontainers/ci@v0.3
with:
push: never
runCmd: /usr/bin/make __ci-arm-release
- name: Build AArch64 Debug
if: always()
uses: devcontainers/ci@v0.3
with:
push: never
runCmd: /usr/bin/make __ci-aarch64-debug
- name: Build AArch64 Release
if: always()
uses: devcontainers/ci@v0.3
with:
push: never
runCmd: /usr/bin/make __ci-aarch64-release
- name: Build Prepare Archive
if: always()
uses: devcontainers/ci@v0.3
with:
push: never
runCmd: /usr/bin/make __ci-prepare-archive
- name: Upload Artifact
if: always()
uses: actions/upload-artifact@v4
with:
name: Fennix

2
.gitignore vendored
View File

@ -4,7 +4,7 @@ tmp_rootfs
rootfs/usr/include/*
!rootfs/usr/include/.gitkeep
doxygen-doc
rootfs.tar
rootfs.tar.gz
.dccache
*.log
*.log.*

251
.vscode/tasks.json vendored
View File

@ -6,6 +6,7 @@
"type": "shell",
"command": "make clean",
"isBackground": false,
"hide": false,
"group": {
"kind": "build",
"isDefault": false
@ -29,6 +30,7 @@
"type": "shell",
"command": "make build",
"isBackground": false,
"hide": false,
"group": {
"kind": "build",
"isDefault": false
@ -52,6 +54,7 @@
"type": "shell",
"command": "make qemu",
"isBackground": false,
"hide": false,
"dependsOn": [
"Build"
],
@ -78,6 +81,7 @@
"type": "shell",
"command": "make -C ../ build_bootloader",
"isBackground": false,
"hide": true,
"group": {
"kind": "build",
"isDefault": false
@ -100,6 +104,7 @@
"type": "shell",
"command": "make -C ../ build_kernel",
"isBackground": false,
"hide": true,
"dependsOn": [
"Build Bootloader"
],
@ -125,6 +130,7 @@
"type": "shell",
"command": "make -C ../ build_drivers",
"isBackground": false,
"hide": true,
"dependsOn": [
"Build Kernel"
],
@ -150,6 +156,7 @@
"type": "shell",
"command": "make -C ../ build_userspace",
"isBackground": false,
"hide": true,
"dependsOn": [
"Build Drivers"
],
@ -175,6 +182,7 @@
"type": "shell",
"command": "make -C ../ build_image",
"isBackground": false,
"hide": true,
"dependsOn": [
"Build Userspace"
],
@ -242,6 +250,249 @@
]
}
}
},
{
"label": "CI AMD64 Debug",
"type": "shell",
"command": "make __ci-amd64-debug",
"isBackground": false,
"hide": true,
"dependsOn": [
"Clean"
],
"group": {
"kind": "build",
"isDefault": false
},
"presentation": {
"reveal": "always",
"panel": "shared"
},
"options": {
"cwd": "${workspaceFolder}/../",
"shell": {
"executable": "bash",
"args": [
"-c"
]
}
}
},
{
"label": "CI AMD64 Release",
"type": "shell",
"command": "make __ci-amd64-release",
"isBackground": false,
"hide": true,
"dependsOn": [
"CI AMD64 Debug"
],
"group": {
"kind": "build",
"isDefault": false
},
"presentation": {
"reveal": "always",
"panel": "shared"
},
"options": {
"cwd": "${workspaceFolder}/../",
"shell": {
"executable": "bash",
"args": [
"-c"
]
}
}
},
{
"label": "CI i386 Debug",
"type": "shell",
"command": "make __ci-i386-debug",
"isBackground": false,
"hide": true,
"dependsOn": [
"CI AMD64 Release"
],
"group": {
"kind": "build",
"isDefault": false
},
"presentation": {
"reveal": "always",
"panel": "shared"
},
"options": {
"cwd": "${workspaceFolder}/../",
"shell": {
"executable": "bash",
"args": [
"-c"
]
}
}
},
{
"label": "CI i386 Release",
"type": "shell",
"command": "make __ci-i386-release",
"isBackground": false,
"hide": true,
"dependsOn": [
"CI i386 Debug"
],
"group": {
"kind": "build",
"isDefault": false
},
"presentation": {
"reveal": "always",
"panel": "shared"
},
"options": {
"cwd": "${workspaceFolder}/../",
"shell": {
"executable": "bash",
"args": [
"-c"
]
}
}
},
{
"label": "CI ARM Debug",
"type": "shell",
"command": "make __ci-arm-debug",
"isBackground": false,
"hide": true,
"dependsOn": [
"CI i386 Release"
],
"group": {
"kind": "build",
"isDefault": false
},
"presentation": {
"reveal": "always",
"panel": "shared"
},
"options": {
"cwd": "${workspaceFolder}/../",
"shell": {
"executable": "bash",
"args": [
"-c"
]
}
}
},
{
"label": "CI ARM Release",
"type": "shell",
"command": "make __ci-arm-release",
"isBackground": false,
"hide": true,
"dependsOn": [
"CI ARM Debug"
],
"group": {
"kind": "build",
"isDefault": false
},
"presentation": {
"reveal": "always",
"panel": "shared"
},
"options": {
"cwd": "${workspaceFolder}/../",
"shell": {
"executable": "bash",
"args": [
"-c"
]
}
}
},
{
"label": "CI AARCH64 Debug",
"type": "shell",
"command": "make __ci-aarch64-debug",
"isBackground": false,
"hide": true,
"dependsOn": [
"CI ARM Release"
],
"group": {
"kind": "build",
"isDefault": false
},
"presentation": {
"reveal": "always",
"panel": "shared"
},
"options": {
"cwd": "${workspaceFolder}/../",
"shell": {
"executable": "bash",
"args": [
"-c"
]
}
}
},
{
"label": "CI AARCH64 Release",
"type": "shell",
"command": "make __ci-aarch64-release",
"isBackground": false,
"hide": true,
"dependsOn": [
"CI AARCH64 Debug"
],
"group": {
"kind": "build",
"isDefault": false
},
"presentation": {
"reveal": "always",
"panel": "shared"
},
"options": {
"cwd": "${workspaceFolder}/../",
"shell": {
"executable": "bash",
"args": [
"-c"
]
}
}
},
{
"label": "Test CI Build",
"type": "shell",
"command": "make __ci-restore-config",
"isBackground": false,
"dependsOn": [
"CI AARCH64 Release",
"clean"
],
"group": {
"kind": "build",
"isDefault": false
},
"presentation": {
"reveal": "always",
"panel": "shared"
},
"options": {
"cwd": "${workspaceFolder}/../",
"shell": {
"executable": "bash",
"args": [
"-c"
]
}
}
}
]
}

View File

@ -7,9 +7,8 @@
"settings": {
"terminal.integrated.cwd": "../",
"debug.allowBreakpointsEverywhere": true,
"git.alwaysSignOff": true,
"git.defaultBranchName": "master",
"git.openRepositoryInParentFolders": "always",
"C_Cpp.autoAddFileAssociations": false
"C_Cpp.autoAddFileAssociations": false,
}
}
}

View File

@ -7,9 +7,8 @@
"settings": {
"terminal.integrated.cwd": "../",
"debug.allowBreakpointsEverywhere": true,
"git.alwaysSignOff": true,
"git.defaultBranchName": "master",
"git.openRepositoryInParentFolders": "always",
"C_Cpp.autoAddFileAssociations": false
"C_Cpp.autoAddFileAssociations": false,
}
}
}

View File

@ -7,23 +7,6 @@
"settings": {
"terminal.integrated.cwd": "../",
"debug.allowBreakpointsEverywhere": true,
"editor.tabCompletion": "on",
"diffEditor.codeLens": true,
"editor.quickSuggestionsDelay": 100,
"zenMode.hideLineNumbers": false,
"zenMode.hideActivityBar": false,
"zenMode.hideStatusBar": true,
"zenMode.centerLayout": true,
"zenMode.fullScreen": true,
"zenMode.restore": true,
"zenMode.silentNotifications": true,
"window.commandCenter": false,
"window.density.editorTabHeight": "default",
"editor.cursorBlinking": "blink",
"editor.cursorSmoothCaretAnimation": "on",
"editor.cursorStyle": "line",
"editor.cursorWidth": 2,
"git.alwaysSignOff": true,
"git.defaultBranchName": "master",
"git.openRepositoryInParentFolders": "always",
"C_Cpp.autoAddFileAssociations": false,
@ -37,7 +20,10 @@
"kernel/drivers",
"kernel/elf",
"kernel/scheduler",
"kernel/tty"
"kernel/tty",
"kernel/std",
"kernel/vfs",
"kernel/memory"
]
}
}

View File

@ -7,7 +7,6 @@
"settings": {
"terminal.integrated.cwd": "../",
"debug.allowBreakpointsEverywhere": true,
"git.alwaysSignOff": true,
"git.defaultBranchName": "master",
"git.openRepositoryInParentFolders": "always",
"C_Cpp.autoAddFileAssociations": false,

View File

@ -6,9 +6,8 @@
],
"settings": {
"debug.allowBreakpointsEverywhere": true,
"git.alwaysSignOff": true,
"git.defaultBranchName": "master",
"git.openRepositoryInParentFolders": "always",
"C_Cpp.autoAddFileAssociations": false
}
}
}

View File

@ -6,14 +6,14 @@
],
"settings": {
"debug.allowBreakpointsEverywhere": true,
"git.alwaysSignOff": true,
"git.defaultBranchName": "master",
"git.openRepositoryInParentFolders": "always",
"C_Cpp.autoAddFileAssociations": false,
"conventionalCommits.scopes": [
"rootfs",
"tools",
"devcontainer"
"devcontainer",
"workspace"
]
}
}

View File

@ -92,7 +92,7 @@ __naked __used __no_stack_protector void InitLimine()
asmv("jmp InitLimineAfterStack");
}
nsa NIF void InitLimineAfterStack()
nsa nif void InitLimineAfterStack()
{
struct BootInfo binfo = {};
struct limine_bootloader_info_response *BootloaderInfoResponse = BootloaderInfoRequest.response;

View File

@ -38,14 +38,14 @@ union __attribute__((packed)) PageTableEntry
};
uint64_t raw;
__always_inline inline nsa NIF void SetAddress(uintptr_t _Address)
__always_inline inline nsa nif void SetAddress(uintptr_t _Address)
{
_Address &= 0x000000FFFFFFFFFF;
this->raw &= 0xFFF0000000000FFF;
this->raw |= (_Address << 12);
}
__always_inline inline nsa NIF uintptr_t GetAddress() { return (this->raw & 0x000FFFFFFFFFF000) >> 12; }
__always_inline inline nsa nif uintptr_t GetAddress() { return (this->raw & 0x000FFFFFFFFFF000) >> 12; }
};
struct __attribute__((packed)) PageTableEntryPtr
@ -72,14 +72,14 @@ union __attribute__((packed)) PageDirectoryEntry
};
uint64_t raw;
__always_inline inline nsa NIF void SetAddress(uintptr_t _Address)
__always_inline inline nsa nif void SetAddress(uintptr_t _Address)
{
_Address &= 0x000000FFFFFFFFFF;
this->raw &= 0xFFF0000000000FFF;
this->raw |= (_Address << 12);
}
__always_inline inline nsa NIF uintptr_t GetAddress() { return (this->raw & 0x000FFFFFFFFFF000) >> 12; }
__always_inline inline nsa nif uintptr_t GetAddress() { return (this->raw & 0x000FFFFFFFFFF000) >> 12; }
};
struct __attribute__((packed)) PageDirectoryEntryPtr
@ -106,14 +106,14 @@ union __attribute__((packed)) PageDirectoryPointerTableEntry
};
uint64_t raw;
__always_inline inline nsa NIF void SetAddress(uintptr_t _Address)
__always_inline inline nsa nif void SetAddress(uintptr_t _Address)
{
_Address &= 0x000000FFFFFFFFFF;
this->raw &= 0xFFF0000000000FFF;
this->raw |= (_Address << 12);
}
__always_inline inline nsa NIF uintptr_t GetAddress() { return (this->raw & 0x000FFFFFFFFFF000) >> 12; }
__always_inline inline nsa nif uintptr_t GetAddress() { return (this->raw & 0x000FFFFFFFFFF000) >> 12; }
};
struct __attribute__((packed)) PageDirectoryPointerTableEntryPtr
@ -140,14 +140,14 @@ union __attribute__((packed)) PageMapLevel4
};
uint64_t raw;
__always_inline inline nsa NIF void SetAddress(uintptr_t _Address)
__always_inline inline nsa nif void SetAddress(uintptr_t _Address)
{
_Address &= 0x000000FFFFFFFFFF;
this->raw &= 0xFFF0000000000FFF;
this->raw |= (_Address << 12);
}
__always_inline inline nsa NIF uintptr_t GetAddress() { return (this->raw & 0x000FFFFFFFFFF000) >> 12; }
__always_inline inline nsa nif uintptr_t GetAddress() { return (this->raw & 0x000FFFFFFFFFF000) >> 12; }
};
struct PageTable4
@ -161,7 +161,7 @@ extern uintptr_t _kernel_start, _kernel_end;
__attribute__((section(".bootstrap.data"))) static PageTable4 *BPTable = (PageTable4 *)BootPageTable;
__attribute__((section(".bootstrap.data"))) static size_t BPT_Allocated = 0x4000;
__always_inline inline nsa NIF void *RequestPage()
__always_inline inline nsa nif void *RequestPage()
{
void *Page = (void *)(BootPageTable + BPT_Allocated);
BPT_Allocated += 0x1000;
@ -180,7 +180,7 @@ public:
uintptr_t PDPTEIndex = 0;
uintptr_t PDEIndex = 0;
uintptr_t PTEIndex = 0;
__always_inline inline nsa NIF PageMapIndexer(uintptr_t VirtualAddress)
__always_inline inline nsa nif PageMapIndexer(uintptr_t VirtualAddress)
{
uintptr_t Address = VirtualAddress;
Address >>= 12;
@ -194,7 +194,7 @@ public:
}
};
__attribute__((section(".bootstrap.text"))) nsa NIF void MB2_64_Map(void *VirtualAddress, void *PhysicalAddress, uint64_t Flags)
__attribute__((section(".bootstrap.text"))) nsa nif void MB2_64_Map(void *VirtualAddress, void *PhysicalAddress, uint64_t Flags)
{
PageMapIndexer Index = PageMapIndexer((uintptr_t)VirtualAddress);
// Clear any flags that are not 1 << 0 (Present) - 1 << 5 (Accessed) because rest are for page table entries only
@ -280,7 +280,7 @@ __attribute__((section(".bootstrap.text"))) nsa NIF void MB2_64_Map(void *Virtua
: "memory");
}
EXTERNC __attribute__((section(".bootstrap.text"))) nsa NIF __attribute__((section(".bootstrap.text"))) void UpdatePageTable64()
EXTERNC __attribute__((section(".bootstrap.text"))) nsa nif __attribute__((section(".bootstrap.text"))) void UpdatePageTable64()
{
BPTable = (PageTable4 *)BootPageTable;

View File

@ -20,6 +20,7 @@
#include <memory.hpp>
#include <stropts.h>
#include <string.h>
#include <thread>
#include <ini.h>
#include "../kernel.h"
@ -112,6 +113,32 @@ namespace KernelConsole
FontRenderer Renderer;
ConsoleTerminal *Terminals[16] = {nullptr};
std::atomic<ConsoleTerminal *> CurrentTerminal = nullptr;
void paint_blinker(bool Enable)
{
if (CurrentTerminal == nullptr)
return;
ConsoleTerminal *term = CurrentTerminal.load();
ConsoleTerminal::Blinker &blinker = term->Blink;
TerminalCell *cell = term->Term->GetCell(Renderer.Cursor.X + Renderer.Cursor.Y * term->Term->GetWinsize()->ws_row);
uint32_t bgColor = cell->attr.Bright ? TermBrightColors[cell->attr.Background] : TermColors[cell->attr.Background];
Renderer.Paint(Renderer.Cursor.X, Renderer.Cursor.Y, blinker.Character, Enable ? blinker.Color : bgColor, bgColor);
}
void paint_blinker_thread()
{
bool blink = false;
while (true)
{
paint_blinker(blink);
blink = !blink;
std::this_thread::sleep_for(std::chrono::milliseconds(CurrentTerminal.load()->Blink.Delay));
}
}
void paint_callback(TerminalCell *cell, long x, long y)
{
if (cell->attr.Bright)
@ -123,11 +150,9 @@ namespace KernelConsole
void cursor_callback(TerminalCursor *cur)
{
Renderer.Cursor = {cur->X, cur->Y};
paint_blinker(false);
}
VirtualTerminal *Terminals[16] = {nullptr};
std::atomic<VirtualTerminal *> CurrentTerminal = nullptr;
bool SetTheme(std::string Theme)
{
FileNode *rn = fs->GetByPath("/sys/cfg/term", thisProcess->Info.RootNode);
@ -267,24 +292,15 @@ namespace KernelConsole
size_t Rows = Display->GetWidth / Renderer.CurrentFont->GetInfo().Width;
size_t Cols = Display->GetHeight / Renderer.CurrentFont->GetInfo().Height;
debug("Terminal size: %ux%u", Rows, Cols);
Terminals[0] = new VirtualTerminal(Rows, Cols, Display->GetWidth, Display->GetHeight, paint_callback, cursor_callback);
Terminals[0]->Clear(0, 0, Rows, Cols - 1);
Terminals[0] = new ConsoleTerminal;
Terminals[0]->Term = new VirtualTerminal(Rows, Cols, Display->GetWidth, Display->GetHeight, paint_callback, cursor_callback);
Terminals[0]->Term->Clear(0, 0, Rows, Cols - 1);
CurrentTerminal.store(Terminals[0], std::memory_order_release);
}
void LateInit()
void LoadConsoleConfig(std::string &Config)
{
FileNode *rn = fs->GetByPath("/sys/cfg/term", thisProcess->Info.RootNode);
if (rn == nullptr)
return;
kstat st{};
rn->Stat(&st);
char *sh = new char[st.Size];
rn->Read(sh, st.Size, 0);
ini_t *ini = ini_load(sh, NULL);
ini_t *ini = ini_load(Config.c_str(), NULL);
int general = ini_find_section(ini, "general", NULL);
int cursor = ini_find_section(ini, "cursor", NULL);
assert(general != INI_NOT_FOUND && cursor != INI_NOT_FOUND);
@ -292,16 +308,22 @@ namespace KernelConsole
int themeIndex = ini_find_property(ini, general, "theme", NULL);
assert(themeIndex != INI_NOT_FOUND);
int cursorColor = ini_find_property(ini, cursor, "color", NULL);
int cursorBlink = ini_find_property(ini, cursor, "blink", NULL);
assert(cursorColor != INI_NOT_FOUND && cursorBlink != INI_NOT_FOUND);
int cursorColor = ini_find_property(ini, cursor, "color", NULL);
int cursorChar = ini_find_property(ini, cursor, "char", NULL);
int cursorDelay = ini_find_property(ini, cursor, "delay", NULL);
assert(cursorBlink != INI_NOT_FOUND && cursorColor != INI_NOT_FOUND && cursorChar != INI_NOT_FOUND && cursorDelay != INI_NOT_FOUND);
const char *colorThemeStr = ini_property_value(ini, general, themeIndex);
const char *cursorColorStr = ini_property_value(ini, cursor, cursorColor);
const char *cursorBlinkStr = ini_property_value(ini, cursor, cursorBlink);
const char *cursorCharStr = ini_property_value(ini, cursor, cursorChar);
const char *cursorDelayStr = ini_property_value(ini, cursor, cursorDelay);
debug("colorThemeStr=%s", colorThemeStr);
debug("cursorColorStr=%s", cursorColorStr);
debug("cursorBlinkStr=%s", cursorBlinkStr);
debug("cursorColorStr=%s", cursorColorStr);
debug("cursorCharStr=%s", cursorCharStr);
debug("cursorDelayStr=%s", cursorDelayStr);
auto getColorComponent = [](const char *str, int &index) -> int
{
@ -335,11 +357,36 @@ namespace KernelConsole
uint32_t blinkColor = 0xFFFFFF;
if (cursorColorStr != 0)
blinkColor = parseColor(cursorColorStr);
fixme("cursor blink with colors %X", blinkColor);
debug("cursor blink with colors %X and char '%s' and delay %s", blinkColor, cursorCharStr, cursorDelayStr);
Terminals[0]->Blink.Enabled = true;
Terminals[0]->Blink.Color = blinkColor;
Terminals[0]->Blink.Character = *cursorCharStr;
Terminals[0]->Blink.Delay = atoi(cursorDelayStr);
}
ini_destroy(ini);
delete[] sh;
}
void LateInit()
{
FileNode *rn = fs->GetByPath("/sys/cfg/term", thisProcess->Info.RootNode);
if (rn == nullptr)
return;
{
kstat st;
rn->Stat(&st);
std::string cfg;
cfg.reserve(st.Size);
rn->Read(cfg.data(), st.Size, 0);
LoadConsoleConfig(cfg);
}
if (Terminals[0]->Blink.Enabled)
{
std::thread t = std::thread(paint_blinker_thread);
t.detach();
}
#ifdef DEBUG
// __test_themes();

View File

@ -27,12 +27,12 @@ NewLock(DebuggerLock);
extern bool serialports[8];
EXTERNC NIF void uart_wrapper(char c, void *)
EXTERNC nif void uart_wrapper(char c, void *)
{
uart.DebugWrite(c);
}
static inline NIF bool WritePrefix(DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, va_list args)
static inline nif bool WritePrefix(DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, va_list args)
{
const char *DbgLvlString;
switch (Level)
@ -79,7 +79,7 @@ static inline NIF bool WritePrefix(DebugLevel Level, const char *File, int Line,
namespace SysDbg
{
NIF void Write(DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...)
nif void Write(DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...)
{
va_list args;
va_start(args, Format);
@ -92,7 +92,7 @@ namespace SysDbg
va_end(args);
}
NIF void WriteLine(DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...)
nif void WriteLine(DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...)
{
va_list args;
va_start(args, Format);
@ -106,7 +106,7 @@ namespace SysDbg
uart_wrapper('\n', nullptr);
}
NIF void LockedWrite(DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...)
nif void LockedWrite(DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...)
{
SmartTimeoutLock(DebuggerLock, 1000);
va_list args;
@ -120,7 +120,7 @@ namespace SysDbg
va_end(args);
}
NIF void LockedWriteLine(DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...)
nif void LockedWriteLine(DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...)
{
SmartTimeoutLock(DebuggerLock, 1000);
va_list args;
@ -137,7 +137,7 @@ namespace SysDbg
}
// C compatibility
extern "C" NIF void SysDbgWrite(enum DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...)
extern "C" nif void SysDbgWrite(enum DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...)
{
va_list args;
va_start(args, Format);
@ -151,7 +151,7 @@ extern "C" NIF void SysDbgWrite(enum DebugLevel Level, const char *File, int Lin
}
// C compatibility
extern "C" NIF void SysDbgWriteLine(enum DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...)
extern "C" nif void SysDbgWriteLine(enum DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...)
{
va_list args;
va_start(args, Format);
@ -166,7 +166,7 @@ extern "C" NIF void SysDbgWriteLine(enum DebugLevel Level, const char *File, int
}
// C compatibility
extern "C" NIF void SysDbgLockedWrite(enum DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...)
extern "C" nif void SysDbgLockedWrite(enum DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...)
{
SmartTimeoutLock(DebuggerLock, 1000);
va_list args;
@ -181,7 +181,7 @@ extern "C" NIF void SysDbgLockedWrite(enum DebugLevel Level, const char *File, i
}
// C compatibility
extern "C" NIF void SysDbgLockedWriteLine(enum DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...)
extern "C" nif void SysDbgLockedWriteLine(enum DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...)
{
SmartTimeoutLock(DebuggerLock, 1000);
va_list args;

View File

@ -363,11 +363,11 @@ namespace Driver
driverInfo.License = (const char *)(Drv.BaseAddress + (uintptr_t)driverInfo.License);
}
for (size_t h = 0; h < (sht_symtab.sh_size / sizeof(Elf64_Sym)); h++)
for (size_t h = 0; h < (sht_symtab.sh_size / sizeof(Elf_Sym)); h++)
{
Elf64_Sym symEntry{};
uintptr_t symOffset = sht_symtab.sh_offset + (h * sizeof(Elf64_Sym));
File->Read(&symEntry, sizeof(Elf64_Sym), symOffset);
Elf_Sym symEntry{};
uintptr_t symOffset = sht_symtab.sh_offset + (h * sizeof(Elf_Sym));
File->Read(&symEntry, sizeof(Elf_Sym), symOffset);
if (symEntry.st_name == 0)
continue;
@ -477,10 +477,10 @@ namespace Driver
{
AssertReturnError(relaSize != nullptr, -ENOEXEC);
Elf64_Rela *rela = (Elf64_Rela *)(Drv.BaseAddress + dyn->d_un.d_ptr);
for (size_t i = 0; i < (relaSize->d_un.d_val / sizeof(Elf64_Rela)); i++)
Elf_Rela *rela = (Elf_Rela *)(Drv.BaseAddress + dyn->d_un.d_ptr);
for (size_t i = 0; i < (relaSize->d_un.d_val / sizeof(Elf_Rela)); i++)
{
Elf64_Rela *r = &rela[i];
Elf_Rela *r = &rela[i];
uintptr_t *reloc = (uintptr_t *)(Drv.BaseAddress + r->r_offset);
uintptr_t relocTarget = 0;
@ -500,8 +500,7 @@ namespace Driver
}
default:
{
fixme("Unhandled relocation type: %#lx",
ELF64_R_TYPE(r->r_info));
fixme("Unhandled relocation type: %#lx", ELF_R_TYPE(r->r_info));
break;
}
}
@ -517,24 +516,24 @@ namespace Driver
{
AssertReturnError(pltrelSize != nullptr, -ENOEXEC);
std::vector<Elf64_Dyn> symtab = Execute::ELFGetDynamicTag(File, DT_SYMTAB);
Elf64_Sym *symbols = (Elf64_Sym *)((uintptr_t)Drv.BaseAddress + symtab[0].d_un.d_ptr);
std::vector<Elf_Dyn> symtab = Execute::ELFGetDynamicTag(File, DT_SYMTAB);
Elf_Sym *symbols = (Elf_Sym *)((uintptr_t)Drv.BaseAddress + symtab[0].d_un.d_ptr);
std::vector<Elf64_Dyn> StrTab = Execute::ELFGetDynamicTag(File, DT_STRTAB);
std::vector<Elf_Dyn> StrTab = Execute::ELFGetDynamicTag(File, DT_STRTAB);
char *dynStr = (char *)((uintptr_t)Drv.BaseAddress + StrTab[0].d_un.d_ptr);
Elf64_Rela *rela = (Elf64_Rela *)(Drv.BaseAddress + dyn->d_un.d_ptr);
for (size_t i = 0; i < (pltrelSize->d_un.d_val / sizeof(Elf64_Rela)); i++)
Elf_Rela *rela = (Elf_Rela *)(Drv.BaseAddress + dyn->d_un.d_ptr);
for (size_t i = 0; i < (pltrelSize->d_un.d_val / sizeof(Elf_Rela)); i++)
{
Elf64_Rela *r = &rela[i];
Elf_Rela *r = &rela[i];
uintptr_t *reloc = (uintptr_t *)(Drv.BaseAddress + r->r_offset);
switch (ELF64_R_TYPE(r->r_info))
switch (ELF_R_TYPE(r->r_info))
{
case R_X86_64_JUMP_SLOT:
{
Elf64_Xword symIndex = ELF64_R_SYM(r->r_info);
Elf64_Sym *sym = symbols + symIndex;
Elf_Xword symIndex = ELF_R_SYM(r->r_info);
Elf_Sym *sym = symbols + symIndex;
const char *symName = dynStr + sym->st_name;
debug("Resolving symbol %s", symName);
@ -544,8 +543,7 @@ namespace Driver
}
default:
{
fixme("Unhandled relocation type: %#lx",
ELF64_R_TYPE(r->r_info));
fixme("Unhandled relocation type: %#lx", ELF_R_TYPE(r->r_info));
break;
}
}

View File

@ -331,6 +331,80 @@ namespace Driver
: ScanCodeConversionTableLower[ScanCode];
}
char GetControlCharacter(KeyScanCodes ScanCode)
{
ScanCode = static_cast<KeyScanCodes>(static_cast<int>(ScanCode) & 0x7F); /* Remove KEY_PRESSED bit */
switch (ScanCode)
{
case KEY_2:
return 0x00; /* Ctrl-@ (NUL) */
case KEY_A:
return 0x01; /* Ctrl-A (SOH) */
case KEY_B:
return 0x02; /* Ctrl-B (STX) */
case KEY_C:
return 0x03; /* Ctrl-C (ETX) */
case KEY_D:
return 0x04; /* Ctrl-D (EOT) */
case KEY_E:
return 0x05; /* Ctrl-E (ENQ) */
case KEY_F:
return 0x06; /* Ctrl-F (ACK) */
case KEY_G:
return 0x07; /* Ctrl-G (BEL) */
case KEY_H:
return 0x08; /* Ctrl-H (BS) */
case KEY_I:
return 0x09; /* Ctrl-I (HT) */
case KEY_J:
return 0x0A; /* Ctrl-J (LF) */
case KEY_K:
return 0x0B; /* Ctrl-K (VT) */
case KEY_L:
return 0x0C; /* Ctrl-L (FF) */
case KEY_M:
return 0x0D; /* Ctrl-M (CR) */
case KEY_N:
return 0x0E; /* Ctrl-N (SO) */
case KEY_O:
return 0x0F; /* Ctrl-O (SI) */
case KEY_P:
return 0x10; /* Ctrl-P (DLE) */
case KEY_Q:
return 0x11; /* Ctrl-Q (DC1) */
case KEY_R:
return 0x12; /* Ctrl-R (DC2) */
case KEY_S:
return 0x13; /* Ctrl-S (DC3) */
case KEY_T:
return 0x14; /* Ctrl-T (DC4) */
case KEY_U:
return 0x15; /* Ctrl-U (NAK) */
case KEY_V:
return 0x16; /* Ctrl-V (SYN) */
case KEY_W:
return 0x17; /* Ctrl-W (ETB) */
case KEY_X:
return 0x18; /* Ctrl-X (CAN) */
case KEY_Y:
return 0x19; /* Ctrl-Y (EM) */
case KEY_Z:
return 0x1A; /* Ctrl-Z (SUB) */
case KEY_LEFT_BRACKET:
return 0x1B; /* Ctrl-[ (ESC) */
case KEY_BACKSLASH:
return 0x1C; /* Ctrl-\ (FS) */
case KEY_RIGHT_BRACKET:
return 0x1D; /* Ctrl-] (GS) */
case KEY_6:
return 0x1E; /* Ctrl-^ (RS) */
case KEY_MINUS:
return 0x1F; /* Ctrl-_ (US) */
default:
return 0x00; /* Not a control character */
}
}
bool IsValidChar(uint8_t ScanCode)
{
ScanCode &= 0x7F; /* Remove KEY_PRESSED bit */

View File

@ -28,8 +28,7 @@
namespace Memory
{
__no_sanitize("alignment") void Physical::FindBitmapRegion(uintptr_t &BitmapAddress,
size_t &BitmapAddressSize)
__no_sanitize("alignment") void Physical::FindBitmapRegion(uintptr_t &BitmapAddress, size_t &BitmapAddressSize)
{
size_t BitmapSize = (size_t)(bInfo.Memory.Size / PAGE_SIZE) / 8 + 1;
@ -47,24 +46,19 @@ namespace Memory
uintptr_t RSDPStart = 0x0;
uintptr_t RSDPEnd = 0x0;
if (bInfo.Kernel.Symbols.Num &&
bInfo.Kernel.Symbols.EntSize &&
bInfo.Kernel.Symbols.Shndx)
if (bInfo.Kernel.Symbols.Num && bInfo.Kernel.Symbols.EntSize && bInfo.Kernel.Symbols.Shndx)
{
char *sections = r_cst(char *, bInfo.Kernel.Symbols.Sections);
SectionsStart = (uintptr_t)sections;
SectionsEnd = (uintptr_t)sections + bInfo.Kernel.Symbols.EntSize *
bInfo.Kernel.Symbols.Num;
SectionsEnd = (uintptr_t)sections + bInfo.Kernel.Symbols.EntSize * bInfo.Kernel.Symbols.Num;
for (size_t i = 0; i < bInfo.Kernel.Symbols.Num; ++i)
{
Elf_Shdr *sym = (Elf_Shdr *)&sections[bInfo.Kernel.Symbols.EntSize * i];
Elf_Shdr *str = (Elf_Shdr *)&sections[bInfo.Kernel.Symbols.EntSize *
sym->sh_link];
Elf_Shdr *str = (Elf_Shdr *)&sections[bInfo.Kernel.Symbols.EntSize * sym->sh_link];
if (sym->sh_type == SHT_SYMTAB &&
str->sh_type == SHT_STRTAB)
if (sym->sh_type == SHT_SYMTAB && str->sh_type == SHT_STRTAB)
{
Symbols = (uintptr_t)sym->sh_addr;
StringAddress = (uintptr_t)str->sh_addr;
@ -95,8 +89,7 @@ namespace Memory
if (Memory::Virtual().Check(ACPIPtr))
{
size_t TableSize = ((ACPIPtr->Length - sizeof(ACPI::ACPI::ACPIHeader)) /
(XSDT ? 8 : 4));
size_t TableSize = ((ACPIPtr->Length - sizeof(ACPI::ACPI::ACPIHeader)) / (XSDT ? 8 : 4));
debug("There are %d ACPI tables", TableSize);
}
#endif
@ -131,6 +124,7 @@ namespace Memory
{
uintptr_t Start;
uintptr_t End;
char Description[16];
};
auto SortAddresses = [](AddrRange *Array, size_t n)
@ -151,61 +145,57 @@ namespace Memory
AddrRange PtrArray[] =
{
{KernelStart,
KernelEnd},
{SectionsStart,
SectionsEnd},
{Symbols,
Symbols + SymbolSize},
{StringAddress,
StringAddress + StringSize},
{RSDPStart,
RSDPEnd},
{(uintptr_t)bInfo.Kernel.FileBase,
(uintptr_t)bInfo.Kernel.FileBase + bInfo.Kernel.Size},
{(uintptr_t)bInfo.Modules[0].Address,
(uintptr_t)bInfo.Modules[0].Address + bInfo.Modules[0].Size},
{(uintptr_t)bInfo.Modules[1].Address,
(uintptr_t)bInfo.Modules[1].Address + bInfo.Modules[1].Size},
{(uintptr_t)bInfo.Modules[2].Address,
(uintptr_t)bInfo.Modules[2].Address + bInfo.Modules[2].Size},
{(uintptr_t)bInfo.Modules[3].Address,
(uintptr_t)bInfo.Modules[3].Address + bInfo.Modules[3].Size},
{KernelStart, KernelEnd, "kernel"},
{SectionsStart, SectionsEnd, "sections"},
{Symbols, Symbols + SymbolSize, "symbols"},
{StringAddress, StringAddress + StringSize, "string"},
{RSDPStart, RSDPEnd, "rsdp"},
{(uintptr_t)bInfo.Kernel.FileBase, (uintptr_t)bInfo.Kernel.FileBase + bInfo.Kernel.Size, "file"},
{(uintptr_t)bInfo.Modules[0].Address, (uintptr_t)bInfo.Modules[0].Address + bInfo.Modules[0].Size, "module 0"},
{(uintptr_t)bInfo.Modules[1].Address, (uintptr_t)bInfo.Modules[1].Address + bInfo.Modules[1].Size, "module 1"},
{(uintptr_t)bInfo.Modules[2].Address, (uintptr_t)bInfo.Modules[2].Address + bInfo.Modules[2].Size, "module 2"},
{(uintptr_t)bInfo.Modules[3].Address, (uintptr_t)bInfo.Modules[3].Address + bInfo.Modules[3].Size, "module 3"},
/* MAX_MODULES == 4 */
};
SortAddresses(PtrArray, sizeof(PtrArray) / sizeof(PtrArray[0]));
uintptr_t MaxEnd = RegionAddress;
for (size_t i = 0; i < sizeof(PtrArray) / sizeof(PtrArray[0]); i++)
{
if (PtrArray[i].Start == 0x0)
{
debug("skipping %#lx %zu %s", PtrArray[i].Start, i, PtrArray[i].Description);
continue;
}
uintptr_t Start = PtrArray[i].Start;
uintptr_t End = PtrArray[i].End;
debug("%#lx - %#lx", Start, End);
debug("[%s] %#lx - %#lx", PtrArray[i].Description, Start, End);
if (RegionAddress >= Start &&
End <= (RegionAddress + RegionSize))
if ((Start < (RegionAddress + RegionSize)) && (End > RegionAddress))
{
BitmapAddress = End;
BitmapAddressSize = RegionSize - (End - RegionAddress);
if (End > MaxEnd)
MaxEnd = End;
}
}
if ((BitmapSize + 0x100) > BitmapAddressSize)
if (MaxEnd >= RegionAddress && MaxEnd < (RegionAddress + RegionSize))
{
debug("Region %p-%p (%d MiB) is too small for bitmap.",
(void *)BitmapAddress,
(void *)(BitmapAddress + BitmapAddressSize),
TO_MiB(BitmapAddressSize));
continue;
}
BitmapAddress = MaxEnd;
BitmapAddressSize = RegionAddress + RegionSize - MaxEnd;
debug("Found free memory for bitmap: %p (%d MiB)",
(void *)BitmapAddress,
TO_MiB(BitmapAddressSize));
break;
debug("BitmapAddress = %#lx; Size = %zu", BitmapAddress, BitmapAddressSize);
if ((BitmapSize + 0x100) > BitmapAddressSize)
{
debug("Region %#lx-%#lx (%d MiB) is too small for bitmap.", BitmapAddress, BitmapAddress + BitmapAddressSize, TO_MiB(BitmapAddressSize));
continue;
}
debug("Found free memory for bitmap: %#lx (%d MiB)", BitmapAddress, TO_MiB(BitmapAddressSize));
break;
}
}
}
}

View File

@ -52,7 +52,7 @@ Xalloc::V1 *XallocV1Allocator = nullptr;
Xalloc::V2 *XallocV2Allocator = nullptr;
#ifdef DEBUG
NIF void tracepagetable(PageTable *pt)
nif void tracepagetable(PageTable *pt)
{
for (int i = 0; i < 512; i++)
{
@ -71,7 +71,7 @@ NIF void tracepagetable(PageTable *pt)
}
#endif
NIF void MapEntries(PageTable *PT)
nif void MapEntries(PageTable *PT)
{
debug("mapping %d memory entries", bInfo.Memory.Entries);
Virtual vmm = Virtual(PT);
@ -89,7 +89,7 @@ NIF void MapEntries(PageTable *PT)
vmm.Unmap((void *)0);
}
NIF void MapFramebuffer(PageTable *PT)
nif void MapFramebuffer(PageTable *PT)
{
debug("Mapping Framebuffer");
Virtual vmm = Virtual(PT);
@ -123,7 +123,7 @@ NIF void MapFramebuffer(PageTable *PT)
}
}
NIF void MapKernel(PageTable *PT)
nif void MapKernel(PageTable *PT)
{
debug("Mapping Kernel");
@ -237,7 +237,7 @@ NIF void MapKernel(PageTable *PT)
info("Cannot determine kernel file address. Ignoring.");
}
NIF void CreatePageTable(PageTable *pt)
nif void CreatePageTable(PageTable *pt)
{
static int check_cpuid = 0;
@ -286,7 +286,7 @@ NIF void CreatePageTable(PageTable *pt)
#endif
}
NIF void InitializeMemoryManagement()
nif void InitializeMemoryManagement()
{
#ifdef DEBUG
#ifndef __i386__
@ -340,7 +340,7 @@ NIF void InitializeMemoryManagement()
KernelAllocator.Init();
debug("Memory Info:\n\n%lld MiB / %lld MiB (%lld MiB reserved)\n",
TO_MiB(KernelAllocator.GetUsedMemory()),
TO_MiB(KernelAllocator.GetTotalMemory()),
TO_MiB(KernelAllocator.GetTotalMemory() - KernelAllocator.GetReservedMemory()),
TO_MiB(KernelAllocator.GetReservedMemory()));
/* -- Debugging --
@ -361,8 +361,7 @@ NIF void InitializeMemoryManagement()
CreatePageTable(KernelPageTable);
trace("Applying new page table from address %#lx",
KernelPageTable);
trace("Applying new page table from address %#lx", KernelPageTable);
CPU::PageTable(KernelPageTable);
debug("Page table updated.");

View File

@ -264,7 +264,7 @@ namespace Memory
uintptr_t Index = ((uintptr_t)Address + (t * PAGE_SIZE)) / PAGE_SIZE;
if (unlikely(PageBitmap[Index] == true))
return;
continue;
if (PageBitmap.Set(Index, true))
{
@ -322,8 +322,7 @@ namespace Memory
SmartLock(this->MemoryLock);
uint64_t MemorySize = bInfo.Memory.Size;
debug("Memory size: %lld bytes (%ld pages)",
MemorySize, TO_PAGES(MemorySize));
debug("Memory size: %lld bytes (%ld pages)", MemorySize, TO_PAGES(MemorySize));
TotalMemory.store(MemorySize);
FreeMemory.store(MemorySize);
@ -338,16 +337,10 @@ namespace Memory
CPU::Stop();
}
debug("Initializing Bitmap at %p-%p (%d Bytes)",
BitmapAddress,
(void *)(BitmapAddress + BitmapSize),
BitmapSize);
debug("Initializing Bitmap at %#lx-%#lx (%zu Bytes)", BitmapAddress, BitmapAddress + BitmapSize, BitmapSize);
PageBitmap.Size = BitmapSize;
PageBitmap.Buffer = (uint8_t *)BitmapAddress;
for (size_t i = 0; i < BitmapSize; i++)
*(uint8_t *)(PageBitmap.Buffer + i) = 0;
memset((void *)BitmapAddress, 0, BitmapSize);
ReserveEssentials();
}

View File

@ -80,12 +80,9 @@ namespace Memory
{
char *sections = r_cst(char *, bInfo.Kernel.Symbols.Sections);
debug("Reserving sections region %#lx-%#lx...",
sections,
(void *)((uintptr_t)sections + bInfo.Kernel.Symbols.EntSize *
bInfo.Kernel.Symbols.Num));
sections, (uintptr_t)sections + bInfo.Kernel.Symbols.EntSize * bInfo.Kernel.Symbols.Num);
this->ReservePages(sections, TO_PAGES(bInfo.Kernel.Symbols.EntSize *
bInfo.Kernel.Symbols.Num));
this->ReservePages(sections, TO_PAGES(bInfo.Kernel.Symbols.EntSize * bInfo.Kernel.Symbols.Num));
Elf_Sym *Symbols = nullptr;
uint8_t *StringAddress = nullptr;
@ -101,11 +98,9 @@ namespace Memory
for (size_t i = 0; i < bInfo.Kernel.Symbols.Num; ++i)
{
Elf_Shdr *sym = (Elf_Shdr *)&sections[bInfo.Kernel.Symbols.EntSize * i];
Elf_Shdr *str = (Elf_Shdr *)&sections[bInfo.Kernel.Symbols.EntSize *
sym->sh_link];
Elf_Shdr *str = (Elf_Shdr *)&sections[bInfo.Kernel.Symbols.EntSize * sym->sh_link];
if (sym->sh_type == SHT_SYMTAB &&
str->sh_type == SHT_STRTAB)
if (sym->sh_type == SHT_SYMTAB && str->sh_type == SHT_STRTAB)
{
Symbols = (Elf_Sym *)sym->sh_addr;
StringAddress = (uint8_t *)str->sh_addr;
@ -145,8 +140,7 @@ namespace Memory
bInfo.Modules[i].Address,
(void *)((uintptr_t)bInfo.Modules[i].Address + bInfo.Modules[i].Size));
this->ReservePages((void *)bInfo.Modules[i].Address,
TO_PAGES(bInfo.Modules[i].Size));
this->ReservePages((void *)bInfo.Modules[i].Address, TO_PAGES(bInfo.Modules[i].Size));
}
#if defined(__amd64__) || defined(__i386__)

View File

@ -84,7 +84,7 @@ void paint_callback(TerminalCell *cell, long x, long y)
nsa void __printfWrapper(char c, void *)
{
KernelConsole::Terminals[15]->Process(c);
KernelConsole::Terminals[15]->Term->Process(c);
}
nsa void ExPrint(const char *Format, ...)
@ -162,7 +162,8 @@ nsa void InitFont()
{
size_t Cols = Display->GetWidth / CrashFontRenderer.CurrentFont->GetInfo().Width;
size_t Rows = Display->GetHeight / CrashFontRenderer.CurrentFont->GetInfo().Height;
Terminals[15] = new VirtualTerminal(Cols, Rows, Display->GetWidth, Display->GetHeight, paint_callback, nullptr);
Terminals[15] = new ConsoleTerminal;
Terminals[15]->Term = new VirtualTerminal(Cols, Rows, Display->GetWidth, Display->GetHeight, paint_callback, nullptr);
}
}
@ -372,7 +373,8 @@ nsa void BaseBufferStackError(bool Stack)
{
size_t Cols = Display->GetWidth / CrashFontRenderer.CurrentFont->GetInfo().Width;
size_t Rows = Display->GetHeight / CrashFontRenderer.CurrentFont->GetInfo().Height;
Terminals[15] = new VirtualTerminal(Cols, Rows, Display->GetWidth, Display->GetHeight, paint_callback, nullptr);
Terminals[15] = new ConsoleTerminal;
Terminals[15]->Term = new VirtualTerminal(Cols, Rows, Display->GetWidth, Display->GetHeight, paint_callback, nullptr);
}
ExceptionLock.store(true, std::memory_order_release);

View File

@ -18,6 +18,7 @@
#include <symbols.hpp>
#include <memory.hpp>
#include <convert.h>
#include <algorithm>
#include <debug.h>
#include <elf.h>
@ -25,7 +26,7 @@
namespace SymbolResolver
{
const NIF char *Symbols::GetSymbol(uintptr_t Address)
const nif char *Symbols::GetSymbol(uintptr_t Address)
{
SymbolTable Result{};
@ -115,8 +116,7 @@ namespace SymbolResolver
Elf_Shdr *sym = (Elf_Shdr *)&sections[EntSize * i];
Elf_Shdr *str = (Elf_Shdr *)&sections[EntSize * sym->sh_link];
if (sym->sh_type == SHT_SYMTAB &&
str->sh_type == SHT_STRTAB)
if (sym->sh_type == SHT_SYMTAB && str->sh_type == SHT_STRTAB)
{
Symbols = (Elf_Sym *)sym->sh_addr;
StringAddress = (uint8_t *)str->sh_addr;
@ -124,26 +124,15 @@ namespace SymbolResolver
// StringSize = (int)str->sh_size;
// TotalEntries = Section.sh_size / sizeof(Elf64_Sym)
TotalEntries = sym->sh_size / sym->sh_entsize;
trace("Symbol table found, %d entries",
SymbolSize / sym->sh_entsize);
UNUSED(SymbolSize);
trace("Symbol table found, %d entries", SymbolSize / sym->sh_entsize);
break;
}
}
if (Symbols != nullptr && StringAddress != nullptr)
{
size_t Index, MinimumIndex;
for (size_t i = 0; i < TotalEntries - 1; i++)
{
MinimumIndex = i;
for (Index = i + 1; Index < TotalEntries; Index++)
if (Symbols[Index].st_value < Symbols[MinimumIndex].st_value)
MinimumIndex = Index;
Elf_Sym tmp = Symbols[MinimumIndex];
Symbols[MinimumIndex] = Symbols[i];
Symbols[i] = tmp;
}
std::sort(Symbols, Symbols + TotalEntries, [](const Elf_Sym &a, const Elf_Sym &b)
{ return a.st_value < b.st_value; });
while (Symbols[0].st_value == 0)
{
@ -159,8 +148,7 @@ namespace SymbolResolver
return;
}
trace("Symbol table loaded, %d entries (%ld KiB)",
TotalEntries, TO_KiB(TotalEntries * sizeof(SymbolTable)));
trace("Symbol table loaded, %d entries (%ld KiB)", TotalEntries, TO_KiB(TotalEntries * sizeof(SymbolTable)));
Elf_Sym *sym;
const char *name;
Memory::Virtual vmm;
@ -178,6 +166,12 @@ namespace SymbolResolver
continue;
}
if (unlikely(sym->st_name == (Elf_Word)-1 || sym->st_value == (Elf_Addr)-1 || sym->st_size == (uintptr_t)-1))
{
error("Symbol %d is invalid; ptr:%#lx", i, sym);
continue;
}
name = (const char *)&StringAddress[Symbols[i].st_name];
if (!vmm.Check((void *)name))
{

View File

@ -37,7 +37,7 @@ namespace Driver::TeleTypeDevices
{
dev_t min = Node->GetMinor();
if (min == ids.kcon)
return KernelConsole::CurrentTerminal.load()->Open(Flags, Mode);
return KernelConsole::CurrentTerminal.load()->Term->Open(Flags, Mode);
else if (min == ids.tty)
{
TTY::TeletypeDriver *tty = (TTY::TeletypeDriver *)thisProcess->tty;
@ -55,7 +55,7 @@ namespace Driver::TeleTypeDevices
{
dev_t min = Node->GetMinor();
if (min == ids.kcon)
return KernelConsole::CurrentTerminal.load()->Close();
return KernelConsole::CurrentTerminal.load()->Term->Close();
else if (min == ids.tty)
{
TTY::TeletypeDriver *tty = (TTY::TeletypeDriver *)thisProcess->tty;
@ -73,7 +73,7 @@ namespace Driver::TeleTypeDevices
{
dev_t min = Node->GetMinor();
if (min == ids.kcon)
return KernelConsole::CurrentTerminal.load()->Ioctl(Request, Argp);
return KernelConsole::CurrentTerminal.load()->Term->Ioctl(Request, Argp);
else if (min == ids.tty)
{
TTY::TeletypeDriver *tty = (TTY::TeletypeDriver *)thisProcess->tty;
@ -91,7 +91,7 @@ namespace Driver::TeleTypeDevices
{
dev_t min = Node->GetMinor();
if (min == ids.kcon)
return KernelConsole::CurrentTerminal.load()->Read(Buffer, Size, Offset);
return KernelConsole::CurrentTerminal.load()->Term->Read(Buffer, Size, Offset);
else if (min == ids.tty)
{
TTY::TeletypeDriver *tty = (TTY::TeletypeDriver *)thisProcess->tty;
@ -109,7 +109,7 @@ namespace Driver::TeleTypeDevices
{
dev_t min = Node->GetMinor();
if (min == ids.kcon)
return KernelConsole::CurrentTerminal.load()->Write(Buffer, Size, Offset);
return KernelConsole::CurrentTerminal.load()->Term->Write(Buffer, Size, Offset);
else if (min == ids.tty)
{
TTY::TeletypeDriver *tty = (TTY::TeletypeDriver *)thisProcess->tty;

View File

@ -1,4 +1,4 @@
const char *trusted_drivers[] = {
"ae08d2e120c8370278ca9e17085a6b9e2f4a470ab6cec824c77ab1f8706c7144f5d4e1c9820914ed4fc7a4fd22de4b18bfed7c3b5d9c1e604e82280d7d45a5c7",
"66ff6a13e27cfee4b37e153fbdeeabb2de44f2a6a4d7f929f0b48d05a08b44c8c543f15c6cee05b5392166088f5ba260db5a64476d150ce81b295e4aa5a85d32",
};
const __SIZE_TYPE__ trusted_drivers_count = sizeof(trusted_drivers) / sizeof(trusted_drivers[0]);

View File

@ -65,9 +65,9 @@ namespace Execute
uintptr_t *relPtr = (uintptr_t *)(((uintptr_t)BaseImage + target->sh_offset) + rel->r_offset);
uintptr_t value = 0;
if (ELF64_R_SYM(rel->r_info) != SHN_UNDEF)
if (ELF_R_SYM(rel->r_info) != SHN_UNDEF)
{
value = ELFGetSymbolValue(((Elf_Ehdr *)BaseImage), section->sh_link, ELF64_R_SYM(rel->r_info));
value = ELFGetSymbolValue(((Elf_Ehdr *)BaseImage), section->sh_link, ELF_R_SYM(rel->r_info));
if (value == (uintptr_t)-1)
return;
}

View File

@ -30,7 +30,7 @@ using namespace Tasking;
namespace Execute
{
int Spawn(char *Path, const char **argv, const char **envp,
int Spawn(const char *Path, const char **argv, const char **envp,
Tasking::PCB *Parent, bool Fork,
Tasking::TaskCompatibility Compatibility,
bool Critical)
@ -170,7 +170,7 @@ namespace Execute
fixme("remove workarounds for stdio and tty");
if (!Parent->tty)
Process->tty = KernelConsole::CurrentTerminal.load();
Process->tty = KernelConsole::CurrentTerminal.load()->Term;
if (!ForkStdio(Parent->stdin))
fdt->usr_open("/dev/console", O_RDWR, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);

View File

@ -86,6 +86,7 @@ extern const BuiltInDriver __kernel_builtin_drivers_end[];
namespace Driver
{
char GetScanCode(uint8_t ScanCode, bool Upper);
char GetControlCharacter(KeyScanCodes Key);
bool IsValidChar(uint8_t ScanCode);
struct DriverHandlers

View File

@ -327,6 +327,7 @@ enum DynamicArrayTags
#define ELF32_ST_BIND(info) ((info) >> 4)
#define ELF32_ST_TYPE(info) ((info) & 0xf)
#define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
#define ELF64_ST_BIND(info) ((info) >> 4)
#define ELF64_ST_TYPE(info) ((info) & 0xf)
#define ELF64_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
@ -956,7 +957,7 @@ typedef struct
char pr_psargs[ELF_PRARGSZ];
} Elf64_Prpsinfo;
#if defined(__amd64__) || defined(__aarch64__)
#ifdef __LP64__
typedef Elf64_Addr Elf_Addr;
typedef Elf64_Half Elf_Half;
typedef Elf64_Off Elf_Off;
@ -973,7 +974,16 @@ typedef Elf64_Rela Elf_Rela;
typedef Elf64_Nhdr Elf_Nhdr;
typedef Elf64_Prstatus Elf_Prstatus;
typedef Elf64_Prpsinfo Elf_Prpsinfo;
#elif defined(__i386__) || defined(__arm__)
typedef Elf64_Xword Elf_Xword;
#define ELF_ST_BIND(info) ELF64_ST_BIND(info)
#define ELF_ST_TYPE(info) ELF64_ST_TYPE(info)
#define ELF_ST_INFO(bind, type) ELF64_ST_INFO(bind, type)
#define ELF_ST_VISIBILITY(o) ELF64_ST_VISIBILITY(o)
#define ELF_R_SYM(i) ELF64_R_SYM(i)
#define ELF_R_TYPE(i) ELF64_R_TYPE(i)
#define ELF_R_INFO(s, t) ELF64_R_INFO(s, t)
#else
typedef Elf32_Addr Elf_Addr;
typedef Elf32_Half Elf_Half;
typedef Elf32_Off Elf_Off;
@ -990,6 +1000,15 @@ typedef Elf32_Rela Elf_Rela;
typedef Elf32_Nhdr Elf_Nhdr;
typedef Elf32_Prstatus Elf_Prstatus;
typedef Elf32_Prpsinfo Elf_Prpsinfo;
typedef Elf32_Word Elf_Xword;
#define ELF_ST_BIND(info) ELF32_ST_BIND(info)
#define ELF_ST_TYPE(info) ELF32_ST_TYPE(info)
#define ELF_ST_INFO(bind, type) ELF32_ST_INFO(bind, type)
#define ELF_ST_VISIBILITY(o) ELF32_ST_VISIBILITY(o)
#define ELF_R_SYM(i) ELF32_R_SYM(i)
#define ELF_R_TYPE(i) ELF32_R_TYPE(i)
#define ELF_R_INFO(s, t) ELF32_R_INFO(s, t)
#endif
#endif // !__FENNIX_KERNEL_ELF_H__

View File

@ -77,7 +77,7 @@ namespace Execute
BinaryType GetBinaryType(FileNode *Path);
BinaryType GetBinaryType(std::string Path);
int Spawn(char *Path, const char **argv, const char **envp,
int Spawn(const char *Path, const char **argv, const char **envp,
Tasking::PCB *Parent = nullptr, bool Fork = false,
Tasking::TaskCompatibility Compatibility = Tasking::Native,
bool Critical = false);

View File

@ -132,13 +132,21 @@ namespace vfs
FileNode *CacheSearchReturnLast(FileNode *Parent, const char **Path);
FileNode *CacheRecursiveSearch(FileNode *Root, const char *NameOrPath, bool IsName);
FileNode *CacheLookup(const char *Path);
FileNode *CacheLookup(FileNode *Parent, const char *Path);
FileNode *CreateCacheNode(FileNode *Parent, Inode *Node, const char *Name, mode_t Mode);
int RemoveCacheNode(FileNode *Node);
public:
vfsInode *FileSystemRoots = nullptr;
/**
* Default reserved roots:
*
* 0 - Native
* 1 - Linux
* 2 - Windows
*/
std::unordered_map<ino_t, FileNode *> FileRoots;
bool PathIsRelative(const char *Path);
@ -161,7 +169,11 @@ namespace vfs
int UnregisterFileSystem(dev_t Device);
void AddRoot(Inode *Root);
void AddRootAt(Inode *Root, size_t Index);
bool SetRootAt(Inode *Root, size_t Index);
void RemoveRoot(Inode *Root);
FileNode *GetRoot(size_t Index);
bool RootExists(size_t Index);
FileNode *Create(FileNode *Parent, const char *Name, mode_t Mode);
FileNode *ForceCreate(FileNode *Parent, const char *Name, mode_t Mode);

View File

@ -0,0 +1,150 @@
/*
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 <filesystem.hpp>
#include <memory.hpp>
namespace vfs
{
class RAMFS
{
public:
class InodeBuffer
{
public:
void *Data = nullptr;
size_t DataSize = 0;
void Allocate(size_t size, bool extend = false, bool atEnd = true)
{
if (extend == false)
{
if (Data)
Free();
Data = kmalloc(size);
if (!Data)
throw std::bad_alloc();
DataSize = size;
}
else
{
if (Data == nullptr)
{
Data = kmalloc(size);
if (!Data)
throw std::bad_alloc();
DataSize = size;
}
else
{
size_t newSize = DataSize + size;
void *newData = kmalloc(newSize);
if (!newData)
throw std::bad_alloc();
if (atEnd)
memcpy(newData, Data, DataSize);
else
memcpy(static_cast<char *>(newData) + size, Data, DataSize);
kfree(Data);
Data = newData;
DataSize = newSize;
}
}
}
void Free()
{
if (Data)
{
kfree(Data);
Data = nullptr;
DataSize = 0;
}
}
bool IsAllocated() const
{
return Data != nullptr;
}
InodeBuffer() = default;
~InodeBuffer() { Free(); }
};
class RAMFSInode
{
public:
struct Inode Node;
RAMFSInode *Parent = nullptr;
std::string Name;
kstat Stat{};
mode_t Mode = 0;
InodeBuffer Buffer;
std::string SymLink;
std::vector<RAMFSInode *> Children;
void AddChild(RAMFSInode *child)
{
Children.push_back(child);
child->Parent = this;
}
void RemoveChild(RAMFSInode *child)
{
auto it = std::find(Children.begin(), Children.end(), child);
if (it != Children.end())
{
Children.erase(it);
child->Parent = nullptr;
}
}
RAMFSInode() = default;
~RAMFSInode()
{
for (auto child : Children)
delete child;
}
};
private:
std::unordered_map<ino_t, RAMFSInode *> Files;
public:
dev_t DeviceID = -1;
ino_t NextInode = 0;
std::string RootName;
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 Write(struct Inode *Node, const 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);
RAMFS() = default;
~RAMFS() = default;
};
}
bool MountRAMFS(FileNode *Parent, const char *Name, size_t Index);

View File

@ -127,11 +127,11 @@ namespace vfs
bool TestArchive(uintptr_t Address);
void ReadArchive(uintptr_t Address, size_t Size);
USTAR(){};
~USTAR(){};
USTAR() = default;
~USTAR() = default;
};
}
bool TestAndInitializeUSTAR(uintptr_t Address, size_t Size);
bool TestAndInitializeUSTAR(uintptr_t Address, size_t Size, size_t Index);
#endif // !__FENNIX_KERNEL_FILESYSTEM_USTAR_H__

View File

@ -97,7 +97,7 @@ namespace KernelConsole
PaintCallback PaintCB = nullptr;
CursorCallback CursorCB = nullptr;
std::mutex Mutex;
std::mutex vt_mutex;
public:
termios *GetTermios() { return &this->TerminalConfig; }
@ -124,22 +124,37 @@ namespace KernelConsole
void csi_cnl(ANSIArgument *Args, int ArgsCount);
void csi_cpl(ANSIArgument *Args, int ArgsCount);
void csi_cha(ANSIArgument *Args, int ArgsCount);
void ProcessControlCharacter(char c);
void Process(char c);
TerminalCell *GetCell(size_t index) { return &Cells[index]; }
VirtualTerminal(unsigned short Rows, unsigned short Columns,
unsigned short XPixels, unsigned short YPixels,
PaintCallback Paint, CursorCallback Print);
~VirtualTerminal();
};
struct ConsoleTerminal
{
VirtualTerminal *Term = nullptr;
struct Blinker
{
bool Enabled = false;
uint32_t Color = 0x000000;
char Character = '\0';
int Delay = 500;
} Blink;
};
/**
* 0 - Default
* 1...11 - User
* ...
* 15 - Panic
*/
extern VirtualTerminal *Terminals[16];
extern std::atomic<VirtualTerminal *> CurrentTerminal;
extern ConsoleTerminal *Terminals[16];
extern std::atomic<ConsoleTerminal *> CurrentTerminal;
extern int TermColors[];
extern int TermBrightColors[];

View File

@ -15,4 +15,10 @@
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "../../kernel.h"
#pragma once
#include <types.h>
namespace Security
{
}

View File

@ -0,0 +1,31 @@
/*
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 Subsystem
{
namespace Linux
{
void InitializeSubSystem();
}
namespace Windows
{
void InitializeSubSystem();
}
}

View File

@ -34,8 +34,34 @@ namespace TTY
public:
TerminalBuffer(size_t Size) : Buffer(Size), ReadIndex(0), WriteIndex(0) {}
ssize_t Read(char *OutputBuffer, size_t Size);
ssize_t Write(const char *InputBuffer, size_t Size);
ssize_t Read(char *OutputBuffer, size_t Size)
{
std::lock_guard<std::mutex> lock(Mutex);
size_t bytesRead = 0;
while (bytesRead < Size && ReadIndex != WriteIndex)
{
OutputBuffer[bytesRead++] = Buffer[ReadIndex];
ReadIndex = (ReadIndex + 1) % Buffer.size();
}
return bytesRead;
}
ssize_t Write(const char *InputBuffer, size_t Size)
{
std::lock_guard<std::mutex> lock(Mutex);
size_t bytesWritten = 0;
for (size_t i = 0; i < Size; ++i)
{
Buffer[WriteIndex] = InputBuffer[i];
WriteIndex = (WriteIndex + 1) % Buffer.size();
bytesWritten++;
}
return bytesWritten;
}
void DrainOutput()
{
@ -57,9 +83,10 @@ namespace TTY
class TeletypeDriver
{
protected:
termios TerminalConfig;
winsize TerminalSize;
termios TerminalConfig{};
winsize TerminalSize{};
TerminalBuffer TermBuf;
pid_t ProcessGroup;
public:
virtual int Open(int Flags, mode_t Mode);
@ -69,7 +96,7 @@ namespace TTY
virtual int Ioctl(unsigned long Request, void *Argp);
TeletypeDriver();
virtual ~TeletypeDriver();
virtual ~TeletypeDriver() = default;
};
class PTYDevice
@ -81,10 +108,18 @@ namespace TTY
TerminalBuffer TermBuf;
public:
PTYMaster();
~PTYMaster();
ssize_t Read(void *Buffer, size_t Size);
ssize_t Write(const void *Buffer, size_t Size);
PTYMaster() : TermBuf(1024) {}
~PTYMaster() = default;
ssize_t Read(void *Buffer, size_t Size)
{
return TermBuf.Read((char *)Buffer, Size);
}
ssize_t Write(const void *Buffer, size_t Size)
{
return TermBuf.Write((const char *)Buffer, Size);
}
};
class PTYSlave
@ -93,22 +128,48 @@ namespace TTY
TerminalBuffer TermBuf;
public:
PTYSlave();
~PTYSlave();
ssize_t Read(void *Buffer, size_t Size);
ssize_t Write(const void *Buffer, size_t Size);
PTYSlave() : TermBuf(1024) {}
~PTYSlave() = default;
ssize_t Read(void *Buffer, size_t Size)
{
return TermBuf.Read((char *)Buffer, Size);
}
ssize_t Write(const void *Buffer, size_t Size)
{
return TermBuf.Write((const char *)Buffer, Size);
}
};
PTYMaster Master;
PTYSlave Slave;
public:
PTYDevice();
~PTYDevice();
int Open();
int Close();
ssize_t Read(void *Buffer, size_t Size);
ssize_t Write(const void *Buffer, size_t Size);
PTYDevice() : Master(), Slave() {}
~PTYDevice() = default;
int Open()
{
stub;
return -ENOSYS;
}
int Close()
{
stub;
return -ENOSYS;
}
ssize_t Read(void *Buffer, size_t Size)
{
return Slave.Read(Buffer, Size);
}
ssize_t Write(const void *Buffer, size_t Size)
{
return Master.Write(Buffer, Size);
}
};
class PTMXDevice
@ -118,8 +179,14 @@ namespace TTY
std::mutex PTYMutex;
public:
PTMXDevice();
~PTMXDevice();
PTMXDevice() = default;
~PTMXDevice()
{
for (auto pty : PTYs)
delete pty;
}
int Open();
int Close();
PTYDevice *CreatePTY();

View File

@ -461,7 +461,7 @@ typedef uint48_t uint_fast48_t;
#define NoSecurityAnalysis __no_stack_protector __no_sanitize_address __no_sanitize_undefined __no_sanitize_thread
#define nsa NoSecurityAnalysis
#define NIF __no_instrument_function
#define nif __no_instrument_function
#define int3 \
__asm__ __volatile__("int3" \

View File

@ -324,4 +324,42 @@ namespace std
}
return true;
}
template <class RandomIt>
constexpr void sort(RandomIt first, RandomIt last)
{
if (first == last)
return;
for (RandomIt i = first; i != last; ++i)
{
for (RandomIt j = i + 1; j != last; ++j)
{
if (*j < *i)
std::swap(*i, *j);
}
}
}
template <class ExecutionPolicy, class RandomIt>
void sort(ExecutionPolicy &&policy, RandomIt first, RandomIt last);
template <class RandomIt, class Compare>
constexpr void sort(RandomIt first, RandomIt last, Compare comp)
{
if (first == last)
return;
for (RandomIt i = first; i != last; ++i)
{
for (RandomIt j = i + 1; j != last; ++j)
{
if (comp(*j, *i))
std::swap(*i, *j);
}
}
}
template <class ExecutionPolicy, class RandomIt, class Compare>
void sort(ExecutionPolicy &&policy, RandomIt first, RandomIt last, Compare comp);
}

112
Kernel/include_std/array Normal file
View File

@ -0,0 +1,112 @@
/*
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 <initializer_list>
#include <cstddef>
#include <iterator>
#include <algorithm>
#include <stdexcept>
namespace std
{
template <class T, std::size_t N>
struct array
{
public:
using value_type = T;
using size_type = std::size_t;
using difference_type = std::ptrdiff_t;
using reference = value_type &;
using const_reference = const value_type &;
using pointer = value_type *;
using const_pointer = const value_type *;
using iterator = value_type *;
using const_iterator = const value_type *;
// using reverse_iterator = std::reverse_iterator<iterator>;
// using const_reverse_iterator = std::reverse_iterator<const_iterator>;
private:
value_type ptr[N]{};
public:
constexpr array() = default;
constexpr array(std::initializer_list<T> list)
{
if (list.size() != N)
throw std::length_error("array initializer_list size mismatch");
std::copy(list.begin(), list.end(), ptr);
}
constexpr reference at(size_type pos)
{
if (pos >= size())
throw std::out_of_range("array::at: index out of range");
return this->operator[](pos);
}
constexpr const_reference at(size_type pos) const
{
if (pos >= size())
throw std::out_of_range("array::at: index out of range");
return this->operator[](pos);
}
constexpr reference operator[](size_type pos) { return *(begin() + pos); }
constexpr const_reference operator[](size_type pos) const { return *(begin() + pos); }
constexpr reference front() { return *begin(); }
constexpr const_reference front() const { return *begin(); }
reference back() { return *(end() - 1); }
const_reference back() const { return *(end() - 1); }
constexpr T *data() noexcept { return ptr; }
constexpr const T *data() const noexcept { return ptr; }
constexpr iterator begin() noexcept { return ptr; }
constexpr const_iterator begin() const noexcept { return ptr; }
constexpr const_iterator cbegin() const noexcept { return ptr; }
constexpr iterator end() noexcept { return ptr + N; }
constexpr const_iterator end() const noexcept { return ptr + N; }
constexpr const_iterator cend() const noexcept { return ptr + N; }
// constexpr reverse_iterator rbegin() noexcept { return reverse_iterator(end()); }
// constexpr const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(end()); }
// constexpr const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(end()); }
// constexpr reverse_iterator rend() noexcept { return reverse_iterator(begin()); }
// constexpr const_reverse_iterator rend() const noexcept { return const_reverse_iterator(begin()); }
// constexpr const_reverse_iterator crend() const noexcept { return const_reverse_iterator(begin()); }
constexpr bool empty() const noexcept { return begin() == end(); }
constexpr size_type size() const noexcept { return /*std::distance(begin(), end());*/ N; }
constexpr size_type max_size() const noexcept { return N; }
constexpr void fill(const T &value)
{
for (size_type i = 0; i < N; ++i)
ptr[i] = value;
}
constexpr void swap(array &other) noexcept(std::is_nothrow_swappable_v<T>)
{
for (size_type i = 0; i < N; ++i)
{
auto tmp = ptr[i];
ptr[i] = other.ptr[i];
other.ptr[i] = tmp;
}
}
};
}

View File

@ -34,15 +34,6 @@ EXTERNC void __attribute__((noreturn)) HandleAssertionFailed(const char *File, i
} \
} while (0)
#define assert_allow_continue(x) \
do \
{ \
if (__builtin_expect(!!(!(x)), 0)) \
{ \
error("Assertion failed! [%s]", #x); \
} \
} while (0)
#if __STDC_VERSION__ >= 201112L && !defined(__cplusplus)
#define static_assert _Static_assert
#endif

View File

@ -24,7 +24,7 @@ namespace std
class exception
{
public:
exception() noexcept {}
exception() noexcept = default;
exception(const exception &) noexcept = default;
virtual ~exception() noexcept = default;
exception &operator=(const exception &) noexcept = default;

View File

@ -17,6 +17,8 @@
#pragma once
#include <type_traits>
namespace std
{
struct input_iterator_tag
@ -54,28 +56,31 @@ namespace std
using iterator_category = typename Iter::iterator_category;
};
template <class InputIt>
constexpr typename std::iterator_traits<InputIt>::difference_type __do_distance(InputIt first, InputIt last, std::input_iterator_tag)
namespace detail
{
typename std::iterator_traits<InputIt>::difference_type result = 0;
while (first != last)
template <class It>
constexpr typename std::iterator_traits<It>::difference_type do_distance(It first, It last, std::input_iterator_tag)
{
++first;
++result;
typename std::iterator_traits<It>::difference_type result = 0;
while (first != last)
{
++first;
++result;
}
return result;
}
template <class It>
constexpr typename std::iterator_traits<It>::difference_type do_distance(It first, It last, std::random_access_iterator_tag)
{
return last - first;
}
return result;
}
template <class InputIt>
constexpr typename std::iterator_traits<InputIt>::difference_type __do_distance(InputIt first, InputIt last, std::random_access_iterator_tag)
template <class It>
constexpr typename std::iterator_traits<It>::difference_type distance(It first, It last)
{
return last - first;
}
template <class InputIt>
constexpr typename std::iterator_traits<InputIt>::difference_type distance(InputIt first, InputIt last)
{
return __do_distance(first, last, typename std::iterator_traits<InputIt>::iterator_category());
return detail::do_distance(first, last, typename std::iterator_traits<It>::iterator_category());
}
template <class InputIt>
@ -135,4 +140,118 @@ namespace std
};
inline constexpr default_sentinel_t default_sentinel{};
template <class T>
using iter_value_t = typename std::iterator_traits<T>::value_type;
template <class T>
using iter_difference_t = typename std::iterator_traits<T>::difference_type;
template <class T>
using iter_reference_t = decltype(*std::declval<T &>());
template <class Iter>
class reverse_iterator
{
public:
using iterator_type = Iter;
using iterator_concept = std::bidirectional_iterator_tag;
using iterator_category = std::iterator_traits<Iter>::iterator_category;
using value_type = std::iter_value_t<Iter>;
using difference_type = std::iter_difference_t<Iter>;
using pointer = std::iterator_traits<Iter>::pointer;
using reference = std::iter_reference_t<Iter>;
protected:
Iter current = Iter();
public:
reverse_iterator() = default;
constexpr explicit reverse_iterator(Iter x) : current(x) {}
// template <class U>
// requires(!std::is_same_v<U, Iter> && std::convertible_to<const U &, Iter>)
// constexpr explicit reverse_iterator(const U &other) : current(other.base())
// {
// }
template <class U>
reverse_iterator(const reverse_iterator<U> &other) : current(other.base()) {}
template <class U>
reverse_iterator &operator=(const reverse_iterator<U> &other)
{
current = other.base();
return *this;
}
constexpr Iter base() const { return current; }
constexpr decltype(auto) operator*() const
{
return *std::prev(current);
// Iter tmp = current;
// return *--tmp;
}
pointer operator->() const
{
if constexpr (std::is_pointer_v<Iter>)
return current - 1;
else
return std::prev(current).operator->();
}
constexpr decltype(auto) operator[](difference_type n) const
{
return current[-n - 1];
}
constexpr reverse_iterator &operator++()
{
--current;
return *this;
}
constexpr reverse_iterator operator++(int)
{
auto tmp = *this;
--current;
return tmp;
}
constexpr reverse_iterator &operator--()
{
++current;
return *this;
}
constexpr reverse_iterator operator--(int)
{
auto tmp = *this;
++current;
return tmp;
}
constexpr reverse_iterator operator+(difference_type n) const
{
return reverse_iterator(current - n);
}
constexpr reverse_iterator operator-(difference_type n) const
{
return reverse_iterator(current + n);
}
constexpr reverse_iterator &operator+=(difference_type n)
{
current -= n;
return *this;
}
constexpr reverse_iterator &operator-=(difference_type n)
{
current += n;
return *this;
}
};
}

View File

@ -84,6 +84,14 @@ namespace std
class runtime_error : public exception
{
private:
__simple_string what_arg;
public:
// runtime_error(const std::string &what_arg);
runtime_error(const char *what_arg) : what_arg(what_arg) {}
runtime_error(const runtime_error &other) : what_arg(other.what_arg) {}
runtime_error &operator=(const runtime_error &other) = default;
};
class logic_error : public exception
@ -126,4 +134,13 @@ namespace std
invalid_argument(const invalid_argument &other) = default;
invalid_argument &operator=(const invalid_argument &other) = default;
};
class length_error : public logic_error
{
public:
// length_error(const std::string &what_arg);
length_error(const char *what_arg) : logic_error(what_arg) {}
length_error(const length_error &other) : logic_error(other) {}
length_error &operator=(const length_error &other) = default;
};
}

View File

@ -1579,6 +1579,7 @@ namespace std
{
std::copy(begin() + index + count, end(), begin() + index);
_size -= count;
_data[_size] = '\0';
}
return *this;

View File

@ -693,4 +693,32 @@ namespace std
template <class F, class... ArgTypes>
using invoke_result_t = typename invoke_result<F, ArgTypes...>::type;
template <class T>
struct is_pointer : std::false_type
{
};
template <class T>
struct is_pointer<T *> : std::true_type
{
};
template <class T>
struct is_pointer<T *const> : std::true_type
{
};
template <class T>
struct is_pointer<T *volatile> : std::true_type
{
};
template <class T>
struct is_pointer<T *const volatile> : std::true_type
{
};
template <class T>
constexpr bool is_pointer_v = is_pointer<T>::value;
}

View File

@ -784,7 +784,7 @@ namespace std
{
size_type index = pos - begin();
if (_size == _capacity)
reserve(_capacity * 2);
reserve(_capacity + (_capacity / 2) + 1);
for (size_type i = _size; i > index; i--)
_data[i] = _data[i - 1];
@ -850,7 +850,7 @@ namespace std
{
size_type index = pos - begin();
if (_size == _capacity)
reserve(_capacity * 2);
reserve(_capacity + (_capacity / 2) + 1);
for (size_type i = _size; i > index; i--)
_data[i] = _data[i - 1];
@ -891,7 +891,7 @@ namespace std
reserve(sizeof(T) * 2);
if (_size == _capacity)
reserve(_capacity * 2);
reserve(_capacity + (_capacity / 2) + 1);
_data[_size] = value;
_size++;
@ -903,7 +903,7 @@ namespace std
reserve(sizeof(T) * 2);
if (_size == _capacity)
reserve(_capacity * 2);
reserve(_capacity + (_capacity / 2) + 1);
_data[_size] = std::move(value);
_size++;
@ -913,7 +913,7 @@ namespace std
constexpr reference emplace_back(Args &&...args)
{
if (_size == _capacity)
reserve(_capacity * 2);
reserve(_capacity + (_capacity / 2) + 1);
std::allocator_traits<Allocator>::construct(_alloc, _data + _size, std::forward<Args>(args)...);
_size++;

View File

@ -33,7 +33,6 @@
#include "tests/t.h"
bool DebuggerIsAttached = false;
extern bool EnableProfiler;
NewLock(KernelLock);
__aligned(16) BootInfo bInfo{};
@ -63,7 +62,7 @@ UART::Driver uart;
EXTERNC void putchar(char c)
{
KernelConsole::VirtualTerminal *vt = KernelConsole::CurrentTerminal.load(std::memory_order_acquire);
KernelConsole::VirtualTerminal *vt = KernelConsole::CurrentTerminal.load(std::memory_order_acquire)->Term;
if (vt != nullptr)
vt->Process(c);
else
@ -117,7 +116,7 @@ EXTERNC void KPrint(const char *Format, ...)
#endif
}
EXTERNC NIF cold void Main()
EXTERNC nif cold void Main()
{
Display = new Video::Display(bInfo.Framebuffer[0]);
KernelConsole::EarlyInit();
@ -191,19 +190,14 @@ EXTERNC NIF cold void Main()
KPrint("COM8 is present.");
KPrint("Display: %dx%d %d bpp R:%d %d G:%d %d B:%d %d",
Display->GetFramebufferStruct().Width,
Display->GetFramebufferStruct().Height,
Display->GetFramebufferStruct().Width, Display->GetFramebufferStruct().Height,
Display->GetFramebufferStruct().BitsPerPixel,
Display->GetFramebufferStruct().RedMaskSize,
Display->GetFramebufferStruct().RedMaskShift,
Display->GetFramebufferStruct().GreenMaskSize,
Display->GetFramebufferStruct().GreenMaskShift,
Display->GetFramebufferStruct().BlueMaskSize,
Display->GetFramebufferStruct().BlueMaskShift);
Display->GetFramebufferStruct().RedMaskSize, Display->GetFramebufferStruct().RedMaskShift,
Display->GetFramebufferStruct().GreenMaskSize, Display->GetFramebufferStruct().GreenMaskShift,
Display->GetFramebufferStruct().BlueMaskSize, Display->GetFramebufferStruct().BlueMaskShift);
KPrint("%lld MiB / %lld MiB (%lld MiB reserved)",
TO_MiB(KernelAllocator.GetUsedMemory()),
TO_MiB(KernelAllocator.GetTotalMemory()),
KPrint("%lld MiB / %lld MiB (%lld MiB reserved)", TO_MiB(KernelAllocator.GetUsedMemory()),
TO_MiB(KernelAllocator.GetTotalMemory() - KernelAllocator.GetReservedMemory()),
TO_MiB(KernelAllocator.GetReservedMemory()));
#endif
@ -219,8 +213,7 @@ EXTERNC NIF cold void Main()
Interrupts::Initialize(0);
KPrint("Loading Kernel Symbols");
KernelSymbolTable =
new SymbolResolver::Symbols((uintptr_t)bInfo.Kernel.FileBase);
KernelSymbolTable = new SymbolResolver::Symbols((uintptr_t)bInfo.Kernel.FileBase);
if (!KernelSymbolTable->SymTableExists)
KernelSymbolTable->AddSymbolInfoFromGRUB(bInfo.Kernel.Symbols.Num,
@ -265,7 +258,7 @@ typedef void (*CallPtr)(void);
extern CallPtr __init_array_start[0], __init_array_end[0];
extern CallPtr __fini_array_start[0], __fini_array_end[0];
EXTERNC __no_stack_protector NIF cold void Entry(BootInfo *Info)
EXTERNC __no_stack_protector nif cold void Entry(BootInfo *Info)
{
memcpy(&bInfo, Info, sizeof(BootInfo));
@ -358,7 +351,6 @@ EXTERNC __no_stack_protector NIF cold void Entry(BootInfo *Info)
#warning "FIXME: Test_stl() is not implemented for other architectures"
#endif
#endif // DEBUG
EnableProfiler = true;
Main();
}

View File

@ -21,6 +21,7 @@
#endif
#include <filesystem/ustar.hpp>
#include <subsystems.hpp>
#include <kshell.hpp>
#include <power.hpp>
#include <lock.hpp>
@ -31,30 +32,73 @@
#include <vm.hpp>
#include <vector>
cold int SpawnInit()
int SpawnNativeInit()
{
const char *envp[] = {
"PATH=/sys/bin:/usr/bin",
"LD_LIBRARY_PATH=/sys/lib:/usr/lib",
"TERM=tty",
"HOME=/home/root",
"USER=root",
"TZ=UTC",
nullptr};
const char *argv[] = {Config.InitPath, nullptr};
return Execute::Spawn(Config.InitPath, argv, envp, nullptr, false, Tasking::Native, true);
}
int SpawnLinuxInit()
{
const char *envp[] = {
"PATH=/bin:/usr/bin",
"LD_LIBRARY_PATH=/sys/lib:/usr/lib",
"LD_LIBRARY_PATH=/lib:/usr/lib",
"TERM=tty",
"HOME=/root",
"USER=root",
"TZ=UTC",
nullptr};
const char *argv[] = {
Config.InitPath,
nullptr};
std::string init = Config.InitPath;
std::vector<std::string> fallbackPaths = {
init,
"/bin/init",
"/sbin/init",
"/system/init",
"/usr/bin/init",
"/boot/init",
"/startup/init"};
Tasking::TaskCompatibility compat = Tasking::Native;
if (Config.LinuxSubsystem)
compat = Tasking::Linux;
const char *foundPath = nullptr;
FileNode *root = fs->GetRoot(1);
for (const std::string &path : fallbackPaths)
{
const char *str = path.c_str();
if (!fs->PathExists(str, root))
continue;
foundPath = str;
break;
}
return Execute::Spawn(Config.InitPath, argv, envp,
nullptr, false, compat, true);
if (!foundPath)
{
error("No valid init found in fallback paths");
return -ENOENT;
}
const char *argv[] = {foundPath, nullptr};
return Execute::Spawn(foundPath, argv, envp, nullptr, false, Tasking::Linux, true);
}
cold void KernelMainThread()
int SpawnInit()
{
if (Config.LinuxSubsystem)
return SpawnLinuxInit();
else
return SpawnNativeInit();
}
void KernelMainThread()
{
thisThread->SetPriority(Tasking::Critical);
@ -93,6 +137,10 @@ cold void KernelMainThread()
// ->Rename("Kernel Shell");
#endif
KPrint("Loading Subsystems");
Subsystem::Linux::InitializeSubSystem();
Subsystem::Windows::InitializeSubSystem();
KPrint("Executing %s", Config.InitPath);
int ExitCode = -1;
Tasking::PCB *initProc;
@ -100,13 +148,11 @@ cold void KernelMainThread()
int tid = SpawnInit();
if (tid < 0)
{
KPrint("\x1b[1;37;41mFailed to start %s! Error: %s (%d)",
Config.InitPath, strerror(tid), tid);
KPrint("\x1b[1;37;41mFailed to start init program! Error: %s (%d)", strerror(tid), tid);
goto Exit;
}
KPrint("Waiting for \x1b[32m%s\x1b[0m to start...",
Config.InitPath);
KPrint("Waiting for init program to start...");
thisThread->SetPriority(Tasking::Idle);
initProc = TaskManager->GetProcessByID(tid);
@ -122,14 +168,12 @@ Exit:
KPrint("Dropping to kernel shell");
TaskManager->Sleep(1000);
TaskManager->CreateThread(thisProcess,
Tasking::IP(KShellThread))
->Rename("Kernel Shell");
TaskManager->CreateThread(thisProcess, Tasking::IP(KShellThread))->Rename("Kernel Shell");
CPU::Halt(true);
}
NewLock(ShutdownLock);
cold void __no_stack_protector KernelShutdownThread(bool Reboot)
void __no_stack_protector KernelShutdownThread(bool Reboot)
{
SmartLock(ShutdownLock);
debug("KernelShutdownThread(%s)", Reboot ? "true" : "false");

View File

@ -26,30 +26,30 @@ void SearchForInitrd()
{
for (size_t i = 0; i < MAX_MODULES; i++)
{
uintptr_t initrdAddress = (uintptr_t)bInfo.Modules[i].Address;
uintptr_t moduleAddress = (uintptr_t)bInfo.Modules[i].Address;
size_t moduleSize = bInfo.Modules[i].Size;
const char *moduleCommand = bInfo.Modules[i].CommandLine;
if (!initrdAddress)
if (moduleAddress == 0)
continue;
if (strcmp(bInfo.Modules[i].CommandLine, "rootfs") != 0)
continue;
KPrint("rootfs found at %#lx", initrdAddress);
Memory::Virtual vmm;
if (!vmm.Check((void *)initrdAddress))
if (!vmm.CheckRegion((void *)moduleAddress, moduleSize))
{
warn("Initrd is not mapped!");
vmm.Map((void *)initrdAddress, (void *)initrdAddress,
bInfo.Modules[i].Size, Memory::RW);
warn("module entry is not mapped!");
vmm.Map((void *)moduleAddress, (void *)moduleAddress, moduleSize, Memory::RW);
}
if (TestAndInitializeUSTAR(initrdAddress, bInfo.Modules[i].Size))
continue; /* Maybe add another root? */
if (strcmp(moduleCommand, "rootfs") == 0)
{
KPrint("rootfs found at %#lx", moduleAddress);
if (TestAndInitializeUSTAR(moduleAddress, moduleSize, 0))
continue;
}
}
}
EXTERNC NIF void KernelVFS()
EXTERNC nif void KernelVFS()
{
KPrint("Initializing Virtual File System");

View File

@ -603,8 +603,7 @@ void KShellThread()
if (Config.LinuxSubsystem)
compat = Tasking::Linux;
int ret = Execute::Spawn((char *)path.c_str(), argv, envp,
nullptr, false, compat, false);
int ret = Execute::Spawn(path.c_str(), argv, envp, nullptr, false, compat, false);
if (argv[1])
delete argv[1];
delete argv;

View File

@ -268,14 +268,14 @@ typedef union
// 1. Some compilers are finicky about this;
// 2. Some people may want to convert this to C89;
// 3. If you try to use it as C++, only C++20 supports compound literals
static inline NIF double_with_bit_access get_bit_access(double x)
static inline nif double_with_bit_access get_bit_access(double x)
{
double_with_bit_access dwba;
dwba.F = x;
return dwba;
}
static inline NIF int get_sign_bit(double x)
static inline nif int get_sign_bit(double x)
{
// The sign is stored in the highest bit
return (int)(get_bit_access(x).U >> (DOUBLE_SIZE_IN_BITS - 1));
@ -319,7 +319,7 @@ typedef struct
// or alternatively, that '\0' can be passed to the function in the output
// gadget. The former assumption holds within the printf library. It also
// assumes that the output gadget has been properly initialized.
static inline NIF void putchar_via_gadget(output_gadget_t *gadget, char c)
static inline nif void putchar_via_gadget(output_gadget_t *gadget, char c)
{
printf_size_t write_pos = gadget->pos++;
// We're _always_ increasing pos, so as to count how may characters
@ -342,7 +342,7 @@ static inline NIF void putchar_via_gadget(output_gadget_t *gadget, char c)
}
// Possibly-write the string-terminating '\0' character
static inline NIF void append_termination_with_gadget(output_gadget_t *gadget)
static inline nif void append_termination_with_gadget(output_gadget_t *gadget)
{
if (gadget->function != NULL || gadget->max_chars == 0)
{
@ -360,13 +360,13 @@ extern void putchar(char c);
// We can't use putchar_ as is, since our output gadget
// only takes pointers to functions with an extra argument
static inline NIF void putchar_wrapper(char c, void *unused)
static inline nif void putchar_wrapper(char c, void *unused)
{
putchar(c);
UNUSED(unused);
}
static inline NIF output_gadget_t discarding_gadget(void)
static inline nif output_gadget_t discarding_gadget(void)
{
output_gadget_t gadget;
gadget.function = NULL;
@ -377,7 +377,7 @@ static inline NIF output_gadget_t discarding_gadget(void)
return gadget;
}
static inline NIF output_gadget_t buffer_gadget(char *buffer, size_t buffer_size)
static inline nif output_gadget_t buffer_gadget(char *buffer, size_t buffer_size)
{
printf_size_t usable_buffer_size = (buffer_size > PRINTF_MAX_POSSIBLE_BUFFER_SIZE) ? PRINTF_MAX_POSSIBLE_BUFFER_SIZE : (printf_size_t)buffer_size;
output_gadget_t result = discarding_gadget();
@ -389,7 +389,7 @@ static inline NIF output_gadget_t buffer_gadget(char *buffer, size_t buffer_size
return result;
}
static inline NIF output_gadget_t function_gadget(void (*function)(char, void *), void *extra_arg)
static inline nif output_gadget_t function_gadget(void (*function)(char, void *), void *extra_arg)
{
output_gadget_t result = discarding_gadget();
result.function = function;
@ -398,7 +398,7 @@ static inline NIF output_gadget_t function_gadget(void (*function)(char, void *)
return result;
}
static inline NIF output_gadget_t extern_putchar_gadget(void)
static inline nif output_gadget_t extern_putchar_gadget(void)
{
return function_gadget(putchar_wrapper, NULL);
}
@ -407,7 +407,7 @@ static inline NIF output_gadget_t extern_putchar_gadget(void)
// @return The length of the string (excluding the terminating 0) limited by 'maxsize'
// @note strlen uses size_t, but wes only use this function with printf_size_t
// variables - hence the signature.
static inline NIF printf_size_t strnlen_s_(const char *str, printf_size_t maxsize)
static inline nif printf_size_t strnlen_s_(const char *str, printf_size_t maxsize)
{
const char *s;
for (s = str; *s && maxsize--; ++s)
@ -417,13 +417,13 @@ static inline NIF printf_size_t strnlen_s_(const char *str, printf_size_t maxsiz
// internal test if char is a digit (0-9)
// @return true if char is a digit
static inline NIF bool is_digit_(char ch)
static inline nif bool is_digit_(char ch)
{
return (ch >= '0') && (ch <= '9');
}
// internal ASCII string to printf_size_t conversion
static NIF printf_size_t atou_(const char **str)
static nif printf_size_t atou_(const char **str)
{
printf_size_t i = 0U;
while (is_digit_(**str))
@ -434,7 +434,7 @@ static NIF printf_size_t atou_(const char **str)
}
// output the specified string in reverse, taking care of any zero-padding
static NIF void out_rev_(output_gadget_t *output, const char *buf, printf_size_t len, printf_size_t width, printf_flags_t flags)
static nif void out_rev_(output_gadget_t *output, const char *buf, printf_size_t len, printf_size_t width, printf_flags_t flags)
{
const printf_size_t start_pos = output->pos;
@ -465,7 +465,7 @@ static NIF void out_rev_(output_gadget_t *output, const char *buf, printf_size_t
// Invoked by print_integer after the actual number has been printed, performing necessary
// work on the number's prefix (as the number is initially printed in reverse order)
static NIF void print_integer_finalization(output_gadget_t *output, char *buf, printf_size_t len, bool negative, numeric_base_t base, printf_size_t precision, printf_size_t width, printf_flags_t flags)
static nif void print_integer_finalization(output_gadget_t *output, char *buf, printf_size_t len, bool negative, numeric_base_t base, printf_size_t precision, printf_size_t width, printf_flags_t flags)
{
printf_size_t unpadded_len = len;
@ -549,7 +549,7 @@ static NIF void print_integer_finalization(output_gadget_t *output, char *buf, p
}
// An internal itoa-like function
static NIF void print_integer(output_gadget_t *output, printf_unsigned_value_t value, bool negative, numeric_base_t base, printf_size_t precision, printf_size_t width, printf_flags_t flags)
static nif void print_integer(output_gadget_t *output, printf_unsigned_value_t value, bool negative, numeric_base_t base, printf_size_t precision, printf_size_t width, printf_flags_t flags)
{
char buf[PRINTF_INTEGER_BUFFER_SIZE];
printf_size_t len = 0U;
@ -608,7 +608,7 @@ static const double powers_of_10[NUM_DECIMAL_DIGITS_IN_INT64_T] = {
// Break up a double number - which is known to be a finite non-negative number -
// into its base-10 parts: integral - before the decimal point, and fractional - after it.
// Taken the precision into account, but does not change it even internally.
static struct NIF double_components get_components(double number, printf_size_t precision)
static struct nif double_components get_components(double number, printf_size_t precision)
{
struct double_components number_;
number_.is_negative = get_sign_bit(number);
@ -745,7 +745,7 @@ static struct double_components get_normalized_components(bool negative, printf_
}
#endif // PRINTF_SUPPORT_EXPONENTIAL_SPECIFIERS
static NIF void print_broken_up_decimal(
static nif void print_broken_up_decimal(
struct double_components number_, output_gadget_t *output, printf_size_t precision,
printf_size_t width, printf_flags_t flags, char *buf, printf_size_t len)
{
@ -847,7 +847,7 @@ static NIF void print_broken_up_decimal(
}
// internal ftoa for fixed decimal floating point
static NIF void print_decimal_number(output_gadget_t *output, double number, printf_size_t precision, printf_size_t width, printf_flags_t flags, char *buf, printf_size_t len)
static nif void print_decimal_number(output_gadget_t *output, double number, printf_size_t precision, printf_size_t width, printf_flags_t flags, char *buf, printf_size_t len)
{
struct double_components value_ = get_components(number, precision);
print_broken_up_decimal(value_, output, precision, width, flags, buf, len);
@ -920,7 +920,7 @@ static double pow10_of_int(int floored_exp10)
return dwba.F;
}
static NIF void print_exponential_number(output_gadget_t *output, double number, printf_size_t precision, printf_size_t width, printf_flags_t flags, char *buf, printf_size_t len)
static nif void print_exponential_number(output_gadget_t *output, double number, printf_size_t precision, printf_size_t width, printf_flags_t flags, char *buf, printf_size_t len)
{
const bool negative = get_sign_bit(number);
// This number will decrease gradually (by factors of 10) as we "extract" the exponent out of it
@ -1043,7 +1043,7 @@ static NIF void print_exponential_number(output_gadget_t *output, double number,
}
#endif // PRINTF_SUPPORT_EXPONENTIAL_SPECIFIERS
static NIF void print_floating_point(output_gadget_t *output, double value, printf_size_t precision, printf_size_t width, printf_flags_t flags, bool prefer_exponential)
static nif void print_floating_point(output_gadget_t *output, double value, printf_size_t precision, printf_size_t width, printf_flags_t flags, bool prefer_exponential)
{
char buf[PRINTF_DECIMAL_BUFFER_SIZE];
printf_size_t len = 0U;
@ -1102,7 +1102,7 @@ static NIF void print_floating_point(output_gadget_t *output, double value, prin
// Advances the format pointer past the flags, and returns the parsed flags
// due to the characters passed
static NIF printf_flags_t parse_flags(const char **format)
static nif printf_flags_t parse_flags(const char **format)
{
printf_flags_t flags = 0U;
do
@ -1135,7 +1135,7 @@ static NIF printf_flags_t parse_flags(const char **format)
} while (true);
}
static inline NIF void format_string_loop(output_gadget_t *output, const char *format, va_list args)
static inline nif void format_string_loop(output_gadget_t *output, const char *format, va_list args)
{
#if PRINTF_CHECK_FOR_NUL_IN_FORMAT_SPECIFIER
#define ADVANCE_IN_FORMAT_STRING(cptr_) \
@ -1517,7 +1517,7 @@ static inline NIF void format_string_loop(output_gadget_t *output, const char *f
}
// internal vsnprintf - used for implementing _all library functions
static NIF int vsnprintf_impl(output_gadget_t *output, const char *format, va_list args)
static nif int vsnprintf_impl(output_gadget_t *output, const char *format, va_list args)
{
// Note: The library only calls vsnprintf_impl() with output->pos being 0. However, it is
// possible to call this function with a non-zero pos value for some "remedial printing".
@ -1532,30 +1532,30 @@ static NIF int vsnprintf_impl(output_gadget_t *output, const char *format, va_li
///////////////////////////////////////////////////////////////////////////////
NIF int vprintf(const char *format, va_list arg)
nif int vprintf(const char *format, va_list arg)
{
output_gadget_t gadget = extern_putchar_gadget();
return vsnprintf_impl(&gadget, format, arg);
}
NIF int vsnprintf(char *s, size_t n, const char *format, va_list arg)
nif int vsnprintf(char *s, size_t n, const char *format, va_list arg)
{
output_gadget_t gadget = buffer_gadget(s, n);
return vsnprintf_impl(&gadget, format, arg);
}
NIF int vsprintf(char *s, const char *format, va_list arg)
nif int vsprintf(char *s, const char *format, va_list arg)
{
return vsnprintf(s, PRINTF_MAX_POSSIBLE_BUFFER_SIZE, format, arg);
}
NIF int vfctprintf(void (*out)(char c, void *extra_arg), void *extra_arg, const char *format, va_list arg)
nif int vfctprintf(void (*out)(char c, void *extra_arg), void *extra_arg, const char *format, va_list arg)
{
output_gadget_t gadget = function_gadget(out, extra_arg);
return vsnprintf_impl(&gadget, format, arg);
}
NIF int printf(const char *format, ...)
nif int printf(const char *format, ...)
{
va_list args;
va_start(args, format);
@ -1564,7 +1564,7 @@ NIF int printf(const char *format, ...)
return ret;
}
NIF int sprintf(char *s, const char *format, ...)
nif int sprintf(char *s, const char *format, ...)
{
va_list args;
va_start(args, format);
@ -1573,7 +1573,7 @@ NIF int sprintf(char *s, const char *format, ...)
return ret;
}
NIF int snprintf(char *s, size_t n, const char *format, ...)
nif int snprintf(char *s, size_t n, const char *format, ...)
{
va_list args;
va_start(args, format);
@ -1582,7 +1582,7 @@ NIF int snprintf(char *s, size_t n, const char *format, ...)
return ret;
}
NIF int fctprintf(void (*out)(char c, void *extra_arg), void *extra_arg, const char *format, ...)
nif int fctprintf(void (*out)(char c, void *extra_arg), void *extra_arg, const char *format, ...)
{
va_list args;
va_start(args, format);

View File

@ -16,95 +16,15 @@
*/
#include <types.h>
#include <printf.h>
#include <uart.hpp>
#include "../kernel.h"
bool EnableProfiler = false;
bool Wait = false;
unsigned long long LogDepth = 0;
unsigned int Level = 0;
static inline nsa NIF void profiler_uart_wrapper(char c, void *unused)
EXTERNC nsa nif void __cyg_profile_func_enter(void *this_fn, void *call_site)
{
bool renable = EnableProfiler;
EnableProfiler = false;
UNUSED(unused);
if (renable)
EnableProfiler = true;
UNUSED(this_fn);
UNUSED(call_site);
}
EXTERNC nsa NIF void __cyg_profile_func_enter(void *Function, void *CallSite)
EXTERNC nsa nif void __cyg_profile_func_exit(void *this_fn, void *call_site)
{
if (!EnableProfiler)
return;
while (Wait)
#if defined(__amd64__) || defined(__i386__)
asmv("pause");
#elif defined(__aarch64__)
asmv("yield");
#endif
Wait = true;
if (Level > 40)
Level--;
Level++;
if (!KernelSymbolTable)
fctprintf(profiler_uart_wrapper, nullptr, "%lld [%02d]: \033[42m->\033[0m%*c \033[33m%p\033[0m - \033[33m%p\033[0m\n",
LogDepth++,
Level - 1,
Level,
' ',
Function,
CallSite);
else
fctprintf(profiler_uart_wrapper, nullptr, "%lld [%02d]: \033[42m->\033[0m%*c \033[33m%s\033[0m - \033[33m%s\033[0m\n",
LogDepth++,
Level - 1,
Level,
' ',
KernelSymbolTable->GetSymbol((uintptr_t)Function),
KernelSymbolTable->GetSymbol((uintptr_t)CallSite));
Wait = false;
}
EXTERNC nsa NIF void __cyg_profile_func_exit(void *Function, void *CallSite)
{
if (!EnableProfiler)
return;
while (Wait)
#if defined(__amd64__) || defined(__i386__)
asmv("pause");
#elif defined(__aarch64__)
asmv("yield");
#endif
Wait = true;
if (Level > 40)
Level--;
Level--;
if (!KernelSymbolTable)
fctprintf(profiler_uart_wrapper, nullptr, "%lld [%02d]: \033[41m<-\033[0m%*c \033[33m%p\033[0m - \033[33m%p\033[0m\n",
LogDepth++,
Level - 1,
Level,
' ',
Function,
CallSite);
else
fctprintf(profiler_uart_wrapper, nullptr, "%lld [%02d]: \033[41m<-\033[0m%*c \033[33m%s\033[0m - \033[33m%s\033[0m\n",
LogDepth++,
Level - 1,
Level,
' ',
KernelSymbolTable->GetSymbol((uintptr_t)Function),
KernelSymbolTable->GetSymbol((uintptr_t)CallSite));
Wait = false;
UNUSED(this_fn);
UNUSED(call_site);
}

View File

@ -16,10 +16,6 @@
*/
#include <types.h>
#include <printf.h>
#include <uart.hpp>
#include "../kernel.h"
#if BITS_PER_LONG >= 64
typedef long gcov_type;
@ -53,33 +49,26 @@ struct gcov_info
struct gcov_ctr_info counts[0];
};
static inline nsa NIF void gcov_uart_wrapper(char c, void *unused)
EXTERNC nsa nif void __gcov_init(gcov_info *info)
{
UNUSED(c);
UNUSED(unused);
UNUSED(info);
}
// TODO: Implement
EXTERNC nsa NIF void __gcov_init(gcov_info *p __unused)
EXTERNC nsa nif void __gcov_exit(void)
{
}
EXTERNC nsa NIF void __gcov_exit(void)
EXTERNC nsa nif void __gcov_flush(void)
{
}
EXTERNC nsa NIF void __gcov_flush(void)
{
}
EXTERNC nsa NIF void __gcov_merge_add(gcov_type *counters, unsigned int n_counters)
EXTERNC nsa nif void __gcov_merge_add(gcov_type *counters, unsigned int n_counters)
{
UNUSED(counters);
UNUSED(n_counters);
}
EXTERNC nsa NIF void __gcov_merge_single(gcov_type *counters, unsigned int n_counters)
EXTERNC nsa nif void __gcov_merge_single(gcov_type *counters, unsigned int n_counters)
{
UNUSED(counters);
UNUSED(n_counters);

View File

@ -16,18 +16,8 @@
*/
#include <types.h>
#include <printf.h>
#include <uart.hpp>
#include "../kernel.h"
static inline nsa NIF void gprof_uart_wrapper(char c, void *unused)
{
UNUSED(c);
UNUSED(unused);
}
EXTERNC nsa NIF void mcount(unsigned long frompc, unsigned long selfpc)
EXTERNC nsa nif void mcount(void *frompc, size_t selfpc)
{
// TODO: Implement
/* https://docs.kernel.org/trace/ftrace-design.html */

View File

@ -15,4 +15,8 @@
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "../../kernel.h"
#include <security.hpp>
namespace Security
{
}

View File

@ -175,12 +175,13 @@ namespace vfs
return nullptr;
}
FileNode *Virtual::CacheLookup(const char *Path)
FileNode *Virtual::CacheLookup(FileNode *Parent, const char *Path)
{
debug("Cache lookup for \"%s\"", Path);
FileNode *rootNode = thisProcess ? thisProcess->Info.RootNode : this->GetRoot(0);
if (Parent == nullptr)
Parent = thisProcess ? thisProcess->Info.RootNode : this->GetRoot(0);
FileNode *ret = CacheRecursiveSearch(rootNode, Path, false);
FileNode *ret = CacheRecursiveSearch(Parent, Path, false);
if (ret)
return ret;

View File

@ -37,6 +37,47 @@ namespace vfs
FileSystemRoots->Children.push_back(Root);
}
void Virtual::AddRootAt(Inode *Root, size_t Index)
{
SmartLock(VirtualLock);
if (Index >= FileSystemRoots->Children.size())
FileSystemRoots->Children.resize(Index + 1);
if (FileSystemRoots->Children[Index] == nullptr)
FileSystemRoots->Children[Index] = Root;
else
{
debug("Root %ld already exists", Index);
}
}
bool Virtual::SetRootAt(Inode *Root, size_t Index)
{
SmartLock(VirtualLock);
assert(Index < FileSystemRoots->Children.size());
if (FileSystemRoots->Children[Index] != nullptr)
{
debug("Root %ld already exists", Index);
return false;
}
FileSystemRoots->Children[Index] = Root;
return true;
}
void Virtual::RemoveRoot(Inode *Root)
{
SmartLock(VirtualLock);
for (size_t i = 0; i < FileSystemRoots->Children.size(); i++)
{
if (FileSystemRoots->Children[i] != Root)
continue;
FileSystemRoots->Children[i] = nullptr;
break;
}
debug("removed root %p", Root);
}
FileNode *Virtual::GetRoot(size_t Index)
{
assert(Index < FileSystemRoots->Children.size());
@ -46,6 +87,7 @@ namespace vfs
return it->second;
Inode *rootNode = FileSystemRoots->Children[Index];
assert(rootNode != nullptr);
char rootName[128]{};
snprintf(rootName, sizeof(rootName), "\x06root-%ld\x06", Index);
FileNode *ret = this->CreateCacheNode(nullptr, rootNode, rootName, 0);
@ -53,6 +95,13 @@ namespace vfs
return ret;
}
bool Virtual::RootExists(size_t Index)
{
if (Index >= FileSystemRoots->Children.size())
return false;
return FileSystemRoots->Children[Index] != nullptr;
}
FileNode *Virtual::Create(FileNode *Parent, const char *Name, mode_t Mode)
{
FileNode *existingNode = this->GetByPath(Name, Parent);
@ -90,14 +139,22 @@ namespace vfs
{
char *path = strdup(Path);
char *lastSlash = strrchr(path, '/');
if (lastSlash == path)
lastSlash++;
*lastSlash = '\0';
if (lastSlash)
{
if (lastSlash == path)
lastSlash++;
*lastSlash = '\0';
}
FileNode *parentNode = this->GetByPath(path, Parent);
if (parentNode == nullptr && Parent != nullptr)
parentNode = Parent;
free(path);
lastSlash = strrchr(Path, '/');
lastSlash++;
if (lastSlash)
lastSlash++;
else
lastSlash = (char *)Path;
return this->CreateCacheNode(parentNode, Node, lastSlash, Node->Mode);
}
@ -113,8 +170,13 @@ namespace vfs
FileNode *Virtual::GetByPath(const char *Path, FileNode *Parent)
{
debug("GetByPath: %s", Path);
if (Parent == nullptr || this->PathIsAbsolute(Path))
Parent = thisProcess ? thisProcess->Info.RootNode : this->GetRoot(0);
if (Parent == nullptr)
{
if (fs->PathIsRelative(Path))
Parent = thisProcess ? thisProcess->CWD : thisProcess->Info.RootNode;
else
Parent = thisProcess ? thisProcess->Info.RootNode : this->GetRoot(0);
}
if (strcmp(Path, ".") == 0)
return Parent;
@ -167,6 +229,7 @@ namespace vfs
auto it = DeviceMap.find(__Parent->Node->Device);
if (unlikely(it == DeviceMap.end()))
ReturnLogError(nullptr, "Device %d not found", __Parent->Node->Device);
debug("found fs %s", it->second.fsi->Name);
if (it->second.fsi->Ops.Lookup == NULL)
ReturnLogError(nullptr, "Lookup not supported for %d", it->first);
@ -274,7 +337,7 @@ namespace vfs
bool Virtual::PathExists(const char *Path, FileNode *Parent)
{
FileNode *fn = this->CacheLookup(Path);
FileNode *fn = this->CacheLookup(Parent, Path);
if (fn)
return true;

417
Kernel/storage/fs/ramfs.cpp Normal file
View File

@ -0,0 +1,417 @@
/*
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 <filesystem/ramfs.hpp>
#include <memory.hpp>
#include <functional>
#include <debug.h>
#include "../../kernel.h"
namespace vfs
{
int RAMFS::Lookup(struct Inode *_Parent, const char *Name, struct Inode **Result)
{
auto Parent = (RAMFSInode *)_Parent;
const char *basename;
size_t length;
cwk_path_get_basename(Name, &basename, &length);
if (basename == NULL)
{
if (strcmp(Name, RootName.c_str()) == 0)
{
auto &it = Files.at(0);
*Result = &it->Node;
return 0;
}
error("Invalid name %s", Name);
return -EINVAL;
}
if (Parent)
{
for (auto &&child : Parent->Children)
{
if (strcmp(child->Name.c_str(), basename) != 0)
continue;
*Result = &child->Node;
return 0;
}
return -ENOENT;
}
for (auto &&i : Files)
{
RAMFSInode *node = i.second;
if (strcmp(node->Name.c_str(), basename) != 0)
continue;
*Result = &i.second->Node;
return 0;
}
return -ENOENT;
}
int RAMFS::Create(struct Inode *_Parent, const char *Name, mode_t Mode, struct Inode **Result)
{
RAMFSInode *Parent = (RAMFSInode *)_Parent;
Inode inode{};
inode.Mode = Mode;
inode.Device = this->DeviceID;
inode.RawDevice = 0;
inode.Index = NextInode;
inode.Offset = 0;
inode.PrivateData = this;
inode.Flags = I_FLAG_CACHE_KEEP;
const char *basename;
size_t length;
cwk_path_get_basename(Name, &basename, &length);
RAMFSInode *node = new RAMFSInode;
node->Name.assign(basename, length);
node->Mode = Mode;
node->Node = inode;
auto file = Files.insert(std::make_pair(NextInode, node));
assert(file.second == true);
*Result = &Files.at(NextInode)->Node;
if (Parent)
Parent->AddChild(node);
NextInode++;
return 0;
}
ssize_t RAMFS::Read(struct Inode *Node, void *Buffer, size_t Size, off_t Offset)
{
auto fileItr = Files.find(Node->Index);
assert(fileItr != Files.end());
RAMFSInode *node = fileItr->second;
size_t fileSize = node->Stat.Size;
if (Size <= 0)
{
debug("Size is less than or equal to 0");
Size = fileSize;
}
if ((size_t)Offset > fileSize)
{
debug("Offset %d is greater than file size %d", Offset, fileSize);
return 0;
}
if ((fileSize - Offset) == 0)
{
debug("Offset %d is equal to file size %d", Offset, fileSize);
return 0; /* EOF */
}
if ((size_t)Offset + Size > fileSize)
{
debug("Offset %d + Size %d is greater than file size %d",
Offset, Size, fileSize);
Size = fileSize;
}
memcpy(Buffer, node->Buffer.Data, Size);
return Size;
}
ssize_t RAMFS::Write(struct Inode *Node, const void *Buffer, size_t Size, off_t Offset)
{
auto fileItr = Files.find(Node->Index);
assert(fileItr != Files.end());
RAMFSInode *node = fileItr->second;
if (node->Buffer.IsAllocated() == false)
node->Buffer.Allocate(node->Stat.Size);
size_t fileSize = node->Stat.Size;
if (Size <= 0)
{
debug("Size is less than or equal to 0");
return -EINVAL;
}
if ((size_t)Offset > fileSize)
{
debug("Offset %d is greater than file size %d", Offset, fileSize);
node->Buffer.Allocate(Offset + Size, true, true);
}
if ((fileSize - Offset) == 0)
{
debug("Offset %d is equal to file size %d", Offset, fileSize);
node->Buffer.Allocate(Size, true, true);
}
if ((size_t)Offset + Size > fileSize)
{
debug("Offset %d + Size %d is greater than file size %d",
Offset, Size, fileSize);
node->Buffer.Allocate(Offset + Size, true, true);
}
memcpy(static_cast<char *>(node->Buffer.Data) + Offset, Buffer, Size);
node->Stat.Size = Size;
return Size;
}
__no_sanitize("alignment")
ssize_t RAMFS::ReadDir(struct Inode *_Node, struct kdirent *Buffer, size_t Size, off_t Offset, off_t Entries)
{
/* FIXME: FIX ALIGNMENT FOR DIRENT! */
auto Node = (RAMFSInode *)_Node;
off_t realOffset = Offset;
size_t totalSize = 0;
uint16_t reclen = 0;
struct kdirent *ent = nullptr;
if (Offset == 0)
{
reclen = (uint16_t)(offsetof(struct kdirent, d_name) + strlen(".") + 1);
if (totalSize + reclen >= Size)
return -EINVAL;
ent = (struct kdirent *)((uintptr_t)Buffer + totalSize);
ent->d_ino = Node->Node.Index;
ent->d_off = Offset++;
ent->d_reclen = reclen;
ent->d_type = DT_DIR;
strcpy(ent->d_name, ".");
totalSize += reclen;
}
if (Offset <= 1)
{
reclen = (uint16_t)(offsetof(struct kdirent, d_name) + strlen("..") + 1);
if (totalSize + reclen >= Size)
{
if (realOffset == 1)
return -EINVAL;
return totalSize;
}
ent = (struct kdirent *)((uintptr_t)Buffer + totalSize);
if (Node->Parent)
ent->d_ino = Node->Parent->Node.Index;
else
{
warn("Parent is null for %s", Node->Name.c_str());
ent->d_ino = Node->Node.Index;
}
ent->d_off = Offset++;
ent->d_reclen = reclen;
ent->d_type = DT_DIR;
strcpy(ent->d_name, "..");
totalSize += reclen;
}
if (!S_ISDIR(Node->Node.Mode))
return -ENOTDIR;
if ((Offset >= 2 ? (Offset - 2) : Offset) > (off_t)Node->Children.size())
return -EINVAL;
off_t entries = 0;
for (const auto &var : Node->Children)
{
if (var->Node.Offset < Offset)
continue;
if (entries >= Entries)
break;
reclen = (uint16_t)(offsetof(struct kdirent, d_name) + strlen(var->Name.c_str()) + 1);
if (totalSize + reclen >= Size)
break;
ent = (struct kdirent *)((uintptr_t)Buffer + totalSize);
ent->d_ino = var->Node.Index;
ent->d_off = var->Node.Offset;
ent->d_reclen = reclen;
if (S_ISREG(var->Stat.Mode))
ent->d_type = DT_REG;
else if (S_ISDIR(var->Stat.Mode))
ent->d_type = DT_DIR;
else if (S_ISLNK(var->Stat.Mode))
ent->d_type = DT_LNK;
else if (S_ISCHR(var->Stat.Mode))
ent->d_type = DT_CHR;
else if (S_ISBLK(var->Stat.Mode))
ent->d_type = DT_BLK;
else if (S_ISFIFO(var->Stat.Mode))
ent->d_type = DT_FIFO;
else if (S_ISSOCK(var->Stat.Mode))
ent->d_type = DT_SOCK;
else
ent->d_type = DT_UNKNOWN;
strncpy(ent->d_name, var->Name.c_str(), strlen(var->Name.c_str()));
totalSize += reclen;
entries++;
}
if (totalSize + sizeof(struct kdirent) >= Size)
return totalSize;
ent = (struct kdirent *)((uintptr_t)Buffer + totalSize);
ent->d_ino = 0;
ent->d_off = 0;
ent->d_reclen = 0;
ent->d_type = DT_UNKNOWN;
ent->d_name[0] = '\0';
return totalSize;
}
int RAMFS::SymLink(struct Inode *Node, const char *Name, const char *Target, struct Inode **Result)
{
int ret = this->Create(Node, Name, S_IFLNK, Result);
if (ret < 0)
return ret;
RAMFSInode *node = (RAMFSInode *)*Result;
node->SymLink.assign(Target, strlen(Target));
return 0;
}
ssize_t RAMFS::ReadLink(struct Inode *Node, char *Buffer, size_t Size)
{
auto fileItr = Files.find(Node->Index);
assert(fileItr != Files.end());
RAMFSInode *node = fileItr->second;
if (node->SymLink.size() > Size)
Size = node->SymLink.size();
strncpy(Buffer, node->SymLink.data(), Size);
debug("Read link %d bytes from %d: \"%s\"", Size, Node->Index, Buffer);
return Size;
}
int RAMFS::Stat(struct Inode *Node, struct kstat *Stat)
{
auto fileItr = Files.find(Node->Index);
assert(fileItr != Files.end());
RAMFSInode *node = fileItr->second;
*Stat = node->Stat;
return 0;
}
}
O2 int __ramfs_Lookup(struct Inode *Parent, const char *Name, struct Inode **Result)
{
return ((vfs::RAMFS *)Parent->PrivateData)->Lookup(Parent, Name, Result);
}
O2 int __ramfs_Create(struct Inode *Parent, const char *Name, mode_t Mode, struct Inode **Result)
{
return ((vfs::RAMFS *)Parent->PrivateData)->Create(Parent, Name, Mode, Result);
}
O2 ssize_t __ramfs_Read(struct Inode *Node, void *Buffer, size_t Size, off_t Offset)
{
return ((vfs::RAMFS *)Node->PrivateData)->Read(Node, Buffer, Size, Offset);
}
O2 ssize_t __ramfs_Write(struct Inode *Node, const void *Buffer, size_t Size, off_t Offset)
{
return ((vfs::RAMFS *)Node->PrivateData)->Write(Node, Buffer, Size, Offset);
}
O2 ssize_t __ramfs_Readdir(struct Inode *Node, struct kdirent *Buffer, size_t Size, off_t Offset, off_t Entries)
{
return ((vfs::RAMFS *)Node->PrivateData)->ReadDir(Node, Buffer, Size, Offset, Entries);
}
O2 int __ramfs_SymLink(Inode *Parent, const char *Name, const char *Target, Inode **Result)
{
return ((vfs::RAMFS *)Parent->PrivateData)->SymLink(Parent, Name, Target, Result);
}
O2 ssize_t __ramfs_ReadLink(Inode *Node, char *Buffer, size_t Size)
{
return ((vfs::RAMFS *)Node->PrivateData)->ReadLink(Node, Buffer, Size);
}
O2 int __ramfs_Stat(struct Inode *Node, kstat *Stat)
{
return ((vfs::RAMFS *)Node->PrivateData)->Stat(Node, Stat);
}
O2 int __ramfs_DestroyInode(FileSystemInfo *Info, Inode *Node)
{
vfs::RAMFS::RAMFSInode *inode = (vfs::RAMFS::RAMFSInode *)Node;
delete inode;
return 0;
}
O2 int __ramfs_Destroy(FileSystemInfo *fsi)
{
assert(fsi->PrivateData);
delete (vfs::RAMFS *)fsi->PrivateData;
delete fsi;
return 0;
}
bool MountRAMFS(FileNode *Parent, const char *Name, size_t Index)
{
vfs::RAMFS *ramfs = new vfs::RAMFS;
ramfs->DeviceID = fs->EarlyReserveDevice();
ramfs->RootName.assign(Name);
FileSystemInfo *fsi = new FileSystemInfo;
fsi->Name = "ramfs";
fsi->RootName = Name;
fsi->Flags = I_FLAG_ROOT | I_FLAG_MOUNTPOINT | I_FLAG_CACHE_KEEP;
fsi->SuperOps.DeleteInode = __ramfs_DestroyInode;
fsi->SuperOps.Destroy = __ramfs_Destroy;
fsi->Ops.Lookup = __ramfs_Lookup;
fsi->Ops.Create = __ramfs_Create;
fsi->Ops.Read = __ramfs_Read;
fsi->Ops.Write = __ramfs_Write;
fsi->Ops.ReadDir = __ramfs_Readdir;
fsi->Ops.SymLink = __ramfs_SymLink;
fsi->Ops.ReadLink = __ramfs_ReadLink;
fsi->Ops.Stat = __ramfs_Stat;
fsi->PrivateData = ramfs;
Inode *root = nullptr;
ramfs->Create(nullptr, Name, S_IFDIR | 0755, &root);
fs->LateRegisterFileSystem(ramfs->DeviceID, fsi, root);
fs->AddRootAt(root, Index);
fs->Mount(Parent, root, Name);
return true;
}

View File

@ -16,7 +16,6 @@
*/
#include <filesystem/ustar.hpp>
#include <memory.hpp>
#include <functional>
#include <debug.h>
@ -160,10 +159,14 @@ namespace vfs
node->Name.assign(basename, length);
node->Path.assign(Name, strlen(Name));
Files.insert(std::make_pair(NextInode, node));
auto file = Files.insert(std::make_pair(NextInode, node));
assert(file.second == true);
*Result = &Files.at(NextInode)->Node;
if (Parent)
{
Parent->Children.push_back(Files.at(NextInode));
Files.at(NextInode)->Parent = Parent;
}
NextInode++;
return 0;
}
@ -491,6 +494,10 @@ namespace vfs
FileHeader *header = (FileHeader *)Address;
if (strncmp(header->signature, TMAGIC, TMAGLEN) != 0)
{
/* For some reason if GRUB inflates the archive, the magic is "ustar " */
if (strncmp(header->signature, TMAGIC, TMAGLEN - 1) == 0)
return true;
error("Invalid signature!");
return false;
}
@ -564,7 +571,7 @@ namespace vfs
FileHeader *header = (FileHeader *)Address;
debug("USTAR signature valid! Name:%s Signature:%s Mode:%d Size:%lu",
debug("USTAR signature valid! Name:\"%s\" Signature:\"%s\" Mode:%d Size:%lu",
header->name, header->signature, StringToInt(header->mode), header->size);
Memory::Virtual vmm;
@ -577,7 +584,7 @@ namespace vfs
return;
}
if (strncmp(header->signature, TMAGIC, TMAGLEN) != 0)
if (strncmp(header->signature, TMAGIC, TMAGLEN - 1) != 0)
break;
// debug("\"%s\"", header->name);
@ -817,13 +824,13 @@ O2 int __ustar_Stat(struct Inode *Node, kstat *Stat)
return ((vfs::USTAR *)Node->PrivateData)->Stat(Node, Stat);
}
int __ustar_DestroyInode(FileSystemInfo *Info, Inode *Node)
O2 int __ustar_DestroyInode(FileSystemInfo *Info, Inode *Node)
{
((vfs::USTAR::USTARInode *)Node)->Deleted = true;
return 0;
}
int __ustar_Destroy(FileSystemInfo *fsi)
O2 int __ustar_Destroy(FileSystemInfo *fsi)
{
assert(fsi->PrivateData);
delete (vfs::USTAR *)fsi->PrivateData;
@ -831,7 +838,7 @@ int __ustar_Destroy(FileSystemInfo *fsi)
return 0;
}
bool TestAndInitializeUSTAR(uintptr_t Address, size_t Size)
bool TestAndInitializeUSTAR(uintptr_t Address, size_t Size, size_t Index)
{
vfs::USTAR *ustar = new vfs::USTAR();
if (!ustar->TestArchive(Address))
@ -863,6 +870,6 @@ bool TestAndInitializeUSTAR(uintptr_t Address, size_t Size)
fsi->PrivateData = ustar;
fs->LateRegisterFileSystem(ustar->DeviceID, fsi, rootfs);
fs->AddRoot(rootfs);
fs->AddRootAt(rootfs, Index);
return true;
}

View File

@ -447,4 +447,26 @@ struct sysinfo
char _f[20 - 2 * sizeof(long) - sizeof(int)]; /* Padding to 64 bytes */
};
struct linux_pollfd
{
int fd; /* File Descriptor */
short events; /* Requested Events */
short revents; /* Returned Events */
};
typedef unsigned long nfds_t;
#define linux_POLLIN 0x001
#define linux_POLLPRI 0x002
#define linux_POLLOUT 0x004
#define linux_POLLERR 0x008
#define linux_POLLHUP 0x010
#define linux_POLLNVAL 0x020
#define linux_POLLRDNORM 0x040
#define linux_POLLRDBAND 0x080
#define linux_POLLWRNORM 0x100
#define linux_POLLWRBAND 0x200
#define linux_POLLMSG 0x400
#define linux_POLLRDHUP 0x2000
#endif // !__FENNIX_KERNEL_LINUX_DEFS_H__

View File

@ -0,0 +1,59 @@
/*
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 <filesystem/ramfs.hpp>
#include "../../kernel.h"
namespace Subsystem::Linux
{
bool Initialized = false;
void InitializeSubSystem()
{
if (fs->RootExists(1) == false)
{
FileNode *nmnt = fs->GetByPath("/mnt", fs->GetRoot(0));
assert(MountRAMFS(nmnt, "linux", 1));
FileNode *linux = fs->GetRoot(1);
FileNode *bin = fs->ForceCreate(linux, "bin", 0755);
FileNode *boot = fs->ForceCreate(linux, "boot", 0755);
FileNode *dev = fs->ForceCreate(linux, "dev", 0755);
FileNode *etc = fs->ForceCreate(linux, "etc", 0755);
FileNode *home = fs->ForceCreate(linux, "home", 0755);
FileNode *lib = fs->ForceCreate(linux, "lib", 0755);
FileNode *lib64 = fs->ForceCreate(linux, "lib64", 0755);
FileNode *media = fs->ForceCreate(linux, "media", 0755);
FileNode *mnt = fs->ForceCreate(linux, "mnt", 0755);
FileNode *opt = fs->ForceCreate(linux, "opt", 0755);
FileNode *proc = fs->ForceCreate(linux, "proc", 0755);
UNUSED(bin);
UNUSED(boot);
UNUSED(dev);
UNUSED(etc);
UNUSED(home);
UNUSED(lib);
UNUSED(lib64);
UNUSED(media);
UNUSED(mnt);
UNUSED(opt);
UNUSED(proc);
}
}
}

View File

@ -899,6 +899,32 @@ static int linux_lstat(SysFrm *, const char *pathname, struct linux_kstat *statb
return ret;
}
static int linux_poll(SysFrm *, linux_pollfd *fds, nfds_t nfds, int timeout)
{
PCB *pcb = thisProcess;
Memory::VirtualMemoryArea *vma = pcb->vma;
auto pFds = vma->UserCheckAndGetAddress(fds, nfds * sizeof(linux_pollfd));
if (pFds == nullptr)
return -linux_EFAULT;
for (int i = 0; i < nfds; i++)
{
if (pFds[i].fd < 0)
return -linux_EBADF;
debug("poll[%zu].fd=%d .events=%d .revents=%d",
i, pFds[i].fd, pFds[i].events, pFds[i].revents);
pFds[i].revents = 0;
}
vfs::FileDescriptorTable *fdt = pcb->FileDescriptors;
UNUSED(fdt);
UNUSED(timeout);
fixme("poll is stub! returning 1");
return 1;
}
// #include "../syscalls.h"
static off_t linux_lseek(SysFrm *, int fd, off_t offset, int whence)
@ -3568,7 +3594,7 @@ static SyscallData LinuxSyscallsTableAMD64[] = {
[__NR_amd64_stat] = {"stat", (void *)linux_stat},
[__NR_amd64_fstat] = {"fstat", (void *)linux_fstat},
[__NR_amd64_lstat] = {"lstat", (void *)linux_lstat},
[__NR_amd64_poll] = {"poll", (void *)nullptr},
[__NR_amd64_poll] = {"poll", (void *)linux_poll},
[__NR_amd64_lseek] = {"lseek", (void *)linux_lseek},
[__NR_amd64_mmap] = {"mmap", (void *)linux_mmap},
[__NR_amd64_mprotect] = {"mprotect", (void *)linux_mprotect},
@ -4179,7 +4205,7 @@ static SyscallData LinuxSyscallsTableI386[] = {
[__NR_i386_getresuid] = {"getresuid", (void *)nullptr},
[__NR_i386_vm86] = {"vm86", (void *)nullptr},
[__NR_i386_query_module] = {"query_module", (void *)nullptr},
[__NR_i386_poll] = {"poll", (void *)nullptr},
[__NR_i386_poll] = {"poll", (void *)linux_poll},
[__NR_i386_nfsservctl] = {"nfsservctl", (void *)nullptr},
[__NR_i386_setresgid] = {"setresgid", (void *)nullptr},
[__NR_i386_getresgid] = {"getresgid", (void *)nullptr},

View File

@ -0,0 +1,47 @@
/*
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 <filesystem/ramfs.hpp>
#include "../../kernel.h"
namespace Subsystem::Windows
{
bool Initialized = false;
void InitializeSubSystem()
{
if (fs->RootExists(2) == false)
{
FileNode *nmnt = fs->GetByPath("/mnt", fs->GetRoot(0));
assert(MountRAMFS(nmnt, "windows", 2));
FileNode *win = fs->GetRoot(2);
FileNode *windows = fs->ForceCreate(win, "Windows", 0755);
FileNode *programFiles = fs->ForceCreate(windows, "Program Files", 0755);
FileNode *programFilesX86 = fs->ForceCreate(windows, "Program Files (x86)", 0755);
FileNode *programData = fs->ForceCreate(windows, "ProgramData", 0755);
FileNode *users = fs->ForceCreate(windows, "Users", 0755);
UNUSED(windows);
UNUSED(programFiles);
UNUSED(programFilesX86);
UNUSED(programData);
UNUSED(users);
}
}
}

View File

@ -282,7 +282,7 @@ namespace Tasking
/* FIXME: DON'T DELETE THE TTY
spawn.cpp is using this as workaround
tty == KernelConsole::CurrentTerminal.load();
tty == KernelConsole::CurrentTerminal.load()->Term;
*/
/* If we own the pointer to the

View File

@ -300,7 +300,7 @@ namespace Tasking::Scheduler
Info->KernelTime += TimePassed;
}
hot nsa NIF bool Custom::FindNewProcess(void *CPUDataPointer)
hot nsa nif bool Custom::FindNewProcess(void *CPUDataPointer)
{
CPUData *CurrentCPU = (CPUData *)CPUDataPointer;
fnp_schedbg("%d processes", ProcessList.size());
@ -347,7 +347,7 @@ namespace Tasking::Scheduler
return false;
}
hot nsa NIF bool Custom::GetNextAvailableThread(void *CPUDataPointer)
hot nsa nif bool Custom::GetNextAvailableThread(void *CPUDataPointer)
{
CPUData *CurrentCPU = (CPUData *)CPUDataPointer;
@ -399,7 +399,7 @@ namespace Tasking::Scheduler
return false;
}
hot nsa NIF bool Custom::GetNextAvailableProcess(void *CPUDataPointer)
hot nsa nif bool Custom::GetNextAvailableProcess(void *CPUDataPointer)
{
CPUData *CurrentCPU = (CPUData *)CPUDataPointer;
@ -447,7 +447,7 @@ namespace Tasking::Scheduler
return false;
}
hot nsa NIF bool Custom::SchedulerSearchProcessThread(void *CPUDataPointer)
hot nsa nif bool Custom::SchedulerSearchProcessThread(void *CPUDataPointer)
{
CPUData *CurrentCPU = (CPUData *)CPUDataPointer;
@ -480,7 +480,7 @@ namespace Tasking::Scheduler
return false;
}
nsa NIF void Custom::UpdateProcessState()
nsa nif void Custom::UpdateProcessState()
{
for (auto process : ProcessList)
{
@ -513,7 +513,7 @@ namespace Tasking::Scheduler
}
}
nsa NIF void Custom::WakeUpThreads()
nsa nif void Custom::WakeUpThreads()
{
for (auto process : ProcessList)
{
@ -547,7 +547,7 @@ namespace Tasking::Scheduler
}
}
nsa NIF void Custom::CleanupTerminated()
nsa nif void Custom::CleanupTerminated()
{
for (auto pcb : ProcessList)
{
@ -566,7 +566,7 @@ namespace Tasking::Scheduler
}
}
hot nsa NIF void Custom::Schedule(CPU::SchedulerFrame *Frame)
hot nsa nif void Custom::Schedule(CPU::SchedulerFrame *Frame)
{
if (unlikely(StopScheduler))
{
@ -723,7 +723,7 @@ namespace Tasking::Scheduler
this->SchedulerTicks.store(size_t(TimeManager->GetCounter() - SchedTmpTicks));
}
hot nsa NIF void Custom::OnInterruptReceived(CPU::SchedulerFrame *Frame)
hot nsa nif void Custom::OnInterruptReceived(CPU::SchedulerFrame *Frame)
{
SmartCriticalSection(SchedulerLock);
this->Schedule(Frame);

View File

@ -588,20 +588,18 @@ namespace Tasking
switch (Compatibility)
{
case TaskCompatibility::Native:
// this->Info.RootNode = fs->FileSystemRoots->GetChildren()[0];
this->Info.RootNode = fs->GetRoot(0);
break;
case TaskCompatibility::Linux:
// this->Info.RootNode = fs->FileSystemRoots->GetChildren()[1];
this->Info.RootNode = fs->GetRoot(1);
break;
case TaskCompatibility::Windows:
// this->Info.RootNode = fs->FileSystemRoots->GetChildren()[2];
this->Info.RootNode = fs->GetRoot(2);
break;
default:
assert(!"Invalid compatibility mode");
break;
}
/* FIXME */
this->Info.RootNode = fs->GetRoot(0);
if (this->Parent->Threads.size() == 0)
{

View File

@ -0,0 +1,88 @@
/*
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/>.
*/
#ifdef DEBUG
#include <array>
#include <cstddef>
#include <cstdint>
void test_stl_array()
{
{
std::array<int, 3> a = {1, 2, 3};
UNUSED(a);
}
{
std::array<int, 5> arr = {1, 2, 3, 4, 5};
for (size_t i = 0; i < arr.size(); ++i)
{
if (arr[i] != int(i + 1))
throw std::runtime_error("Array test failed");
}
}
{
std::array<int, 5> arr = {1, 2, 3, 4, 5};
std::array<int, 5> arr2 = arr;
for (size_t i = 0; i < arr.size(); ++i)
{
if (arr2[i] != int(i + 1))
throw std::runtime_error("Array copy test failed");
}
}
{
std::array<int, 5> arr = {1, 2, 3, 4, 5};
arr.fill(0);
for (size_t i = 0; i < arr.size(); ++i)
{
if (arr[i] != 0)
throw std::runtime_error("Array fill test failed");
}
}
{
std::array<int, 5> arr = {1, 2, 3, 4, 5};
std::array<int, 5> arr2 = {6, 7, 8, 9, 10};
arr.swap(arr2);
for (size_t i = 0; i < arr.size(); ++i)
{
if (arr[i] != int(i + 6))
throw std::runtime_error("Array swap test failed");
}
}
{
std::array<int, 5> arr = {1, 2, 3, 4, 5};
if (arr.empty())
throw std::runtime_error("Array empty test failed");
if (arr.size() != 5)
throw std::runtime_error("Array size test failed");
if (arr.max_size() != 5)
throw std::runtime_error("Array max_size test failed");
if (arr.front() != 1)
throw std::runtime_error("Array front test failed");
if (arr.back() != 5)
throw std::runtime_error("Array back test failed");
if (arr.data() != &arr[0])
throw std::runtime_error("Array data test failed");
}
}
#endif

View File

@ -26,6 +26,7 @@ void test_stl_bitset();
void test_stl_string();
void test_stl_unordered_map() {}
void test_stl_future();
void test_stl_array();
void Test_stl()
{
@ -38,6 +39,7 @@ void Test_stl()
test_stl_string();
test_stl_unordered_map();
test_stl_future();
test_stl_array();
}
#endif // DEBUG

View File

@ -24,16 +24,6 @@
namespace TTY
{
PTMXDevice::PTMXDevice()
{
}
PTMXDevice::~PTMXDevice()
{
for (auto pty : PTYs)
delete pty;
}
int PTMXDevice::Open()
{
stub;

View File

@ -1,95 +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 <tty.hpp>
#include <filesystem/ioctl.hpp>
#include <string.h>
#include <errno.h>
#include "../kernel.h"
namespace TTY
{
PTYDevice::PTYDevice()
: Master(), Slave()
{
}
PTYDevice::~PTYDevice()
{
}
int PTYDevice::Open()
{
stub;
return -ENOSYS;
}
int PTYDevice::Close()
{
stub;
return -ENOSYS;
}
ssize_t PTYDevice::Read(void *Buffer, size_t Size)
{
return Slave.Read(Buffer, Size);
}
ssize_t PTYDevice::Write(const void *Buffer, size_t Size)
{
return Master.Write(Buffer, Size);
}
PTYDevice::PTYMaster::PTYMaster()
: TermBuf(1024)
{
}
PTYDevice::PTYMaster::~PTYMaster()
{
}
ssize_t PTYDevice::PTYMaster::Read(void *Buffer, size_t Size)
{
return TermBuf.Read((char *)Buffer, Size);
}
ssize_t PTYDevice::PTYMaster::Write(const void *Buffer, size_t Size)
{
return TermBuf.Write((const char *)Buffer, Size);
}
PTYDevice::PTYSlave::PTYSlave()
: TermBuf(1024)
{
}
PTYDevice::PTYSlave::~PTYSlave()
{
}
ssize_t PTYDevice::PTYSlave::Read(void *Buffer, size_t Size)
{
return TermBuf.Read((char *)Buffer, Size);
}
ssize_t PTYDevice::PTYSlave::Write(const void *Buffer, size_t Size)
{
return TermBuf.Write((const char *)Buffer, Size);
}
}

View File

@ -26,37 +26,6 @@
namespace TTY
{
ssize_t TerminalBuffer::Read(char *OutputBuffer, size_t Size)
{
std::lock_guard<std::mutex> lock(Mutex);
size_t bytesRead = 0;
while (bytesRead < Size && ReadIndex != WriteIndex)
{
OutputBuffer[bytesRead++] = Buffer[ReadIndex];
ReadIndex = (ReadIndex + 1) % Buffer.size();
}
return bytesRead;
}
ssize_t TerminalBuffer::Write(const char *InputBuffer, size_t Size)
{
std::lock_guard<std::mutex> lock(Mutex);
size_t bytesWritten = 0;
for (size_t i = 0; i < Size; ++i)
{
Buffer[WriteIndex] = InputBuffer[i];
WriteIndex = (WriteIndex + 1) % Buffer.size();
bytesWritten++;
}
return bytesWritten;
}
/* ======================================================================== */
int TeletypeDriver::Open(int Flags, mode_t Mode)
{
warn("Unimplemented open(%#x, %#x)", Flags, Mode);
@ -87,15 +56,12 @@ namespace TTY
return -ENOSYS;
}
TeletypeDriver::TeletypeDriver()
: TermBuf(1024)
TeletypeDriver::TeletypeDriver() : TermBuf(1024)
{
this->TerminalSize = {
.ws_row = 0,
.ws_col = 0,
.ws_xpixel = 0,
.ws_ypixel = 0,
};
if (thisProcess)
this->ProcessGroup = thisProcess->Security.ProcessGroupID;
else
this->ProcessGroup = 0;
/*
- ICRNL - Map Carriage Return to New Line
@ -110,32 +76,24 @@ namespace TTY
- ECHO - Echo input characters
- ICANON - Enable canonical input (enable line editing)
- ISIG - Enable signals
*/
this->TerminalConfig.c_iflag = /*ICRNL |*/ IXON;
this->TerminalConfig.c_oflag = OPOST | ONLCR;
this->TerminalConfig.c_cflag = CS8 | CREAD | HUPCL;
this->TerminalConfig.c_lflag = ECHO | ICANON;
this->TerminalConfig.c_lflag = ECHO | ICANON | ISIG;
this->TerminalConfig.c_cc[VINTR] = 0x03; /* ^C */
this->TerminalConfig.c_cc[VQUIT] = 0x1C; /* ^\ */
this->TerminalConfig.c_cc[VERASE] = 0x7F; /* DEL */
this->TerminalConfig.c_cc[VKILL] = 0x15; /* ^U */
this->TerminalConfig.c_cc[VEOF] = 0x04; /* ^D */
this->TerminalConfig.c_cc[VTIME] = 0; /* Timeout for non-canonical read */
this->TerminalConfig.c_cc[VMIN] = 1; /* Minimum number of characters for non-canonical read */
this->TerminalConfig.c_cc[VSWTC] = 0; /* ^O */
this->TerminalConfig.c_cc[VSTART] = 0x11; /* ^Q */
this->TerminalConfig.c_cc[VSTOP] = 0x13; /* ^S */
this->TerminalConfig.c_cc[VSUSP] = 0x1A; /* ^Z */
this->TerminalConfig.c_cc[VEOL] = 0x00; /* NUL */
this->TerminalConfig.c_cc[VREPRINT] = 0x12; /* ^R */
this->TerminalConfig.c_cc[VDISCARD] = 0x14; /* ^T */
this->TerminalConfig.c_cc[VWERASE] = 0x17; /* ^W */
this->TerminalConfig.c_cc[VLNEXT] = 0x19; /* ^Y */
this->TerminalConfig.c_cc[VEOL2] = 0x7F; /* DEL (or sometimes EOF) */
}
TeletypeDriver::~TeletypeDriver()
{
this->TerminalConfig.c_cc[VINTR] = 'C' - 0x40;
this->TerminalConfig.c_cc[VQUIT] = '\\' - 0x40;
this->TerminalConfig.c_cc[VERASE] = '\177';
this->TerminalConfig.c_cc[VKILL] = 'U' - 0x40;
this->TerminalConfig.c_cc[VEOF] = 'D' - 0x40;
this->TerminalConfig.c_cc[VSTART] = 'Q' - 0x40;
this->TerminalConfig.c_cc[VSTOP] = 'S' - 0x40;
this->TerminalConfig.c_cc[VSUSP] = 'Z' - 0x40;
this->TerminalConfig.c_cc[VREPRINT] = 'R' - 0x40;
this->TerminalConfig.c_cc[VDISCARD] = 'O' - 0x40;
this->TerminalConfig.c_cc[VWERASE] = 'W' - 0x40;
this->TerminalConfig.c_cc[VLNEXT] = 'V' - 0x40;
}
}

View File

@ -29,26 +29,27 @@ namespace KernelConsole
{
int VirtualTerminal::Open(int Flags, mode_t Mode)
{
std::lock_guard<std::mutex> lock(Mutex);
std::lock_guard<std::mutex> lock(vt_mutex);
stub;
return 0;
}
int VirtualTerminal::Close()
{
std::lock_guard<std::mutex> lock(Mutex);
std::lock_guard<std::mutex> lock(vt_mutex);
stub;
return 0;
}
ssize_t VirtualTerminal::Read(void *Buffer, size_t Size, off_t Offset)
{
std::lock_guard<std::mutex> lock(Mutex);
std::lock_guard<std::mutex> lock(vt_mutex);
KeyboardReport report{};
/* FIXME: this is a hack, "static" is not a good idea */
static bool upperCase = false;
static bool controlKey = false;
RecheckKeyboard:
while (DriverManager->GlobalKeyboardInputReports.Count() == 0)
@ -65,6 +66,36 @@ namespace KernelConsole
upperCase = false;
goto RecheckKeyboard;
}
else if (pkey == KEY_LEFT_CTRL || pkey == KEY_RIGHT_CTRL)
{
if (report.Key & KEY_PRESSED)
controlKey = true;
else
controlKey = false;
debug("controlKey = %d", controlKey);
goto RecheckKeyboard;
}
if (controlKey && this->TerminalConfig.c_lflag & ICANON)
{
if (report.Key & KEY_PRESSED)
{
char cc = Driver::GetControlCharacter(report.Key);
if (cc == 0x00)
goto RecheckKeyboard;
if (this->TerminalConfig.c_lflag & ECHO)
{
char c = Driver::GetScanCode(report.Key, true);
this->Append('^');
this->Append(c);
this->Append('\n');
}
this->Process(cc);
goto RecheckKeyboard;
}
}
if (!(report.Key & KEY_PRESSED))
goto RecheckKeyboard;
@ -99,7 +130,7 @@ namespace KernelConsole
ssize_t VirtualTerminal::Write(const void *Buffer, size_t Size, off_t Offset)
{
std::lock_guard<std::mutex> lock(Mutex);
std::lock_guard<std::mutex> lock(vt_mutex);
char *buf = (char *)Buffer;
debug("string: \"%*s\"", Size, buf);
@ -117,7 +148,7 @@ namespace KernelConsole
int VirtualTerminal::Ioctl(unsigned long Request, void *Argp)
{
std::lock_guard<std::mutex> lock(Mutex);
std::lock_guard<std::mutex> lock(vt_mutex);
switch (Request)
{
@ -143,6 +174,12 @@ namespace KernelConsole
*t = TerminalConfig;
return 0;
}
case TCSETS:
{
struct termios *t = (struct termios *)Argp;
TerminalConfig = *t;
return 0;
}
case TCSETSW:
{
debug("draining output buffer...");
@ -160,14 +197,14 @@ namespace KernelConsole
}
case TIOCGPGRP:
{
*((pid_t *)Argp) = thisProcess->Security.ProcessGroupID;
debug("returning pgid %d", thisProcess->Security.ProcessGroupID);
*((pid_t *)Argp) = this->ProcessGroup;
debug("returning pgid %d", this->ProcessGroup);
return 0;
}
case TIOCSPGRP:
{
thisProcess->Security.ProcessGroupID = *((pid_t *)Argp);
debug("updated pgid to %d", thisProcess->Security.ProcessGroupID);
this->ProcessGroup = *((pid_t *)Argp);
debug("updated pgid to %d", this->ProcessGroup);
return 0;
}
case TIOCGSID:
@ -455,6 +492,133 @@ namespace KernelConsole
CursorCB(&Cursor);
}
void VirtualTerminal::ProcessControlCharacter(char c)
{
auto ccheck = [&](int v)
{
return (this->TerminalConfig.c_cc[v] != 0x00 &&
this->TerminalConfig.c_cc[v] == c);
};
auto ciflag = [&](int f)
{
return (this->TerminalConfig.c_iflag & f) != 0;
};
auto clflag = [&](int f)
{
return (this->TerminalConfig.c_lflag & f) != 0;
};
if (ciflag(IXON) && ccheck(VSTOP))
{
fixme("flow control: stopping output");
return;
}
if (ciflag(IXON) && ccheck(VSTART))
{
fixme("flow control: resuming output");
return;
}
if (clflag(ISIG))
{
if (ccheck(VINTR))
{
if (this->ProcessGroup == 0)
{
debug("Process group is 0!!!");
return;
}
for (auto proc : thisProcess->GetContext()->GetProcessList())
{
if (proc->Security.ProcessGroupID != this->ProcessGroup)
continue;
debug("Sending signal SIGINT to %s(%d)", proc->Name, proc->ID);
proc->SendSignal(SIGINT);
}
return;
}
else if (ccheck(VQUIT))
{
if (this->ProcessGroup == 0)
{
debug("Process group is 0!!!");
return;
}
for (auto proc : thisProcess->GetContext()->GetProcessList())
{
if (proc->Security.ProcessGroupID != this->ProcessGroup)
continue;
debug("Sending signal SIGQUIT to %s(%d)", proc->Name, proc->ID);
proc->SendSignal(SIGQUIT);
}
return;
}
else if (ccheck(VSUSP))
{
if (this->ProcessGroup == 0)
{
debug("Process group is 0!!!");
return;
}
for (auto proc : thisProcess->GetContext()->GetProcessList())
{
if (proc->Security.ProcessGroupID != this->ProcessGroup)
continue;
debug("Sending signal SIGTSTP to %s(%d)", proc->Name, proc->ID);
proc->SendSignal(SIGTSTP);
}
return;
}
}
if (c == '\r')
{
if (ciflag(IGNCR))
return;
if (ciflag(ICRNL))
c = '\n';
}
else if (c == '\n' && (ciflag(INLCR)))
c = '\r';
if (clflag(ICANON))
{
if (ccheck(VERASE))
{
if (this->Cursor.X > 0)
{
this->Cursor.X--;
this->Append('\b');
this->Append(' ');
this->Append('\b');
}
return;
}
else if (ccheck(VKILL))
{
fixme("clear the current line");
return;
}
}
if (clflag(ECHO))
{
if (c == '\n')
this->Append('\n');
else
this->Append(c);
}
}
void VirtualTerminal::Process(char c)
{
#ifdef DEBUG
@ -490,6 +654,15 @@ namespace KernelConsole
#endif
#endif
if (this->TerminalConfig.c_lflag & ICANON)
{
if ((c > 0x00 && c <= 0x1F) && c != '\x1b')
{
this->ProcessControlCharacter(c);
return;
}
}
ANSIParser *parser = &this->Parser;
switch (parser->State)
@ -630,30 +803,28 @@ namespace KernelConsole
- ECHO - Echo input characters
- ICANON - Enable canonical input (enable line editing)
- ISIG - Enable signals
*/
this->TerminalConfig.c_iflag = /*ICRNL |*/ IXON;
this->TerminalConfig.c_oflag = OPOST | ONLCR;
this->TerminalConfig.c_cflag = CS8 | CREAD | HUPCL;
this->TerminalConfig.c_lflag = ECHO | ICANON;
this->TerminalConfig.c_lflag &= ~ICANON; /* FIXME: not ready for this yet */
this->TerminalConfig.c_lflag = ECHO | ICANON | ISIG;
this->TerminalConfig.c_cc[VINTR] = 0x03; /* ^C */
this->TerminalConfig.c_cc[VQUIT] = 0x1C; /* ^\ */
this->TerminalConfig.c_cc[VERASE] = 0x7F; /* DEL */
this->TerminalConfig.c_cc[VKILL] = 0x15; /* ^U */
this->TerminalConfig.c_cc[VEOF] = 0x04; /* ^D */
this->TerminalConfig.c_cc[VTIME] = 0; /* Timeout for non-canonical read */
this->TerminalConfig.c_cc[VMIN] = 1; /* Minimum number of characters for non-canonical read */
this->TerminalConfig.c_cc[VSWTC] = 0; /* ^O */
this->TerminalConfig.c_cc[VSTART] = 0x11; /* ^Q */
this->TerminalConfig.c_cc[VSTOP] = 0x13; /* ^S */
this->TerminalConfig.c_cc[VSUSP] = 0x1A; /* ^Z */
this->TerminalConfig.c_cc[VEOL] = 0x00; /* NUL */
this->TerminalConfig.c_cc[VREPRINT] = 0x12; /* ^R */
this->TerminalConfig.c_cc[VDISCARD] = 0x14; /* ^T */
this->TerminalConfig.c_cc[VWERASE] = 0x17; /* ^W */
this->TerminalConfig.c_cc[VLNEXT] = 0x19; /* ^Y */
this->TerminalConfig.c_cc[VEOL2] = 0x7F; /* DEL (or sometimes EOF) */
this->TerminalConfig.c_cc[VINTR] = 'C' - 0x40;
this->TerminalConfig.c_cc[VQUIT] = '\\' - 0x40;
this->TerminalConfig.c_cc[VERASE] = '\177';
this->TerminalConfig.c_cc[VKILL] = 'U' - 0x40;
this->TerminalConfig.c_cc[VEOF] = 'D' - 0x40;
this->TerminalConfig.c_cc[VSTART] = 'Q' - 0x40;
this->TerminalConfig.c_cc[VSTOP] = 'S' - 0x40;
this->TerminalConfig.c_cc[VSUSP] = 'Z' - 0x40;
this->TerminalConfig.c_cc[VREPRINT] = 'R' - 0x40;
this->TerminalConfig.c_cc[VDISCARD] = 'O' - 0x40;
this->TerminalConfig.c_cc[VWERASE] = 'W' - 0x40;
this->TerminalConfig.c_cc[VLNEXT] = 'V' - 0x40;
this->TerminalConfig.c_cc[VTIME] = 0; /* Timeout for non-canonical read */
this->TerminalConfig.c_cc[VMIN] = 1; /* Minimum number of characters for non-canonical read */
this->Cells = new TerminalCell[Rows * Columns];
@ -661,8 +832,5 @@ namespace KernelConsole
(Rows * Columns) * sizeof(TerminalCell));
}
VirtualTerminal::~VirtualTerminal()
{
delete[] this->Cells;
}
VirtualTerminal::~VirtualTerminal() { delete[] this->Cells; }
}

View File

@ -82,6 +82,10 @@ QEMUFLAGS += -M raspi4b \
-kernel $(OSNAME).img
endif
ifeq ($(QUIET_BUILD), 1)
MAKE_QUIET_FLAG := --quiet
endif
doxygen:
mkdir -p doxygen-doc
doxygen Doxyfile
@ -131,6 +135,7 @@ mkdir_rootfs:
$(MKDIR_ROOTFS)/usr/share/
$(MKDIR_ROOTFS)/usr/include/
$(MKDIR_ROOTFS)/mnt/
$(MKDIR_ROOTFS)/tmp/
setup:
@ -141,7 +146,13 @@ setup:
setup-no-qemu:
$(MAKE) --quiet -C tools ci
build: build_kernel build_bootloader build_userspace build_drivers build_image
build:
$(MAKE) $(MAKE_QUIET_FLAG) mkdir_rootfs
$(MAKE) $(MAKE_QUIET_FLAG) build_kernel
$(MAKE) $(MAKE_QUIET_FLAG) build_bootloader
$(MAKE) $(MAKE_QUIET_FLAG) build_userspace
$(MAKE) $(MAKE_QUIET_FLAG) build_drivers
$(MAKE) $(MAKE_QUIET_FLAG) build_image
dump:
$(MAKE) --quiet -C Kernel dump
@ -157,66 +168,100 @@ __ci-build-set-debug:
ci-setup:
$(MAKE) --quiet -C tools ci
ci-build:
# Prepare
$(MAKE) prepare
$(MAKE) mkdir_rootfs
$(MAKE) --quiet -C tools do_limine
# amd64
__ci-amd64-debug:
$(MAKE) -C tools do_limine
$(MAKE) __ci-build-set-debug
sed -i 's/.*OSARCH = .*/OSARCH = amd64/' ./config.mk && cat config.mk | grep OSARCH
$(MAKE) build
mv Fennix.iso Fennix-amd64-debug.iso
$(MAKE) clean
__ci-amd64-release:
$(MAKE) -C tools do_limine
$(MAKE) __ci-build-set-release
sed -i 's/.*OSARCH = .*/OSARCH = amd64/' ./config.mk && cat config.mk | grep OSARCH
$(MAKE) build
mv Fennix.iso Fennix-amd64-release.iso
$(MAKE) clean
# i386
__ci-i386-debug:
$(MAKE) -C tools do_limine
$(MAKE) __ci-build-set-debug
sed -i 's/.*OSARCH = .*/OSARCH = i386/' ./config.mk && cat config.mk | grep OSARCH
$(MAKE) build
mv Fennix.iso Fennix-i386-debug.iso
$(MAKE) clean
__ci-i386-release:
$(MAKE) -C tools do_limine
$(MAKE) __ci-build-set-release
sed -i 's/.*OSARCH = .*/OSARCH = i386/' ./config.mk && cat config.mk | grep OSARCH
$(MAKE) build
mv Fennix.iso Fennix-i386-release.iso
$(MAKE) clean
# ARM
__ci-arm-debug:
$(MAKE) -C tools do_limine
$(MAKE) __ci-build-set-debug
sed -i 's/.*OSARCH = .*/OSARCH = arm/' ./config.mk && cat config.mk | grep OSARCH
$(MAKE) build
mv Fennix.iso Fennix-arm-debug.iso
$(MAKE) clean
__ci-arm-release:
$(MAKE) -C tools do_limine
$(MAKE) __ci-build-set-release
sed -i 's/.*OSARCH = .*/OSARCH = arm/' ./config.mk && cat config.mk | grep OSARCH
$(MAKE) build
mv Fennix.iso Fennix-arm-release.iso
$(MAKE) clean
# AArch64
__ci-aarch64-debug:
$(MAKE) -C tools do_limine
$(MAKE) __ci-build-set-debug
sed -i 's/.*OSARCH = .*/OSARCH = aarch64/' ./config.mk && cat config.mk | grep OSARCH
$(MAKE) build
mv Fennix.iso Fennix-aarch64-debug.iso
$(MAKE) clean
__ci-aarch64-release:
$(MAKE) -C tools do_limine
$(MAKE) __ci-build-set-release
sed -i 's/.*OSARCH = .*/OSARCH = aarch64/' ./config.mk && cat config.mk | grep OSARCH
$(MAKE) build
mv Fennix.iso Fennix-aarch64-release.iso
$(MAKE) clean
# Restore original config
__ci-restore-config:
$(MAKE) __ci-build-set-debug
sed -i 's/.*OSARCH = .*/OSARCH = amd64/' ./config.mk && cat config.mk | grep OSARCH
# Move all files to artifacts directory
__ci-prepare-archive:
mkdir -p artifacts
$(MAKE) changelog
cp -f CHANGELOG.md artifacts/
mv -f Fennix-*.iso artifacts/
ci-build:
# Prepare
$(MAKE) prepare
$(MAKE) mkdir_rootfs
$(MAKE) clean
$(MAKE) __ci-amd64-debug
$(MAKE) __ci-amd64-release
$(MAKE) __ci-i386-debug
$(MAKE) __ci-i386-release
$(MAKE) __ci-arm-debug
$(MAKE) __ci-arm-release
$(MAKE) __ci-aarch64-debug
$(MAKE) __ci-aarch64-release
$(MAKE) __ci-restore-config
$(MAKE) __ci-prepare-archive
changelog:
git cliff > CHANGELOG.md
ifeq ($(QUIET_BUILD), 1)
MAKE_QUIET_FLAG = --quiet
endif
build_kernel:
ifeq ($(BUILD_KERNEL), 1)
$(MAKE) -j$(shell nproc) $(MAKE_QUIET_FLAG) -C Kernel build
@ -252,10 +297,8 @@ endif
chmod 755 tmp_rootfs/home/
chmod -R 750 tmp_rootfs/home/root/
chmod -R 777 tmp_rootfs/tmp/
# tar czf rootfs.tar -C tmp_rootfs/ --owner=0 --group=0 ./ --format=ustar
tar cf rootfs.tar -C tmp_rootfs/ --owner=0 --group=0 ./ --format=ustar
cp Kernel/fennix.elf rootfs.tar \
iso_tmp_data/
tar czf rootfs.tar.gz -C tmp_rootfs/ --owner=0 --group=0 ./ --format=ustar
cp Kernel/fennix.elf rootfs.tar.gz iso_tmp_data/
ifeq ($(BOOTLOADER), limine)
cp tools/limine.conf \
tools/limine/limine-bios.sys \
@ -314,7 +357,7 @@ ifeq ($(OSARCH), amd64)
QEMUHWACCELERATION = -machine q35 -enable-kvm
QEMUMEMORY = -m 4G
QEMU_DBG_SMP = -smp 1
QEMU_DBG_MEMORY = -m 512M
QEMU_DBG_MEMORY = -m 256M
else ifeq ($(OSARCH), i386)
QEMUHWACCELERATION = -machine q35 -enable-kvm
QEMUMEMORY = -m 4G
@ -372,7 +415,7 @@ run: build qemu
clean: clean_logs
rm -rf doxygen-doc iso_tmp_data tmp_rootfs
rm -f rootfs.tar $(OSNAME).iso $(OSNAME).img
rm -f rootfs.tar.gz $(OSNAME).iso $(OSNAME).img
$(MAKE) -C Kernel clean
$(MAKE) -C Userspace clean
$(MAKE) -C Drivers clean

View File

@ -7,6 +7,14 @@ if(NOT DEFINED ENV{WORKSPACE_DIR})
else()
set(STANDALONE_BUILD OFF)
message(STATUS "Compiling within workspace")
if(DEFINED ENV{QUIET_BUILD})
message(STATUS "Quiet build enabled")
set(CMAKE_INSTALL_MESSAGE NEVER)
set(CMAKE_MESSAGE_LOG_LEVEL "WARNING")
set(MAKEFLAGS "--no-print-directory")
set(CMAKE_VERBOSE_MAKEFILE OFF)
set_property(GLOBAL PROPERTY RULE_MESSAGES OFF)
endif()
endif()
set(CMAKE_C_COMPILER "$ENV{CC}")

View File

@ -16,6 +16,14 @@ if(NOT DEFINED ENV{WORKSPACE_DIR})
else()
set(STANDALONE_BUILD OFF)
message(STATUS "Compiling within workspace")
if(DEFINED ENV{QUIET_BUILD})
message(STATUS "Quiet build enabled")
set(CMAKE_INSTALL_MESSAGE NEVER)
set(CMAKE_MESSAGE_LOG_LEVEL "WARNING")
set(MAKEFLAGS "--no-print-directory")
set(CMAKE_VERBOSE_MAKEFILE OFF)
set_property(GLOBAL PROPERTY RULE_MESSAGES OFF)
endif()
if(NOT DEFINED ENV{CMAKE_INSTALL_PREFIX})
set(CMAKE_INSTALL_PREFIX "$ENV{WORKSPACE_DIR}/out/sys")

View File

@ -0,0 +1,34 @@
cmake_minimum_required(VERSION 3.10)
project(FennixRuntime_${TARGET_OS}_${TARGET_ARCH})
find_program(COMPILER_PATH NAMES $ENV{CC} gcc REQUIRED)
set(LIB_OUTPUT_DIR "${CMAKE_INSTALL_PREFIX}/lib")
file(MAKE_DIRECTORY ${LIB_OUTPUT_DIR})
add_custom_target(copy_crt_files ALL
COMMAND ${COMPILER_PATH} -print-file-name=libgcc.a | xargs cp -t ${LIB_OUTPUT_DIR}
COMMAND ${COMPILER_PATH} -print-file-name=crtbegin.o | xargs cp -t ${LIB_OUTPUT_DIR}
COMMAND ${COMPILER_PATH} -print-file-name=crtend.o | xargs cp -t ${LIB_OUTPUT_DIR}
COMMAND ${COMPILER_PATH} -print-file-name=crti.o | xargs cp -t ${LIB_OUTPUT_DIR}
COMMAND ${COMPILER_PATH} -print-file-name=crtn.o | xargs cp -t ${LIB_OUTPUT_DIR}
COMMENT "Copying CRT files"
)
file(GLOB CRT_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/*.c")
set(OBJECT_FILES "")
foreach(source ${CRT_SOURCES})
get_filename_component(name ${source} NAME_WE)
set(obj "${CMAKE_BINARY_DIR}/${name}.o")
add_custom_command(
OUTPUT ${obj}
COMMAND ${COMPILER_PATH} -c ${source} -o ${obj}
DEPENDS ${source}
)
list(APPEND OBJECT_FILES ${obj})
endforeach()
if(OBJECT_FILES)
add_custom_target(crt_objects ALL DEPENDS ${OBJECT_FILES})
install(FILES ${OBJECT_FILES} DESTINATION lib)
endif()

View File

@ -0,0 +1 @@
#include "crt1.c"

View File

@ -0,0 +1,53 @@
/*
This file is part of Fennix C Library.
Fennix C Library 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 C Library 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 C Library. If not, see <https://www.gnu.org/licenses/>.
*/
__attribute__((naked, used, no_stack_protector, section(".text"))) void _start()
{
#warning "crt1.c: _start() is not implemented yet"
}
/* These are declared in GNU ld */
enum
{
NT_FNX_ABI_TAG = 1,
NT_FNX_VERSION = 2,
NT_FNX_BUILD_ID = 3,
NT_FNX_ARCH = 4
};
typedef struct Elf_Nhdr
{
__UINT32_TYPE__ n_namesz;
__UINT32_TYPE__ n_descsz;
__UINT32_TYPE__ n_type;
char n_name[];
} __attribute__((packed)) Elf_Nhdr;
const struct
{
Elf_Nhdr header;
char name[4];
__UINT32_TYPE__ desc[4];
} __abi_tag __attribute__((used, aligned(4), section(".note.ABI-tag"))) = {
.header = {
.n_namesz = 4, /* "FNX" + '\0' */
.n_descsz = sizeof(__UINT32_TYPE__) * 4, /* Description Size */
.n_type = NT_FNX_ABI_TAG, /* Type */
},
.name = "FNX",
.desc = {0, 0, 0, 0},
};

View File

@ -0,0 +1,34 @@
cmake_minimum_required(VERSION 3.10)
project(FennixRuntime_${TARGET_OS}_${TARGET_ARCH})
find_program(COMPILER_PATH NAMES $ENV{CC} gcc REQUIRED)
set(LIB_OUTPUT_DIR "${CMAKE_INSTALL_PREFIX}/lib")
file(MAKE_DIRECTORY ${LIB_OUTPUT_DIR})
add_custom_target(copy_crt_files ALL
COMMAND ${COMPILER_PATH} -print-file-name=libgcc.a | xargs cp -t ${LIB_OUTPUT_DIR}
COMMAND ${COMPILER_PATH} -print-file-name=crtbegin.o | xargs cp -t ${LIB_OUTPUT_DIR}
COMMAND ${COMPILER_PATH} -print-file-name=crtend.o | xargs cp -t ${LIB_OUTPUT_DIR}
COMMAND ${COMPILER_PATH} -print-file-name=crti.o | xargs cp -t ${LIB_OUTPUT_DIR}
COMMAND ${COMPILER_PATH} -print-file-name=crtn.o | xargs cp -t ${LIB_OUTPUT_DIR}
COMMENT "Copying CRT files"
)
file(GLOB CRT_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/*.c")
set(OBJECT_FILES "")
foreach(source ${CRT_SOURCES})
get_filename_component(name ${source} NAME_WE)
set(obj "${CMAKE_BINARY_DIR}/${name}.o")
add_custom_command(
OUTPUT ${obj}
COMMAND ${COMPILER_PATH} -c ${source} -o ${obj}
DEPENDS ${source}
)
list(APPEND OBJECT_FILES ${obj})
endforeach()
if(OBJECT_FILES)
add_custom_target(crt_objects ALL DEPENDS ${OBJECT_FILES})
install(FILES ${OBJECT_FILES} DESTINATION lib)
endif()

View File

@ -0,0 +1 @@
#include "crt1.c"

View File

@ -0,0 +1,53 @@
/*
This file is part of Fennix C Library.
Fennix C Library 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 C Library 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 C Library. If not, see <https://www.gnu.org/licenses/>.
*/
__attribute__((naked, used, no_stack_protector, section(".text"))) void _start()
{
#warning "crt1.c: _start() is not implemented yet"
}
/* These are declared in GNU ld */
enum
{
NT_FNX_ABI_TAG = 1,
NT_FNX_VERSION = 2,
NT_FNX_BUILD_ID = 3,
NT_FNX_ARCH = 4
};
typedef struct Elf_Nhdr
{
__UINT32_TYPE__ n_namesz;
__UINT32_TYPE__ n_descsz;
__UINT32_TYPE__ n_type;
char n_name[];
} __attribute__((packed)) Elf_Nhdr;
const struct
{
Elf_Nhdr header;
char name[4];
__UINT32_TYPE__ desc[4];
} __abi_tag __attribute__((used, aligned(4), section(".note.ABI-tag"))) = {
.header = {
.n_namesz = 4, /* "FNX" + '\0' */
.n_descsz = sizeof(__UINT32_TYPE__) * 4, /* Description Size */
.n_type = NT_FNX_ABI_TAG, /* Type */
},
.name = "FNX",
.desc = {0, 0, 0, 0},
};

View File

@ -0,0 +1,34 @@
cmake_minimum_required(VERSION 3.10)
project(FennixRuntime_${TARGET_OS}_${TARGET_ARCH})
find_program(COMPILER_PATH NAMES $ENV{CC} gcc REQUIRED)
set(LIB_OUTPUT_DIR "${CMAKE_INSTALL_PREFIX}/lib")
file(MAKE_DIRECTORY ${LIB_OUTPUT_DIR})
add_custom_target(copy_crt_files ALL
COMMAND ${COMPILER_PATH} -print-file-name=libgcc.a | xargs cp -t ${LIB_OUTPUT_DIR}
COMMAND ${COMPILER_PATH} -print-file-name=crtbegin.o | xargs cp -t ${LIB_OUTPUT_DIR}
COMMAND ${COMPILER_PATH} -print-file-name=crtend.o | xargs cp -t ${LIB_OUTPUT_DIR}
COMMAND ${COMPILER_PATH} -print-file-name=crti.o | xargs cp -t ${LIB_OUTPUT_DIR}
COMMAND ${COMPILER_PATH} -print-file-name=crtn.o | xargs cp -t ${LIB_OUTPUT_DIR}
COMMENT "Copying CRT files"
)
file(GLOB CRT_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/*.c")
set(OBJECT_FILES "")
foreach(source ${CRT_SOURCES})
get_filename_component(name ${source} NAME_WE)
set(obj "${CMAKE_BINARY_DIR}/${name}.o")
add_custom_command(
OUTPUT ${obj}
COMMAND ${COMPILER_PATH} -c ${source} -o ${obj}
DEPENDS ${source}
)
list(APPEND OBJECT_FILES ${obj})
endforeach()
if(OBJECT_FILES)
add_custom_target(crt_objects ALL DEPENDS ${OBJECT_FILES})
install(FILES ${OBJECT_FILES} DESTINATION lib)
endif()

View File

@ -0,0 +1 @@
#include "crt1.c"

View File

@ -0,0 +1,53 @@
/*
This file is part of Fennix C Library.
Fennix C Library 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 C Library 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 C Library. If not, see <https://www.gnu.org/licenses/>.
*/
__attribute__((naked, used, no_stack_protector, section(".text"))) void _start()
{
#warning "crt1.c: _start() is not implemented yet"
}
/* These are declared in GNU ld */
enum
{
NT_FNX_ABI_TAG = 1,
NT_FNX_VERSION = 2,
NT_FNX_BUILD_ID = 3,
NT_FNX_ARCH = 4
};
typedef struct Elf_Nhdr
{
__UINT32_TYPE__ n_namesz;
__UINT32_TYPE__ n_descsz;
__UINT32_TYPE__ n_type;
char n_name[];
} __attribute__((packed)) Elf_Nhdr;
const struct
{
Elf_Nhdr header;
char name[4];
__UINT32_TYPE__ desc[4];
} __abi_tag __attribute__((used, aligned(4), section(".note.ABI-tag"))) = {
.header = {
.n_namesz = 4, /* "FNX" + '\0' */
.n_descsz = sizeof(__UINT32_TYPE__) * 4, /* Description Size */
.n_type = NT_FNX_ABI_TAG, /* Type */
},
.name = "FNX",
.desc = {0, 0, 0, 0},
};

View File

@ -100,6 +100,7 @@ export OSNAME
export OSARCH
export BOARD_TYPE
export KERNEL_VERSION
export QUIET_BUILD
export TOOLCHAIN_AMD64_PREFIX := $(COMPILER_PATH)/bin/x86_64-fennix-
export TOOLCHAIN_I386_PREFIX := $(COMPILER_PATH)/bin/i386-fennix-

View File

@ -2,8 +2,10 @@
theme=vga
[cursor]
color=255,255,255
blink=true
color=244,244,244
char=_
delay=250
[vga]
color0=0,0,0:133,133,133

View File

@ -9,7 +9,7 @@ menuentry "Fennix" {
echo "Loading kernel"
multiboot2 /fennix.elf --init=/sys/bin/init
echo "Loading rootfs"
module2 /rootfs.tar rootfs
module2 /rootfs.tar.gz rootfs
echo "Booting..."
boot
}
@ -19,9 +19,9 @@ submenu "Advanced Options..." {
load_video
clear
echo "Loading kernel in Linux Subsystem mode"
multiboot2 /fennix.elf --init=/bin/init --linux=true
multiboot2 /fennix.elf --linux=true
echo "Loading rootfs"
module2 /rootfs.tar rootfs
module2 /rootfs.tar.gz rootfs
echo "Booting..."
boot
}
@ -32,7 +32,7 @@ submenu "Advanced Options..." {
echo "Loading kernel in recovery mode"
multiboot2 /fennix.elf
echo "Loading rootfs"
module2 /rootfs.tar rootfs
module2 /rootfs.tar.gz rootfs
echo "Booting..."
boot
}