mirror of
https://github.com/EnderIce2/Fennix.git
synced 2025-05-25 22:14:34 +00:00
Compare commits
47 Commits
0041300a00
...
abb7899a9d
Author | SHA1 | Date | |
---|---|---|---|
abb7899a9d | |||
8c4c8d36de | |||
0fffc6c914 | |||
34e24df7c9 | |||
550e98e87c | |||
4ff6790072 | |||
205ddb1e49 | |||
0735743f44 | |||
33eee9c628 | |||
ef5d61df9d | |||
11d326b693 | |||
5293bb2039 | |||
bc84c406d9 | |||
ed1f4f3c1b | |||
ec04e5abe9 | |||
5ecfffc049 | |||
c7d501b466 | |||
1f646d6826 | |||
3315d79742 | |||
a1b58bacd8 | |||
69122746de | |||
764dfe67a5 | |||
3d87345a51 | |||
eb89b060f6 | |||
25713e0f13 | |||
03147b532c | |||
d8cd27196d | |||
832833a56f | |||
a4e5f4785c | |||
a268f8dc2f | |||
a16a88b5f9 | |||
2d2d28689c | |||
d4346202ca | |||
b1a30059ed | |||
58accf8acf | |||
24c0848797 | |||
b232dc6b40 | |||
120d67fb1a | |||
f6eb4bd3dc | |||
7e7e475dac | |||
23d0056098 | |||
3edb4b4761 | |||
fd24431eea | |||
5c1c26b135 | |||
a333d8aa7c | |||
f054e9976a | |||
f87c3d7e11 |
62
.github/workflows/makefile.yml
vendored
62
.github/workflows/makefile.yml
vendored
@ -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
2
.gitignore
vendored
@ -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
251
.vscode/tasks.json
vendored
@ -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"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,6 @@
|
||||
"settings": {
|
||||
"terminal.integrated.cwd": "../",
|
||||
"debug.allowBreakpointsEverywhere": true,
|
||||
"git.alwaysSignOff": true,
|
||||
"git.defaultBranchName": "master",
|
||||
"git.openRepositoryInParentFolders": "always",
|
||||
"C_Cpp.autoAddFileAssociations": false,
|
||||
|
@ -6,9 +6,8 @@
|
||||
],
|
||||
"settings": {
|
||||
"debug.allowBreakpointsEverywhere": true,
|
||||
"git.alwaysSignOff": true,
|
||||
"git.defaultBranchName": "master",
|
||||
"git.openRepositoryInParentFolders": "always",
|
||||
"C_Cpp.autoAddFileAssociations": false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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 *)§ions[bInfo.Kernel.Symbols.EntSize * i];
|
||||
Elf_Shdr *str = (Elf_Shdr *)§ions[bInfo.Kernel.Symbols.EntSize *
|
||||
sym->sh_link];
|
||||
Elf_Shdr *str = (Elf_Shdr *)§ions[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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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.");
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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 *)§ions[bInfo.Kernel.Symbols.EntSize * i];
|
||||
Elf_Shdr *str = (Elf_Shdr *)§ions[bInfo.Kernel.Symbols.EntSize *
|
||||
sym->sh_link];
|
||||
Elf_Shdr *str = (Elf_Shdr *)§ions[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__)
|
||||
|
@ -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);
|
||||
|
@ -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 *)§ions[EntSize * i];
|
||||
Elf_Shdr *str = (Elf_Shdr *)§ions[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))
|
||||
{
|
||||
|
@ -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;
|
||||
|
@ -1,4 +1,4 @@
|
||||
const char *trusted_drivers[] = {
|
||||
"ae08d2e120c8370278ca9e17085a6b9e2f4a470ab6cec824c77ab1f8706c7144f5d4e1c9820914ed4fc7a4fd22de4b18bfed7c3b5d9c1e604e82280d7d45a5c7",
|
||||
"66ff6a13e27cfee4b37e153fbdeeabb2de44f2a6a4d7f929f0b48d05a08b44c8c543f15c6cee05b5392166088f5ba260db5a64476d150ce81b295e4aa5a85d32",
|
||||
};
|
||||
const __SIZE_TYPE__ trusted_drivers_count = sizeof(trusted_drivers) / sizeof(trusted_drivers[0]);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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__
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
150
Kernel/include/filesystem/ramfs.hpp
Normal file
150
Kernel/include/filesystem/ramfs.hpp
Normal 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);
|
@ -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__
|
||||
|
@ -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[];
|
||||
|
||||
|
@ -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
|
||||
{
|
||||
}
|
31
Kernel/include/subsystems.hpp
Normal file
31
Kernel/include/subsystems.hpp
Normal 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();
|
||||
}
|
||||
}
|
@ -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();
|
||||
|
@ -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" \
|
||||
|
@ -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
112
Kernel/include_std/array
Normal 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;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
}
|
||||
|
@ -1579,6 +1579,7 @@ namespace std
|
||||
{
|
||||
std::copy(begin() + index + count, end(), begin() + index);
|
||||
_size -= count;
|
||||
_data[_size] = '\0';
|
||||
}
|
||||
|
||||
return *this;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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++;
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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");
|
||||
|
@ -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");
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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 */
|
||||
|
@ -15,4 +15,8 @@
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "../../kernel.h"
|
||||
#include <security.hpp>
|
||||
|
||||
namespace Security
|
||||
{
|
||||
}
|
@ -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;
|
||||
|
||||
|
@ -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
417
Kernel/storage/fs/ramfs.cpp
Normal 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;
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
@ -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__
|
||||
|
59
Kernel/subsystem/linux/init.cpp
Normal file
59
Kernel/subsystem/linux/init.cpp
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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},
|
||||
|
47
Kernel/subsystem/windows/init.cpp
Normal file
47
Kernel/subsystem/windows/init.cpp
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
{
|
||||
|
88
Kernel/tests/stl/array.cpp
Normal file
88
Kernel/tests/stl/array.cpp
Normal 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
|
@ -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
|
||||
|
@ -24,16 +24,6 @@
|
||||
|
||||
namespace TTY
|
||||
{
|
||||
PTMXDevice::PTMXDevice()
|
||||
{
|
||||
}
|
||||
|
||||
PTMXDevice::~PTMXDevice()
|
||||
{
|
||||
for (auto pty : PTYs)
|
||||
delete pty;
|
||||
}
|
||||
|
||||
int PTMXDevice::Open()
|
||||
{
|
||||
stub;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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; }
|
||||
}
|
||||
|
87
Makefile
87
Makefile
@ -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
|
||||
|
@ -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}")
|
||||
|
@ -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")
|
||||
|
34
Userspace/libc/runtime/fennix/aarch64/CMakeLists.txt
Normal file
34
Userspace/libc/runtime/fennix/aarch64/CMakeLists.txt
Normal 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()
|
1
Userspace/libc/runtime/fennix/aarch64/Scrt1.c
Normal file
1
Userspace/libc/runtime/fennix/aarch64/Scrt1.c
Normal file
@ -0,0 +1 @@
|
||||
#include "crt1.c"
|
53
Userspace/libc/runtime/fennix/aarch64/crt1.c
Normal file
53
Userspace/libc/runtime/fennix/aarch64/crt1.c
Normal 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},
|
||||
};
|
34
Userspace/libc/runtime/fennix/arm/CMakeLists.txt
Normal file
34
Userspace/libc/runtime/fennix/arm/CMakeLists.txt
Normal 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()
|
1
Userspace/libc/runtime/fennix/arm/Scrt1.c
Normal file
1
Userspace/libc/runtime/fennix/arm/Scrt1.c
Normal file
@ -0,0 +1 @@
|
||||
#include "crt1.c"
|
53
Userspace/libc/runtime/fennix/arm/crt1.c
Normal file
53
Userspace/libc/runtime/fennix/arm/crt1.c
Normal 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},
|
||||
};
|
34
Userspace/libc/runtime/fennix/i386/CMakeLists.txt
Normal file
34
Userspace/libc/runtime/fennix/i386/CMakeLists.txt
Normal 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()
|
1
Userspace/libc/runtime/fennix/i386/Scrt1.c
Normal file
1
Userspace/libc/runtime/fennix/i386/Scrt1.c
Normal file
@ -0,0 +1 @@
|
||||
#include "crt1.c"
|
53
Userspace/libc/runtime/fennix/i386/crt1.c
Normal file
53
Userspace/libc/runtime/fennix/i386/crt1.c
Normal 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},
|
||||
};
|
@ -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-
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user