mirror of
https://github.com/Fennix-Project/Kernel.git
synced 2025-05-25 14:04:36 +00:00
Update kernel
This commit is contained in:
parent
fd15592608
commit
96daa43d38
91
.gdbinit
Normal file
91
.gdbinit
Normal file
@ -0,0 +1,91 @@
|
||||
# Usage: add-symbol-file-all <filename> [<offset>]
|
||||
# remove-symbol-file-all <filename> [<offset>]
|
||||
#
|
||||
# Credit: https://stackoverflow.com/a/33087762/9352057
|
||||
# CC BY-SA 4.0
|
||||
|
||||
python
|
||||
import subprocess
|
||||
import re
|
||||
|
||||
def relocatesections(filename, addr):
|
||||
p = subprocess.Popen(["readelf", "-S", filename], stdout = subprocess.PIPE)
|
||||
|
||||
sections = []
|
||||
textaddr = '0'
|
||||
for line in p.stdout.readlines():
|
||||
line = line.decode("utf-8").strip()
|
||||
if not line.startswith('[') or line.startswith('[Nr]'):
|
||||
continue
|
||||
|
||||
line = re.sub(r' +', ' ', line)
|
||||
line = re.sub(r'\[ *(\d+)\]', '\g<1>', line)
|
||||
fieldsvalue = line.split(' ')
|
||||
fieldsname = ['number', 'name', 'type', 'addr', 'offset', 'size', 'entsize', 'flags', 'link', 'info', 'addralign']
|
||||
sec = dict(zip(fieldsname, fieldsvalue))
|
||||
|
||||
if sec['number'] == '0':
|
||||
continue
|
||||
|
||||
sections.append(sec)
|
||||
|
||||
if sec['name'] == '.text':
|
||||
textaddr = sec['addr']
|
||||
|
||||
return (textaddr, sections)
|
||||
|
||||
|
||||
class AddSymbolFileAll(gdb.Command):
|
||||
"""The right version for add-symbol-file"""
|
||||
|
||||
def __init__(self):
|
||||
super(AddSymbolFileAll, self).__init__("add-symbol-file-all", gdb.COMMAND_USER)
|
||||
self.dont_repeat()
|
||||
|
||||
def invoke(self, arg, from_tty):
|
||||
argv = gdb.string_to_argv(arg)
|
||||
filename = argv[0]
|
||||
|
||||
if len(argv) > 1:
|
||||
offset = int(str(gdb.parse_and_eval(argv[1])), 0)
|
||||
else:
|
||||
offset = 0
|
||||
|
||||
(textaddr, sections) = relocatesections(filename, offset)
|
||||
|
||||
cmd = "add-symbol-file %s 0x%08x" % (filename, int(textaddr, 16) + offset)
|
||||
|
||||
for s in sections:
|
||||
addr = int(s['addr'], 16)
|
||||
if s['name'] == '.text' or addr == 0:
|
||||
continue
|
||||
|
||||
cmd += " -s %s 0x%08x" % (s['name'], addr + offset)
|
||||
|
||||
gdb.execute(cmd)
|
||||
|
||||
class RemoveSymbolFileAll(gdb.Command):
|
||||
"""The right version for remove-symbol-file"""
|
||||
|
||||
def __init__(self):
|
||||
super(RemoveSymbolFileAll, self).__init__("remove-symbol-file-all", gdb.COMMAND_USER)
|
||||
self.dont_repeat()
|
||||
|
||||
def invoke(self, arg, from_tty):
|
||||
argv = gdb.string_to_argv(arg)
|
||||
filename = argv[0]
|
||||
|
||||
if len(argv) > 1:
|
||||
offset = int(str(gdb.parse_and_eval(argv[1])), 0)
|
||||
else:
|
||||
offset = 0
|
||||
|
||||
(textaddr, _) = relocatesections(filename, offset)
|
||||
|
||||
cmd = "remove-symbol-file -a 0x%08x" % (int(textaddr, 16) + offset)
|
||||
gdb.execute(cmd)
|
||||
|
||||
|
||||
AddSymbolFileAll()
|
||||
RemoveSymbolFileAll()
|
||||
end
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -2,5 +2,5 @@
|
||||
*.su
|
||||
*.gcno
|
||||
*.map
|
||||
*.fsys
|
||||
fennix.elf
|
||||
*.log
|
||||
|
137
.vscode/c_boilerplates.code-snippets
vendored
137
.vscode/c_boilerplates.code-snippets
vendored
@ -21,14 +21,14 @@
|
||||
"\talong with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.",
|
||||
"*/",
|
||||
"",
|
||||
"#ifndef __FENNIX_KERNEL_${2:header}_H__",
|
||||
"#define __FENNIX_KERNEL_${2:header}_H__",
|
||||
"#ifndef __FENNIX_KERNEL_${1:header}_H__",
|
||||
"#define __FENNIX_KERNEL_${1:header}_H__",
|
||||
"",
|
||||
"#include <types.h>",
|
||||
"",
|
||||
"$0",
|
||||
"",
|
||||
"#endif // !__FENNIX_KERNEL_${2:header}_H__",
|
||||
"#endif // !__FENNIX_KERNEL_${1:header}_H__",
|
||||
""
|
||||
],
|
||||
"description": "Create kernel header."
|
||||
@ -42,7 +42,7 @@
|
||||
],
|
||||
"description": "Create kernel documentation brief."
|
||||
},
|
||||
"For Iteratoion": {
|
||||
"For Iteration": {
|
||||
"prefix": [
|
||||
"foritr",
|
||||
],
|
||||
@ -77,5 +77,134 @@
|
||||
"*/"
|
||||
],
|
||||
"description": "Create kernel license."
|
||||
},
|
||||
"Driver Code": {
|
||||
"prefix": [
|
||||
"driver",
|
||||
],
|
||||
"body": [
|
||||
"/*",
|
||||
"\tThis file is part of Fennix Kernel.",
|
||||
"",
|
||||
"\tFennix Kernel is free software: you can redistribute it and/or",
|
||||
"\tmodify it under the terms of the GNU General Public License as",
|
||||
"\tpublished by the Free Software Foundation, either version 3 of",
|
||||
"\tthe License, or (at your option) any later version.",
|
||||
"",
|
||||
"\tFennix Kernel is distributed in the hope that it will be useful,",
|
||||
"\tbut WITHOUT ANY WARRANTY; without even the implied warranty of",
|
||||
"\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the",
|
||||
"\tGNU General Public License for more details.",
|
||||
"",
|
||||
"\tYou should have received a copy of the GNU General Public License",
|
||||
"\talong with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.",
|
||||
"*/",
|
||||
"",
|
||||
"#include \"${1:driver}.hpp\"",
|
||||
"",
|
||||
"#include <debug.h>",
|
||||
"",
|
||||
"#include \"../../../kernel.h\"",
|
||||
"",
|
||||
"namespace Driver",
|
||||
"{",
|
||||
"\tint ${2:driver}::drvOpen(int Flags, mode_t Mode) { return 0; }",
|
||||
"",
|
||||
"\tint ${2:driver}::drvClose() { return 0; }",
|
||||
"",
|
||||
"\tsize_t ${2:driver}::drvRead(uint8_t *Buffer, size_t Size, off_t Offset) { return 0; }",
|
||||
"",
|
||||
"\tsize_t ${2:driver}::drvWrite(uint8_t *Buffer, size_t Size, off_t Offset) { return 0; }",
|
||||
"",
|
||||
"\tint ${2:driver}::drvIoctl(unsigned long Request, void *Argp) { return 0; }",
|
||||
"",
|
||||
"\tvoid ${2:driver}::OnInterruptReceived(CPU::TrapFrame *) {}",
|
||||
"",
|
||||
"\tvoid ${2:driver}::Panic() {}",
|
||||
"",
|
||||
"\t${2:driver}::${2:driver}(PCI::PCIDevice dev)",
|
||||
"\t\t: Object(dev),",
|
||||
"\t\t Interrupts::Handler(dev)",
|
||||
"\t{",
|
||||
"\t}",
|
||||
"",
|
||||
"\t${2:driver}::${2:driver}(int irq)",
|
||||
"\t\t: Object(irq),",
|
||||
"\t\t Interrupts::Handler(irq)",
|
||||
"\t{",
|
||||
"\t}",
|
||||
"",
|
||||
"\t${2:driver}::${2:driver}()",
|
||||
"\t{",
|
||||
"\t}",
|
||||
"",
|
||||
"\t${2:driver}::~${2:driver}()",
|
||||
"\t{",
|
||||
"\t\tif (GetError() != 0)",
|
||||
"\t\t\treturn;",
|
||||
"\t}",
|
||||
"}",
|
||||
"",
|
||||
|
||||
],
|
||||
"description": "Kernel driver code template."
|
||||
},
|
||||
"Driver Header": {
|
||||
"prefix": [
|
||||
"driver",
|
||||
],
|
||||
"body": [
|
||||
"/*",
|
||||
"\tThis file is part of Fennix Kernel.",
|
||||
"",
|
||||
"\tFennix Kernel is free software: you can redistribute it and/or",
|
||||
"\tmodify it under the terms of the GNU General Public License as",
|
||||
"\tpublished by the Free Software Foundation, either version 3 of",
|
||||
"\tthe License, or (at your option) any later version.",
|
||||
"",
|
||||
"\tFennix Kernel is distributed in the hope that it will be useful,",
|
||||
"\tbut WITHOUT ANY WARRANTY; without even the implied warranty of",
|
||||
"\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the",
|
||||
"\tGNU General Public License for more details.",
|
||||
"",
|
||||
"\tYou should have received a copy of the GNU General Public License",
|
||||
"\talong with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.",
|
||||
"*/",
|
||||
"",
|
||||
"#pragma once",
|
||||
"#include <driver.hpp>",
|
||||
"",
|
||||
"namespace Driver",
|
||||
"{",
|
||||
"\tclass ${1:driver} : public Object, public Interrupts::Handler",
|
||||
"\t{",
|
||||
"\tprivate:",
|
||||
"\t\tvoid OnInterruptReceived(CPU::TrapFrame *Frame) final;",
|
||||
"\t\tvoid Panic(Driver::DriverContext *ctx) final;",
|
||||
"",
|
||||
"\tpublic:",
|
||||
"\t\tint drvOpen(int Flags, mode_t Mode);",
|
||||
"\t\tint drvClose();",
|
||||
"\t\tsize_t drvRead(uint8_t *Buffer, size_t Size, off_t Offset);",
|
||||
"\t\tsize_t drvWrite(uint8_t *Buffer, size_t Size, off_t Offset);",
|
||||
"\t\tint drvIoctl(unsigned long Request, void *Argp);",
|
||||
"",
|
||||
"\t\tconst char *drvName() final { return \"${2:MyDriver}\"; }",
|
||||
"\t\tconst char *drvDescription() final { return \"${3:MyDescription}\"; }",
|
||||
"\t\tconst char *drvVersion() final { return \"${4:0.0.0}\"; }",
|
||||
"\t\tconst char *drvAuthor() final { return \"${5:Author}\"; }",
|
||||
"\t\tconst char *drvLicense() final { return \"${6:License}\"; }",
|
||||
"\t\tDriverType drvType() final { return DriverType_${7:Generic}; }",
|
||||
"",
|
||||
"\t\t${1:driver}(PCI::PCIDevice dev);",
|
||||
"\t\t${1:driver}(int irq);",
|
||||
"\t\t${1:driver}();",
|
||||
"\t\t~${1:driver}();",
|
||||
"\t};",
|
||||
"}",
|
||||
"",
|
||||
|
||||
],
|
||||
"description": "Kernel driver header template."
|
||||
}
|
||||
}
|
18
.vscode/c_cpp_properties.json
vendored
18
.vscode/c_cpp_properties.json
vendored
@ -19,6 +19,9 @@
|
||||
"a86",
|
||||
"DEBUG=\"1\""
|
||||
],
|
||||
"forcedInclude": [
|
||||
"${workspaceFolder}/.vscode/preinclude.h"
|
||||
],
|
||||
"compilerPath": "${workspaceFolder}/../tools/cross/bin/x86_64-fennix-gcc",
|
||||
"cStandard": "c17",
|
||||
"cppStandard": "c++20",
|
||||
@ -34,7 +37,6 @@
|
||||
"-mcmodel=kernel",
|
||||
"-fno-builtin",
|
||||
"-m64",
|
||||
|
||||
// Warnings
|
||||
"-Wall",
|
||||
"-Wextra",
|
||||
@ -46,11 +48,9 @@
|
||||
"-Wswitch-default",
|
||||
"-Wstrict-overflow=5",
|
||||
"-Wconversion",
|
||||
|
||||
// C++ flags
|
||||
"-fno-rtti",
|
||||
"-fno-exceptions",
|
||||
|
||||
// Linker flags
|
||||
"-T${workspaceFolder}/arch/amd64/linker.ld",
|
||||
"-Wl,-static,--no-dynamic-linker,-ztext",
|
||||
@ -59,7 +59,6 @@
|
||||
"-nolibc",
|
||||
"-zmax-page-size=0x1000",
|
||||
"-shared",
|
||||
|
||||
// Debug flags
|
||||
"-ggdb3",
|
||||
"-O0",
|
||||
@ -68,7 +67,6 @@
|
||||
"-fstack-usage",
|
||||
"-fstack-check",
|
||||
"-fsanitize=undefined",
|
||||
|
||||
// VSCode flags
|
||||
"-ffreestanding",
|
||||
"-nostdinc",
|
||||
@ -112,7 +110,6 @@
|
||||
"-msoft-float",
|
||||
"-fno-builtin",
|
||||
"-m32",
|
||||
|
||||
// Warnings
|
||||
"-Wall",
|
||||
"-Wextra",
|
||||
@ -124,11 +121,9 @@
|
||||
"-Wswitch-default",
|
||||
"-Wstrict-overflow=5",
|
||||
"-Wconversion",
|
||||
|
||||
// C++ flags
|
||||
"-fno-rtti",
|
||||
"-fno-exceptions",
|
||||
|
||||
// Linker flags
|
||||
"-T${workspaceFolder}/arch/i386/linker.ld",
|
||||
"-Wl,-static,--no-dynamic-linker,-ztext",
|
||||
@ -137,7 +132,6 @@
|
||||
"-nolibc",
|
||||
"-zmax-page-size=0x1000",
|
||||
"-shared",
|
||||
|
||||
// Debug flags
|
||||
"-ggdb3",
|
||||
"-O0",
|
||||
@ -146,7 +140,6 @@
|
||||
"-fstack-usage",
|
||||
"-fstack-check",
|
||||
"-fsanitize=undefined",
|
||||
|
||||
// VSCode flags
|
||||
"-ffreestanding",
|
||||
"-nostdinc",
|
||||
@ -183,7 +176,6 @@
|
||||
"-msoft-float",
|
||||
"-fPIC",
|
||||
"-Wstack-protector",
|
||||
|
||||
// Warnings
|
||||
"-Wall",
|
||||
"-Wextra",
|
||||
@ -195,15 +187,12 @@
|
||||
"-Wswitch-default",
|
||||
"-Wstrict-overflow=5",
|
||||
"-Wconversion",
|
||||
|
||||
// C++ flags
|
||||
"-fno-rtti",
|
||||
"-fno-exceptions",
|
||||
|
||||
// Linker flags
|
||||
"-T${workspaceFolder}/arch/aarch64/linker.ld",
|
||||
"-fPIC",
|
||||
|
||||
// Debug flags
|
||||
"-ggdb3",
|
||||
"-O0",
|
||||
@ -212,7 +201,6 @@
|
||||
"-fstack-usage",
|
||||
"-fstack-check",
|
||||
"-fsanitize=undefined",
|
||||
|
||||
// VSCode flags
|
||||
"-ffreestanding",
|
||||
"-nostdinc",
|
||||
|
86
.vscode/launch.json
vendored
86
.vscode/launch.json
vendored
@ -5,7 +5,7 @@
|
||||
"name": "Attach to a running VM instance",
|
||||
"type": "cppdbg",
|
||||
"request": "launch",
|
||||
"program": "${workspaceFolder}/kernel.fsys",
|
||||
"program": "${workspaceFolder}/fennix.elf",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"args": [],
|
||||
"targetArchitecture": "x64",
|
||||
@ -31,63 +31,20 @@
|
||||
"description": "Make breakpoint pending on future shared library load."
|
||||
},
|
||||
{
|
||||
"text": "file ${workspaceFolder}/kernel.fsys",
|
||||
"description": "Load binary."
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Attach to VM w/userspace binaries",
|
||||
"type": "cppdbg",
|
||||
"request": "launch",
|
||||
"program": "${workspaceFolder}/kernel.fsys",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"args": [],
|
||||
"targetArchitecture": "x64",
|
||||
"MIMode": "gdb",
|
||||
"miDebuggerPath": "${workspaceFolder}/../tools/cross/bin/x86_64-fennix-gdb",
|
||||
"miDebuggerArgs": "",
|
||||
"externalConsole": false,
|
||||
"additionalSOLibSearchPath": "${workspaceFolder}",
|
||||
"customLaunchSetupCommands": [
|
||||
{
|
||||
"text": "target remote localhost:1234",
|
||||
"description": "Connect to QEMU remote debugger"
|
||||
}
|
||||
],
|
||||
"setupCommands": [
|
||||
{
|
||||
"description": "Enable pretty-printing for gdb",
|
||||
"text": "-enable-pretty-printing",
|
||||
"ignoreFailures": true
|
||||
},
|
||||
{
|
||||
"text": "set breakpoint pending on",
|
||||
"description": "Make breakpoint pending on future shared library load."
|
||||
},
|
||||
{
|
||||
"text": "file ${workspaceFolder}/kernel.fsys",
|
||||
"text": "file ${workspaceFolder}/fennix.elf",
|
||||
"description": "Load binary."
|
||||
},
|
||||
{
|
||||
"text": "add-symbol-file ${workspaceFolder}/../initrd_tmp_data/bin/init",
|
||||
"description": "Load /bin/init."
|
||||
},
|
||||
{
|
||||
"text": "add-symbol-file ${workspaceFolder}/../initrd_tmp_data/bin/utest",
|
||||
"description": "Load /bin/utest."
|
||||
},
|
||||
{
|
||||
"text": "add-symbol-file ${workspaceFolder}/../initrd_tmp_data/usr/bin/doom",
|
||||
"description": "Load /usr/bin/doom."
|
||||
},
|
||||
"text": "source ${workspaceFolder}/.gdbinit"
|
||||
}
|
||||
],
|
||||
"preLaunchTask": "launch-qemu"
|
||||
},
|
||||
{
|
||||
"name": "Attach to VM w/utest",
|
||||
"type": "cppdbg",
|
||||
"request": "launch",
|
||||
"program": "${workspaceFolder}/kernel.fsys",
|
||||
"program": "${workspaceFolder}/fennix.elf",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"args": [],
|
||||
"targetArchitecture": "x64",
|
||||
@ -113,20 +70,25 @@
|
||||
"description": "Make breakpoint pending on future shared library load."
|
||||
},
|
||||
{
|
||||
"text": "file ${workspaceFolder}/kernel.fsys",
|
||||
"text": "file ${workspaceFolder}/fennix.elf",
|
||||
"description": "Load binary."
|
||||
},
|
||||
{
|
||||
"text": "add-symbol-file ${workspaceFolder}/../initrd_tmp_data/bin/utest",
|
||||
"description": "Load /bin/utest."
|
||||
"description": "Load /bin/utest.",
|
||||
"ignoreFailures": true
|
||||
},
|
||||
{
|
||||
"text": "source ${workspaceFolder}/.gdbinit"
|
||||
}
|
||||
],
|
||||
"preLaunchTask": "launch-qemu",
|
||||
},
|
||||
{
|
||||
"name": "Attach to VM w/doom",
|
||||
"name": "Attach to VM w/utest_linux",
|
||||
"type": "cppdbg",
|
||||
"request": "launch",
|
||||
"program": "${workspaceFolder}/kernel.fsys",
|
||||
"program": "${workspaceFolder}/fennix.elf",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"args": [],
|
||||
"targetArchitecture": "x64",
|
||||
@ -152,14 +114,24 @@
|
||||
"description": "Make breakpoint pending on future shared library load."
|
||||
},
|
||||
{
|
||||
"text": "file ${workspaceFolder}/kernel.fsys",
|
||||
"text": "file ${workspaceFolder}/fennix.elf",
|
||||
"description": "Load binary."
|
||||
},
|
||||
{
|
||||
"text": "add-symbol-file ${workspaceFolder}/../initrd_tmp_data/usr/bin/doom",
|
||||
"description": "Load /usr/bin/doom."
|
||||
"text": "set debug-file-directory /usr/lib/debug",
|
||||
"description": "Set debug-file-directory to /usr/lib/debug.",
|
||||
"ignoreFailures": true
|
||||
},
|
||||
{
|
||||
"text": "add-symbol-file ${workspaceFolder}/../initrd_tmp_data/bin/utest_linux",
|
||||
"description": "Load /bin/utest_linux.",
|
||||
"ignoreFailures": true
|
||||
},
|
||||
{
|
||||
"text": "source ${workspaceFolder}/.gdbinit"
|
||||
}
|
||||
],
|
||||
}
|
||||
"preLaunchTask": "launch-qemu",
|
||||
},
|
||||
]
|
||||
}
|
7
.vscode/preinclude.h
vendored
Normal file
7
.vscode/preinclude.h
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
#undef __linux__
|
||||
#undef __WIN32__
|
||||
#undef __WIN64__
|
||||
#undef _WIN32
|
||||
#undef _WIN64
|
||||
#undef __APPLE__
|
||||
#undef __clang__
|
26
.vscode/tasks.json
vendored
Normal file
26
.vscode/tasks.json
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
{
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"label": "launch-qemu",
|
||||
"type": "shell",
|
||||
"command": "make -j$(shell nproc) build && make -C ../ build_image && make -C ../ vscode_debug_only",
|
||||
"isBackground": true,
|
||||
"problemMatcher": [],
|
||||
"group": {
|
||||
"kind": "build",
|
||||
"isDefault": true
|
||||
},
|
||||
"presentation": {
|
||||
"reveal": "always",
|
||||
"panel": "shared"
|
||||
},
|
||||
"options": {
|
||||
"shell": {
|
||||
"executable": "bash",
|
||||
"args": ["-c"]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
17
CREDITS.md
17
CREDITS.md
@ -8,6 +8,9 @@ License information can be found in the [LICENSES.md](LICENSES.md) file.
|
||||
- [OSDev Wiki](https://wiki.osdev.org/Main_Page)
|
||||
- [GCC x86 Built-in Functions](https://gcc.gnu.org/onlinedocs/gcc/x86-Built-in-Functions.html#x86-Built-in-Functions)
|
||||
- [GCC Common Function Attributes](https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#Common-Function-Attributes)
|
||||
- [LemonOS Project](https://github.com/LemonOSProject/LemonOS)
|
||||
- [ToaruOS](https://github.com/klange/toaruos)
|
||||
- [Various SIMD functions](https://wiki.osdev.org/User:01000101/optlib/)
|
||||
|
||||
## Font
|
||||
- [Tamsyn Font](http://www.fial.com/~scott/tamsyn-font/)
|
||||
@ -56,7 +59,6 @@ License information can be found in the [LICENSES.md](LICENSES.md) file.
|
||||
## Audio
|
||||
- [FFmpeg Audio Types](https://trac.ffmpeg.org/wiki/audio%20types)
|
||||
- [AC97 on OSDev](https://wiki.osdev.org/AC97)
|
||||
- [LemonOS Project](https://github.com/LemonOSProject/LemonOS)
|
||||
- [AC97 Revision 2.3 Specification](https://inst.eecs.berkeley.edu//~cs150/Documents/ac97_r23.pdf)
|
||||
|
||||
## Intrinsics (x86)
|
||||
@ -96,14 +98,19 @@ License information can be found in the [LICENSES.md](LICENSES.md) file.
|
||||
- [GCC libstdc++ Source](https://github.com/gcc-mirror/gcc/tree/master/libstdc%2B%2B-v3)
|
||||
- [Itanium C++ ABI](https://itanium-cxx-abi.github.io/cxx-abi/abi.html)
|
||||
|
||||
## Keyboard
|
||||
- [Scan Codes](https://www.win.tue.nl/~aeb/linux/kbd/scancodes-11.html)
|
||||
- [PS/2 Keyboard on OSDev](https://wiki.osdev.org/PS/2_Keyboard)
|
||||
|
||||
## signal.h
|
||||
- [POSIX signal.h](https://pubs.opengroup.org/onlinepubs/009695399/basedefs/signal.h.html)
|
||||
- [Linux signal(7) Manual](https://man7.org/linux/man-pages/man7/signal.7.html)
|
||||
|
||||
## PS/2
|
||||
- [Scan Codes](https://www.win.tue.nl/~aeb/linux/kbd/scancodes-11.html)
|
||||
- [PS/2 Keyboard on OSDev](https://wiki.osdev.org/PS2_Keyboard)
|
||||
- [PS/2 Mouse on OSDev](https://wiki.osdev.org/PS2_Mouse)
|
||||
- [Mouse Input on OSDev](https://wiki.osdev.org/Mouse_Input)
|
||||
- [I/O Ports on OSDev](https://wiki.osdev.org/I/O_ports)
|
||||
- [PS/2 Controller on OSDev](https://wiki.osdev.org/%228042%22_PS/2_Controller)
|
||||
- [AIP on OSDev](https://wiki.osdev.org/Advanced_Integrated_Peripheral)
|
||||
|
||||
---
|
||||
|
||||
Special thanks to all contributors and the creators of the referenced projects and resources!
|
||||
|
6
Doxyfile
6
Doxyfile
@ -44,7 +44,7 @@ PROJECT_NUMBER = 1.0.0
|
||||
# for a project that appears at the top of each page and should give viewer a
|
||||
# quick idea about the purpose of the project. Keep the description short.
|
||||
|
||||
PROJECT_BRIEF = "Opeating System from scratch made in C and C++"
|
||||
PROJECT_BRIEF = "Kernel Documentation"
|
||||
|
||||
# With the PROJECT_LOGO tag one can specify a logo or an icon that is included
|
||||
# in the documentation. The maximum height of the logo should not exceed 55
|
||||
@ -864,7 +864,7 @@ WARN_LOGFILE =
|
||||
# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
|
||||
# Note: If this tag is empty the current directory is searched.
|
||||
|
||||
INPUT = Kernel tools/Doxygen_README.md
|
||||
INPUT = Kernel tools/doxymds/kernel.md
|
||||
|
||||
# This tag can be used to specify the character encoding of the source files
|
||||
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
|
||||
@ -1064,7 +1064,7 @@ FILTER_SOURCE_PATTERNS =
|
||||
# (index.html). This can be useful if you have a project on for instance GitHub
|
||||
# and want to reuse the introduction page also for the doxygen output.
|
||||
|
||||
USE_MDFILE_AS_MAINPAGE = tools/Doxygen_README.md
|
||||
USE_MDFILE_AS_MAINPAGE = tools/doxymds/kernel.md
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to source browsing
|
||||
|
161
Fex.hpp
161
Fex.hpp
@ -1,161 +0,0 @@
|
||||
/*
|
||||
BSD 3-Clause License
|
||||
|
||||
Copyright (c) 2023, EnderIce2
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef __FENNIX_FILE_FEX_H__
|
||||
#define __FENNIX_FILE_FEX_H__
|
||||
|
||||
// TODO: EXPERIMENTAL
|
||||
|
||||
/**
|
||||
* @brief Fex file format (not finalized)
|
||||
*
|
||||
* @note Instead of HEAD, we can include everything in linker script like this:
|
||||
* @example .header : { BYTE(0x46) BYTE(0x45) BYTE(0x58) BYTE(0x0) } for 'F' 'E' 'X' '\0'
|
||||
*
|
||||
*/
|
||||
|
||||
/** @brief This may change */
|
||||
#define EXTENDED_SECTION_ADDRESS 0x20
|
||||
|
||||
enum FexFormatType
|
||||
{
|
||||
FexFormatType_Unknown,
|
||||
FexFormatType_Executable,
|
||||
FexFormatType_Module
|
||||
/* ... */
|
||||
};
|
||||
|
||||
enum FexOSType
|
||||
{
|
||||
FexOSType_Unknown,
|
||||
FexOSType_Fennix,
|
||||
FexOSType_Linux
|
||||
/* ... */
|
||||
};
|
||||
|
||||
enum FexModuleType
|
||||
{
|
||||
FexModuleType_Unknown,
|
||||
FexModuleType_Generic,
|
||||
FexModuleType_Display,
|
||||
FexModuleType_Network,
|
||||
FexModuleType_Storage,
|
||||
FexModuleType_FileSystem,
|
||||
FexModuleType_Input,
|
||||
FexModuleType_Audio,
|
||||
FexModuleType_ACPI,
|
||||
/* ... */
|
||||
};
|
||||
|
||||
enum FexDriverInputTypes
|
||||
{
|
||||
FexDriverInputTypes_None = 0b00000000,
|
||||
FexDriverInputTypes_Mouse = 0b00000001,
|
||||
FexDriverInputTypes_Keyboard = 0b00000010,
|
||||
/* ... */
|
||||
};
|
||||
|
||||
struct Fex
|
||||
{
|
||||
char Magic[4];
|
||||
enum FexFormatType Type : 4;
|
||||
enum FexOSType OS : 4;
|
||||
int (*EntryPoint)(void *);
|
||||
} __attribute__((packed));
|
||||
|
||||
union KernelCallback;
|
||||
union CPURegisters;
|
||||
|
||||
struct FexExtended
|
||||
{
|
||||
struct
|
||||
{
|
||||
|
||||
} Executable;
|
||||
|
||||
struct
|
||||
{
|
||||
char Name[64];
|
||||
enum FexModuleType Type : 4;
|
||||
enum FexDriverInputTypes TypeFlags : 4;
|
||||
char OverrideOnConflict;
|
||||
int (*Callback)(union KernelCallback *);
|
||||
int (*InterruptCallback)(union CPURegisters *);
|
||||
|
||||
struct ModuleBind
|
||||
{
|
||||
int Type;
|
||||
struct
|
||||
{
|
||||
unsigned char Vector[16];
|
||||
} Interrupt;
|
||||
|
||||
struct
|
||||
{
|
||||
unsigned int ProcessId[16];
|
||||
} Process;
|
||||
|
||||
struct
|
||||
{
|
||||
unsigned short VendorID[16];
|
||||
unsigned short DeviceID[16];
|
||||
unsigned short Class;
|
||||
unsigned short SubClass;
|
||||
unsigned short ProgIF;
|
||||
} PCI;
|
||||
|
||||
struct
|
||||
{
|
||||
char AttachToMouse;
|
||||
char AttachToKeyboard;
|
||||
} Input;
|
||||
} Bind;
|
||||
} Module;
|
||||
} __attribute__((packed));
|
||||
|
||||
/**
|
||||
* @brief Add file header
|
||||
*
|
||||
* @param FormatType FexFormatType
|
||||
* @param OperatingSystem FexOSType
|
||||
* @param Address EntryPoint to the start function
|
||||
*
|
||||
* @note Must include ".header : { *(.header .header.*) }" in linker script
|
||||
*/
|
||||
#define HEAD(FormatType, OperatingSystem, Address) \
|
||||
__attribute__((section(".header"))) struct Fex FexHeader = { \
|
||||
.Magic = {'F', 'E', 'X', '\0'}, \
|
||||
.Type = FormatType, \
|
||||
.OS = OperatingSystem, \
|
||||
.EntryPoint = Address}
|
||||
|
||||
#endif // !__FENNIX_FILE_FEX_H__
|
12
LICENSES.md
12
LICENSES.md
@ -39,6 +39,16 @@ Make sure to read and comply with these licenses before using or redistributing
|
||||
- **License:** Public Domain
|
||||
- **Location:** [https://raw.githubusercontent.com/blanham/liballoc/master/LICENSE](https://raw.githubusercontent.com/blanham/liballoc/master/LICENSE)
|
||||
|
||||
...
|
||||
## rpmalloc
|
||||
|
||||
- **License:** The MIT License (MIT) and Public Domain
|
||||
- **Location:** [https://raw.githubusercontent.com/mjansson/rpmalloc/develop/LICENSE](https://raw.githubusercontent.com/mjansson/rpmalloc/develop/LICENSE)
|
||||
|
||||
## ini.h
|
||||
|
||||
- **License:** The MIT License (MIT) and Public Domain
|
||||
- **Location:** [include/ini.h](include/ini.h)
|
||||
|
||||
---
|
||||
|
||||
Please refer to the respective license files for the full text of each license.
|
||||
|
2
Makefile
2
Makefile
@ -1,7 +1,7 @@
|
||||
# Config file
|
||||
include ../Makefile.conf
|
||||
|
||||
KERNEL_FILENAME = kernel.fsys
|
||||
KERNEL_FILENAME = fennix.elf
|
||||
|
||||
CC = ../$(COMPILER_PATH)/$(COMPILER_ARCH)gcc
|
||||
CPP = ../$(COMPILER_PATH)/$(COMPILER_ARCH)g++
|
||||
|
40
TODO.md
40
TODO.md
@ -1,20 +1,24 @@
|
||||
# TODO
|
||||
|
||||
---
|
||||
|
||||
- [x] Optimize SMP.
|
||||
- [ ] Support IPv6.
|
||||
- [ ] Endianess of the network stack (currently: [HOST](LSB)<=>[NETWORK](MSB)). Not sure if this is a standard or not.
|
||||
- [ ] ~~Endianess of the network stack (currently: [HOST](LSB)<=>[NETWORK](MSB)). Not sure if this is a standard or not.~~ (???)
|
||||
- [ ] Support 32-bit applications (ELF, PE, etc).
|
||||
- [ ] Do not map the entire memory. Map only the needed memory address at allocation time.
|
||||
- [ ] ~~Do not map the entire memory. Map only the needed memory address at allocation time.~~ (we just copy the pages for userland, see `Fork()` inside [core/memory/page_table.cpp](core/memory/page_table.cpp))
|
||||
- [ ] Implementation of logging (beside serial) with log rotation.
|
||||
- [x] Implement a better task manager. (replace struct P/TCB with classes)
|
||||
- [ ] Rewrite virtual file system. (it's very bad, I don't know how I wrote it this bad)
|
||||
- [ ] Rewrite virtual file system.
|
||||
- [ ] Colors in crash screen are not following the kernel color scheme.
|
||||
- [x] Find a way to add intrinsics.
|
||||
- [x] ~~Find a way to add intrinsics.~~ (not feasible, use inline assembly)
|
||||
- [ ] Rework PSF1 font loader.
|
||||
- [x] The cleanup should be done by a thread (tasking). This is done to avoid a deadlock.
|
||||
- [x] ~~The cleanup should be done by a thread (tasking). This is done to avoid a deadlock.~~ (not needed, everything is done by the scheduler)
|
||||
- [ ] Implement a better Display::SetBrightness() function.
|
||||
- [ ] Fix memcpy, memset and memcmp functions (they are not working properly with SIMD).
|
||||
- [x] Fully support i386.
|
||||
- [ ] Fully support i386.
|
||||
- [ ] Support Aarch64.
|
||||
- [ ] SMP trampoline shouldn't be hardcoded at 0x2000.
|
||||
- [ ] ~~SMP trampoline shouldn't be hardcoded at 0x2000.~~ (0x2000 is in the conventional memory, it's fine)
|
||||
- [ ] Rework the stack guard.
|
||||
- [x] Mutex implementation.
|
||||
- [ ] Update SMBIOS functions to support newer versions and actually use it.
|
||||
@ -22,7 +26,23 @@
|
||||
- [ ] Implement lazy allocation. (page faults)
|
||||
- [ ] Bootstrap should have a separate bss section + PHDR.
|
||||
- [ ] Reimplement the driver conflict detection.
|
||||
- [ ] Elf loader shouldn't create a full copy of the elf binary. Copy only the needed sections.
|
||||
- [x] Elf loader shouldn't create a full copy of the elf binary. Copy only the needed sections.
|
||||
- [ ] Use NX-bit.
|
||||
- [ ] Fix std::string
|
||||
- [ ] Rewrite PS/2 drivers.
|
||||
- [ ] Fix std::string.
|
||||
- [x] Rewrite PS/2 drivers.
|
||||
- [ ] Improve signal handling.
|
||||
|
||||
- [ ] Improve the way the kernel crashes.
|
||||
- Add panic() function.
|
||||
- Handle assertion failures.
|
||||
|
||||
- [ ] Optimize screen printing.
|
||||
- On real hardware it's very slow, a solution is dirty printing.
|
||||
|
||||
- [ ] Thread ids should follow the POSIX standard.
|
||||
- When a new process is created, the first thread should have the same id as the process id.
|
||||
- If pid is 400, the first thread should have the id 400. The second thread should have the id 401, etc.
|
||||
|
||||
- [ ] Optimize the scheduler
|
||||
- Create a separate list for processes that are waiting for a resource or a signal, etc.
|
||||
- Use all cores to schedule threads.
|
||||
|
@ -8,29 +8,29 @@
|
||||
|
||||
.extern arm64Entry
|
||||
memzero:
|
||||
str xzr, [x0], #8
|
||||
subs x1, x1, #8
|
||||
b.gt memzero
|
||||
ret
|
||||
str xzr, [x0], #8
|
||||
subs x1, x1, #8
|
||||
b.gt memzero
|
||||
ret
|
||||
|
||||
.global _start
|
||||
_start:
|
||||
mrs x0, mpidr_el1
|
||||
and x0, x0, #0xFF
|
||||
cbz x0, _start2
|
||||
b CPU_Loop
|
||||
mrs x0, mpidr_el1
|
||||
and x0, x0, #0xFF
|
||||
cbz x0, _start2
|
||||
b CPU_Loop
|
||||
|
||||
_start2:
|
||||
adr x0, _bss_start
|
||||
adr x1, _bss_end
|
||||
sub x1, x1, x0
|
||||
bl memzero
|
||||
mov sp, #0x200000
|
||||
bl arm64Entry
|
||||
adr x0, _bss_start
|
||||
adr x1, _bss_end
|
||||
sub x1, x1, x0
|
||||
bl memzero
|
||||
mov sp, #0x200000
|
||||
bl arm64Entry
|
||||
|
||||
Halt:
|
||||
wfe
|
||||
b Halt
|
||||
wfe
|
||||
b Halt
|
||||
|
||||
CPU_Loop:
|
||||
b CPU_Loop
|
||||
b CPU_Loop
|
||||
|
@ -22,6 +22,6 @@
|
||||
|
||||
EXTERNC void arm64Entry(uint64_t dtb_ptr32, uint64_t x1, uint64_t x2, uint64_t x3)
|
||||
{
|
||||
trace("Hello, World!");
|
||||
CPU::Halt(true);
|
||||
trace("Hello, World!");
|
||||
CPU::Halt(true);
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ using namespace CPU::x64;
|
||||
using namespace CPU::x86;
|
||||
|
||||
/*
|
||||
In constructor ‘APIC::APIC::APIC(int)’:
|
||||
In constructor 'APIC::APIC::APIC(int)':
|
||||
warning: left shift count >= width of type
|
||||
| APICBaseAddress = BaseStruct.ApicBaseLo << 12u | BaseStruct.ApicBaseHi << 32u;
|
||||
| ~~~~~~~~~~~~~~~~~~~~~~^~~~~~
|
||||
@ -55,8 +55,8 @@ namespace APIC
|
||||
debug("APIC::Read(%#lx) [x2=%d]",
|
||||
Register, x2APICSupported ? 1 : 0);
|
||||
#endif
|
||||
if (x2APICSupported)
|
||||
assert(false);
|
||||
if (unlikely(x2APICSupported))
|
||||
assert(!"x2APIC is not supported");
|
||||
|
||||
CPU::MemBar::Barrier();
|
||||
uint32_t ret = *((volatile uint32_t *)((uintptr_t)APICBaseAddress + Register));
|
||||
@ -76,8 +76,8 @@ namespace APIC
|
||||
debug("APIC::Write(%#lx, %#lx) [x2=%d]",
|
||||
Register, Value, x2APICSupported ? 1 : 0);
|
||||
#endif
|
||||
if (x2APICSupported)
|
||||
assert(false);
|
||||
if (unlikely(x2APICSupported))
|
||||
assert(!"x2APIC is not supported");
|
||||
|
||||
CPU::MemBar::Barrier();
|
||||
*((volatile uint32_t *)(((uintptr_t)APICBaseAddress) + Register)) = Value;
|
||||
@ -107,6 +107,8 @@ namespace APIC
|
||||
|
||||
void APIC::EOI()
|
||||
{
|
||||
Memory::SwapPT swap =
|
||||
Memory::SwapPT(KernelPageTable, thisPageTable);
|
||||
if (this->x2APICSupported)
|
||||
wrmsr(MSR_X2APIC_EOI, 0);
|
||||
else
|
||||
@ -396,20 +398,18 @@ namespace APIC
|
||||
|
||||
APIC::~APIC() {}
|
||||
|
||||
void Timer::OnInterruptReceived(TrapFrame *Frame) { UNUSED(Frame); }
|
||||
void Timer::OnInterruptReceived(CPU::TrapFrame *Frame) { UNUSED(Frame); }
|
||||
|
||||
void Timer::OneShot(uint32_t Vector, uint64_t Miliseconds)
|
||||
{
|
||||
SmartCriticalSection(APICLock);
|
||||
/* FIXME: Sometimes APIC stops firing when debugging, why? */
|
||||
LVTTimer timer{};
|
||||
timer.VEC = uint8_t(Vector);
|
||||
timer.TMM = LVTTimerMode::OneShot;
|
||||
|
||||
LVTTimerDivide Divider = DivideBy8;
|
||||
|
||||
if (unlikely(strcmp(CPU::Hypervisor(), x86_CPUID_VENDOR_TCG) != 0))
|
||||
Divider = DivideBy128;
|
||||
|
||||
SmartCriticalSection(APICLock);
|
||||
if (this->lapic->x2APIC)
|
||||
{
|
||||
// wrmsr(MSR_X2APIC_DIV_CONF, Divider); <- gpf on real hardware
|
||||
|
@ -373,7 +373,7 @@ namespace APIC
|
||||
private:
|
||||
APIC *lapic;
|
||||
uint64_t Ticks = 0;
|
||||
void OnInterruptReceived(CPU::x64::TrapFrame *Frame);
|
||||
void OnInterruptReceived(CPU::TrapFrame *Frame);
|
||||
|
||||
public:
|
||||
uint64_t GetTicks() { return Ticks; }
|
||||
|
@ -122,7 +122,7 @@ namespace GlobalDescriptorTable
|
||||
|
||||
SafeFunction void Init(int Core)
|
||||
{
|
||||
memcpy(&GDTEntries[Core], &GDTEntriesTemplate, sizeof(GlobalDescriptorTableEntries));
|
||||
GDTEntries[Core] = GDTEntriesTemplate;
|
||||
gdt[Core] =
|
||||
{
|
||||
.Limit = sizeof(GlobalDescriptorTableEntries) - 1,
|
||||
|
@ -25,7 +25,7 @@
|
||||
#include "gdt.hpp"
|
||||
#include "../../../kernel.h"
|
||||
|
||||
/* conversion from ‘uint64_t’ {aka ‘long unsigned int’} to ‘unsigned char:2’ may change value */
|
||||
/* conversion from 'uint64_t' {aka 'long unsigned int'} to 'unsigned char:2' may change value */
|
||||
#pragma GCC diagnostic ignored "-Wconversion"
|
||||
|
||||
extern "C" void MainInterruptHandler(void *Data);
|
||||
@ -532,11 +532,11 @@ namespace InterruptDescriptorTable
|
||||
}
|
||||
|
||||
bool EnableISRs = true;
|
||||
#ifdef DEBUG
|
||||
// #ifdef DEBUG
|
||||
EnableISRs = !DebuggerIsAttached;
|
||||
if (!EnableISRs)
|
||||
KPrint("\eFFA500The debugger is attached, disabling all ISRs.");
|
||||
#endif
|
||||
// #endif
|
||||
|
||||
/* ISR */
|
||||
SetEntry(0x0, InterruptHandler_0x0, IST1, TRAP_GATE_64BIT, RING0, EnableISRs, GDT_KERNEL_CODE);
|
||||
@ -553,7 +553,7 @@ namespace InterruptDescriptorTable
|
||||
SetEntry(0xb, InterruptHandler_0xb, IST1, TRAP_GATE_64BIT, RING0, (!DebuggerIsAttached), GDT_KERNEL_CODE);
|
||||
SetEntry(0xc, InterruptHandler_0xc, IST3, TRAP_GATE_64BIT, RING0, EnableISRs, GDT_KERNEL_CODE);
|
||||
SetEntry(0xd, InterruptHandler_0xd, IST3, TRAP_GATE_64BIT, RING0, EnableISRs, GDT_KERNEL_CODE);
|
||||
SetEntry(0xe, InterruptHandler_0xe, IST3, TRAP_GATE_64BIT, RING0, EnableISRs, GDT_KERNEL_CODE);
|
||||
SetEntry(0xe, InterruptHandler_0xe, IST3, TRAP_GATE_64BIT, RING0, EnableISRs /* FIXME: CoW? */, GDT_KERNEL_CODE);
|
||||
SetEntry(0xf, InterruptHandler_0xf, IST1, TRAP_GATE_64BIT, RING0, EnableISRs, GDT_KERNEL_CODE);
|
||||
SetEntry(0x10, InterruptHandler_0x10, IST1, TRAP_GATE_64BIT, RING0, EnableISRs, GDT_KERNEL_CODE);
|
||||
SetEntry(0x11, InterruptHandler_0x11, IST1, TRAP_GATE_64BIT, RING0, EnableISRs, GDT_KERNEL_CODE);
|
||||
|
@ -57,6 +57,9 @@ SafeFunction CPUData *GetCurrentCPU()
|
||||
int CoreID = 0;
|
||||
if (CPUEnabled.load(std::memory_order_acquire) == true)
|
||||
{
|
||||
Memory::SwapPT swap =
|
||||
Memory::SwapPT(KernelPageTable, thisPageTable);
|
||||
|
||||
if (apic->x2APIC)
|
||||
CoreID = int(CPU::x64::rdmsr(CPU::x64::MSR_X2APIC_APICID));
|
||||
else
|
||||
@ -125,7 +128,8 @@ namespace SMP
|
||||
(uintptr_t)&_trampoline_start;
|
||||
Memory::Virtual().Map(0x0, 0x0, Memory::PTFlag::RW);
|
||||
/* We reserved the TRAMPOLINE_START address inside Physical class. */
|
||||
Memory::Virtual().Map((void *)TRAMPOLINE_START, (void *)TRAMPOLINE_START,
|
||||
Memory::Virtual().Map((void *)TRAMPOLINE_START,
|
||||
(void *)TRAMPOLINE_START,
|
||||
TrampolineLength, Memory::PTFlag::RW);
|
||||
memcpy((void *)TRAMPOLINE_START, &_trampoline_start, TrampolineLength);
|
||||
debug("Trampoline address: %#lx-%#lx",
|
||||
|
@ -29,7 +29,7 @@ namespace Memory
|
||||
Address &= 0xFFFFFFFFFFFFF000;
|
||||
|
||||
PageMapIndexer Index = PageMapIndexer(Address);
|
||||
PageMapLevel4 *PML4 = &this->Table->Entries[Index.PMLIndex];
|
||||
PageMapLevel4 *PML4 = &this->pTable->Entries[Index.PMLIndex];
|
||||
|
||||
PageDirectoryPointerTableEntryPtr *PDPTE = nullptr;
|
||||
PageDirectoryEntryPtr *PDE = nullptr;
|
||||
@ -74,7 +74,7 @@ namespace Memory
|
||||
Address &= 0xFFFFFFFFFFFFF000;
|
||||
|
||||
PageMapIndexer Index = PageMapIndexer(Address);
|
||||
PageMapLevel4 *PML4 = &this->Table->Entries[Index.PMLIndex];
|
||||
PageMapLevel4 *PML4 = &this->pTable->Entries[Index.PMLIndex];
|
||||
|
||||
PageDirectoryPointerTableEntryPtr *PDPTE = nullptr;
|
||||
PageDirectoryEntryPtr *PDE = nullptr;
|
||||
@ -119,7 +119,7 @@ namespace Memory
|
||||
Address &= 0xFFFFFFFFFFFFF000;
|
||||
|
||||
PageMapIndexer Index = PageMapIndexer(Address);
|
||||
PageMapLevel4 *PML4 = &this->Table->Entries[Index.PMLIndex];
|
||||
PageMapLevel4 *PML4 = &this->pTable->Entries[Index.PMLIndex];
|
||||
|
||||
PageDirectoryPointerTableEntryPtr *PDPTE = nullptr;
|
||||
PageDirectoryEntryPtr *PDE = nullptr;
|
||||
@ -172,9 +172,11 @@ namespace Memory
|
||||
Address &= 0xFFFFFFFFFFFFF000;
|
||||
|
||||
PageMapIndexer Index = PageMapIndexer(Address);
|
||||
PageMapLevel4 *PML4 = &this->Table->Entries[Index.PMLIndex];
|
||||
PageMapLevel4 *PML4 = &this->pTable->Entries[Index.PMLIndex];
|
||||
if (PML4->Present)
|
||||
return PML4;
|
||||
|
||||
debug("PML4 not present for %#lx", VirtualAddress);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -185,14 +187,19 @@ namespace Memory
|
||||
Address &= 0xFFFFFFFFFFFFF000;
|
||||
|
||||
PageMapIndexer Index = PageMapIndexer(Address);
|
||||
PageMapLevel4 *PML4 = &this->Table->Entries[Index.PMLIndex];
|
||||
PageMapLevel4 *PML4 = &this->pTable->Entries[Index.PMLIndex];
|
||||
if (!PML4->Present)
|
||||
{
|
||||
debug("PML4 not present for %#lx", VirtualAddress);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
PageDirectoryPointerTableEntryPtr *PDPTEPtr = (PageDirectoryPointerTableEntryPtr *)((uintptr_t)PML4->Address << 12);
|
||||
PageDirectoryPointerTableEntry *PDPTE = &PDPTEPtr->Entries[Index.PDPTEIndex];
|
||||
if (PDPTE->Present)
|
||||
return PDPTE;
|
||||
|
||||
debug("PDPTE not present for %#lx", VirtualAddress);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -203,19 +210,27 @@ namespace Memory
|
||||
Address &= 0xFFFFFFFFFFFFF000;
|
||||
|
||||
PageMapIndexer Index = PageMapIndexer(Address);
|
||||
PageMapLevel4 *PML4 = &this->Table->Entries[Index.PMLIndex];
|
||||
PageMapLevel4 *PML4 = &this->pTable->Entries[Index.PMLIndex];
|
||||
if (!PML4->Present)
|
||||
{
|
||||
debug("PML4 not present for %#lx", VirtualAddress);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
PageDirectoryPointerTableEntryPtr *PDPTEPtr = (PageDirectoryPointerTableEntryPtr *)((uintptr_t)PML4->Address << 12);
|
||||
PageDirectoryPointerTableEntry *PDPTE = &PDPTEPtr->Entries[Index.PDPTEIndex];
|
||||
if (!PDPTE->Present)
|
||||
{
|
||||
debug("PDPTE not present for %#lx", VirtualAddress);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
PageDirectoryEntryPtr *PDEPtr = (PageDirectoryEntryPtr *)(PDPTE->GetAddress() << 12);
|
||||
PageDirectoryEntry *PDE = &PDEPtr->Entries[Index.PDEIndex];
|
||||
if (PDE->Present)
|
||||
return PDE;
|
||||
|
||||
debug("PDE not present for %#lx", VirtualAddress);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -226,31 +241,42 @@ namespace Memory
|
||||
Address &= 0xFFFFFFFFFFFFF000;
|
||||
|
||||
PageMapIndexer Index = PageMapIndexer(Address);
|
||||
PageMapLevel4 *PML4 = &this->Table->Entries[Index.PMLIndex];
|
||||
PageMapLevel4 *PML4 = &this->pTable->Entries[Index.PMLIndex];
|
||||
if (!PML4->Present)
|
||||
{
|
||||
debug("PML4 not present for %#lx", VirtualAddress);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
PageDirectoryPointerTableEntryPtr *PDPTEPtr = (PageDirectoryPointerTableEntryPtr *)((uintptr_t)PML4->Address << 12);
|
||||
PageDirectoryPointerTableEntry *PDPTE = &PDPTEPtr->Entries[Index.PDPTEIndex];
|
||||
if (!PDPTE->Present)
|
||||
{
|
||||
debug("PDPTE not present for %#lx", VirtualAddress);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
PageDirectoryEntryPtr *PDEPtr = (PageDirectoryEntryPtr *)(PDPTE->GetAddress() << 12);
|
||||
PageDirectoryEntry *PDE = &PDEPtr->Entries[Index.PDEIndex];
|
||||
if (!PDE->Present)
|
||||
{
|
||||
debug("PDE not present for %#lx", VirtualAddress);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
PageTableEntryPtr *PTEPtr = (PageTableEntryPtr *)(PDE->GetAddress() << 12);
|
||||
PageTableEntry *PTE = &PTEPtr->Entries[Index.PTEIndex];
|
||||
if (PTE->Present)
|
||||
return PTE;
|
||||
|
||||
debug("PTE not present for %#lx", VirtualAddress);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void Virtual::Map(void *VirtualAddress, void *PhysicalAddress, uint64_t Flags, MapType Type)
|
||||
{
|
||||
SmartLock(this->MemoryLock);
|
||||
if (unlikely(!this->Table))
|
||||
if (unlikely(!this->pTable))
|
||||
{
|
||||
error("No page table");
|
||||
return;
|
||||
@ -262,7 +288,7 @@ namespace Memory
|
||||
// Clear any flags that are not 1 << 0 (Present) - 1 << 5 (Accessed) because rest are for page table entries only
|
||||
uint64_t DirectoryFlags = Flags & 0x3F;
|
||||
|
||||
PageMapLevel4 *PML4 = &this->Table->Entries[Index.PMLIndex];
|
||||
PageMapLevel4 *PML4 = &this->pTable->Entries[Index.PMLIndex];
|
||||
PageDirectoryPointerTableEntryPtr *PDPTEPtr = nullptr;
|
||||
if (!PML4->Present)
|
||||
{
|
||||
@ -323,7 +349,7 @@ namespace Memory
|
||||
PTE->Present = true;
|
||||
PTE->raw |= Flags;
|
||||
PTE->SetAddress((uintptr_t)PhysicalAddress >> 12);
|
||||
CPU::x32::invlpg(VirtualAddress);
|
||||
CPU::x64::invlpg(VirtualAddress);
|
||||
|
||||
#ifdef DEBUG
|
||||
/* https://stackoverflow.com/a/3208376/9352057 */
|
||||
@ -346,14 +372,14 @@ namespace Memory
|
||||
void Virtual::Unmap(void *VirtualAddress, MapType Type)
|
||||
{
|
||||
SmartLock(this->MemoryLock);
|
||||
if (!this->Table)
|
||||
if (!this->pTable)
|
||||
{
|
||||
error("No page table");
|
||||
return;
|
||||
}
|
||||
|
||||
PageMapIndexer Index = PageMapIndexer((uintptr_t)VirtualAddress);
|
||||
PageMapLevel4 *PML4 = &this->Table->Entries[Index.PMLIndex];
|
||||
PageMapLevel4 *PML4 = &this->pTable->Entries[Index.PMLIndex];
|
||||
if (!PML4->Present)
|
||||
{
|
||||
warn("Page %#lx not present", PML4->GetAddress());
|
||||
@ -398,6 +424,6 @@ namespace Memory
|
||||
|
||||
PTE.Present = false;
|
||||
PTEPtr->Entries[Index.PTEIndex] = PTE;
|
||||
CPU::x32::invlpg(VirtualAddress);
|
||||
CPU::x64::invlpg(VirtualAddress);
|
||||
}
|
||||
}
|
||||
|
@ -15,24 +15,24 @@
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __FENNIX_KERNEL_AMD_PCNET_H__
|
||||
#define __FENNIX_KERNEL_AMD_PCNET_H__
|
||||
.code64
|
||||
|
||||
#include <types.h>
|
||||
#include "../../mapi.hpp"
|
||||
.global _sig_native_trampoline_start
|
||||
_sig_native_trampoline_start:
|
||||
int $0x3
|
||||
|
||||
namespace PCNET
|
||||
{
|
||||
struct BARData
|
||||
{
|
||||
uint8_t Type;
|
||||
uint16_t IOBase;
|
||||
uint64_t MemoryBase;
|
||||
};
|
||||
.global _sig_native_trampoline_end
|
||||
_sig_native_trampoline_end:
|
||||
|
||||
int DriverEntry(void *);
|
||||
int CallbackHandler(KernelCallback *);
|
||||
int InterruptCallback(CPURegisters *);
|
||||
}
|
||||
.global _sig_linux_trampoline_start
|
||||
_sig_linux_trampoline_start:
|
||||
movq %rsp, %rbp
|
||||
movq (%rbp), %rax
|
||||
call %rax
|
||||
mov %rbp, %rsp
|
||||
/* rt_sigreturn = 15 */
|
||||
movq $15, %rax
|
||||
syscall
|
||||
|
||||
#endif // !__FENNIX_KERNEL_AMD_PCNET_H__
|
||||
.global _sig_linux_trampoline_end
|
||||
_sig_linux_trampoline_end:
|
@ -23,29 +23,29 @@ KERNEL_PAGE_NUMBER = 768 /* KERNEL_VIRTUAL_BASE >> 22 */
|
||||
.align 0x1000
|
||||
.global BootPageTable
|
||||
BootPageTable:
|
||||
.long 0x00000083
|
||||
.long 0x00400083
|
||||
.long 0x00800083
|
||||
.long 0x00C00083
|
||||
.long 0x01000083
|
||||
.long 0x01400083
|
||||
.long 0x01800083
|
||||
.long 0x01C00083
|
||||
.long 0x02000083
|
||||
.long 0x02400083
|
||||
.long 0x00000083
|
||||
.long 0x00400083
|
||||
.long 0x00800083
|
||||
.long 0x00C00083
|
||||
.long 0x01000083
|
||||
.long 0x01400083
|
||||
.long 0x01800083
|
||||
.long 0x01C00083
|
||||
.long 0x02000083
|
||||
.long 0x02400083
|
||||
.rept (KERNEL_PAGE_NUMBER - 10)
|
||||
.long 0
|
||||
.endr
|
||||
.long 0x00000083
|
||||
.long 0x00400083
|
||||
.long 0x00800083
|
||||
.long 0x00C00083
|
||||
.long 0x01000083
|
||||
.long 0x01400083
|
||||
.long 0x01800083
|
||||
.long 0x01C00083
|
||||
.long 0x02000083
|
||||
.long 0x02400083
|
||||
.long 0x00000083
|
||||
.long 0x00400083
|
||||
.long 0x00800083
|
||||
.long 0x00C00083
|
||||
.long 0x01000083
|
||||
.long 0x01400083
|
||||
.long 0x01800083
|
||||
.long 0x01C00083
|
||||
.long 0x02000083
|
||||
.long 0x02400083
|
||||
.rept (1024 - KERNEL_PAGE_NUMBER - 10)
|
||||
.long 0
|
||||
.endr
|
||||
|
@ -33,7 +33,7 @@ using namespace CPU::x32;
|
||||
using namespace CPU::x86;
|
||||
|
||||
/*
|
||||
In constructor ‘APIC::APIC::APIC(int)’:
|
||||
In constructor 'APIC::APIC::APIC(int)':
|
||||
warning: left shift count >= width of type
|
||||
| APICBaseAddress = BaseStruct.ApicBaseLo << 12u | BaseStruct.ApicBaseHi << 32u;
|
||||
| ~~~~~~~~~~~~~~~~~~~~~~^~~~~~
|
||||
@ -358,7 +358,7 @@ namespace APIC
|
||||
|
||||
APIC::~APIC() {}
|
||||
|
||||
void Timer::OnInterruptReceived(TrapFrame *Frame) { UNUSED(Frame); }
|
||||
void Timer::OnInterruptReceived(CPU::TrapFrame *Frame) { UNUSED(Frame); }
|
||||
|
||||
void Timer::OneShot(uint32_t Vector, uint64_t Miliseconds)
|
||||
{
|
||||
|
@ -343,7 +343,7 @@ namespace APIC
|
||||
private:
|
||||
APIC *lapic;
|
||||
uint64_t Ticks = 0;
|
||||
void OnInterruptReceived(CPU::x32::TrapFrame *Frame);
|
||||
void OnInterruptReceived(CPU::TrapFrame *Frame);
|
||||
|
||||
public:
|
||||
uint64_t GetTicks() { return Ticks; }
|
||||
|
@ -25,7 +25,7 @@
|
||||
#include "gdt.hpp"
|
||||
#include "../../../kernel.h"
|
||||
|
||||
/* conversion from ‘uint64_t’ {aka ‘long unsigned int’} to ‘unsigned char:2’ may change value */
|
||||
/* conversion from 'uint64_t' {aka 'long unsigned int'} to 'unsigned char:2' may change value */
|
||||
#pragma GCC diagnostic ignored "-Wconversion"
|
||||
|
||||
extern "C" void MainInterruptHandler(void *Data);
|
||||
@ -461,11 +461,11 @@ namespace InterruptDescriptorTable
|
||||
/* ISR */
|
||||
|
||||
bool EnableISRs = true;
|
||||
#ifdef DEBUG
|
||||
// #ifdef DEBUG
|
||||
EnableISRs = !DebuggerIsAttached;
|
||||
if (!EnableISRs)
|
||||
KPrint("\eFFA500The debugger is attached, disabling all ISRs.");
|
||||
#endif
|
||||
// #endif
|
||||
|
||||
SetEntry(0x0, InterruptHandler_0x0, TRAP_GATE_32BIT, RING0, EnableISRs, GDT_KERNEL_CODE);
|
||||
SetEntry(0x1, InterruptHandler_0x1, TRAP_GATE_32BIT, RING0, EnableISRs, GDT_KERNEL_CODE);
|
||||
|
@ -21,120 +21,120 @@
|
||||
|
||||
namespace PIC
|
||||
{
|
||||
PIC::PIC(uint8_t MasterCommandPort, uint8_t MasterDataPort, uint8_t SlaveCommandPort, uint8_t SlaveDataPort, uint8_t MasterOffset, uint8_t SlaveOffset)
|
||||
{
|
||||
this->MasterCommandPort = MasterCommandPort;
|
||||
this->MasterDataPort = MasterDataPort;
|
||||
this->SlaveCommandPort = SlaveCommandPort;
|
||||
this->SlaveDataPort = SlaveDataPort;
|
||||
this->MasterOffset = MasterOffset;
|
||||
this->SlaveOffset = SlaveOffset;
|
||||
PIC::PIC(uint8_t MasterCommandPort, uint8_t MasterDataPort, uint8_t SlaveCommandPort, uint8_t SlaveDataPort, uint8_t MasterOffset, uint8_t SlaveOffset)
|
||||
{
|
||||
this->MasterCommandPort = MasterCommandPort;
|
||||
this->MasterDataPort = MasterDataPort;
|
||||
this->SlaveCommandPort = SlaveCommandPort;
|
||||
this->SlaveDataPort = SlaveDataPort;
|
||||
this->MasterOffset = MasterOffset;
|
||||
this->SlaveOffset = SlaveOffset;
|
||||
|
||||
MasterMask = 0xFF;
|
||||
SlaveMask = 0xFF;
|
||||
MasterMask = 0xFF;
|
||||
SlaveMask = 0xFF;
|
||||
|
||||
// ICW1
|
||||
outb(MasterCommandPort, 0x11);
|
||||
outb(SlaveCommandPort, 0x11);
|
||||
// ICW1
|
||||
outb(MasterCommandPort, 0x11);
|
||||
outb(SlaveCommandPort, 0x11);
|
||||
|
||||
// ICW2
|
||||
outb(MasterDataPort, MasterOffset);
|
||||
outb(SlaveDataPort, SlaveOffset);
|
||||
// ICW2
|
||||
outb(MasterDataPort, MasterOffset);
|
||||
outb(SlaveDataPort, SlaveOffset);
|
||||
|
||||
// ICW3
|
||||
outb(MasterDataPort, 0x04);
|
||||
outb(SlaveDataPort, 0x02);
|
||||
// ICW3
|
||||
outb(MasterDataPort, 0x04);
|
||||
outb(SlaveDataPort, 0x02);
|
||||
|
||||
// ICW4
|
||||
outb(MasterDataPort, 0x01);
|
||||
outb(SlaveDataPort, 0x01);
|
||||
// ICW4
|
||||
outb(MasterDataPort, 0x01);
|
||||
outb(SlaveDataPort, 0x01);
|
||||
|
||||
// OCW1
|
||||
outb(MasterDataPort, MasterMask);
|
||||
outb(SlaveDataPort, SlaveMask);
|
||||
}
|
||||
// OCW1
|
||||
outb(MasterDataPort, MasterMask);
|
||||
outb(SlaveDataPort, SlaveMask);
|
||||
}
|
||||
|
||||
PIC::~PIC()
|
||||
{
|
||||
outb(MasterDataPort, 0xFF);
|
||||
outb(SlaveDataPort, 0xFF);
|
||||
}
|
||||
PIC::~PIC()
|
||||
{
|
||||
outb(MasterDataPort, 0xFF);
|
||||
outb(SlaveDataPort, 0xFF);
|
||||
}
|
||||
|
||||
void PIC::Mask(uint8_t IRQ)
|
||||
{
|
||||
uint16_t Port;
|
||||
uint8_t Value;
|
||||
void PIC::Mask(uint8_t IRQ)
|
||||
{
|
||||
uint16_t Port;
|
||||
uint8_t Value;
|
||||
|
||||
if (IRQ < 8)
|
||||
{
|
||||
Port = MasterDataPort;
|
||||
Value = (uint8_t)(MasterMask & ~(1 << IRQ));
|
||||
MasterMask = Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
Port = SlaveDataPort;
|
||||
Value = (uint8_t)(SlaveMask & ~(1 << (IRQ - 8)));
|
||||
SlaveMask = Value;
|
||||
}
|
||||
if (IRQ < 8)
|
||||
{
|
||||
Port = MasterDataPort;
|
||||
Value = (uint8_t)(MasterMask & ~(1 << IRQ));
|
||||
MasterMask = Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
Port = SlaveDataPort;
|
||||
Value = (uint8_t)(SlaveMask & ~(1 << (IRQ - 8)));
|
||||
SlaveMask = Value;
|
||||
}
|
||||
|
||||
outb(Port, Value);
|
||||
}
|
||||
outb(Port, Value);
|
||||
}
|
||||
|
||||
void PIC::Unmask(uint8_t IRQ)
|
||||
{
|
||||
uint16_t Port;
|
||||
uint8_t Value;
|
||||
void PIC::Unmask(uint8_t IRQ)
|
||||
{
|
||||
uint16_t Port;
|
||||
uint8_t Value;
|
||||
|
||||
if (IRQ < 8)
|
||||
{
|
||||
Port = MasterDataPort;
|
||||
Value = MasterMask | (1 << IRQ);
|
||||
MasterMask = Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
Port = SlaveDataPort;
|
||||
Value = SlaveMask | (1 << (IRQ - 8));
|
||||
SlaveMask = Value;
|
||||
}
|
||||
if (IRQ < 8)
|
||||
{
|
||||
Port = MasterDataPort;
|
||||
Value = MasterMask | (1 << IRQ);
|
||||
MasterMask = Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
Port = SlaveDataPort;
|
||||
Value = SlaveMask | (1 << (IRQ - 8));
|
||||
SlaveMask = Value;
|
||||
}
|
||||
|
||||
outb(Port, Value);
|
||||
}
|
||||
outb(Port, Value);
|
||||
}
|
||||
|
||||
void PIC::SendEOI(uint8_t IRQ)
|
||||
{
|
||||
if (IRQ >= 8)
|
||||
outb(SlaveCommandPort, 0x20);
|
||||
void PIC::SendEOI(uint8_t IRQ)
|
||||
{
|
||||
if (IRQ >= 8)
|
||||
outb(SlaveCommandPort, 0x20);
|
||||
|
||||
outb(MasterCommandPort, 0x20);
|
||||
}
|
||||
outb(MasterCommandPort, 0x20);
|
||||
}
|
||||
|
||||
PIT::PIT(uint16_t Port, uint16_t Frequency)
|
||||
{
|
||||
this->Port = Port;
|
||||
this->Frequency = Frequency;
|
||||
}
|
||||
PIT::PIT(uint16_t Port, uint16_t Frequency)
|
||||
{
|
||||
this->Port = Port;
|
||||
this->Frequency = Frequency;
|
||||
}
|
||||
|
||||
PIT::~PIT()
|
||||
{
|
||||
}
|
||||
PIT::~PIT()
|
||||
{
|
||||
}
|
||||
|
||||
void PIT::PrepareSleep(uint32_t Milliseconds)
|
||||
{
|
||||
uint16_t Divisor = (uint16_t)(1193182 / Frequency);
|
||||
uint8_t Low = (uint8_t)(Divisor & 0xFF);
|
||||
uint8_t High = (uint8_t)((Divisor >> 8) & 0xFF);
|
||||
void PIT::PrepareSleep(uint32_t Milliseconds)
|
||||
{
|
||||
uint16_t Divisor = (uint16_t)(1193182 / Frequency);
|
||||
uint8_t Low = (uint8_t)(Divisor & 0xFF);
|
||||
uint8_t High = (uint8_t)((Divisor >> 8) & 0xFF);
|
||||
|
||||
outb(Port + 3, 0x36);
|
||||
outb(Port + 0, Low);
|
||||
outb(Port + 1, High);
|
||||
}
|
||||
outb(Port + 3, 0x36);
|
||||
outb(Port + 0, Low);
|
||||
outb(Port + 1, High);
|
||||
}
|
||||
|
||||
void PIT::PerformSleep()
|
||||
{
|
||||
uint8_t Value = inb(Port + 0);
|
||||
while (Value != 0)
|
||||
Value = inb(Port + 0);
|
||||
}
|
||||
void PIT::PerformSleep()
|
||||
{
|
||||
uint8_t Value = inb(Port + 0);
|
||||
while (Value != 0)
|
||||
Value = inb(Port + 0);
|
||||
}
|
||||
}
|
||||
|
@ -22,38 +22,38 @@
|
||||
|
||||
namespace PIC
|
||||
{
|
||||
class PIC
|
||||
{
|
||||
private:
|
||||
uint8_t MasterCommandPort;
|
||||
uint8_t MasterDataPort;
|
||||
uint8_t SlaveCommandPort;
|
||||
uint8_t SlaveDataPort;
|
||||
uint8_t MasterOffset;
|
||||
uint8_t SlaveOffset;
|
||||
uint8_t MasterMask;
|
||||
uint8_t SlaveMask;
|
||||
class PIC
|
||||
{
|
||||
private:
|
||||
uint8_t MasterCommandPort;
|
||||
uint8_t MasterDataPort;
|
||||
uint8_t SlaveCommandPort;
|
||||
uint8_t SlaveDataPort;
|
||||
uint8_t MasterOffset;
|
||||
uint8_t SlaveOffset;
|
||||
uint8_t MasterMask;
|
||||
uint8_t SlaveMask;
|
||||
|
||||
public:
|
||||
PIC(uint8_t MasterCommandPort, uint8_t MasterDataPort, uint8_t SlaveCommandPort, uint8_t SlaveDataPort, uint8_t MasterOffset, uint8_t SlaveOffset);
|
||||
~PIC();
|
||||
void Mask(uint8_t IRQ);
|
||||
void Unmask(uint8_t IRQ);
|
||||
void SendEOI(uint8_t IRQ);
|
||||
};
|
||||
public:
|
||||
PIC(uint8_t MasterCommandPort, uint8_t MasterDataPort, uint8_t SlaveCommandPort, uint8_t SlaveDataPort, uint8_t MasterOffset, uint8_t SlaveOffset);
|
||||
~PIC();
|
||||
void Mask(uint8_t IRQ);
|
||||
void Unmask(uint8_t IRQ);
|
||||
void SendEOI(uint8_t IRQ);
|
||||
};
|
||||
|
||||
class PIT
|
||||
{
|
||||
private:
|
||||
uint16_t Port;
|
||||
uint16_t Frequency;
|
||||
class PIT
|
||||
{
|
||||
private:
|
||||
uint16_t Port;
|
||||
uint16_t Frequency;
|
||||
|
||||
public:
|
||||
PIT(uint16_t Port, uint16_t Frequency);
|
||||
~PIT();
|
||||
void PrepareSleep(uint32_t Milliseconds);
|
||||
void PerformSleep();
|
||||
};
|
||||
public:
|
||||
PIT(uint16_t Port, uint16_t Frequency);
|
||||
~PIT();
|
||||
void PrepareSleep(uint32_t Milliseconds);
|
||||
void PerformSleep();
|
||||
};
|
||||
}
|
||||
|
||||
#endif // !__FENNIX_KERNEL_8259PIC_H__
|
||||
|
@ -26,79 +26,79 @@ PF_X = 0x1;
|
||||
|
||||
PHDRS
|
||||
{
|
||||
bootstrap PT_LOAD FLAGS( PF_R | PF_W /*| PF_X*/ );
|
||||
text PT_LOAD FLAGS( PF_R | PF_X );
|
||||
data PT_LOAD FLAGS( PF_R | PF_W );
|
||||
rodata PT_LOAD FLAGS( PF_R );
|
||||
bss PT_LOAD FLAGS( PF_R | PF_W );
|
||||
bootstrap PT_LOAD FLAGS( PF_R | PF_W /*| PF_X*/ );
|
||||
text PT_LOAD FLAGS( PF_R | PF_X );
|
||||
data PT_LOAD FLAGS( PF_R | PF_W );
|
||||
rodata PT_LOAD FLAGS( PF_R );
|
||||
bss PT_LOAD FLAGS( PF_R | PF_W );
|
||||
}
|
||||
|
||||
KERNEL_VMA = 0xC0000000;
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
. = 0x100000;
|
||||
_bootstrap_start = .;
|
||||
.bootstrap ALIGN(CONSTANT(MAXPAGESIZE)) :
|
||||
{
|
||||
*(.multiboot)
|
||||
*(.multiboot2)
|
||||
*(.bootstrap .bootstrap.*)
|
||||
} :bootstrap
|
||||
_bootstrap_end = ALIGN(CONSTANT(MAXPAGESIZE));
|
||||
. = 0x100000;
|
||||
_bootstrap_start = .;
|
||||
.bootstrap ALIGN(CONSTANT(MAXPAGESIZE)) :
|
||||
{
|
||||
*(.multiboot)
|
||||
*(.multiboot2)
|
||||
*(.bootstrap .bootstrap.*)
|
||||
} :bootstrap
|
||||
_bootstrap_end = ALIGN(CONSTANT(MAXPAGESIZE));
|
||||
|
||||
. += KERNEL_VMA;
|
||||
. += KERNEL_VMA;
|
||||
|
||||
_kernel_start = ALIGN(CONSTANT(MAXPAGESIZE));
|
||||
_kernel_text_start = ALIGN(CONSTANT(MAXPAGESIZE));
|
||||
.text ALIGN(CONSTANT(MAXPAGESIZE)) : AT(ADDR(.text) - KERNEL_VMA)
|
||||
{
|
||||
*(.text .text.*)
|
||||
} :text
|
||||
_kernel_text_end = ALIGN(CONSTANT(MAXPAGESIZE));
|
||||
_kernel_start = ALIGN(CONSTANT(MAXPAGESIZE));
|
||||
_kernel_text_start = ALIGN(CONSTANT(MAXPAGESIZE));
|
||||
.text ALIGN(CONSTANT(MAXPAGESIZE)) : AT(ADDR(.text) - KERNEL_VMA)
|
||||
{
|
||||
*(.text .text.*)
|
||||
} :text
|
||||
_kernel_text_end = ALIGN(CONSTANT(MAXPAGESIZE));
|
||||
|
||||
_kernel_data_start = ALIGN(CONSTANT(MAXPAGESIZE));
|
||||
.data ALIGN(CONSTANT(MAXPAGESIZE)) : AT(ADDR(.data) - KERNEL_VMA)
|
||||
{
|
||||
*(.data .data.*)
|
||||
} :data
|
||||
_kernel_data_end = ALIGN(CONSTANT(MAXPAGESIZE));
|
||||
_kernel_data_start = ALIGN(CONSTANT(MAXPAGESIZE));
|
||||
.data ALIGN(CONSTANT(MAXPAGESIZE)) : AT(ADDR(.data) - KERNEL_VMA)
|
||||
{
|
||||
*(.data .data.*)
|
||||
} :data
|
||||
_kernel_data_end = ALIGN(CONSTANT(MAXPAGESIZE));
|
||||
|
||||
_kernel_rodata_start = ALIGN(CONSTANT(MAXPAGESIZE));
|
||||
.rodata ALIGN(CONSTANT(MAXPAGESIZE)) : AT(ADDR(.rodata) - KERNEL_VMA)
|
||||
{
|
||||
*(.rodata .rodata.*)
|
||||
} :rodata
|
||||
_kernel_rodata_start = ALIGN(CONSTANT(MAXPAGESIZE));
|
||||
.rodata ALIGN(CONSTANT(MAXPAGESIZE)) : AT(ADDR(.rodata) - KERNEL_VMA)
|
||||
{
|
||||
*(.rodata .rodata.*)
|
||||
} :rodata
|
||||
|
||||
.init_array ALIGN(CONSTANT(MAXPAGESIZE)) : AT(ADDR(.init_array) - KERNEL_VMA)
|
||||
{
|
||||
PROVIDE_HIDDEN(__init_array_start = .);
|
||||
KEEP(*(.init_array .ctors))
|
||||
KEEP(*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
|
||||
PROVIDE_HIDDEN (__init_array_end = .);
|
||||
} :rodata
|
||||
.init_array ALIGN(CONSTANT(MAXPAGESIZE)) : AT(ADDR(.init_array) - KERNEL_VMA)
|
||||
{
|
||||
PROVIDE_HIDDEN(__init_array_start = .);
|
||||
KEEP(*(.init_array .ctors))
|
||||
KEEP(*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
|
||||
PROVIDE_HIDDEN (__init_array_end = .);
|
||||
} :rodata
|
||||
|
||||
.fini_array ALIGN(CONSTANT(MAXPAGESIZE)) : AT(ADDR(.fini_array) - KERNEL_VMA)
|
||||
{
|
||||
PROVIDE_HIDDEN(__fini_array_start = .);
|
||||
KEEP(*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
|
||||
KEEP(*(.fini_array .dtors))
|
||||
PROVIDE_HIDDEN (__fini_array_end = .);
|
||||
} :rodata
|
||||
_kernel_rodata_end = ALIGN(CONSTANT(MAXPAGESIZE));
|
||||
.fini_array ALIGN(CONSTANT(MAXPAGESIZE)) : AT(ADDR(.fini_array) - KERNEL_VMA)
|
||||
{
|
||||
PROVIDE_HIDDEN(__fini_array_start = .);
|
||||
KEEP(*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
|
||||
KEEP(*(.fini_array .dtors))
|
||||
PROVIDE_HIDDEN (__fini_array_end = .);
|
||||
} :rodata
|
||||
_kernel_rodata_end = ALIGN(CONSTANT(MAXPAGESIZE));
|
||||
|
||||
_kernel_bss_start = ALIGN(CONSTANT(MAXPAGESIZE));
|
||||
.bss ALIGN(CONSTANT(MAXPAGESIZE)) : AT(ADDR(.bss) - KERNEL_VMA)
|
||||
{
|
||||
*(COMMON)
|
||||
*(.bss .bss.*)
|
||||
} :bss
|
||||
_kernel_bss_end = ALIGN(CONSTANT(MAXPAGESIZE));
|
||||
_kernel_end = ALIGN(CONSTANT(MAXPAGESIZE));
|
||||
_kernel_bss_start = ALIGN(CONSTANT(MAXPAGESIZE));
|
||||
.bss ALIGN(CONSTANT(MAXPAGESIZE)) : AT(ADDR(.bss) - KERNEL_VMA)
|
||||
{
|
||||
*(COMMON)
|
||||
*(.bss .bss.*)
|
||||
} :bss
|
||||
_kernel_bss_end = ALIGN(CONSTANT(MAXPAGESIZE));
|
||||
_kernel_end = ALIGN(CONSTANT(MAXPAGESIZE));
|
||||
|
||||
/DISCARD/ :
|
||||
{
|
||||
*(.comment*)
|
||||
*(.note*)
|
||||
}
|
||||
/DISCARD/ :
|
||||
{
|
||||
*(.comment*)
|
||||
*(.note*)
|
||||
}
|
||||
}
|
||||
|
@ -22,205 +22,205 @@
|
||||
|
||||
namespace Memory
|
||||
{
|
||||
bool Virtual::Check(void *VirtualAddress, PTFlag Flag, MapType Type)
|
||||
{
|
||||
// 0x1000 aligned
|
||||
uintptr_t Address = (uintptr_t)VirtualAddress;
|
||||
Address &= 0xFFFFF000;
|
||||
bool Virtual::Check(void *VirtualAddress, PTFlag Flag, MapType Type)
|
||||
{
|
||||
// 0x1000 aligned
|
||||
uintptr_t Address = (uintptr_t)VirtualAddress;
|
||||
Address &= 0xFFFFF000;
|
||||
|
||||
PageMapIndexer Index = PageMapIndexer(Address);
|
||||
PageDirectoryEntry *PDE = &this->Table->Entries[Index.PDEIndex];
|
||||
PageTableEntryPtr *PTE = nullptr;
|
||||
PageMapIndexer Index = PageMapIndexer(Address);
|
||||
PageDirectoryEntry *PDE = &this->Table->Entries[Index.PDEIndex];
|
||||
PageTableEntryPtr *PTE = nullptr;
|
||||
|
||||
if ((PDE->raw & Flag) > 0)
|
||||
{
|
||||
if (Type == MapType::FourMiB && PDE->PageSize)
|
||||
return true;
|
||||
if ((PDE->raw & Flag) > 0)
|
||||
{
|
||||
if (Type == MapType::FourMiB && PDE->PageSize)
|
||||
return true;
|
||||
|
||||
PTE = (PageTableEntryPtr *)((uintptr_t)PDE->GetAddress() << 12);
|
||||
if (PTE)
|
||||
{
|
||||
if ((PTE->Entries[Index.PTEIndex].Present))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
PTE = (PageTableEntryPtr *)((uintptr_t)PDE->GetAddress() << 12);
|
||||
if (PTE)
|
||||
{
|
||||
if ((PTE->Entries[Index.PTEIndex].Present))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void *Virtual::GetPhysical(void *VirtualAddress)
|
||||
{
|
||||
// 0x1000 aligned
|
||||
uintptr_t Address = (uintptr_t)VirtualAddress;
|
||||
Address &= 0xFFFFF000;
|
||||
void *Virtual::GetPhysical(void *VirtualAddress)
|
||||
{
|
||||
// 0x1000 aligned
|
||||
uintptr_t Address = (uintptr_t)VirtualAddress;
|
||||
Address &= 0xFFFFF000;
|
||||
|
||||
PageMapIndexer Index = PageMapIndexer(Address);
|
||||
PageDirectoryEntry *PDE = &this->Table->Entries[Index.PDEIndex];
|
||||
PageTableEntryPtr *PTE = nullptr;
|
||||
PageMapIndexer Index = PageMapIndexer(Address);
|
||||
PageDirectoryEntry *PDE = &this->Table->Entries[Index.PDEIndex];
|
||||
PageTableEntryPtr *PTE = nullptr;
|
||||
|
||||
if (PDE->Present)
|
||||
{
|
||||
if (PDE->PageSize)
|
||||
return (void *)((uintptr_t)PDE->GetAddress() << 12);
|
||||
if (PDE->Present)
|
||||
{
|
||||
if (PDE->PageSize)
|
||||
return (void *)((uintptr_t)PDE->GetAddress() << 12);
|
||||
|
||||
PTE = (PageTableEntryPtr *)((uintptr_t)PDE->GetAddress() << 12);
|
||||
if (PTE)
|
||||
{
|
||||
if (PTE->Entries[Index.PTEIndex].Present)
|
||||
return (void *)((uintptr_t)PTE->Entries[Index.PTEIndex].GetAddress() << 12);
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
PTE = (PageTableEntryPtr *)((uintptr_t)PDE->GetAddress() << 12);
|
||||
if (PTE)
|
||||
{
|
||||
if (PTE->Entries[Index.PTEIndex].Present)
|
||||
return (void *)((uintptr_t)PTE->Entries[Index.PTEIndex].GetAddress() << 12);
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Virtual::MapType Virtual::GetMapType(void *VirtualAddress)
|
||||
{
|
||||
// 0x1000 aligned
|
||||
uintptr_t Address = (uintptr_t)VirtualAddress;
|
||||
Address &= 0xFFFFF000;
|
||||
Virtual::MapType Virtual::GetMapType(void *VirtualAddress)
|
||||
{
|
||||
// 0x1000 aligned
|
||||
uintptr_t Address = (uintptr_t)VirtualAddress;
|
||||
Address &= 0xFFFFF000;
|
||||
|
||||
PageMapIndexer Index = PageMapIndexer(Address);
|
||||
PageMapIndexer Index = PageMapIndexer(Address);
|
||||
|
||||
PageDirectoryEntry *PDE = &this->Table->Entries[Index.PDEIndex];
|
||||
PageTableEntryPtr *PTE = nullptr;
|
||||
PageDirectoryEntry *PDE = &this->Table->Entries[Index.PDEIndex];
|
||||
PageTableEntryPtr *PTE = nullptr;
|
||||
|
||||
if (PDE->Present)
|
||||
{
|
||||
if (PDE->PageSize)
|
||||
return MapType::FourMiB;
|
||||
if (PDE->Present)
|
||||
{
|
||||
if (PDE->PageSize)
|
||||
return MapType::FourMiB;
|
||||
|
||||
PTE = (PageTableEntryPtr *)((uintptr_t)PDE->GetAddress() << 12);
|
||||
if (PTE)
|
||||
{
|
||||
if (PTE->Entries[Index.PTEIndex].Present)
|
||||
return MapType::FourKiB;
|
||||
}
|
||||
}
|
||||
return MapType::NoMapType;
|
||||
}
|
||||
PTE = (PageTableEntryPtr *)((uintptr_t)PDE->GetAddress() << 12);
|
||||
if (PTE)
|
||||
{
|
||||
if (PTE->Entries[Index.PTEIndex].Present)
|
||||
return MapType::FourKiB;
|
||||
}
|
||||
}
|
||||
return MapType::NoMapType;
|
||||
}
|
||||
|
||||
PageDirectoryEntry *Virtual::GetPDE(void *VirtualAddress, MapType Type)
|
||||
{
|
||||
uintptr_t Address = (uintptr_t)VirtualAddress;
|
||||
Address &= 0xFFFFF000;
|
||||
PageDirectoryEntry *Virtual::GetPDE(void *VirtualAddress, MapType Type)
|
||||
{
|
||||
uintptr_t Address = (uintptr_t)VirtualAddress;
|
||||
Address &= 0xFFFFF000;
|
||||
|
||||
PageMapIndexer Index = PageMapIndexer(Address);
|
||||
PageDirectoryEntry *PDE = &this->Table->Entries[Index.PDEIndex];
|
||||
if (PDE->Present)
|
||||
return PDE;
|
||||
return nullptr;
|
||||
}
|
||||
PageMapIndexer Index = PageMapIndexer(Address);
|
||||
PageDirectoryEntry *PDE = &this->Table->Entries[Index.PDEIndex];
|
||||
if (PDE->Present)
|
||||
return PDE;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
PageTableEntry *Virtual::GetPTE(void *VirtualAddress, MapType Type)
|
||||
{
|
||||
uintptr_t Address = (uintptr_t)VirtualAddress;
|
||||
Address &= 0xFFFFF000;
|
||||
PageTableEntry *Virtual::GetPTE(void *VirtualAddress, MapType Type)
|
||||
{
|
||||
uintptr_t Address = (uintptr_t)VirtualAddress;
|
||||
Address &= 0xFFFFF000;
|
||||
|
||||
PageMapIndexer Index = PageMapIndexer(Address);
|
||||
PageDirectoryEntry *PDE = &this->Table->Entries[Index.PDEIndex];
|
||||
if (!PDE->Present)
|
||||
return nullptr;
|
||||
PageMapIndexer Index = PageMapIndexer(Address);
|
||||
PageDirectoryEntry *PDE = &this->Table->Entries[Index.PDEIndex];
|
||||
if (!PDE->Present)
|
||||
return nullptr;
|
||||
|
||||
PageTableEntryPtr *PTEPtr = (PageTableEntryPtr *)(PDE->GetAddress() << 12);
|
||||
PageTableEntry *PTE = &PTEPtr->Entries[Index.PTEIndex];
|
||||
if (PTE->Present)
|
||||
return PTE;
|
||||
return nullptr;
|
||||
}
|
||||
PageTableEntryPtr *PTEPtr = (PageTableEntryPtr *)(PDE->GetAddress() << 12);
|
||||
PageTableEntry *PTE = &PTEPtr->Entries[Index.PTEIndex];
|
||||
if (PTE->Present)
|
||||
return PTE;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void Virtual::Map(void *VirtualAddress, void *PhysicalAddress, uint64_t Flags, MapType Type)
|
||||
{
|
||||
SmartLock(this->MemoryLock);
|
||||
if (unlikely(!this->Table))
|
||||
{
|
||||
error("No page table");
|
||||
return;
|
||||
}
|
||||
void Virtual::Map(void *VirtualAddress, void *PhysicalAddress, uint64_t Flags, MapType Type)
|
||||
{
|
||||
SmartLock(this->MemoryLock);
|
||||
if (unlikely(!this->Table))
|
||||
{
|
||||
error("No page table");
|
||||
return;
|
||||
}
|
||||
|
||||
Flags |= PTFlag::P;
|
||||
Flags |= PTFlag::P;
|
||||
|
||||
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
|
||||
uint64_t DirectoryFlags = Flags & 0x3F;
|
||||
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
|
||||
uint64_t DirectoryFlags = Flags & 0x3F;
|
||||
|
||||
PageDirectoryEntry *PDE = &this->Table->Entries[Index.PDEIndex];
|
||||
if (Type == MapType::FourMiB)
|
||||
{
|
||||
PDE->raw |= (uintptr_t)Flags;
|
||||
PDE->PageSize = true;
|
||||
PDE->SetAddress((uintptr_t)PhysicalAddress >> 12);
|
||||
debug("Mapped 4MB page at %p to %p", VirtualAddress, PhysicalAddress);
|
||||
return;
|
||||
}
|
||||
PageDirectoryEntry *PDE = &this->Table->Entries[Index.PDEIndex];
|
||||
if (Type == MapType::FourMiB)
|
||||
{
|
||||
PDE->raw |= (uintptr_t)Flags;
|
||||
PDE->PageSize = true;
|
||||
PDE->SetAddress((uintptr_t)PhysicalAddress >> 12);
|
||||
debug("Mapped 4MB page at %p to %p", VirtualAddress, PhysicalAddress);
|
||||
return;
|
||||
}
|
||||
|
||||
PageTableEntryPtr *PTEPtr = nullptr;
|
||||
if (!PDE->Present)
|
||||
{
|
||||
PTEPtr = (PageTableEntryPtr *)KernelAllocator.RequestPages(TO_PAGES(sizeof(PageTableEntryPtr) + 1));
|
||||
memset(PTEPtr, 0, sizeof(PageTableEntryPtr));
|
||||
PDE->Present = true;
|
||||
PDE->SetAddress((uintptr_t)PTEPtr >> 12);
|
||||
}
|
||||
else
|
||||
PTEPtr = (PageTableEntryPtr *)(PDE->GetAddress() << 12);
|
||||
PDE->raw |= (uintptr_t)DirectoryFlags;
|
||||
PageTableEntryPtr *PTEPtr = nullptr;
|
||||
if (!PDE->Present)
|
||||
{
|
||||
PTEPtr = (PageTableEntryPtr *)KernelAllocator.RequestPages(TO_PAGES(sizeof(PageTableEntryPtr) + 1));
|
||||
memset(PTEPtr, 0, sizeof(PageTableEntryPtr));
|
||||
PDE->Present = true;
|
||||
PDE->SetAddress((uintptr_t)PTEPtr >> 12);
|
||||
}
|
||||
else
|
||||
PTEPtr = (PageTableEntryPtr *)(PDE->GetAddress() << 12);
|
||||
PDE->raw |= (uintptr_t)DirectoryFlags;
|
||||
|
||||
PageTableEntry *PTE = &PTEPtr->Entries[Index.PTEIndex];
|
||||
PTE->Present = true;
|
||||
PTE->raw |= (uintptr_t)Flags;
|
||||
PTE->SetAddress((uintptr_t)PhysicalAddress >> 12);
|
||||
CPU::x32::invlpg(VirtualAddress);
|
||||
PageTableEntry *PTE = &PTEPtr->Entries[Index.PTEIndex];
|
||||
PTE->Present = true;
|
||||
PTE->raw |= (uintptr_t)Flags;
|
||||
PTE->SetAddress((uintptr_t)PhysicalAddress >> 12);
|
||||
CPU::x32::invlpg(VirtualAddress);
|
||||
|
||||
#ifdef DEBUG
|
||||
/* https://stackoverflow.com/a/3208376/9352057 */
|
||||
#define BYTE_TO_BINARY_PATTERN "%c%c%c%c%c%c%c%c"
|
||||
#define BYTE_TO_BINARY(byte) \
|
||||
(byte & 0x80 ? '1' : '0'), \
|
||||
(byte & 0x40 ? '1' : '0'), \
|
||||
(byte & 0x20 ? '1' : '0'), \
|
||||
(byte & 0x10 ? '1' : '0'), \
|
||||
(byte & 0x08 ? '1' : '0'), \
|
||||
(byte & 0x04 ? '1' : '0'), \
|
||||
(byte & 0x02 ? '1' : '0'), \
|
||||
(byte & 0x01 ? '1' : '0')
|
||||
(byte & 0x80 ? '1' : '0'), \
|
||||
(byte & 0x40 ? '1' : '0'), \
|
||||
(byte & 0x20 ? '1' : '0'), \
|
||||
(byte & 0x10 ? '1' : '0'), \
|
||||
(byte & 0x08 ? '1' : '0'), \
|
||||
(byte & 0x04 ? '1' : '0'), \
|
||||
(byte & 0x02 ? '1' : '0'), \
|
||||
(byte & 0x01 ? '1' : '0')
|
||||
|
||||
if (!this->Check(VirtualAddress, (PTFlag)Flags, Type)) // quick workaround just to see where it fails
|
||||
warn("Failed to map v:%#lx p:%#lx with flags: " BYTE_TO_BINARY_PATTERN, VirtualAddress, PhysicalAddress, BYTE_TO_BINARY(Flags));
|
||||
if (!this->Check(VirtualAddress, (PTFlag)Flags, Type)) // quick workaround just to see where it fails
|
||||
warn("Failed to map v:%#lx p:%#lx with flags: " BYTE_TO_BINARY_PATTERN, VirtualAddress, PhysicalAddress, BYTE_TO_BINARY(Flags));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void Virtual::Unmap(void *VirtualAddress, MapType Type)
|
||||
{
|
||||
SmartLock(this->MemoryLock);
|
||||
if (!this->Table)
|
||||
{
|
||||
error("No page table");
|
||||
return;
|
||||
}
|
||||
void Virtual::Unmap(void *VirtualAddress, MapType Type)
|
||||
{
|
||||
SmartLock(this->MemoryLock);
|
||||
if (!this->Table)
|
||||
{
|
||||
error("No page table");
|
||||
return;
|
||||
}
|
||||
|
||||
PageMapIndexer Index = PageMapIndexer((uintptr_t)VirtualAddress);
|
||||
PageDirectoryEntry *PDE = &this->Table->Entries[Index.PDEIndex];
|
||||
if (!PDE->Present)
|
||||
{
|
||||
warn("Page %#lx not present", PDE->GetAddress());
|
||||
return;
|
||||
}
|
||||
PageMapIndexer Index = PageMapIndexer((uintptr_t)VirtualAddress);
|
||||
PageDirectoryEntry *PDE = &this->Table->Entries[Index.PDEIndex];
|
||||
if (!PDE->Present)
|
||||
{
|
||||
warn("Page %#lx not present", PDE->GetAddress());
|
||||
return;
|
||||
}
|
||||
|
||||
if (Type == MapType::FourMiB && PDE->PageSize)
|
||||
{
|
||||
PDE->Present = false;
|
||||
return;
|
||||
}
|
||||
if (Type == MapType::FourMiB && PDE->PageSize)
|
||||
{
|
||||
PDE->Present = false;
|
||||
return;
|
||||
}
|
||||
|
||||
PageTableEntryPtr *PTEPtr = (PageTableEntryPtr *)((uintptr_t)PDE->Address << 12);
|
||||
PageTableEntry PTE = PTEPtr->Entries[Index.PTEIndex];
|
||||
if (!PTE.Present)
|
||||
{
|
||||
warn("Page %#lx not present", PTE.GetAddress());
|
||||
return;
|
||||
}
|
||||
PageTableEntryPtr *PTEPtr = (PageTableEntryPtr *)((uintptr_t)PDE->Address << 12);
|
||||
PageTableEntry PTE = PTEPtr->Entries[Index.PTEIndex];
|
||||
if (!PTE.Present)
|
||||
{
|
||||
warn("Page %#lx not present", PTE.GetAddress());
|
||||
return;
|
||||
}
|
||||
|
||||
PTE.Present = false;
|
||||
PTEPtr->Entries[Index.PTEIndex] = PTE;
|
||||
CPU::x32::invlpg(VirtualAddress);
|
||||
}
|
||||
PTE.Present = false;
|
||||
PTEPtr->Entries[Index.PTEIndex] = PTE;
|
||||
CPU::x32::invlpg(VirtualAddress);
|
||||
}
|
||||
}
|
||||
|
181
boot_logo.cpp
181
boot_logo.cpp
@ -1,181 +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 "kernel.h"
|
||||
|
||||
#include <filesystem/ustar.hpp>
|
||||
#include <kshell.hpp>
|
||||
#include <power.hpp>
|
||||
#include <lock.hpp>
|
||||
#include <printf.h>
|
||||
#include <exec.hpp>
|
||||
#include <cwalk.h>
|
||||
#include <vm.hpp>
|
||||
#include <vector>
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#define STBI_NO_STDIO
|
||||
#define STBI_NO_LINEAR
|
||||
#define STBI_NO_THREAD_LOCALS
|
||||
#define STBI_NO_HDR
|
||||
#define STBI_ONLY_TGA
|
||||
#include <stb/image.h>
|
||||
|
||||
#include "mapi.hpp"
|
||||
#include "Fex.hpp"
|
||||
|
||||
using vfs::RefNode;
|
||||
|
||||
/* Files: 0.tga 1.tga ... 26.tga */
|
||||
uint8_t *Frames[27];
|
||||
uint32_t FrameSizes[27];
|
||||
size_t FrameCount = 1;
|
||||
|
||||
void BootLogoAnimationThread()
|
||||
{
|
||||
char BootAnimPath[16];
|
||||
while (FrameCount < 27)
|
||||
{
|
||||
sprintf(BootAnimPath, "/etc/boot/%ld.tga", FrameCount);
|
||||
RefNode *frame = fs->Open(BootAnimPath);
|
||||
if (!frame)
|
||||
{
|
||||
debug("Failed to load boot animation frame %s", BootAnimPath);
|
||||
break;
|
||||
}
|
||||
|
||||
FrameSizes[FrameCount] = s_cst(uint32_t, frame->Size);
|
||||
Frames[FrameCount] = new uint8_t[frame->Size];
|
||||
frame->read(Frames[FrameCount], frame->Size);
|
||||
delete frame;
|
||||
FrameCount++;
|
||||
}
|
||||
|
||||
uint32_t DispX = Display->GetBuffer(1)->Width;
|
||||
uint32_t DispY = Display->GetBuffer(1)->Height;
|
||||
|
||||
for (size_t i = 1; i < FrameCount; i++)
|
||||
{
|
||||
int x, y, channels;
|
||||
|
||||
if (!stbi_info_from_memory((uint8_t *)Frames[i], FrameSizes[i],
|
||||
&x, &y, &channels))
|
||||
continue;
|
||||
|
||||
uint8_t *img = stbi_load_from_memory((uint8_t *)Frames[i],
|
||||
FrameSizes[i], &x, &y,
|
||||
&channels, STBI_rgb_alpha);
|
||||
|
||||
if (img == NULL)
|
||||
continue;
|
||||
|
||||
int offsetX = DispX / 2 - x / 2;
|
||||
int offsetY = DispY / 2 - y / 2;
|
||||
|
||||
for (int i = 0; i < x * y; i++)
|
||||
{
|
||||
uint32_t pixel = ((uint32_t *)img)[i];
|
||||
int r = (pixel >> 16) & 0xFF;
|
||||
int g = (pixel >> 8) & 0xFF;
|
||||
int b = (pixel >> 0) & 0xFF;
|
||||
int a = (pixel >> 24) & 0xFF;
|
||||
|
||||
if (a != 0xFF)
|
||||
{
|
||||
r = (r * a) / 0xFF;
|
||||
g = (g * a) / 0xFF;
|
||||
b = (b * a) / 0xFF;
|
||||
}
|
||||
|
||||
Display->SetPixel((i % x) + offsetX, (i / x) + offsetY,
|
||||
(r << 16) | (g << 8) | (b << 0), 1);
|
||||
}
|
||||
|
||||
free(img);
|
||||
Display->SetBuffer(1);
|
||||
TaskManager->Sleep(50);
|
||||
}
|
||||
|
||||
int brightness = 100;
|
||||
while (brightness >= 0)
|
||||
{
|
||||
brightness -= 10;
|
||||
Display->SetBrightness(brightness, 1);
|
||||
Display->SetBuffer(1);
|
||||
TaskManager->Sleep(5);
|
||||
}
|
||||
}
|
||||
|
||||
void ExitLogoAnimationThread()
|
||||
{
|
||||
Display->SetBrightness(100, 1);
|
||||
Display->SetBuffer(1);
|
||||
|
||||
/* Files: 26.tga 25.tga ... 1.tga */
|
||||
uint32_t DispX = Display->GetBuffer(1)->Width;
|
||||
uint32_t DispY = Display->GetBuffer(1)->Height;
|
||||
|
||||
for (size_t i = FrameCount - 1; i > 0; i--)
|
||||
{
|
||||
int x, y, channels;
|
||||
|
||||
if (!stbi_info_from_memory((uint8_t *)Frames[i], FrameSizes[i],
|
||||
&x, &y, &channels))
|
||||
continue;
|
||||
|
||||
uint8_t *img = stbi_load_from_memory((uint8_t *)Frames[i],
|
||||
FrameSizes[i], &x, &y,
|
||||
&channels, STBI_rgb_alpha);
|
||||
|
||||
if (img == NULL)
|
||||
continue;
|
||||
|
||||
int offsetX = DispX / 2 - x / 2;
|
||||
int offsetY = DispY / 2 - y / 2;
|
||||
|
||||
for (int i = 0; i < x * y; i++)
|
||||
{
|
||||
uint32_t pixel = ((uint32_t *)img)[i];
|
||||
int r = (pixel >> 16) & 0xFF;
|
||||
int g = (pixel >> 8) & 0xFF;
|
||||
int b = (pixel >> 0) & 0xFF;
|
||||
int a = (pixel >> 24) & 0xFF;
|
||||
|
||||
if (a != 0xFF)
|
||||
{
|
||||
r = (r * a) / 0xFF;
|
||||
g = (g * a) / 0xFF;
|
||||
b = (b * a) / 0xFF;
|
||||
}
|
||||
|
||||
Display->SetPixel((i % x) + offsetX, (i / x) + offsetY,
|
||||
(r << 16) | (g << 8) | (b << 0), 1);
|
||||
}
|
||||
|
||||
free(img);
|
||||
Display->SetBuffer(1);
|
||||
TaskManager->Sleep(50);
|
||||
}
|
||||
|
||||
int brightness = 100;
|
||||
while (brightness >= 0)
|
||||
{
|
||||
brightness -= 10;
|
||||
Display->SetBrightness(brightness, 1);
|
||||
Display->SetBuffer(1);
|
||||
TaskManager->Sleep(5);
|
||||
}
|
||||
}
|
@ -40,13 +40,23 @@ namespace ACPI
|
||||
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
for (short i = 0; i < 4; i++)
|
||||
size_t signLength = strlen(Signature);
|
||||
for (size_t i = 0; i < signLength; i++)
|
||||
{
|
||||
if (SDTHdr->Signature[i] != Signature[i])
|
||||
break;
|
||||
if (i == 3)
|
||||
{
|
||||
trace("%s found at address %p", Signature, (uintptr_t)SDTHdr);
|
||||
#ifdef DEBUG
|
||||
KPrint("ACPI: %s [%s:%s] found at address %#lx",
|
||||
Signature,
|
||||
SDTHdr->OEMID,
|
||||
SDTHdr->OEMTableID,
|
||||
(uintptr_t)SDTHdr);
|
||||
#endif
|
||||
trace("%s found at address %#lx", Signature, (uintptr_t)SDTHdr);
|
||||
|
||||
Tables[Signature] = SDTHdr;
|
||||
return SDTHdr;
|
||||
}
|
||||
}
|
||||
@ -70,6 +80,9 @@ namespace ACPI
|
||||
WAET = (WAETHeader *)FindTable(Header, (char *)"WAET");
|
||||
MADT = (MADTHeader *)FindTable(Header, (char *)"APIC");
|
||||
HEST = (HESTHeader *)FindTable(Header, (char *)"HEST");
|
||||
SSDT = (SSDTHeader *)FindTable(Header, (char *)"SSDT");
|
||||
DBGP = (DBGPHeader *)FindTable(Header, (char *)"DBGP");
|
||||
DBG2 = (DBG2Header *)FindTable(Header, (char *)"DBG2");
|
||||
FindTable(Header, (char *)"BERT");
|
||||
FindTable(Header, (char *)"CPEP");
|
||||
FindTable(Header, (char *)"DSDT");
|
||||
@ -86,7 +99,6 @@ namespace ACPI
|
||||
FindTable(Header, (char *)"RSDT");
|
||||
FindTable(Header, (char *)"SBST");
|
||||
FindTable(Header, (char *)"SLIT");
|
||||
FindTable(Header, (char *)"SSDT");
|
||||
FindTable(Header, (char *)"XSDT");
|
||||
FindTable(Header, (char *)"DRTM");
|
||||
FindTable(Header, (char *)"FPDT");
|
||||
@ -102,8 +114,8 @@ namespace ACPI
|
||||
FindTable(Header, (char *)"ASF!");
|
||||
FindTable(Header, (char *)"BOOT");
|
||||
FindTable(Header, (char *)"CSRT");
|
||||
FindTable(Header, (char *)"DBG2");
|
||||
FindTable(Header, (char *)"DBGP");
|
||||
FindTable(Header, (char *)"BDAT");
|
||||
FindTable(Header, (char *)"CDAT");
|
||||
FindTable(Header, (char *)"DMAR");
|
||||
FindTable(Header, (char *)"IBFT");
|
||||
FindTable(Header, (char *)"IORT");
|
||||
@ -125,6 +137,28 @@ namespace ACPI
|
||||
FindTable(Header, (char *)"HMAT");
|
||||
FindTable(Header, (char *)"CEDT");
|
||||
FindTable(Header, (char *)"AEST");
|
||||
FindTable(Header, (char *)"AGDI");
|
||||
FindTable(Header, (char *)"APMT");
|
||||
FindTable(Header, (char *)"ETDT");
|
||||
FindTable(Header, (char *)"MPAM");
|
||||
FindTable(Header, (char *)"PDTT");
|
||||
FindTable(Header, (char *)"PPTT");
|
||||
FindTable(Header, (char *)"RAS2");
|
||||
FindTable(Header, (char *)"SDEI");
|
||||
FindTable(Header, (char *)"STAO");
|
||||
FindTable(Header, (char *)"XENV");
|
||||
FindTable(Header, (char *)"PHAT");
|
||||
FindTable(Header, (char *)"SVKL");
|
||||
FindTable(Header, (char *)"UUID");
|
||||
FindTable(Header, (char *)"CCEL");
|
||||
FindTable(Header, (char *)"WSMT");
|
||||
FindTable(Header, (char *)"PRMT");
|
||||
FindTable(Header, (char *)"NBFT");
|
||||
FindTable(Header, (char *)"RSD PTR");
|
||||
FindTable(Header, (char *)"TDX");
|
||||
FindTable(Header, (char *)"CXL");
|
||||
FindTable(Header, (char *)"DSD");
|
||||
FindTable(Header, (char *)"BSA");
|
||||
}
|
||||
|
||||
ACPI::ACPI()
|
||||
@ -161,8 +195,9 @@ namespace ACPI
|
||||
if (FADT)
|
||||
{
|
||||
outb(s_cst(uint16_t, FADT->SMI_CommandPort), FADT->AcpiEnable);
|
||||
/* TODO: Sleep for ~5 seconds before polling PM1a CB? */
|
||||
while (!(inw(s_cst(uint16_t, FADT->PM1aControlBlock)) & 1))
|
||||
;
|
||||
CPU::Pause();
|
||||
}
|
||||
}
|
||||
|
||||
|
56
core/cpu.cpp
56
core/cpu.cpp
@ -167,9 +167,9 @@ namespace CPU
|
||||
: "=r"(Flags));
|
||||
return Flags & (1 << 9);
|
||||
#elif defined(aa64)
|
||||
asmv("mrs %0, daif"
|
||||
asmv("mrs %0, cpsr"
|
||||
: "=r"(Flags));
|
||||
return !(Flags & (1 << 2));
|
||||
return !(Flags & (1 << 7));
|
||||
#endif
|
||||
}
|
||||
case Enable:
|
||||
@ -177,7 +177,7 @@ namespace CPU
|
||||
#if defined(a86)
|
||||
asmv("sti");
|
||||
#elif defined(aa64)
|
||||
asmv("msr daifclr, #2");
|
||||
asmv("cpsie i");
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
@ -186,7 +186,7 @@ namespace CPU
|
||||
#if defined(a86)
|
||||
asmv("cli");
|
||||
#elif defined(aa64)
|
||||
asmv("msr daifset, #2");
|
||||
asmv("cpsid i");
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
@ -198,32 +198,39 @@ namespace CPU
|
||||
|
||||
void *PageTable(void *PT)
|
||||
{
|
||||
void *ret;
|
||||
#if defined(a64)
|
||||
asmv("movq %%cr3, %0"
|
||||
: "=r"(ret));
|
||||
|
||||
if (PT)
|
||||
{
|
||||
asmv("movq %0, %%cr3"
|
||||
:
|
||||
: "r"(PT));
|
||||
else
|
||||
asmv("movq %%cr3, %0"
|
||||
: "=r"(PT));
|
||||
}
|
||||
#elif defined(a32)
|
||||
asmv("movl %%cr3, %0"
|
||||
: "=r"(ret));
|
||||
|
||||
if (PT)
|
||||
{
|
||||
asmv("movl %0, %%cr3"
|
||||
:
|
||||
: "r"(PT));
|
||||
else
|
||||
asmv("movl %%cr3, %0"
|
||||
: "=r"(PT));
|
||||
}
|
||||
#elif defined(aa64)
|
||||
asmv("mrs %0, ttbr0_el1"
|
||||
: "=r"(ret));
|
||||
|
||||
if (PT)
|
||||
{
|
||||
asmv("msr ttbr0_el1, %0"
|
||||
:
|
||||
: "r"(PT));
|
||||
else
|
||||
asmv("mrs %0, ttbr0_el1"
|
||||
: "=r"(PT));
|
||||
}
|
||||
#endif
|
||||
return PT;
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct SupportedFeat
|
||||
@ -378,7 +385,10 @@ namespace CPU
|
||||
if (!BSP++)
|
||||
trace("Features for BSP initialized.");
|
||||
if (SSEEnableAfter)
|
||||
{
|
||||
SSEEnabled = true;
|
||||
debug("SSE support enabled.");
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t Counter()
|
||||
@ -403,7 +413,8 @@ namespace CPU
|
||||
if (unlikely(!SSEEnabled))
|
||||
return SIMD_NONE;
|
||||
|
||||
// return SIMD_SSE;
|
||||
#warning "TODO: Proper SIMD support"
|
||||
return SIMD_NONE;
|
||||
|
||||
#if defined(a86)
|
||||
static uint64_t SIMDType = SIMD_NONE;
|
||||
@ -415,13 +426,16 @@ namespace CPU
|
||||
{
|
||||
CPU::x86::AMD::CPUID0x00000001 cpuid;
|
||||
asmv("cpuid"
|
||||
: "=a"(cpuid.EAX.raw), "=b"(cpuid.EBX.raw), "=c"(cpuid.ECX.raw), "=d"(cpuid.EDX.raw)
|
||||
: "=a"(cpuid.EAX.raw), "=b"(cpuid.EBX.raw),
|
||||
"=c"(cpuid.ECX.raw), "=d"(cpuid.EDX.raw)
|
||||
: "a"(0x1));
|
||||
|
||||
if (cpuid.ECX.SSE42)
|
||||
SIMDType |= SIMD_SSE42;
|
||||
else if (cpuid.ECX.SSE41)
|
||||
SIMDType |= SIMD_SSE41;
|
||||
else if (cpuid.ECX.SSSE3)
|
||||
SIMDType |= SIMD_SSSE3;
|
||||
else if (cpuid.ECX.SSE3)
|
||||
SIMDType |= SIMD_SSE3;
|
||||
else if (cpuid.EDX.SSE2)
|
||||
@ -434,6 +448,8 @@ namespace CPU
|
||||
debug("SSE4.2 is supported.");
|
||||
if (cpuid.ECX.SSE41)
|
||||
debug("SSE4.1 is supported.");
|
||||
if (cpuid.ECX.SSSE3)
|
||||
debug("SSSE3 is supported.");
|
||||
if (cpuid.ECX.SSE3)
|
||||
debug("SSE3 is supported.");
|
||||
if (cpuid.EDX.SSE2)
|
||||
@ -455,6 +471,8 @@ namespace CPU
|
||||
SIMDType |= SIMD_SSE42;
|
||||
else if (cpuid.ECX.SSE4_1)
|
||||
SIMDType |= SIMD_SSE41;
|
||||
else if (cpuid.ECX.SSSE3)
|
||||
SIMDType |= SIMD_SSSE3;
|
||||
else if (cpuid.ECX.SSE3)
|
||||
SIMDType |= SIMD_SSE3;
|
||||
else if (cpuid.EDX.SSE2)
|
||||
@ -467,6 +485,8 @@ namespace CPU
|
||||
debug("SSE4.2 is supported.");
|
||||
if (cpuid.ECX.SSE4_1)
|
||||
debug("SSE4.1 is supported.");
|
||||
if (cpuid.ECX.SSSE3)
|
||||
debug("SSSE3 is supported.");
|
||||
if (cpuid.ECX.SSE3)
|
||||
debug("SSE3 is supported.");
|
||||
if (cpuid.EDX.SSE2)
|
||||
@ -499,6 +519,8 @@ namespace CPU
|
||||
return cpuid.ECX.SSE42;
|
||||
else if (Type == SIMD_SSE41)
|
||||
return cpuid.ECX.SSE41;
|
||||
else if (Type == SIMD_SSSE3)
|
||||
return cpuid.ECX.SSSE3;
|
||||
else if (Type == SIMD_SSE3)
|
||||
return cpuid.ECX.SSE3;
|
||||
else if (Type == SIMD_SSE2)
|
||||
@ -517,6 +539,8 @@ namespace CPU
|
||||
return cpuid.ECX.SSE4_2;
|
||||
else if (Type == SIMD_SSE41)
|
||||
return cpuid.ECX.SSE4_1;
|
||||
else if (Type == SIMD_SSSE3)
|
||||
return cpuid.ECX.SSSE3;
|
||||
else if (Type == SIMD_SSE3)
|
||||
return cpuid.ECX.SSE3;
|
||||
else if (Type == SIMD_SSE2)
|
||||
|
@ -1,18 +1,18 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
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 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.
|
||||
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/>.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __FENNIX_KERNEL_CRASH_HANDLERS_FUNCTIONS_H__
|
||||
@ -29,22 +29,22 @@ typedef struct CPU::x64::TrapFrame CHArchTrapFrame;
|
||||
|
||||
struct CRData
|
||||
{
|
||||
CHArchTrapFrame *Frame;
|
||||
CHArchTrapFrame *Frame;
|
||||
|
||||
CPU::x64::CR0 cr0;
|
||||
CPU::x64::CR2 cr2;
|
||||
CPU::x64::CR3 cr3;
|
||||
CPU::x64::CR4 cr4;
|
||||
CPU::x64::CR8 cr8;
|
||||
CPU::x64::EFER efer;
|
||||
uintptr_t dr0, dr1, dr2, dr3;
|
||||
CPU::x64::DR6 dr6;
|
||||
CPU::x64::DR7 dr7;
|
||||
CPU::x64::CR0 cr0;
|
||||
CPU::x64::CR2 cr2;
|
||||
CPU::x64::CR3 cr3;
|
||||
CPU::x64::CR4 cr4;
|
||||
CPU::x64::CR8 cr8;
|
||||
CPU::x64::EFER efer;
|
||||
uintptr_t dr0, dr1, dr2, dr3;
|
||||
CPU::x64::DR6 dr6;
|
||||
CPU::x64::DR7 dr7;
|
||||
|
||||
long ID;
|
||||
void *CPUData;
|
||||
Tasking::PCB *Process;
|
||||
Tasking::TCB *Thread;
|
||||
long ID;
|
||||
void *CPUData;
|
||||
Tasking::PCB *Process;
|
||||
Tasking::TCB *Thread;
|
||||
};
|
||||
|
||||
#elif defined(a32)
|
||||
@ -52,251 +52,245 @@ typedef struct CPU::x32::TrapFrame CHArchTrapFrame;
|
||||
|
||||
struct CRData
|
||||
{
|
||||
CHArchTrapFrame *Frame;
|
||||
CHArchTrapFrame *Frame;
|
||||
|
||||
CPU::x32::CR0 cr0;
|
||||
CPU::x32::CR2 cr2;
|
||||
CPU::x32::CR3 cr3;
|
||||
CPU::x32::CR4 cr4;
|
||||
CPU::x32::CR8 cr8;
|
||||
uintptr_t dr0, dr1, dr2, dr3;
|
||||
CPU::x32::DR6 dr6;
|
||||
CPU::x32::DR7 dr7;
|
||||
CPU::x32::CR0 cr0;
|
||||
CPU::x32::CR2 cr2;
|
||||
CPU::x32::CR3 cr3;
|
||||
CPU::x32::CR4 cr4;
|
||||
CPU::x32::CR8 cr8;
|
||||
uintptr_t dr0, dr1, dr2, dr3;
|
||||
CPU::x32::DR6 dr6;
|
||||
CPU::x32::DR7 dr7;
|
||||
|
||||
long ID;
|
||||
void *CPUData;
|
||||
Tasking::PCB *Process;
|
||||
Tasking::TCB *Thread;
|
||||
long ID;
|
||||
void *CPUData;
|
||||
Tasking::PCB *Process;
|
||||
Tasking::TCB *Thread;
|
||||
};
|
||||
#elif defined(aa64)
|
||||
typedef struct CPU::aarch64::TrapFrame CHArchTrapFrame;
|
||||
|
||||
struct CRData
|
||||
{
|
||||
CHArchTrapFrame *Frame;
|
||||
CHArchTrapFrame *Frame;
|
||||
|
||||
long ID;
|
||||
void *CPUData;
|
||||
Tasking::PCB *Process;
|
||||
Tasking::TCB *Thread;
|
||||
long ID;
|
||||
void *CPUData;
|
||||
Tasking::PCB *Process;
|
||||
Tasking::TCB *Thread;
|
||||
};
|
||||
#endif
|
||||
|
||||
enum Keys
|
||||
{
|
||||
KEY_INVALID = 0x0,
|
||||
KEY_D_ESCAPE = 0x1,
|
||||
KEY_D_1 = 0x2,
|
||||
KEY_D_2 = 0x3,
|
||||
KEY_D_3 = 0x4,
|
||||
KEY_D_4 = 0x5,
|
||||
KEY_D_5 = 0x6,
|
||||
KEY_D_6 = 0x7,
|
||||
KEY_D_7 = 0x8,
|
||||
KEY_D_8 = 0x9,
|
||||
KEY_D_9 = 0xa,
|
||||
KEY_D_0 = 0xb,
|
||||
KEY_D_MINUS = 0xc,
|
||||
KEY_D_EQUALS = 0xd,
|
||||
KEY_D_BACKSPACE = 0xe,
|
||||
KEY_D_TAB = 0xf,
|
||||
KEY_D_Q = 0x10,
|
||||
KEY_D_W = 0x11,
|
||||
KEY_D_E = 0x12,
|
||||
KEY_D_R = 0x13,
|
||||
KEY_D_T = 0x14,
|
||||
KEY_D_Y = 0x15,
|
||||
KEY_D_U = 0x16,
|
||||
KEY_D_I = 0x17,
|
||||
KEY_D_O = 0x18,
|
||||
KEY_D_P = 0x19,
|
||||
KEY_D_LBRACKET = 0x1a,
|
||||
KEY_D_RBRACKET = 0x1b,
|
||||
KEY_D_RETURN = 0x1c,
|
||||
KEY_D_LCTRL = 0x1d,
|
||||
KEY_D_A = 0x1e,
|
||||
KEY_D_S = 0x1f,
|
||||
KEY_D_D = 0x20,
|
||||
KEY_D_F = 0x21,
|
||||
KEY_D_G = 0x22,
|
||||
KEY_D_H = 0x23,
|
||||
KEY_D_J = 0x24,
|
||||
KEY_D_K = 0x25,
|
||||
KEY_D_L = 0x26,
|
||||
KEY_D_SEMICOLON = 0x27,
|
||||
KEY_D_APOSTROPHE = 0x28,
|
||||
KEY_D_GRAVE = 0x29,
|
||||
KEY_D_LSHIFT = 0x2a,
|
||||
KEY_D_BACKSLASH = 0x2b,
|
||||
KEY_D_Z = 0x2c,
|
||||
KEY_D_X = 0x2d,
|
||||
KEY_D_C = 0x2e,
|
||||
KEY_D_V = 0x2f,
|
||||
KEY_D_B = 0x30,
|
||||
KEY_D_N = 0x31,
|
||||
KEY_D_M = 0x32,
|
||||
KEY_D_COMMA = 0x33,
|
||||
KEY_D_PERIOD = 0x34,
|
||||
KEY_D_SLASH = 0x35,
|
||||
KEY_D_RSHIFT = 0x36,
|
||||
KEY_D_PRTSC = 0x37,
|
||||
KEY_D_LALT = 0x38,
|
||||
KEY_D_SPACE = 0x39,
|
||||
KEY_D_CAPSLOCK = 0x3a,
|
||||
KEY_D_NUMLOCK = 0x45,
|
||||
KEY_D_SCROLLLOCK = 0x46,
|
||||
KEY_INVALID = 0x0,
|
||||
KEY_D_ESCAPE = 0x1,
|
||||
KEY_D_1 = 0x2,
|
||||
KEY_D_2 = 0x3,
|
||||
KEY_D_3 = 0x4,
|
||||
KEY_D_4 = 0x5,
|
||||
KEY_D_5 = 0x6,
|
||||
KEY_D_6 = 0x7,
|
||||
KEY_D_7 = 0x8,
|
||||
KEY_D_8 = 0x9,
|
||||
KEY_D_9 = 0xa,
|
||||
KEY_D_0 = 0xb,
|
||||
KEY_D_MINUS = 0xc,
|
||||
KEY_D_EQUALS = 0xd,
|
||||
KEY_D_BACKSPACE = 0xe,
|
||||
KEY_D_TAB = 0xf,
|
||||
KEY_D_Q = 0x10,
|
||||
KEY_D_W = 0x11,
|
||||
KEY_D_E = 0x12,
|
||||
KEY_D_R = 0x13,
|
||||
KEY_D_T = 0x14,
|
||||
KEY_D_Y = 0x15,
|
||||
KEY_D_U = 0x16,
|
||||
KEY_D_I = 0x17,
|
||||
KEY_D_O = 0x18,
|
||||
KEY_D_P = 0x19,
|
||||
KEY_D_LBRACKET = 0x1a,
|
||||
KEY_D_RBRACKET = 0x1b,
|
||||
KEY_D_RETURN = 0x1c,
|
||||
KEY_D_LCTRL = 0x1d,
|
||||
KEY_D_A = 0x1e,
|
||||
KEY_D_S = 0x1f,
|
||||
KEY_D_D = 0x20,
|
||||
KEY_D_F = 0x21,
|
||||
KEY_D_G = 0x22,
|
||||
KEY_D_H = 0x23,
|
||||
KEY_D_J = 0x24,
|
||||
KEY_D_K = 0x25,
|
||||
KEY_D_L = 0x26,
|
||||
KEY_D_SEMICOLON = 0x27,
|
||||
KEY_D_APOSTROPHE = 0x28,
|
||||
KEY_D_GRAVE = 0x29,
|
||||
KEY_D_LSHIFT = 0x2a,
|
||||
KEY_D_BACKSLASH = 0x2b,
|
||||
KEY_D_Z = 0x2c,
|
||||
KEY_D_X = 0x2d,
|
||||
KEY_D_C = 0x2e,
|
||||
KEY_D_V = 0x2f,
|
||||
KEY_D_B = 0x30,
|
||||
KEY_D_N = 0x31,
|
||||
KEY_D_M = 0x32,
|
||||
KEY_D_COMMA = 0x33,
|
||||
KEY_D_PERIOD = 0x34,
|
||||
KEY_D_SLASH = 0x35,
|
||||
KEY_D_RSHIFT = 0x36,
|
||||
KEY_D_PRTSC = 0x37,
|
||||
KEY_D_LALT = 0x38,
|
||||
KEY_D_SPACE = 0x39,
|
||||
KEY_D_CAPSLOCK = 0x3a,
|
||||
KEY_D_NUMLOCK = 0x45,
|
||||
KEY_D_SCROLLLOCK = 0x46,
|
||||
|
||||
KEY_D_KP_MULTIPLY = 0x37,
|
||||
KEY_D_KP_7 = 0x47,
|
||||
KEY_D_KP_8 = 0x48,
|
||||
KEY_D_KP_9 = 0x49,
|
||||
KEY_D_KP_MINUS = 0x4a,
|
||||
KEY_D_KP_4 = 0x4b,
|
||||
KEY_D_KP_5 = 0x4c,
|
||||
KEY_D_KP_6 = 0x4d,
|
||||
KEY_D_KP_PLUS = 0x4e,
|
||||
KEY_D_KP_1 = 0x4f,
|
||||
KEY_D_KP_2 = 0x50,
|
||||
KEY_D_KP_3 = 0x51,
|
||||
KEY_D_KP_0 = 0x52,
|
||||
KEY_D_KP_PERIOD = 0x53,
|
||||
KEY_D_KP_MULTIPLY = 0x37,
|
||||
KEY_D_KP_7 = 0x47,
|
||||
KEY_D_KP_8 = 0x48,
|
||||
KEY_D_KP_9 = 0x49,
|
||||
KEY_D_KP_MINUS = 0x4a,
|
||||
KEY_D_KP_4 = 0x4b,
|
||||
KEY_D_KP_5 = 0x4c,
|
||||
KEY_D_KP_6 = 0x4d,
|
||||
KEY_D_KP_PLUS = 0x4e,
|
||||
KEY_D_KP_1 = 0x4f,
|
||||
KEY_D_KP_2 = 0x50,
|
||||
KEY_D_KP_3 = 0x51,
|
||||
KEY_D_KP_0 = 0x52,
|
||||
KEY_D_KP_PERIOD = 0x53,
|
||||
|
||||
KEY_D_F1 = 0x3b,
|
||||
KEY_D_F2 = 0x3c,
|
||||
KEY_D_F3 = 0x3d,
|
||||
KEY_D_F4 = 0x3e,
|
||||
KEY_D_F5 = 0x3f,
|
||||
KEY_D_F6 = 0x40,
|
||||
KEY_D_F7 = 0x41,
|
||||
KEY_D_F8 = 0x42,
|
||||
KEY_D_F9 = 0x43,
|
||||
KEY_D_F10 = 0x44,
|
||||
KEY_D_F11 = 0x57,
|
||||
KEY_D_F12 = 0x58,
|
||||
KEY_D_F1 = 0x3b,
|
||||
KEY_D_F2 = 0x3c,
|
||||
KEY_D_F3 = 0x3d,
|
||||
KEY_D_F4 = 0x3e,
|
||||
KEY_D_F5 = 0x3f,
|
||||
KEY_D_F6 = 0x40,
|
||||
KEY_D_F7 = 0x41,
|
||||
KEY_D_F8 = 0x42,
|
||||
KEY_D_F9 = 0x43,
|
||||
KEY_D_F10 = 0x44,
|
||||
KEY_D_F11 = 0x57,
|
||||
KEY_D_F12 = 0x58,
|
||||
|
||||
KEY_D_UP = 0x48,
|
||||
KEY_D_LEFT = 0x4b,
|
||||
KEY_D_RIGHT = 0x4d,
|
||||
KEY_D_DOWN = 0x50,
|
||||
KEY_D_UP = 0x48,
|
||||
KEY_D_LEFT = 0x4b,
|
||||
KEY_D_RIGHT = 0x4d,
|
||||
KEY_D_DOWN = 0x50,
|
||||
|
||||
KEY_U_ESCAPE = 0x81,
|
||||
KEY_U_1 = 0x82,
|
||||
KEY_U_2 = 0x83,
|
||||
KEY_U_3 = 0x84,
|
||||
KEY_U_4 = 0x85,
|
||||
KEY_U_5 = 0x86,
|
||||
KEY_U_6 = 0x87,
|
||||
KEY_U_7 = 0x88,
|
||||
KEY_U_8 = 0x89,
|
||||
KEY_U_9 = 0x8a,
|
||||
KEY_U_0 = 0x8b,
|
||||
KEY_U_MINUS = 0x8c,
|
||||
KEY_U_EQUALS = 0x8d,
|
||||
KEY_U_BACKSPACE = 0x8e,
|
||||
KEY_U_TAB = 0x8f,
|
||||
KEY_U_Q = 0x90,
|
||||
KEY_U_W = 0x91,
|
||||
KEY_U_E = 0x92,
|
||||
KEY_U_R = 0x93,
|
||||
KEY_U_T = 0x94,
|
||||
KEY_U_Y = 0x95,
|
||||
KEY_U_U = 0x96,
|
||||
KEY_U_I = 0x97,
|
||||
KEY_U_O = 0x98,
|
||||
KEY_U_P = 0x99,
|
||||
KEY_U_LBRACKET = 0x9a,
|
||||
KEY_U_RBRACKET = 0x9b,
|
||||
KEY_U_RETURN = 0x9c,
|
||||
KEY_U_LCTRL = 0x9d,
|
||||
KEY_U_A = 0x9e,
|
||||
KEY_U_S = 0x9f,
|
||||
KEY_U_D = 0xa0,
|
||||
KEY_U_F = 0xa1,
|
||||
KEY_U_G = 0xa2,
|
||||
KEY_U_H = 0xa3,
|
||||
KEY_U_J = 0xa4,
|
||||
KEY_U_K = 0xa5,
|
||||
KEY_U_L = 0xa6,
|
||||
KEY_U_SEMICOLON = 0xa7,
|
||||
KEY_U_APOSTROPHE = 0xa8,
|
||||
KEY_U_GRAVE = 0xa9,
|
||||
KEY_U_LSHIFT = 0xaa,
|
||||
KEY_U_BACKSLASH = 0xab,
|
||||
KEY_U_Z = 0xac,
|
||||
KEY_U_X = 0xad,
|
||||
KEY_U_C = 0xae,
|
||||
KEY_U_V = 0xaf,
|
||||
KEY_U_B = 0xb0,
|
||||
KEY_U_N = 0xb1,
|
||||
KEY_U_M = 0xb2,
|
||||
KEY_U_COMMA = 0xb3,
|
||||
KEY_U_PERIOD = 0xb4,
|
||||
KEY_U_SLASH = 0xb5,
|
||||
KEY_U_RSHIFT = 0xb6,
|
||||
KEY_U_KP_MULTIPLY = 0xb7,
|
||||
KEY_U_LALT = 0xb8,
|
||||
KEY_U_SPACE = 0xb9,
|
||||
KEY_U_CAPSLOCK = 0xba,
|
||||
KEY_U_F1 = 0xbb,
|
||||
KEY_U_F2 = 0xbc,
|
||||
KEY_U_F3 = 0xbd,
|
||||
KEY_U_F4 = 0xbe,
|
||||
KEY_U_F5 = 0xbf,
|
||||
KEY_U_F6 = 0xc0,
|
||||
KEY_U_F7 = 0xc1,
|
||||
KEY_U_F8 = 0xc2,
|
||||
KEY_U_F9 = 0xc3,
|
||||
KEY_U_F10 = 0xc4,
|
||||
KEY_U_NUMLOCK = 0xc5,
|
||||
KEY_U_SCROLLLOCK = 0xc6,
|
||||
KEY_U_KP_7 = 0xc7,
|
||||
KEY_U_KP_8 = 0xc8,
|
||||
KEY_U_KP_9 = 0xc9,
|
||||
KEY_U_KP_MINUS = 0xca,
|
||||
KEY_U_KP_4 = 0xcb,
|
||||
KEY_U_KP_5 = 0xcc,
|
||||
KEY_U_KP_6 = 0xcd,
|
||||
KEY_U_KP_PLUS = 0xce,
|
||||
KEY_U_KP_1 = 0xcf,
|
||||
KEY_U_KP_2 = 0xd0,
|
||||
KEY_U_KP_3 = 0xd1,
|
||||
KEY_U_KP_0 = 0xd2,
|
||||
KEY_U_KP_PERIOD = 0xd3,
|
||||
KEY_U_F11 = 0xd7,
|
||||
KEY_U_F12 = 0xd8,
|
||||
KEY_U_ESCAPE = 0x81,
|
||||
KEY_U_1 = 0x82,
|
||||
KEY_U_2 = 0x83,
|
||||
KEY_U_3 = 0x84,
|
||||
KEY_U_4 = 0x85,
|
||||
KEY_U_5 = 0x86,
|
||||
KEY_U_6 = 0x87,
|
||||
KEY_U_7 = 0x88,
|
||||
KEY_U_8 = 0x89,
|
||||
KEY_U_9 = 0x8a,
|
||||
KEY_U_0 = 0x8b,
|
||||
KEY_U_MINUS = 0x8c,
|
||||
KEY_U_EQUALS = 0x8d,
|
||||
KEY_U_BACKSPACE = 0x8e,
|
||||
KEY_U_TAB = 0x8f,
|
||||
KEY_U_Q = 0x90,
|
||||
KEY_U_W = 0x91,
|
||||
KEY_U_E = 0x92,
|
||||
KEY_U_R = 0x93,
|
||||
KEY_U_T = 0x94,
|
||||
KEY_U_Y = 0x95,
|
||||
KEY_U_U = 0x96,
|
||||
KEY_U_I = 0x97,
|
||||
KEY_U_O = 0x98,
|
||||
KEY_U_P = 0x99,
|
||||
KEY_U_LBRACKET = 0x9a,
|
||||
KEY_U_RBRACKET = 0x9b,
|
||||
KEY_U_RETURN = 0x9c,
|
||||
KEY_U_LCTRL = 0x9d,
|
||||
KEY_U_A = 0x9e,
|
||||
KEY_U_S = 0x9f,
|
||||
KEY_U_D = 0xa0,
|
||||
KEY_U_F = 0xa1,
|
||||
KEY_U_G = 0xa2,
|
||||
KEY_U_H = 0xa3,
|
||||
KEY_U_J = 0xa4,
|
||||
KEY_U_K = 0xa5,
|
||||
KEY_U_L = 0xa6,
|
||||
KEY_U_SEMICOLON = 0xa7,
|
||||
KEY_U_APOSTROPHE = 0xa8,
|
||||
KEY_U_GRAVE = 0xa9,
|
||||
KEY_U_LSHIFT = 0xaa,
|
||||
KEY_U_BACKSLASH = 0xab,
|
||||
KEY_U_Z = 0xac,
|
||||
KEY_U_X = 0xad,
|
||||
KEY_U_C = 0xae,
|
||||
KEY_U_V = 0xaf,
|
||||
KEY_U_B = 0xb0,
|
||||
KEY_U_N = 0xb1,
|
||||
KEY_U_M = 0xb2,
|
||||
KEY_U_COMMA = 0xb3,
|
||||
KEY_U_PERIOD = 0xb4,
|
||||
KEY_U_SLASH = 0xb5,
|
||||
KEY_U_RSHIFT = 0xb6,
|
||||
KEY_U_KP_MULTIPLY = 0xb7,
|
||||
KEY_U_LALT = 0xb8,
|
||||
KEY_U_SPACE = 0xb9,
|
||||
KEY_U_CAPSLOCK = 0xba,
|
||||
KEY_U_F1 = 0xbb,
|
||||
KEY_U_F2 = 0xbc,
|
||||
KEY_U_F3 = 0xbd,
|
||||
KEY_U_F4 = 0xbe,
|
||||
KEY_U_F5 = 0xbf,
|
||||
KEY_U_F6 = 0xc0,
|
||||
KEY_U_F7 = 0xc1,
|
||||
KEY_U_F8 = 0xc2,
|
||||
KEY_U_F9 = 0xc3,
|
||||
KEY_U_F10 = 0xc4,
|
||||
KEY_U_NUMLOCK = 0xc5,
|
||||
KEY_U_SCROLLLOCK = 0xc6,
|
||||
KEY_U_KP_7 = 0xc7,
|
||||
KEY_U_KP_8 = 0xc8,
|
||||
KEY_U_KP_9 = 0xc9,
|
||||
KEY_U_KP_MINUS = 0xca,
|
||||
KEY_U_KP_4 = 0xcb,
|
||||
KEY_U_KP_5 = 0xcc,
|
||||
KEY_U_KP_6 = 0xcd,
|
||||
KEY_U_KP_PLUS = 0xce,
|
||||
KEY_U_KP_1 = 0xcf,
|
||||
KEY_U_KP_2 = 0xd0,
|
||||
KEY_U_KP_3 = 0xd1,
|
||||
KEY_U_KP_0 = 0xd2,
|
||||
KEY_U_KP_PERIOD = 0xd3,
|
||||
KEY_U_F11 = 0xd7,
|
||||
KEY_U_F12 = 0xd8,
|
||||
};
|
||||
|
||||
namespace CrashHandler
|
||||
{
|
||||
extern int SBIdx;
|
||||
extern int SBIdx;
|
||||
|
||||
class CrashKeyboardDriver : public Interrupts::Handler
|
||||
{
|
||||
private:
|
||||
void PS2Wait(bool Read);
|
||||
class CrashKeyboardDriver : public Interrupts::Handler
|
||||
{
|
||||
private:
|
||||
void PS2Wait(bool Read);
|
||||
void OnInterruptReceived(CPU::TrapFrame *Frame);
|
||||
|
||||
#if defined(a64)
|
||||
void OnInterruptReceived(CPU::x64::TrapFrame *Frame);
|
||||
#elif defined(a32)
|
||||
void OnInterruptReceived(CPU::x32::TrapFrame *Frame);
|
||||
#elif defined(aa64)
|
||||
void OnInterruptReceived(CPU::aarch64::TrapFrame *Frame);
|
||||
#endif
|
||||
public:
|
||||
CrashKeyboardDriver();
|
||||
~CrashKeyboardDriver();
|
||||
};
|
||||
public:
|
||||
CrashKeyboardDriver();
|
||||
~CrashKeyboardDriver();
|
||||
};
|
||||
|
||||
void TraceFrames(CRData data, int Count, SymbolResolver::Symbols *SymHandle, bool Kernel);
|
||||
void TraceFrames(CRData data, int Count, SymbolResolver::Symbols *SymHandle, bool Kernel);
|
||||
|
||||
void ArrowInput(uint8_t key);
|
||||
void UserInput(char *Input);
|
||||
void ArrowInput(uint8_t key);
|
||||
void UserInput(char *Input);
|
||||
|
||||
void DisplayMainScreen(CRData data);
|
||||
void DisplayDetailsScreen(CRData data);
|
||||
void DisplayStackFrameScreen(CRData data);
|
||||
void DisplayTasksScreen(CRData data);
|
||||
void DisplayConsoleScreen(CRData data);
|
||||
void DisplayMainScreen(CRData data);
|
||||
void DisplayDetailsScreen(CRData data);
|
||||
void DisplayStackFrameScreen(CRData data);
|
||||
void DisplayTasksScreen(CRData data);
|
||||
void DisplayConsoleScreen(CRData data);
|
||||
}
|
||||
|
||||
void DivideByZeroExceptionHandler(CHArchTrapFrame *Frame);
|
||||
|
@ -33,316 +33,316 @@
|
||||
#include "../../kernel.h"
|
||||
|
||||
static const char *PageFaultDescriptions[8] = {
|
||||
"Supervisory process tried to read a non-present page entry\n",
|
||||
"Supervisory process tried to read a page and caused a protection fault\n",
|
||||
"Supervisory process tried to write to a non-present page entry\n",
|
||||
"Supervisory process tried to write a page and caused a protection fault\n",
|
||||
"User process tried to read a non-present page entry\n",
|
||||
"User process tried to read a page and caused a protection fault\n",
|
||||
"User process tried to write to a non-present page entry\n",
|
||||
"User process tried to write a page and caused a protection fault\n"};
|
||||
"Supervisory process tried to read a non-present page entry\n",
|
||||
"Supervisory process tried to read a page and caused a protection fault\n",
|
||||
"Supervisory process tried to write to a non-present page entry\n",
|
||||
"Supervisory process tried to write a page and caused a protection fault\n",
|
||||
"User process tried to read a non-present page entry\n",
|
||||
"User process tried to read a page and caused a protection fault\n",
|
||||
"User process tried to write to a non-present page entry\n",
|
||||
"User process tried to write a page and caused a protection fault\n"};
|
||||
|
||||
SafeFunction void DivideByZeroExceptionHandler(CHArchTrapFrame *Frame)
|
||||
{
|
||||
fixme("Divide by zero exception\n");
|
||||
UNUSED(Frame);
|
||||
fixme("Divide by zero exception\n");
|
||||
UNUSED(Frame);
|
||||
}
|
||||
|
||||
SafeFunction void DebugExceptionHandler(CHArchTrapFrame *Frame)
|
||||
{
|
||||
CrashHandler::EHPrint("Kernel triggered debug exception.\n");
|
||||
UNUSED(Frame);
|
||||
CrashHandler::EHPrint("Kernel triggered debug exception.\n");
|
||||
UNUSED(Frame);
|
||||
}
|
||||
|
||||
SafeFunction void NonMaskableInterruptExceptionHandler(CHArchTrapFrame *Frame)
|
||||
{
|
||||
fixme("NMI exception");
|
||||
UNUSED(Frame);
|
||||
fixme("NMI exception");
|
||||
UNUSED(Frame);
|
||||
}
|
||||
|
||||
SafeFunction void BreakpointExceptionHandler(CHArchTrapFrame *Frame)
|
||||
{
|
||||
fixme("Breakpoint exception");
|
||||
UNUSED(Frame);
|
||||
fixme("Breakpoint exception");
|
||||
UNUSED(Frame);
|
||||
}
|
||||
|
||||
SafeFunction void OverflowExceptionHandler(CHArchTrapFrame *Frame)
|
||||
{
|
||||
fixme("Overflow exception");
|
||||
UNUSED(Frame);
|
||||
fixme("Overflow exception");
|
||||
UNUSED(Frame);
|
||||
}
|
||||
|
||||
SafeFunction void BoundRangeExceptionHandler(CHArchTrapFrame *Frame)
|
||||
{
|
||||
fixme("Bound range exception");
|
||||
UNUSED(Frame);
|
||||
fixme("Bound range exception");
|
||||
UNUSED(Frame);
|
||||
}
|
||||
|
||||
SafeFunction void InvalidOpcodeExceptionHandler(CHArchTrapFrame *Frame)
|
||||
{
|
||||
CrashHandler::EHPrint("Kernel tried to execute an invalid opcode.\n");
|
||||
UNUSED(Frame);
|
||||
CrashHandler::EHPrint("Kernel tried to execute an invalid opcode.\n");
|
||||
UNUSED(Frame);
|
||||
}
|
||||
|
||||
SafeFunction void DeviceNotAvailableExceptionHandler(CHArchTrapFrame *Frame)
|
||||
{
|
||||
fixme("Device not available exception");
|
||||
UNUSED(Frame);
|
||||
fixme("Device not available exception");
|
||||
UNUSED(Frame);
|
||||
}
|
||||
|
||||
SafeFunction void DoubleFaultExceptionHandler(CHArchTrapFrame *Frame)
|
||||
{
|
||||
fixme("Double fault exception");
|
||||
UNUSED(Frame);
|
||||
fixme("Double fault exception");
|
||||
UNUSED(Frame);
|
||||
}
|
||||
|
||||
SafeFunction void CoprocessorSegmentOverrunExceptionHandler(CHArchTrapFrame *Frame)
|
||||
{
|
||||
fixme("Coprocessor segment overrun exception");
|
||||
UNUSED(Frame);
|
||||
fixme("Coprocessor segment overrun exception");
|
||||
UNUSED(Frame);
|
||||
}
|
||||
|
||||
SafeFunction void InvalidTSSExceptionHandler(CHArchTrapFrame *Frame)
|
||||
{
|
||||
fixme("Invalid TSS exception");
|
||||
UNUSED(Frame);
|
||||
fixme("Invalid TSS exception");
|
||||
UNUSED(Frame);
|
||||
}
|
||||
|
||||
SafeFunction void SegmentNotPresentExceptionHandler(CHArchTrapFrame *Frame)
|
||||
{
|
||||
fixme("Segment not present exception");
|
||||
UNUSED(Frame);
|
||||
fixme("Segment not present exception");
|
||||
UNUSED(Frame);
|
||||
}
|
||||
|
||||
SafeFunction void StackFaultExceptionHandler(CHArchTrapFrame *Frame)
|
||||
{
|
||||
CPU::x64::SelectorErrorCode SelCode = {.raw = Frame->ErrorCode};
|
||||
CPU::x64::SelectorErrorCode SelCode = {.raw = Frame->ErrorCode};
|
||||
#if defined(a64)
|
||||
CrashHandler::EHPrint("Stack segment fault at address %#lx\n", Frame->rip);
|
||||
CrashHandler::EHPrint("Stack segment fault at address %#lx\n", Frame->rip);
|
||||
#elif defined(a32)
|
||||
CrashHandler::EHPrint("Stack segment fault at address %#lx\n", Frame->eip);
|
||||
CrashHandler::EHPrint("Stack segment fault at address %#lx\n", Frame->eip);
|
||||
#elif defined(aa64)
|
||||
#endif
|
||||
CrashHandler::EHPrint("External: %d\n", SelCode.External);
|
||||
CrashHandler::EHPrint("Table: %d\n", SelCode.Table);
|
||||
CrashHandler::EHPrint("Index: %#x\n", SelCode.Idx);
|
||||
CrashHandler::EHPrint("Error code: %#lx\n", Frame->ErrorCode);
|
||||
CrashHandler::EHPrint("External: %d\n", SelCode.External);
|
||||
CrashHandler::EHPrint("Table: %d\n", SelCode.Table);
|
||||
CrashHandler::EHPrint("Index: %#x\n", SelCode.Idx);
|
||||
CrashHandler::EHPrint("Error code: %#lx\n", Frame->ErrorCode);
|
||||
}
|
||||
|
||||
SafeFunction void GeneralProtectionExceptionHandler(CHArchTrapFrame *Frame)
|
||||
{
|
||||
CPU::x64::SelectorErrorCode SelCode = {.raw = Frame->ErrorCode};
|
||||
// switch (SelCode.Table)
|
||||
// {
|
||||
// case CPU::x64::0b00:
|
||||
// memcpy(desc_tmp, "GDT", 3);
|
||||
// break;
|
||||
// case CPU::x64::0b01:
|
||||
// memcpy(desc_tmp, "IDT", 3);
|
||||
// break;
|
||||
// case CPU::x64::0b10:
|
||||
// memcpy(desc_tmp, "LDT", 3);
|
||||
// break;
|
||||
// case CPU::x64::0b11:
|
||||
// memcpy(desc_tmp, "IDT", 3);
|
||||
// break;
|
||||
// default:
|
||||
// memcpy(desc_tmp, "Unknown", 7);
|
||||
// break;
|
||||
// }
|
||||
CrashHandler::EHPrint("Kernel performed an illegal operation.\n");
|
||||
CrashHandler::EHPrint("External: %d\n", SelCode.External);
|
||||
CrashHandler::EHPrint("Table: %d\n", SelCode.Table);
|
||||
CrashHandler::EHPrint("Index: %#x\n", SelCode.Idx);
|
||||
CPU::x64::SelectorErrorCode SelCode = {.raw = Frame->ErrorCode};
|
||||
// switch (SelCode.Table)
|
||||
// {
|
||||
// case CPU::x64::0b00:
|
||||
// memcpy(desc_tmp, "GDT", 3);
|
||||
// break;
|
||||
// case CPU::x64::0b01:
|
||||
// memcpy(desc_tmp, "IDT", 3);
|
||||
// break;
|
||||
// case CPU::x64::0b10:
|
||||
// memcpy(desc_tmp, "LDT", 3);
|
||||
// break;
|
||||
// case CPU::x64::0b11:
|
||||
// memcpy(desc_tmp, "IDT", 3);
|
||||
// break;
|
||||
// default:
|
||||
// memcpy(desc_tmp, "Unknown", 7);
|
||||
// break;
|
||||
// }
|
||||
CrashHandler::EHPrint("Kernel performed an illegal operation.\n");
|
||||
CrashHandler::EHPrint("External: %d\n", SelCode.External);
|
||||
CrashHandler::EHPrint("Table: %d\n", SelCode.Table);
|
||||
CrashHandler::EHPrint("Index: %#x\n", SelCode.Idx);
|
||||
}
|
||||
|
||||
SafeFunction void PageFaultExceptionHandler(CHArchTrapFrame *Frame)
|
||||
{
|
||||
CPU::x64::PageFaultErrorCode params = {.raw = (uint32_t)Frame->ErrorCode};
|
||||
CPU::x64::PageFaultErrorCode params = {.raw = (uint32_t)Frame->ErrorCode};
|
||||
#if defined(a64)
|
||||
CrashHandler::EHPrint("\eAFAFAFAn exception occurred at %#lx by %#lx\n", CrashHandler::PageFaultAddress, Frame->rip);
|
||||
CrashHandler::EHPrint("\eAFAFAFAn exception occurred at %#lx by %#lx\n", CrashHandler::PageFaultAddress, Frame->rip);
|
||||
#elif defined(a32)
|
||||
CrashHandler::EHPrint("\eAFAFAFAn exception occurred at %#lx by %#lx\n", CrashHandler::PageFaultAddress, Frame->eip);
|
||||
CrashHandler::EHPrint("\eAFAFAFAn exception occurred at %#lx by %#lx\n", CrashHandler::PageFaultAddress, Frame->eip);
|
||||
#elif defined(aa64)
|
||||
#endif
|
||||
CrashHandler::EHPrint("Page: %s\n", params.P ? "Present" : "Not Present");
|
||||
CrashHandler::EHPrint("Write Operation: %s\n", params.W ? "Read-Only" : "Read-Write");
|
||||
CrashHandler::EHPrint("Processor Mode: %s\n", params.U ? "User-Mode" : "Kernel-Mode");
|
||||
CrashHandler::EHPrint("CPU Reserved Bits: %s\n", params.R ? "Reserved" : "Unreserved");
|
||||
CrashHandler::EHPrint("Caused By An Instruction Fetch: %s\n", params.I ? "Yes" : "No");
|
||||
CrashHandler::EHPrint("Caused By A Protection-Key Violation: %s\n", params.PK ? "Yes" : "No");
|
||||
CrashHandler::EHPrint("Caused By A Shadow Stack Access: %s\n", params.SS ? "Yes" : "No");
|
||||
CrashHandler::EHPrint("Caused By An SGX Violation: %s\n", params.SGX ? "Yes" : "No");
|
||||
if (Frame->ErrorCode & 0x00000008)
|
||||
CrashHandler::EHPrint("One or more page directory entries contain reserved bits which are set to 1.\n");
|
||||
else
|
||||
CrashHandler::EHPrint(PageFaultDescriptions[Frame->ErrorCode & 0b111]);
|
||||
CrashHandler::EHPrint("Page: %s\n", params.P ? "Present" : "Not Present");
|
||||
CrashHandler::EHPrint("Write Operation: %s\n", params.W ? "Read-Only" : "Read-Write");
|
||||
CrashHandler::EHPrint("Processor Mode: %s\n", params.U ? "User-Mode" : "Kernel-Mode");
|
||||
CrashHandler::EHPrint("CPU Reserved Bits: %s\n", params.R ? "Reserved" : "Unreserved");
|
||||
CrashHandler::EHPrint("Caused By An Instruction Fetch: %s\n", params.I ? "Yes" : "No");
|
||||
CrashHandler::EHPrint("Caused By A Protection-Key Violation: %s\n", params.PK ? "Yes" : "No");
|
||||
CrashHandler::EHPrint("Caused By A Shadow Stack Access: %s\n", params.SS ? "Yes" : "No");
|
||||
CrashHandler::EHPrint("Caused By An SGX Violation: %s\n", params.SGX ? "Yes" : "No");
|
||||
if (Frame->ErrorCode & 0x00000008)
|
||||
CrashHandler::EHPrint("One or more page directory entries contain reserved bits which are set to 1.\n");
|
||||
else
|
||||
CrashHandler::EHPrint(PageFaultDescriptions[Frame->ErrorCode & 0b111]);
|
||||
|
||||
#ifdef DEBUG
|
||||
uintptr_t CheckPageFaultAddress = 0;
|
||||
CheckPageFaultAddress = CrashHandler::PageFaultAddress;
|
||||
if (CheckPageFaultAddress == 0)
|
||||
uintptr_t CheckPageFaultAddress = 0;
|
||||
CheckPageFaultAddress = CrashHandler::PageFaultAddress;
|
||||
if (CheckPageFaultAddress == 0)
|
||||
#ifdef a64
|
||||
CheckPageFaultAddress = Frame->rip;
|
||||
CheckPageFaultAddress = Frame->rip;
|
||||
#elif defined(a32)
|
||||
CheckPageFaultAddress = Frame->eip;
|
||||
CheckPageFaultAddress = Frame->eip;
|
||||
#elif defined(aa64)
|
||||
CheckPageFaultAddress = 0;
|
||||
CheckPageFaultAddress = 0;
|
||||
#endif
|
||||
|
||||
#if defined(a64)
|
||||
Memory::Virtual vmm = Memory::Virtual(((Memory::PageTable *)CPU::x64::readcr3().raw));
|
||||
Memory::Virtual vmm(((Memory::PageTable *)CPU::x64::readcr3().raw));
|
||||
#elif defined(a32)
|
||||
Memory::Virtual vmm = Memory::Virtual(((Memory::PageTable *)CPU::x32::readcr3().raw));
|
||||
Memory::Virtual vmm(((Memory::PageTable *)CPU::x32::readcr3().raw));
|
||||
#elif defined(aa64)
|
||||
Memory::Virtual vmm = Memory::Virtual();
|
||||
Memory::Virtual vmm();
|
||||
#warning "TODO: aa64"
|
||||
#endif
|
||||
|
||||
bool PageAvailable = vmm.Check((void *)CheckPageFaultAddress);
|
||||
debug("Page available (Check(...)): %s. %s",
|
||||
PageAvailable ? "Yes" : "No",
|
||||
(params.P && !PageAvailable) ? "CR2 == Present; Check() != Present??????" : "CR2 confirms Check() result.");
|
||||
bool PageAvailable = vmm.Check((void *)CheckPageFaultAddress);
|
||||
debug("Page available (Check(...)): %s. %s",
|
||||
PageAvailable ? "Yes" : "No",
|
||||
(params.P && !PageAvailable) ? "CR2 == Present; Check() != Present??????" : "CR2 confirms Check() result.");
|
||||
|
||||
if (PageAvailable)
|
||||
{
|
||||
bool Present = vmm.Check((void *)CheckPageFaultAddress);
|
||||
bool ReadWrite = vmm.Check((void *)CheckPageFaultAddress, Memory::PTFlag::RW);
|
||||
bool User = vmm.Check((void *)CheckPageFaultAddress, Memory::PTFlag::US);
|
||||
bool WriteThrough = vmm.Check((void *)CheckPageFaultAddress, Memory::PTFlag::PWT);
|
||||
bool CacheDisabled = vmm.Check((void *)CheckPageFaultAddress, Memory::PTFlag::PCD);
|
||||
bool Accessed = vmm.Check((void *)CheckPageFaultAddress, Memory::PTFlag::A);
|
||||
bool Dirty = vmm.Check((void *)CheckPageFaultAddress, Memory::PTFlag::D);
|
||||
bool Global = vmm.Check((void *)CheckPageFaultAddress, Memory::PTFlag::G);
|
||||
/* ... */
|
||||
if (PageAvailable)
|
||||
{
|
||||
bool Present = vmm.Check((void *)CheckPageFaultAddress);
|
||||
bool ReadWrite = vmm.Check((void *)CheckPageFaultAddress, Memory::PTFlag::RW);
|
||||
bool User = vmm.Check((void *)CheckPageFaultAddress, Memory::PTFlag::US);
|
||||
bool WriteThrough = vmm.Check((void *)CheckPageFaultAddress, Memory::PTFlag::PWT);
|
||||
bool CacheDisabled = vmm.Check((void *)CheckPageFaultAddress, Memory::PTFlag::PCD);
|
||||
bool Accessed = vmm.Check((void *)CheckPageFaultAddress, Memory::PTFlag::A);
|
||||
bool Dirty = vmm.Check((void *)CheckPageFaultAddress, Memory::PTFlag::D);
|
||||
bool Global = vmm.Check((void *)CheckPageFaultAddress, Memory::PTFlag::G);
|
||||
/* ... */
|
||||
|
||||
debug("Page available: %s", Present ? "Yes" : "No");
|
||||
debug("Page read/write: %s", ReadWrite ? "Yes" : "No");
|
||||
debug("Page user/kernel: %s", User ? "User" : "Kernel");
|
||||
debug("Page write-through: %s", WriteThrough ? "Yes" : "No");
|
||||
debug("Page cache disabled: %s", CacheDisabled ? "Yes" : "No");
|
||||
debug("Page accessed: %s", Accessed ? "Yes" : "No");
|
||||
debug("Page dirty: %s", Dirty ? "Yes" : "No");
|
||||
debug("Page global: %s", Global ? "Yes" : "No");
|
||||
debug("Page available: %s", Present ? "Yes" : "No");
|
||||
debug("Page read/write: %s", ReadWrite ? "Yes" : "No");
|
||||
debug("Page user/kernel: %s", User ? "User" : "Kernel");
|
||||
debug("Page write-through: %s", WriteThrough ? "Yes" : "No");
|
||||
debug("Page cache disabled: %s", CacheDisabled ? "Yes" : "No");
|
||||
debug("Page accessed: %s", Accessed ? "Yes" : "No");
|
||||
debug("Page dirty: %s", Dirty ? "Yes" : "No");
|
||||
debug("Page global: %s", Global ? "Yes" : "No");
|
||||
|
||||
if (Present)
|
||||
{
|
||||
if (Present)
|
||||
{
|
||||
#if defined(a64)
|
||||
uintptr_t CheckPageFaultLinearAddress = (uintptr_t)CheckPageFaultAddress;
|
||||
CheckPageFaultLinearAddress &= 0xFFFFFFFFFFFFF000;
|
||||
debug("%#lx -> %#lx", CheckPageFaultAddress, CheckPageFaultLinearAddress);
|
||||
uintptr_t CheckPageFaultLinearAddress = (uintptr_t)CheckPageFaultAddress;
|
||||
CheckPageFaultLinearAddress &= 0xFFFFFFFFFFFFF000;
|
||||
debug("%#lx -> %#lx", CheckPageFaultAddress, CheckPageFaultLinearAddress);
|
||||
|
||||
Memory::Virtual::PageMapIndexer Index = Memory::Virtual::PageMapIndexer((uintptr_t)CheckPageFaultLinearAddress);
|
||||
debug("Index for %#lx is PML:%d PDPTE:%d PDE:%d PTE:%d",
|
||||
CheckPageFaultLinearAddress,
|
||||
Index.PMLIndex,
|
||||
Index.PDPTEIndex,
|
||||
Index.PDEIndex,
|
||||
Index.PTEIndex);
|
||||
Memory::Virtual::PageMapIndexer Index = Memory::Virtual::PageMapIndexer((uintptr_t)CheckPageFaultLinearAddress);
|
||||
debug("Index for %#lx is PML:%d PDPTE:%d PDE:%d PTE:%d",
|
||||
CheckPageFaultLinearAddress,
|
||||
Index.PMLIndex,
|
||||
Index.PDPTEIndex,
|
||||
Index.PDEIndex,
|
||||
Index.PTEIndex);
|
||||
#if defined(a64)
|
||||
Memory::PageMapLevel4 PML4 = ((Memory::PageTable *)CPU::x64::readcr3().raw)->Entries[Index.PMLIndex];
|
||||
Memory::PageMapLevel4 PML4 = ((Memory::PageTable *)CPU::x64::readcr3().raw)->Entries[Index.PMLIndex];
|
||||
#elif defined(a32)
|
||||
Memory::PageMapLevel4 PML4 = ((Memory::PageTable *)CPU::x32::readcr3().raw)->Entries[Index.PMLIndex];
|
||||
Memory::PageMapLevel4 PML4 = ((Memory::PageTable *)CPU::x32::readcr3().raw)->Entries[Index.PMLIndex];
|
||||
#elif defined(aa64)
|
||||
Memory::PageMapLevel4 PML4 = {.raw = 0};
|
||||
Memory::PageMapLevel4 PML4 = {.raw = 0};
|
||||
#warning "TODO: aa64"
|
||||
#endif
|
||||
|
||||
Memory::PageDirectoryPointerTableEntryPtr *PDPTE = (Memory::PageDirectoryPointerTableEntryPtr *)((uintptr_t)PML4.GetAddress() << 12);
|
||||
Memory::PageDirectoryEntryPtr *PDE = (Memory::PageDirectoryEntryPtr *)((uintptr_t)PDPTE->Entries[Index.PDPTEIndex].GetAddress() << 12);
|
||||
Memory::PageTableEntryPtr *PTE = (Memory::PageTableEntryPtr *)((uintptr_t)PDE->Entries[Index.PDEIndex].GetAddress() << 12);
|
||||
Memory::PageDirectoryPointerTableEntryPtr *PDPTE = (Memory::PageDirectoryPointerTableEntryPtr *)((uintptr_t)PML4.GetAddress() << 12);
|
||||
Memory::PageDirectoryEntryPtr *PDE = (Memory::PageDirectoryEntryPtr *)((uintptr_t)PDPTE->Entries[Index.PDPTEIndex].GetAddress() << 12);
|
||||
Memory::PageTableEntryPtr *PTE = (Memory::PageTableEntryPtr *)((uintptr_t)PDE->Entries[Index.PDEIndex].GetAddress() << 12);
|
||||
|
||||
debug("# %03d-%03d-%03d-%03d: P:%s RW:%s US:%s PWT:%s PCB:%s A:%s NX:%s Address:%#lx",
|
||||
Index.PMLIndex, 0, 0, 0,
|
||||
PML4.Present ? "1" : "0",
|
||||
PML4.ReadWrite ? "1" : "0",
|
||||
PML4.UserSupervisor ? "1" : "0",
|
||||
PML4.WriteThrough ? "1" : "0",
|
||||
PML4.CacheDisable ? "1" : "0",
|
||||
PML4.Accessed ? "1" : "0",
|
||||
PML4.ExecuteDisable ? "1" : "0",
|
||||
PML4.GetAddress() << 12);
|
||||
debug("# %03d-%03d-%03d-%03d: P:%s RW:%s US:%s PWT:%s PCB:%s A:%s NX:%s Address:%#lx",
|
||||
Index.PMLIndex, 0, 0, 0,
|
||||
PML4.Present ? "1" : "0",
|
||||
PML4.ReadWrite ? "1" : "0",
|
||||
PML4.UserSupervisor ? "1" : "0",
|
||||
PML4.WriteThrough ? "1" : "0",
|
||||
PML4.CacheDisable ? "1" : "0",
|
||||
PML4.Accessed ? "1" : "0",
|
||||
PML4.ExecuteDisable ? "1" : "0",
|
||||
PML4.GetAddress() << 12);
|
||||
|
||||
debug("# %03d-%03d-%03d-%03d: P:%s RW:%s US:%s PWT:%s PCB:%s A:%s NX:%s Address:%#lx",
|
||||
Index.PMLIndex, Index.PDPTEIndex, 0, 0,
|
||||
PDPTE->Entries[Index.PDPTEIndex].Present ? "1" : "0",
|
||||
PDPTE->Entries[Index.PDPTEIndex].ReadWrite ? "1" : "0",
|
||||
PDPTE->Entries[Index.PDPTEIndex].UserSupervisor ? "1" : "0",
|
||||
PDPTE->Entries[Index.PDPTEIndex].WriteThrough ? "1" : "0",
|
||||
PDPTE->Entries[Index.PDPTEIndex].CacheDisable ? "1" : "0",
|
||||
PDPTE->Entries[Index.PDPTEIndex].Accessed ? "1" : "0",
|
||||
PDPTE->Entries[Index.PDPTEIndex].ExecuteDisable ? "1" : "0",
|
||||
PDPTE->Entries[Index.PDPTEIndex].GetAddress() << 12);
|
||||
debug("# %03d-%03d-%03d-%03d: P:%s RW:%s US:%s PWT:%s PCB:%s A:%s NX:%s Address:%#lx",
|
||||
Index.PMLIndex, Index.PDPTEIndex, 0, 0,
|
||||
PDPTE->Entries[Index.PDPTEIndex].Present ? "1" : "0",
|
||||
PDPTE->Entries[Index.PDPTEIndex].ReadWrite ? "1" : "0",
|
||||
PDPTE->Entries[Index.PDPTEIndex].UserSupervisor ? "1" : "0",
|
||||
PDPTE->Entries[Index.PDPTEIndex].WriteThrough ? "1" : "0",
|
||||
PDPTE->Entries[Index.PDPTEIndex].CacheDisable ? "1" : "0",
|
||||
PDPTE->Entries[Index.PDPTEIndex].Accessed ? "1" : "0",
|
||||
PDPTE->Entries[Index.PDPTEIndex].ExecuteDisable ? "1" : "0",
|
||||
PDPTE->Entries[Index.PDPTEIndex].GetAddress() << 12);
|
||||
|
||||
debug("# %03d-%03d-%03d-%03d: P:%s RW:%s US:%s PWT:%s PCB:%s A:%s NX:%s Address:%#lx",
|
||||
Index.PMLIndex, Index.PDPTEIndex, Index.PDEIndex, 0,
|
||||
PDE->Entries[Index.PDEIndex].Present ? "1" : "0",
|
||||
PDE->Entries[Index.PDEIndex].ReadWrite ? "1" : "0",
|
||||
PDE->Entries[Index.PDEIndex].UserSupervisor ? "1" : "0",
|
||||
PDE->Entries[Index.PDEIndex].WriteThrough ? "1" : "0",
|
||||
PDE->Entries[Index.PDEIndex].CacheDisable ? "1" : "0",
|
||||
PDE->Entries[Index.PDEIndex].Accessed ? "1" : "0",
|
||||
PDE->Entries[Index.PDEIndex].ExecuteDisable ? "1" : "0",
|
||||
PDE->Entries[Index.PDEIndex].GetAddress() << 12);
|
||||
debug("# %03d-%03d-%03d-%03d: P:%s RW:%s US:%s PWT:%s PCB:%s A:%s NX:%s Address:%#lx",
|
||||
Index.PMLIndex, Index.PDPTEIndex, Index.PDEIndex, 0,
|
||||
PDE->Entries[Index.PDEIndex].Present ? "1" : "0",
|
||||
PDE->Entries[Index.PDEIndex].ReadWrite ? "1" : "0",
|
||||
PDE->Entries[Index.PDEIndex].UserSupervisor ? "1" : "0",
|
||||
PDE->Entries[Index.PDEIndex].WriteThrough ? "1" : "0",
|
||||
PDE->Entries[Index.PDEIndex].CacheDisable ? "1" : "0",
|
||||
PDE->Entries[Index.PDEIndex].Accessed ? "1" : "0",
|
||||
PDE->Entries[Index.PDEIndex].ExecuteDisable ? "1" : "0",
|
||||
PDE->Entries[Index.PDEIndex].GetAddress() << 12);
|
||||
|
||||
debug("# %03d-%03d-%03d-%03d: P:%s RW:%s US:%s PWT:%s PCB:%s A:%s D:%s PAT:%s G:%s PK:%d NX:%s Address:%#lx",
|
||||
Index.PMLIndex, Index.PDPTEIndex, Index.PDEIndex, Index.PTEIndex,
|
||||
PTE->Entries[Index.PTEIndex].Present ? "1" : "0",
|
||||
PTE->Entries[Index.PTEIndex].ReadWrite ? "1" : "0",
|
||||
PTE->Entries[Index.PTEIndex].UserSupervisor ? "1" : "0",
|
||||
PTE->Entries[Index.PTEIndex].WriteThrough ? "1" : "0",
|
||||
PTE->Entries[Index.PTEIndex].CacheDisable ? "1" : "0",
|
||||
PTE->Entries[Index.PTEIndex].Accessed ? "1" : "0",
|
||||
PTE->Entries[Index.PTEIndex].Dirty ? "1" : "0",
|
||||
PTE->Entries[Index.PTEIndex].PageAttributeTable ? "1" : "0",
|
||||
PTE->Entries[Index.PTEIndex].Global ? "1" : "0",
|
||||
PTE->Entries[Index.PTEIndex].ProtectionKey,
|
||||
PTE->Entries[Index.PTEIndex].ExecuteDisable ? "1" : "0",
|
||||
PTE->Entries[Index.PTEIndex].GetAddress() << 12);
|
||||
debug("# %03d-%03d-%03d-%03d: P:%s RW:%s US:%s PWT:%s PCB:%s A:%s D:%s PAT:%s G:%s PK:%d NX:%s Address:%#lx",
|
||||
Index.PMLIndex, Index.PDPTEIndex, Index.PDEIndex, Index.PTEIndex,
|
||||
PTE->Entries[Index.PTEIndex].Present ? "1" : "0",
|
||||
PTE->Entries[Index.PTEIndex].ReadWrite ? "1" : "0",
|
||||
PTE->Entries[Index.PTEIndex].UserSupervisor ? "1" : "0",
|
||||
PTE->Entries[Index.PTEIndex].WriteThrough ? "1" : "0",
|
||||
PTE->Entries[Index.PTEIndex].CacheDisable ? "1" : "0",
|
||||
PTE->Entries[Index.PTEIndex].Accessed ? "1" : "0",
|
||||
PTE->Entries[Index.PTEIndex].Dirty ? "1" : "0",
|
||||
PTE->Entries[Index.PTEIndex].PageAttributeTable ? "1" : "0",
|
||||
PTE->Entries[Index.PTEIndex].Global ? "1" : "0",
|
||||
PTE->Entries[Index.PTEIndex].ProtectionKey,
|
||||
PTE->Entries[Index.PTEIndex].ExecuteDisable ? "1" : "0",
|
||||
PTE->Entries[Index.PTEIndex].GetAddress() << 12);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
SafeFunction void x87FloatingPointExceptionHandler(CHArchTrapFrame *Frame)
|
||||
{
|
||||
fixme("x87 floating point exception");
|
||||
UNUSED(Frame);
|
||||
fixme("x87 floating point exception");
|
||||
UNUSED(Frame);
|
||||
}
|
||||
|
||||
SafeFunction void AlignmentCheckExceptionHandler(CHArchTrapFrame *Frame)
|
||||
{
|
||||
fixme("Alignment check exception");
|
||||
UNUSED(Frame);
|
||||
fixme("Alignment check exception");
|
||||
UNUSED(Frame);
|
||||
}
|
||||
|
||||
SafeFunction void MachineCheckExceptionHandler(CHArchTrapFrame *Frame)
|
||||
{
|
||||
fixme("Machine check exception");
|
||||
UNUSED(Frame);
|
||||
fixme("Machine check exception");
|
||||
UNUSED(Frame);
|
||||
}
|
||||
|
||||
SafeFunction void SIMDFloatingPointExceptionHandler(CHArchTrapFrame *Frame)
|
||||
{
|
||||
fixme("SIMD floating point exception");
|
||||
UNUSED(Frame);
|
||||
fixme("SIMD floating point exception");
|
||||
UNUSED(Frame);
|
||||
}
|
||||
|
||||
SafeFunction void VirtualizationExceptionHandler(CHArchTrapFrame *Frame)
|
||||
{
|
||||
fixme("Virtualization exception");
|
||||
UNUSED(Frame);
|
||||
fixme("Virtualization exception");
|
||||
UNUSED(Frame);
|
||||
}
|
||||
|
||||
SafeFunction void SecurityExceptionHandler(CHArchTrapFrame *Frame)
|
||||
{
|
||||
fixme("Security exception");
|
||||
UNUSED(Frame);
|
||||
fixme("Security exception");
|
||||
UNUSED(Frame);
|
||||
}
|
||||
|
||||
SafeFunction void UnknownExceptionHandler(CHArchTrapFrame *Frame)
|
||||
{
|
||||
fixme("Unknown exception");
|
||||
UNUSED(Frame);
|
||||
fixme("Unknown exception");
|
||||
UNUSED(Frame);
|
||||
}
|
||||
|
@ -40,7 +40,6 @@
|
||||
#endif
|
||||
|
||||
#include "../../kernel.h"
|
||||
#include "../../mapi.hpp"
|
||||
|
||||
NewLock(UserInputLock);
|
||||
|
||||
@ -411,7 +410,7 @@ namespace CrashHandler
|
||||
#elif defined(aa64)
|
||||
if ((uintptr_t)EHIntFrames[i] >= 0xFFFFFFFF80000000 && (uintptr_t)EHIntFrames[i] <= (uintptr_t)&_kernel_end)
|
||||
#endif
|
||||
EHPrint("\e25CCC9%s", KernelSymbolTable->GetSymbolFromAddress((uintptr_t)EHIntFrames[i]));
|
||||
EHPrint("\e25CCC9%s", KernelSymbolTable->GetSymbol((uintptr_t)EHIntFrames[i]));
|
||||
else
|
||||
EHPrint("\eFF4CA9Outside Kernel");
|
||||
#if defined(a86)
|
||||
@ -726,7 +725,7 @@ namespace CrashHandler
|
||||
uint64_t ProgressLength = TotalMemLength;
|
||||
UniversalAsynchronousReceiverTransmitter::UART uart(port);
|
||||
Memory::Virtual vmm;
|
||||
uint8_t *Address = reinterpret_cast<uint8_t *>(0x0);
|
||||
uint8_t *Address = 0x0;
|
||||
int Progress = 0;
|
||||
for (size_t i = 0; i < TotalMemLength; i++)
|
||||
{
|
||||
@ -806,33 +805,50 @@ namespace CrashHandler
|
||||
* Also it makes every core to stay at 100% usage for some reason.
|
||||
*/
|
||||
|
||||
// if (SMP::CPUCores > 1)
|
||||
// {
|
||||
// for (int i = 1; i < SMP::CPUCores; i++)
|
||||
// {
|
||||
// APIC::InterruptCommandRegisterLow icr;
|
||||
// icr.Vector = CPU::x86::IRQ29;
|
||||
// icr.Level = APIC::APICLevel::Assert;
|
||||
// ((APIC::APIC *)Interrupts::apic[i])->IPI(i, icr);
|
||||
// __sync;
|
||||
// }
|
||||
// }
|
||||
// APIC::InterruptCommandRegisterLow icr;
|
||||
// icr.Vector = CPU::x86::IRQ29;
|
||||
// icr.Level = APIC::APICLevel::Assert;
|
||||
// icr.DestinationShorthand = APIC::APICDestinationShorthand::AllExcludingSelf;
|
||||
// ((APIC::APIC *)Interrupts::apic[0])->IPI(0, icr);
|
||||
// CPU::Interrupts(CPU::Enable);
|
||||
__sync;
|
||||
CPU::Interrupts(CPU::Disable);
|
||||
// }
|
||||
return;
|
||||
if (SMP::CPUCores > 1)
|
||||
{
|
||||
APIC::InterruptCommandRegister icr{};
|
||||
bool x2APIC = ((APIC::APIC *)Interrupts::apic[0])->x2APIC;
|
||||
|
||||
if (likely(x2APIC))
|
||||
{
|
||||
icr.x2.VEC = s_cst(uint8_t, CPU::x86::IRQ31);
|
||||
icr.x2.MT = APIC::Fixed;
|
||||
icr.x2.L = APIC::Assert;
|
||||
|
||||
for (int i = 1; i < SMP::CPUCores; i++)
|
||||
{
|
||||
icr.x2.DES = uint8_t(i);
|
||||
((APIC::APIC *)Interrupts::apic[i])->ICR(icr);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
icr.VEC = s_cst(uint8_t, CPU::x86::IRQ31);
|
||||
icr.MT = APIC::Fixed;
|
||||
icr.L = APIC::Assert;
|
||||
|
||||
for (int i = 1; i < SMP::CPUCores; i++)
|
||||
{
|
||||
icr.DES = uint8_t(i);
|
||||
((APIC::APIC *)Interrupts::apic[i])->ICR(icr);
|
||||
}
|
||||
}
|
||||
CPU::Interrupts(CPU::Disable);
|
||||
}
|
||||
#elif defined(aa64)
|
||||
#endif
|
||||
}
|
||||
|
||||
SafeFunction inline void Handle_x86_64(CHArchTrapFrame *Frame)
|
||||
SafeFunction inline bool Handle_x86_64(CHArchTrapFrame *Frame)
|
||||
{
|
||||
#ifdef a64
|
||||
trace("Exception at %s",
|
||||
KernelSymbolTable
|
||||
? KernelSymbolTable->GetSymbol(Frame->rip)
|
||||
: "No symbol");
|
||||
|
||||
for (size_t i = 0; i < INT_FRAMES_MAX; i++)
|
||||
EHIntFrames[i] = Interrupts::InterruptFrames[i];
|
||||
PageFaultAddress = CPU::x64::readcr2().PFLA;
|
||||
@ -844,14 +860,14 @@ namespace CrashHandler
|
||||
{
|
||||
debug("Exception in kernel mode (ip: %#lx cr2: %#lx (%s))",
|
||||
Frame->rip, PageFaultAddress,
|
||||
KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress(Frame->rip)
|
||||
KernelSymbolTable ? KernelSymbolTable->GetSymbol(Frame->rip)
|
||||
: "No symbol");
|
||||
}
|
||||
else
|
||||
{
|
||||
debug("Exception in kernel mode (ip: %#lx (%s))",
|
||||
Frame->rip,
|
||||
KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress(Frame->rip)
|
||||
KernelSymbolTable ? KernelSymbolTable->GetSymbol(Frame->rip)
|
||||
: "No symbol");
|
||||
}
|
||||
|
||||
@ -881,7 +897,7 @@ namespace CrashHandler
|
||||
debug("Exception in user mode (ip: %#lx cr2: %#lx (%s))",
|
||||
Frame->rip, PageFaultAddress,
|
||||
data->CurrentProcess->ELFSymbolTable
|
||||
? data->CurrentProcess->ELFSymbolTable->GetSymbolFromAddress(Frame->rip)
|
||||
? data->CurrentProcess->ELFSymbolTable->GetSymbol(Frame->rip)
|
||||
: "No symbol");
|
||||
}
|
||||
else
|
||||
@ -889,16 +905,18 @@ namespace CrashHandler
|
||||
debug("Exception in user mode (ip: %#lx (%s))",
|
||||
Frame->rip,
|
||||
data->CurrentProcess->ELFSymbolTable
|
||||
? data->CurrentProcess->ELFSymbolTable->GetSymbolFromAddress(Frame->rip)
|
||||
? data->CurrentProcess->ELFSymbolTable->GetSymbol(Frame->rip)
|
||||
: "No symbol");
|
||||
}
|
||||
|
||||
if (UserModeExceptionHandler(Frame))
|
||||
return;
|
||||
return true;
|
||||
else if (DebuggerIsAttached)
|
||||
asmv("int $0x8");
|
||||
|
||||
if (unlikely(data->CurrentThread->Security.IsCritical))
|
||||
{
|
||||
debug("Critical thread \"%s\"(%d) died",
|
||||
error("Critical thread \"%s\"(%d) died",
|
||||
data->CurrentThread->Name,
|
||||
data->CurrentThread->ID);
|
||||
if (TaskManager)
|
||||
@ -906,26 +924,29 @@ namespace CrashHandler
|
||||
ForceUnlock = true;
|
||||
Display->CreateBuffer(0, 0, SBIdx);
|
||||
StopAllCores();
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
Tasking::TCB *tcb = data->CurrentThread;
|
||||
Tasking::Task *ctx = tcb->GetContext();
|
||||
tcb->State = Tasking::Terminated;
|
||||
tcb->ExitCode = Tasking::KILL_CRASH;
|
||||
CPU::Interrupts(CPU::Enable);
|
||||
while (true)
|
||||
{
|
||||
ctx->Yield();
|
||||
tcb->GetContext()->Yield();
|
||||
CPU::Halt(TaskManager->IsPanic());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
SafeFunction inline void Handle_x86_32(CHArchTrapFrame *Frame)
|
||||
SafeFunction inline bool Handle_x86_32(CHArchTrapFrame *Frame)
|
||||
{
|
||||
#ifdef a32
|
||||
trace("Exception at %s",
|
||||
KernelSymbolTable
|
||||
? KernelSymbolTable->GetSymbol(Frame->eip)
|
||||
: "No symbol");
|
||||
|
||||
for (size_t i = 0; i < INT_FRAMES_MAX; i++)
|
||||
EHIntFrames[i] = Interrupts::InterruptFrames[i];
|
||||
PageFaultAddress = CPU::x32::readcr2().PFLA;
|
||||
@ -938,7 +959,7 @@ namespace CrashHandler
|
||||
debug("Exception in kernel mode (ip: %#lx cr2: %#lx (%s))",
|
||||
Frame->eip, PageFaultAddress,
|
||||
data->CurrentProcess->ELFSymbolTable
|
||||
? data->CurrentProcess->ELFSymbolTable->GetSymbolFromAddress(Frame->eip)
|
||||
? data->CurrentProcess->ELFSymbolTable->GetSymbol(Frame->eip)
|
||||
: "No symbol");
|
||||
}
|
||||
else
|
||||
@ -946,12 +967,14 @@ namespace CrashHandler
|
||||
debug("Exception in kernel mode (ip: %#lx (%s))",
|
||||
Frame->eip,
|
||||
data->CurrentProcess->ELFSymbolTable
|
||||
? data->CurrentProcess->ELFSymbolTable->GetSymbolFromAddress(Frame->eip)
|
||||
? data->CurrentProcess->ELFSymbolTable->GetSymbol(Frame->eip)
|
||||
: "No symbol");
|
||||
}
|
||||
|
||||
if (UserModeExceptionHandler(Frame))
|
||||
return;
|
||||
return true;
|
||||
else if (DebuggerIsAttached)
|
||||
asmv("int $0x8");
|
||||
|
||||
if (data->CurrentThread)
|
||||
{
|
||||
@ -974,23 +997,25 @@ namespace CrashHandler
|
||||
{
|
||||
debug("Exception in user mode (ip: %#lx cr2: %#lx (%s))",
|
||||
Frame->eip, PageFaultAddress,
|
||||
KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress(Frame->eip)
|
||||
KernelSymbolTable ? KernelSymbolTable->GetSymbol(Frame->eip)
|
||||
: "No symbol");
|
||||
}
|
||||
else
|
||||
{
|
||||
debug("Exception in user mode (ip: %#lx (%s))",
|
||||
Frame->eip,
|
||||
KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress(Frame->eip)
|
||||
KernelSymbolTable ? KernelSymbolTable->GetSymbol(Frame->eip)
|
||||
: "No symbol");
|
||||
}
|
||||
|
||||
if (UserModeExceptionHandler(Frame))
|
||||
return;
|
||||
return true;
|
||||
else if (DebuggerIsAttached)
|
||||
asmv("int $0x8");
|
||||
|
||||
if (unlikely(data->CurrentThread->Security.IsCritical))
|
||||
{
|
||||
debug("Critical thread \"%s\"(%d) died",
|
||||
error("Critical thread \"%s\"(%d) died",
|
||||
data->CurrentThread->Name,
|
||||
data->CurrentThread->ID);
|
||||
if (TaskManager)
|
||||
@ -998,21 +1023,19 @@ namespace CrashHandler
|
||||
ForceUnlock = true;
|
||||
Display->CreateBuffer(0, 0, SBIdx);
|
||||
StopAllCores();
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
Tasking::TCB *tcb = data->CurrentThread;
|
||||
Tasking::Task *ctx = tcb->GetContext();
|
||||
tcb->State = Tasking::Terminated;
|
||||
tcb->ExitCode = Tasking::KILL_CRASH;
|
||||
CPU::Interrupts(CPU::Enable);
|
||||
while (true)
|
||||
{
|
||||
ctx->Yield();
|
||||
tcb->GetContext()->Yield();
|
||||
CPU::Halt(TaskManager->IsPanic());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
SafeFunction inline void Print_x86_64(CHArchTrapFrame *Frame)
|
||||
@ -1155,12 +1178,17 @@ namespace CrashHandler
|
||||
CHArchTrapFrame *Frame = (CHArchTrapFrame *)Data;
|
||||
SBIdx = 255;
|
||||
debug("-----------------------------------------------------------------------------------");
|
||||
debug("%ld MiB / %ld MiB (%ld MiB Reserved)",
|
||||
TO_MiB(KernelAllocator.GetUsedMemory()),
|
||||
TO_MiB(KernelAllocator.GetTotalMemory()),
|
||||
TO_MiB(KernelAllocator.GetReservedMemory()));
|
||||
error("Exception: %#x", Frame->InterruptNumber);
|
||||
#if defined(a64)
|
||||
Handle_x86_64(Frame);
|
||||
if (Handle_x86_64(Frame))
|
||||
#elif defined(a32)
|
||||
Handle_x86_32(Frame);
|
||||
if (Handle_x86_32(Frame))
|
||||
#endif
|
||||
return;
|
||||
|
||||
if (ExceptionOccurred)
|
||||
{
|
||||
@ -1180,8 +1208,8 @@ namespace CrashHandler
|
||||
|
||||
ExceptionOccurred = true;
|
||||
|
||||
if (ModuleManager)
|
||||
ModuleManager->Panic();
|
||||
if (DriverManager)
|
||||
DriverManager->Panic();
|
||||
|
||||
debug("Reading control registers...");
|
||||
crashdata.Frame = Frame;
|
||||
@ -1397,6 +1425,7 @@ namespace CrashHandler
|
||||
DisplayTopOverlay();
|
||||
DisplayMainScreen(crashdata);
|
||||
Display->SetBuffer(255);
|
||||
Interrupts::RemoveAll();
|
||||
kbd = new CrashKeyboardDriver;
|
||||
DisplayBottomOverlay();
|
||||
Display->SetBuffer(255);
|
||||
|
@ -120,125 +120,109 @@ namespace CrashHandler
|
||||
#define WaitWrite PS2Wait(false)
|
||||
CPU::Interrupts(CPU::Disable);
|
||||
#if defined(a86)
|
||||
// Disable devices
|
||||
|
||||
/* Disable Port 1 */
|
||||
WaitWrite;
|
||||
outb(0x64, 0xAD);
|
||||
|
||||
/* Disable Port 2 */
|
||||
WaitWrite;
|
||||
outb(0x64, 0xA7);
|
||||
|
||||
// Flush buffer
|
||||
/* Flush */
|
||||
WaitRead;
|
||||
inb(0x60);
|
||||
|
||||
// outb(0x64, 0xAE);
|
||||
|
||||
// Configure devices
|
||||
WaitWrite;
|
||||
outb(0x64, 0x20);
|
||||
WaitRead;
|
||||
uint8_t cfg = inb(0x60);
|
||||
bool DualChannel = cfg & 0b00100000;
|
||||
if (DualChannel)
|
||||
trace("Dual channel PS/2 controller detected.");
|
||||
cfg |= 0b01000011;
|
||||
WaitWrite;
|
||||
outb(0x64, 0x60);
|
||||
WaitWrite;
|
||||
outb(0x60, cfg);
|
||||
|
||||
/* Test PS/2 controller */
|
||||
WaitWrite;
|
||||
outb(0x64, 0xAA);
|
||||
WaitRead;
|
||||
uint8_t test = inb(0x60);
|
||||
if (test != 0x55)
|
||||
{
|
||||
error("PS/2 controller self test failed! (%#x)", test);
|
||||
printf("PS/2 controller self test failed! (%#x)\n", test);
|
||||
CPU::Stop();
|
||||
if (test == 0xFA)
|
||||
warn("PS/2 controller acknowledged? (expected TEST_PASSED = 0x55)");
|
||||
else
|
||||
{
|
||||
error("PS/2 controller self test failed (%#x)", test);
|
||||
// CPU::Stop();
|
||||
}
|
||||
}
|
||||
|
||||
/* Enable Port 1 */
|
||||
WaitWrite;
|
||||
outb(0x64, 0xAE);
|
||||
|
||||
/* Reset Port 1 */
|
||||
WaitWrite;
|
||||
outb(0x64, 0xFF); /* This may break some keyboards? */
|
||||
|
||||
/* Test Port 1 */
|
||||
WaitWrite;
|
||||
outb(0x64, 0xAB);
|
||||
WaitRead;
|
||||
test = inb(0x60);
|
||||
|
||||
if (test != 0x00)
|
||||
{
|
||||
if (test == 0xFA)
|
||||
warn("PS/2 keyboard acknowledged? (expected TEST_PASSED = 0x00)");
|
||||
else
|
||||
{
|
||||
error("PS/2 keyboard self test failed (%#x)", test);
|
||||
// CPU::Stop();
|
||||
}
|
||||
}
|
||||
|
||||
/* Disable Port 1 */
|
||||
WaitWrite;
|
||||
outb(0x64, 0xAD);
|
||||
|
||||
/* Disable Port 2 */
|
||||
WaitWrite;
|
||||
outb(0x64, 0xA7);
|
||||
|
||||
/* Flush Port 1 */
|
||||
WaitRead;
|
||||
inb(0x60);
|
||||
|
||||
/* Read Controller Configuration */
|
||||
WaitWrite;
|
||||
outb(0x64, 0x20);
|
||||
WaitRead;
|
||||
uint8_t cfg = inb(0x60);
|
||||
|
||||
/* Enable Port 1 & Port 1 translation */
|
||||
cfg |= 0b01000001;
|
||||
|
||||
/* Write Controller Configuration */
|
||||
WaitWrite;
|
||||
outb(0x64, 0x60);
|
||||
WaitWrite;
|
||||
outb(0x60, cfg);
|
||||
|
||||
bool DCExists = false;
|
||||
if (DualChannel)
|
||||
{
|
||||
WaitWrite;
|
||||
outb(0x64, 0xAE);
|
||||
WaitWrite;
|
||||
outb(0x64, 0x20);
|
||||
WaitRead;
|
||||
cfg = inb(0x60);
|
||||
DCExists = !(cfg & 0b00100000);
|
||||
WaitWrite;
|
||||
outb(0x64, 0xAD);
|
||||
debug("DCExists: %d", DCExists);
|
||||
}
|
||||
|
||||
WaitWrite;
|
||||
outb(0x64, 0xAB);
|
||||
WaitRead;
|
||||
test = inb(0x60);
|
||||
if (test != 0x00)
|
||||
{
|
||||
error("PS/2 keyboard self test failed! (%#x)", test);
|
||||
printf("PS/2 keyboard self test failed! (%#x)\n", test);
|
||||
CPU::Stop();
|
||||
}
|
||||
|
||||
if (DCExists)
|
||||
{
|
||||
WaitWrite;
|
||||
outb(0x64, 0xA9);
|
||||
WaitRead;
|
||||
test = inb(0x60);
|
||||
if (test != 0x00)
|
||||
{
|
||||
error("PS/2 mouse self test failed! (%#x)", test);
|
||||
printf("PS/2 mouse self test failed! (%#x)\n", test);
|
||||
CPU::Stop();
|
||||
}
|
||||
}
|
||||
|
||||
WaitWrite;
|
||||
/* Enable Port 1 */
|
||||
outb(0x64, 0xAE);
|
||||
|
||||
if (DCExists)
|
||||
{
|
||||
WaitWrite;
|
||||
outb(0x64, 0xA8);
|
||||
}
|
||||
|
||||
/* Set scan code set 1 */
|
||||
WaitWrite;
|
||||
outb(0x60, 0xFF);
|
||||
outb(0x60, 0xF0);
|
||||
WaitWrite;
|
||||
outb(0x60, 0x02);
|
||||
|
||||
/* Check if we have scan code set 1 */
|
||||
WaitWrite;
|
||||
outb(0x60, 0xF0);
|
||||
WaitWrite;
|
||||
outb(0x60, 0x00);
|
||||
|
||||
/* Read scan code set */
|
||||
WaitRead;
|
||||
test = inb(0x60);
|
||||
if (test == 0xFC)
|
||||
uint8_t scs = inb(0x60);
|
||||
if (scs != 0x41)
|
||||
{
|
||||
error("PS/2 keyboard reset failed! (%#x)", test);
|
||||
printf("PS/2 keyboard reset failed! (%#x)\n", test);
|
||||
CPU::Stop();
|
||||
warn("PS/2 keyboard scan code set 1 not supported (%#x)", scs);
|
||||
}
|
||||
|
||||
WaitWrite;
|
||||
outb(0x60, 0xD4);
|
||||
WaitWrite;
|
||||
outb(0x60, 0xFF);
|
||||
WaitRead;
|
||||
test = inb(0x60);
|
||||
if (test == 0xFC)
|
||||
{
|
||||
error("PS/2 mouse reset failed! (%#x)", test);
|
||||
printf("PS/2 mouse reset failed! (%#x)\n", test);
|
||||
CPU::Stop();
|
||||
}
|
||||
|
||||
// outb(0x60, 0xF4);
|
||||
|
||||
// outb(0x21, 0xFD);
|
||||
// outb(0xA1, 0xFF);
|
||||
#endif // defined(a86)
|
||||
|
||||
CPU::Interrupts(CPU::Enable);
|
||||
@ -246,19 +230,13 @@ namespace CrashHandler
|
||||
|
||||
CrashKeyboardDriver::~CrashKeyboardDriver()
|
||||
{
|
||||
error("CrashKeyboardDriver::~CrashKeyboardDriver() called!");
|
||||
error("CrashKeyboardDriver::~CrashKeyboardDriver() called");
|
||||
}
|
||||
|
||||
int BackSpaceLimit = 0;
|
||||
static char UserInputBuffer[1024];
|
||||
|
||||
#if defined(a64)
|
||||
SafeFunction void CrashKeyboardDriver::OnInterruptReceived(CPU::x64::TrapFrame *Frame)
|
||||
#elif defined(a32)
|
||||
SafeFunction void CrashKeyboardDriver::OnInterruptReceived(CPU::x32::TrapFrame *Frame)
|
||||
#elif defined(aa64)
|
||||
SafeFunction void CrashKeyboardDriver::OnInterruptReceived(CPU::aarch64::TrapFrame *Frame)
|
||||
#endif
|
||||
SafeFunction void CrashKeyboardDriver::OnInterruptReceived(CPU::TrapFrame *Frame)
|
||||
{
|
||||
#if defined(a86)
|
||||
UNUSED(Frame);
|
||||
|
@ -34,9 +34,9 @@
|
||||
|
||||
namespace CrashHandler
|
||||
{
|
||||
SafeFunction void DisplayConsoleScreen(CRData data)
|
||||
{
|
||||
EHPrint("TODO");
|
||||
UNUSED(data);
|
||||
}
|
||||
SafeFunction void DisplayConsoleScreen(CRData data)
|
||||
{
|
||||
EHPrint("TODO");
|
||||
UNUSED(data);
|
||||
}
|
||||
}
|
@ -34,232 +34,232 @@
|
||||
|
||||
namespace CrashHandler
|
||||
{
|
||||
SafeFunction void DisplayDetailsScreen(CRData data)
|
||||
{
|
||||
if (data.Process)
|
||||
EHPrint("\e7981FCCurrent Process: %s(%ld)\n",
|
||||
data.Process->Name,
|
||||
data.Process->ID);
|
||||
if (data.Thread)
|
||||
EHPrint("\e7981FCCurrent Thread: %s(%ld)\n",
|
||||
data.Thread->Name,
|
||||
data.Thread->ID);
|
||||
EHPrint("\e7981FCTechnical Informations on CPU %lld:\n", data.ID);
|
||||
uintptr_t ds;
|
||||
SafeFunction void DisplayDetailsScreen(CRData data)
|
||||
{
|
||||
if (data.Process)
|
||||
EHPrint("\e7981FCCurrent Process: %s(%ld)\n",
|
||||
data.Process->Name,
|
||||
data.Process->ID);
|
||||
if (data.Thread)
|
||||
EHPrint("\e7981FCCurrent Thread: %s(%ld)\n",
|
||||
data.Thread->Name,
|
||||
data.Thread->ID);
|
||||
EHPrint("\e7981FCTechnical Informations on CPU %lld:\n", data.ID);
|
||||
uintptr_t ds;
|
||||
#if defined(a64)
|
||||
|
||||
CPUData *cpu = (CPUData *)data.CPUData;
|
||||
if (cpu)
|
||||
{
|
||||
EHPrint("\eE46CEBCPU Data Address: %#lx\n", cpu);
|
||||
EHPrint("Core Stack: %#lx, Core ID: %ld, Error Code: %ld\n",
|
||||
cpu->Stack, cpu->ID, cpu->ErrorCode);
|
||||
EHPrint("Is Active: %s\n", cpu->IsActive ? "true" : "false");
|
||||
EHPrint("Current Process: %#lx, Current Thread: %#lx\n",
|
||||
cpu->CurrentProcess.load(), cpu->CurrentThread.load());
|
||||
EHPrint("Arch Specific Data: %#lx\n", cpu->Data);
|
||||
EHPrint("Checksum: 0x%X\n", cpu->Checksum);
|
||||
}
|
||||
CPUData *cpu = (CPUData *)data.CPUData;
|
||||
if (cpu)
|
||||
{
|
||||
EHPrint("\eE46CEBCPU Data Address: %#lx\n", cpu);
|
||||
EHPrint("Core Stack: %#lx, Core ID: %ld, Error Code: %ld\n",
|
||||
cpu->Stack, cpu->ID, cpu->ErrorCode);
|
||||
EHPrint("Is Active: %s\n", cpu->IsActive ? "true" : "false");
|
||||
EHPrint("Current Process: %#lx, Current Thread: %#lx\n",
|
||||
cpu->CurrentProcess.load(), cpu->CurrentThread.load());
|
||||
EHPrint("Arch Specific Data: %#lx\n", cpu->Data);
|
||||
EHPrint("Checksum: 0x%X\n", cpu->Checksum);
|
||||
}
|
||||
|
||||
asmv("mov %%ds, %0"
|
||||
: "=r"(ds));
|
||||
asmv("mov %%ds, %0"
|
||||
: "=r"(ds));
|
||||
#elif defined(a32)
|
||||
asmv("mov %%ds, %0"
|
||||
: "=r"(ds));
|
||||
asmv("mov %%ds, %0"
|
||||
: "=r"(ds));
|
||||
#elif defined(aa64)
|
||||
#endif
|
||||
|
||||
#if defined(a64)
|
||||
EHPrint("\e7981FCFS=%#lx GS=%#lx SS=%#lx CS=%#lx DS=%#lx\n",
|
||||
CPU::x64::rdmsr(CPU::x64::MSR_FS_BASE), CPU::x64::rdmsr(CPU::x64::MSR_GS_BASE),
|
||||
data.Frame->ss, data.Frame->cs, ds);
|
||||
EHPrint("R8=%#lx R9=%#lx R10=%#lx R11=%#lx\n", data.Frame->r8, data.Frame->r9, data.Frame->r10, data.Frame->r11);
|
||||
EHPrint("R12=%#lx R13=%#lx R14=%#lx R15=%#lx\n", data.Frame->r12, data.Frame->r13, data.Frame->r14, data.Frame->r15);
|
||||
EHPrint("RAX=%#lx RBX=%#lx RCX=%#lx RDX=%#lx\n", data.Frame->rax, data.Frame->rbx, data.Frame->rcx, data.Frame->rdx);
|
||||
EHPrint("RSI=%#lx RDI=%#lx RBP=%#lx RSP=%#lx\n", data.Frame->rsi, data.Frame->rdi, data.Frame->rbp, data.Frame->rsp);
|
||||
EHPrint("RIP=%#lx RFL=%#lx INT=%#lx ERR=%#lx EFER=%#lx\n", data.Frame->rip, data.Frame->rflags.raw, data.Frame->InterruptNumber, data.Frame->ErrorCode, data.efer.raw);
|
||||
EHPrint("\e7981FCFS=%#lx GS=%#lx SS=%#lx CS=%#lx DS=%#lx\n",
|
||||
CPU::x64::rdmsr(CPU::x64::MSR_FS_BASE), CPU::x64::rdmsr(CPU::x64::MSR_GS_BASE),
|
||||
data.Frame->ss, data.Frame->cs, ds);
|
||||
EHPrint("R8=%#lx R9=%#lx R10=%#lx R11=%#lx\n", data.Frame->r8, data.Frame->r9, data.Frame->r10, data.Frame->r11);
|
||||
EHPrint("R12=%#lx R13=%#lx R14=%#lx R15=%#lx\n", data.Frame->r12, data.Frame->r13, data.Frame->r14, data.Frame->r15);
|
||||
EHPrint("RAX=%#lx RBX=%#lx RCX=%#lx RDX=%#lx\n", data.Frame->rax, data.Frame->rbx, data.Frame->rcx, data.Frame->rdx);
|
||||
EHPrint("RSI=%#lx RDI=%#lx RBP=%#lx RSP=%#lx\n", data.Frame->rsi, data.Frame->rdi, data.Frame->rbp, data.Frame->rsp);
|
||||
EHPrint("RIP=%#lx RFL=%#lx INT=%#lx ERR=%#lx EFER=%#lx\n", data.Frame->rip, data.Frame->rflags.raw, data.Frame->InterruptNumber, data.Frame->ErrorCode, data.efer.raw);
|
||||
#elif defined(a32)
|
||||
EHPrint("\e7981FCFS=%#x GS=%#x CS=%#x DS=%#x\n",
|
||||
CPU::x32::rdmsr(CPU::x32::MSR_FS_BASE), CPU::x32::rdmsr(CPU::x32::MSR_GS_BASE),
|
||||
data.Frame->cs, ds);
|
||||
EHPrint("EAX=%#x EBX=%#x ECX=%#x EDX=%#x\n", data.Frame->eax, data.Frame->ebx, data.Frame->ecx, data.Frame->edx);
|
||||
EHPrint("ESI=%#x EDI=%#x EBP=%#x ESP=%#x\n", data.Frame->esi, data.Frame->edi, data.Frame->ebp, data.Frame->esp);
|
||||
EHPrint("EIP=%#x EFL=%#x INT=%#x ERR=%#x\n", data.Frame->eip, data.Frame->eflags.raw, data.Frame->InterruptNumber, data.Frame->ErrorCode);
|
||||
EHPrint("\e7981FCFS=%#x GS=%#x CS=%#x DS=%#x\n",
|
||||
CPU::x32::rdmsr(CPU::x32::MSR_FS_BASE), CPU::x32::rdmsr(CPU::x32::MSR_GS_BASE),
|
||||
data.Frame->cs, ds);
|
||||
EHPrint("EAX=%#x EBX=%#x ECX=%#x EDX=%#x\n", data.Frame->eax, data.Frame->ebx, data.Frame->ecx, data.Frame->edx);
|
||||
EHPrint("ESI=%#x EDI=%#x EBP=%#x ESP=%#x\n", data.Frame->esi, data.Frame->edi, data.Frame->ebp, data.Frame->esp);
|
||||
EHPrint("EIP=%#x EFL=%#x INT=%#x ERR=%#x\n", data.Frame->eip, data.Frame->eflags.raw, data.Frame->InterruptNumber, data.Frame->ErrorCode);
|
||||
#elif defined(aa64)
|
||||
#endif
|
||||
|
||||
#if defined(a86)
|
||||
EHPrint("CR0=%#lx CR2=%#lx CR3=%#lx CR4=%#lx CR8=%#lx\n", data.cr0.raw, data.cr2.raw, data.cr3.raw, data.cr4.raw, data.cr8.raw);
|
||||
EHPrint("DR0=%#lx DR1=%#lx DR2=%#lx DR3=%#lx DR6=%#lx DR7=%#lx\n", data.dr0, data.dr1, data.dr2, data.dr3, data.dr6, data.dr7.raw);
|
||||
EHPrint("CR0=%#lx CR2=%#lx CR3=%#lx CR4=%#lx CR8=%#lx\n", data.cr0.raw, data.cr2.raw, data.cr3.raw, data.cr4.raw, data.cr8.raw);
|
||||
EHPrint("DR0=%#lx DR1=%#lx DR2=%#lx DR3=%#lx DR6=%#lx DR7=%#lx\n", data.dr0, data.dr1, data.dr2, data.dr3, data.dr6, data.dr7.raw);
|
||||
|
||||
EHPrint("\eFC797BCR0: PE:%s MP:%s EM:%s TS:%s\n ET:%s NE:%s WP:%s AM:%s\n NW:%s CD:%s PG:%s\n",
|
||||
data.cr0.PE ? "True " : "False", data.cr0.MP ? "True " : "False", data.cr0.EM ? "True " : "False", data.cr0.TS ? "True " : "False",
|
||||
data.cr0.ET ? "True " : "False", data.cr0.NE ? "True " : "False", data.cr0.WP ? "True " : "False", data.cr0.AM ? "True " : "False",
|
||||
data.cr0.NW ? "True " : "False", data.cr0.CD ? "True " : "False", data.cr0.PG ? "True " : "False");
|
||||
EHPrint("\eFC797BCR0: PE:%s MP:%s EM:%s TS:%s\n ET:%s NE:%s WP:%s AM:%s\n NW:%s CD:%s PG:%s\n",
|
||||
data.cr0.PE ? "True " : "False", data.cr0.MP ? "True " : "False", data.cr0.EM ? "True " : "False", data.cr0.TS ? "True " : "False",
|
||||
data.cr0.ET ? "True " : "False", data.cr0.NE ? "True " : "False", data.cr0.WP ? "True " : "False", data.cr0.AM ? "True " : "False",
|
||||
data.cr0.NW ? "True " : "False", data.cr0.CD ? "True " : "False", data.cr0.PG ? "True " : "False");
|
||||
|
||||
EHPrint("\eFCBD79CR2: PFLA: %#lx\n",
|
||||
data.cr2.PFLA);
|
||||
EHPrint("\eFCBD79CR2: PFLA: %#lx\n",
|
||||
data.cr2.PFLA);
|
||||
|
||||
EHPrint("\e79FC84CR3: PWT:%s PCD:%s PDBR:%#lx\n",
|
||||
data.cr3.PWT ? "True " : "False", data.cr3.PCD ? "True " : "False", data.cr3.PDBR);
|
||||
EHPrint("\e79FC84CR3: PWT:%s PCD:%s PDBR:%#lx\n",
|
||||
data.cr3.PWT ? "True " : "False", data.cr3.PCD ? "True " : "False", data.cr3.PDBR);
|
||||
|
||||
EHPrint("\eBD79FCCR4: VME:%s PVI:%s TSD:%s DE:%s\n PSE:%s PAE:%s MCE:%s PGE:%s\n PCE:%s UMIP:%s OSFXSR:%s OSXMMEXCPT:%s\n LA57:%s VMXE:%s SMXE:%s PCIDE:%s\n OSXSAVE:%s SMEP:%s SMAP:%s PKE:%s\n",
|
||||
data.cr4.VME ? "True " : "False", data.cr4.PVI ? "True " : "False", data.cr4.TSD ? "True " : "False", data.cr4.DE ? "True " : "False",
|
||||
data.cr4.PSE ? "True " : "False", data.cr4.PAE ? "True " : "False", data.cr4.MCE ? "True " : "False", data.cr4.PGE ? "True " : "False",
|
||||
data.cr4.PCE ? "True " : "False", data.cr4.UMIP ? "True " : "False", data.cr4.OSFXSR ? "True " : "False", data.cr4.OSXMMEXCPT ? "True " : "False",
|
||||
data.cr4.LA57 ? "True " : "False", data.cr4.VMXE ? "True " : "False", data.cr4.SMXE ? "True " : "False", data.cr4.PCIDE ? "True " : "False",
|
||||
data.cr4.OSXSAVE ? "True " : "False", data.cr4.SMEP ? "True " : "False", data.cr4.SMAP ? "True " : "False", data.cr4.PKE ? "True " : "False");
|
||||
EHPrint("\e79FCF5CR8: TPL:%d\n", data.cr8.TPL);
|
||||
EHPrint("\eBD79FCCR4: VME:%s PVI:%s TSD:%s DE:%s\n PSE:%s PAE:%s MCE:%s PGE:%s\n PCE:%s UMIP:%s OSFXSR:%s OSXMMEXCPT:%s\n LA57:%s VMXE:%s SMXE:%s PCIDE:%s\n OSXSAVE:%s SMEP:%s SMAP:%s PKE:%s\n",
|
||||
data.cr4.VME ? "True " : "False", data.cr4.PVI ? "True " : "False", data.cr4.TSD ? "True " : "False", data.cr4.DE ? "True " : "False",
|
||||
data.cr4.PSE ? "True " : "False", data.cr4.PAE ? "True " : "False", data.cr4.MCE ? "True " : "False", data.cr4.PGE ? "True " : "False",
|
||||
data.cr4.PCE ? "True " : "False", data.cr4.UMIP ? "True " : "False", data.cr4.OSFXSR ? "True " : "False", data.cr4.OSXMMEXCPT ? "True " : "False",
|
||||
data.cr4.LA57 ? "True " : "False", data.cr4.VMXE ? "True " : "False", data.cr4.SMXE ? "True " : "False", data.cr4.PCIDE ? "True " : "False",
|
||||
data.cr4.OSXSAVE ? "True " : "False", data.cr4.SMEP ? "True " : "False", data.cr4.SMAP ? "True " : "False", data.cr4.PKE ? "True " : "False");
|
||||
EHPrint("\e79FCF5CR8: TPL:%d\n", data.cr8.TPL);
|
||||
#endif // a64 || a32
|
||||
|
||||
#if defined(a64)
|
||||
EHPrint("\eFCFC02RFL: CF:%s PF:%s AF:%s ZF:%s\n SF:%s TF:%s IF:%s DF:%s\n OF:%s IOPL:%s NT:%s RF:%s\n VM:%s AC:%s VIF:%s VIP:%s\n ID:%s AlwaysOne:%d\n",
|
||||
data.Frame->rflags.CF ? "True " : "False", data.Frame->rflags.PF ? "True " : "False", data.Frame->rflags.AF ? "True " : "False", data.Frame->rflags.ZF ? "True " : "False",
|
||||
data.Frame->rflags.SF ? "True " : "False", data.Frame->rflags.TF ? "True " : "False", data.Frame->rflags.IF ? "True " : "False", data.Frame->rflags.DF ? "True " : "False",
|
||||
data.Frame->rflags.OF ? "True " : "False", data.Frame->rflags.IOPL ? "True " : "False", data.Frame->rflags.NT ? "True " : "False", data.Frame->rflags.RF ? "True " : "False",
|
||||
data.Frame->rflags.VM ? "True " : "False", data.Frame->rflags.AC ? "True " : "False", data.Frame->rflags.VIF ? "True " : "False", data.Frame->rflags.VIP ? "True " : "False",
|
||||
data.Frame->rflags.ID ? "True " : "False", data.Frame->rflags.AlwaysOne);
|
||||
EHPrint("\eFCFC02RFL: CF:%s PF:%s AF:%s ZF:%s\n SF:%s TF:%s IF:%s DF:%s\n OF:%s IOPL:%s NT:%s RF:%s\n VM:%s AC:%s VIF:%s VIP:%s\n ID:%s AlwaysOne:%d\n",
|
||||
data.Frame->rflags.CF ? "True " : "False", data.Frame->rflags.PF ? "True " : "False", data.Frame->rflags.AF ? "True " : "False", data.Frame->rflags.ZF ? "True " : "False",
|
||||
data.Frame->rflags.SF ? "True " : "False", data.Frame->rflags.TF ? "True " : "False", data.Frame->rflags.IF ? "True " : "False", data.Frame->rflags.DF ? "True " : "False",
|
||||
data.Frame->rflags.OF ? "True " : "False", data.Frame->rflags.IOPL ? "True " : "False", data.Frame->rflags.NT ? "True " : "False", data.Frame->rflags.RF ? "True " : "False",
|
||||
data.Frame->rflags.VM ? "True " : "False", data.Frame->rflags.AC ? "True " : "False", data.Frame->rflags.VIF ? "True " : "False", data.Frame->rflags.VIP ? "True " : "False",
|
||||
data.Frame->rflags.ID ? "True " : "False", data.Frame->rflags.AlwaysOne);
|
||||
#elif defined(a32)
|
||||
EHPrint("\eFCFC02EFL: CF:%s PF:%s AF:%s ZF:%s\n SF:%s TF:%s IF:%s DF:%s\n OF:%s IOPL:%s NT:%s RF:%s\n VM:%s AC:%s VIF:%s VIP:%s\n ID:%s AlwaysOne:%d\n",
|
||||
data.Frame->eflags.CF ? "True " : "False", data.Frame->eflags.PF ? "True " : "False", data.Frame->eflags.AF ? "True " : "False", data.Frame->eflags.ZF ? "True " : "False",
|
||||
data.Frame->eflags.SF ? "True " : "False", data.Frame->eflags.TF ? "True " : "False", data.Frame->eflags.IF ? "True " : "False", data.Frame->eflags.DF ? "True " : "False",
|
||||
data.Frame->eflags.OF ? "True " : "False", data.Frame->eflags.IOPL ? "True " : "False", data.Frame->eflags.NT ? "True " : "False", data.Frame->eflags.RF ? "True " : "False",
|
||||
data.Frame->eflags.VM ? "True " : "False", data.Frame->eflags.AC ? "True " : "False", data.Frame->eflags.VIF ? "True " : "False", data.Frame->eflags.VIP ? "True " : "False",
|
||||
data.Frame->eflags.ID ? "True " : "False", data.Frame->eflags.AlwaysOne);
|
||||
EHPrint("\eFCFC02EFL: CF:%s PF:%s AF:%s ZF:%s\n SF:%s TF:%s IF:%s DF:%s\n OF:%s IOPL:%s NT:%s RF:%s\n VM:%s AC:%s VIF:%s VIP:%s\n ID:%s AlwaysOne:%d\n",
|
||||
data.Frame->eflags.CF ? "True " : "False", data.Frame->eflags.PF ? "True " : "False", data.Frame->eflags.AF ? "True " : "False", data.Frame->eflags.ZF ? "True " : "False",
|
||||
data.Frame->eflags.SF ? "True " : "False", data.Frame->eflags.TF ? "True " : "False", data.Frame->eflags.IF ? "True " : "False", data.Frame->eflags.DF ? "True " : "False",
|
||||
data.Frame->eflags.OF ? "True " : "False", data.Frame->eflags.IOPL ? "True " : "False", data.Frame->eflags.NT ? "True " : "False", data.Frame->eflags.RF ? "True " : "False",
|
||||
data.Frame->eflags.VM ? "True " : "False", data.Frame->eflags.AC ? "True " : "False", data.Frame->eflags.VIF ? "True " : "False", data.Frame->eflags.VIP ? "True " : "False",
|
||||
data.Frame->eflags.ID ? "True " : "False", data.Frame->eflags.AlwaysOne);
|
||||
#elif defined(aa64)
|
||||
#endif
|
||||
|
||||
#if defined(a86)
|
||||
EHPrint("\eA0A0A0DR6: B0:%s B1:%s B2:%s B3:%s\n BD:%s BS:%s BT:%s\n",
|
||||
data.dr6.B0 ? "True " : "False", data.dr6.B1 ? "True " : "False", data.dr6.B2 ? "True " : "False", data.dr6.B3 ? "True " : "False",
|
||||
data.dr6.BD ? "True " : "False", data.dr6.BS ? "True " : "False", data.dr6.BT ? "True " : "False");
|
||||
EHPrint("\eA0A0A0DR6: B0:%s B1:%s B2:%s B3:%s\n BD:%s BS:%s BT:%s\n",
|
||||
data.dr6.B0 ? "True " : "False", data.dr6.B1 ? "True " : "False", data.dr6.B2 ? "True " : "False", data.dr6.B3 ? "True " : "False",
|
||||
data.dr6.BD ? "True " : "False", data.dr6.BS ? "True " : "False", data.dr6.BT ? "True " : "False");
|
||||
|
||||
EHPrint("\eA0F0F0DR7: L0:%s G0:%s L1:%s G1:%s\n L2:%s G2:%s L3:%s G3:%s\n LE:%s GE:%s GD:%s\n R/W0:%s LEN0:%s R/W1:%s LEN1:%s\n R/W2:%s LEN2:%s R/W3:%s LEN3:%s\n",
|
||||
data.dr7.L0 ? "True " : "False", data.dr7.G0 ? "True " : "False", data.dr7.L1 ? "True " : "False", data.dr7.G1 ? "True " : "False",
|
||||
data.dr7.L2 ? "True " : "False", data.dr7.G2 ? "True " : "False", data.dr7.L3 ? "True " : "False", data.dr7.G3 ? "True " : "False",
|
||||
data.dr7.LE ? "True " : "False", data.dr7.GE ? "True " : "False", data.dr7.GD ? "True " : "False", data.dr7.RW0 ? "True " : "False",
|
||||
data.dr7.LEN0 ? "True " : "False", data.dr7.RW1 ? "True " : "False", data.dr7.LEN1 ? "True " : "False", data.dr7.RW2 ? "True " : "False",
|
||||
data.dr7.LEN2 ? "True " : "False", data.dr7.RW3 ? "True " : "False", data.dr7.LEN3 ? "True " : "False");
|
||||
EHPrint("\eA0F0F0DR7: L0:%s G0:%s L1:%s G1:%s\n L2:%s G2:%s L3:%s G3:%s\n LE:%s GE:%s GD:%s\n R/W0:%s LEN0:%s R/W1:%s LEN1:%s\n R/W2:%s LEN2:%s R/W3:%s LEN3:%s\n",
|
||||
data.dr7.L0 ? "True " : "False", data.dr7.G0 ? "True " : "False", data.dr7.L1 ? "True " : "False", data.dr7.G1 ? "True " : "False",
|
||||
data.dr7.L2 ? "True " : "False", data.dr7.G2 ? "True " : "False", data.dr7.L3 ? "True " : "False", data.dr7.G3 ? "True " : "False",
|
||||
data.dr7.LE ? "True " : "False", data.dr7.GE ? "True " : "False", data.dr7.GD ? "True " : "False", data.dr7.RW0 ? "True " : "False",
|
||||
data.dr7.LEN0 ? "True " : "False", data.dr7.RW1 ? "True " : "False", data.dr7.LEN1 ? "True " : "False", data.dr7.RW2 ? "True " : "False",
|
||||
data.dr7.LEN2 ? "True " : "False", data.dr7.RW3 ? "True " : "False", data.dr7.LEN3 ? "True " : "False");
|
||||
|
||||
#ifdef a64
|
||||
EHPrint("\e009FF0EFER: SCE:%s LME:%s LMA:%s NXE:%s\n SVME:%s LMSLE:%s FFXSR:%s TCE:%s\n\n",
|
||||
data.efer.SCE ? "True " : "False", data.efer.LME ? "True " : "False", data.efer.LMA ? "True " : "False", data.efer.NXE ? "True " : "False",
|
||||
data.efer.SVME ? "True " : "False", data.efer.LMSLE ? "True " : "False", data.efer.FFXSR ? "True " : "False", data.efer.TCE ? "True " : "False");
|
||||
EHPrint("\e009FF0EFER: SCE:%s LME:%s LMA:%s NXE:%s\n SVME:%s LMSLE:%s FFXSR:%s TCE:%s\n\n",
|
||||
data.efer.SCE ? "True " : "False", data.efer.LME ? "True " : "False", data.efer.LMA ? "True " : "False", data.efer.NXE ? "True " : "False",
|
||||
data.efer.SVME ? "True " : "False", data.efer.LMSLE ? "True " : "False", data.efer.FFXSR ? "True " : "False", data.efer.TCE ? "True " : "False");
|
||||
#endif // a64
|
||||
#endif
|
||||
|
||||
switch (data.Frame->InterruptNumber)
|
||||
{
|
||||
case CPU::x86::DivideByZero:
|
||||
{
|
||||
DivideByZeroExceptionHandler(data.Frame);
|
||||
break;
|
||||
}
|
||||
case CPU::x86::Debug:
|
||||
{
|
||||
DebugExceptionHandler(data.Frame);
|
||||
break;
|
||||
}
|
||||
case CPU::x86::NonMaskableInterrupt:
|
||||
{
|
||||
NonMaskableInterruptExceptionHandler(data.Frame);
|
||||
break;
|
||||
}
|
||||
case CPU::x86::Breakpoint:
|
||||
{
|
||||
BreakpointExceptionHandler(data.Frame);
|
||||
break;
|
||||
}
|
||||
case CPU::x86::Overflow:
|
||||
{
|
||||
OverflowExceptionHandler(data.Frame);
|
||||
break;
|
||||
}
|
||||
case CPU::x86::BoundRange:
|
||||
{
|
||||
BoundRangeExceptionHandler(data.Frame);
|
||||
break;
|
||||
}
|
||||
case CPU::x86::InvalidOpcode:
|
||||
{
|
||||
InvalidOpcodeExceptionHandler(data.Frame);
|
||||
break;
|
||||
}
|
||||
case CPU::x86::DeviceNotAvailable:
|
||||
{
|
||||
DeviceNotAvailableExceptionHandler(data.Frame);
|
||||
break;
|
||||
}
|
||||
case CPU::x86::DoubleFault:
|
||||
{
|
||||
DoubleFaultExceptionHandler(data.Frame);
|
||||
break;
|
||||
}
|
||||
case CPU::x86::CoprocessorSegmentOverrun:
|
||||
{
|
||||
CoprocessorSegmentOverrunExceptionHandler(data.Frame);
|
||||
break;
|
||||
}
|
||||
case CPU::x86::InvalidTSS:
|
||||
{
|
||||
InvalidTSSExceptionHandler(data.Frame);
|
||||
break;
|
||||
}
|
||||
case CPU::x86::SegmentNotPresent:
|
||||
{
|
||||
SegmentNotPresentExceptionHandler(data.Frame);
|
||||
break;
|
||||
}
|
||||
case CPU::x86::StackSegmentFault:
|
||||
{
|
||||
StackFaultExceptionHandler(data.Frame);
|
||||
break;
|
||||
}
|
||||
case CPU::x86::GeneralProtectionFault:
|
||||
{
|
||||
GeneralProtectionExceptionHandler(data.Frame);
|
||||
break;
|
||||
}
|
||||
case CPU::x86::PageFault:
|
||||
{
|
||||
PageFaultExceptionHandler(data.Frame);
|
||||
break;
|
||||
}
|
||||
case CPU::x86::x87FloatingPoint:
|
||||
{
|
||||
x87FloatingPointExceptionHandler(data.Frame);
|
||||
break;
|
||||
}
|
||||
case CPU::x86::AlignmentCheck:
|
||||
{
|
||||
AlignmentCheckExceptionHandler(data.Frame);
|
||||
break;
|
||||
}
|
||||
case CPU::x86::MachineCheck:
|
||||
{
|
||||
MachineCheckExceptionHandler(data.Frame);
|
||||
break;
|
||||
}
|
||||
case CPU::x86::SIMDFloatingPoint:
|
||||
{
|
||||
SIMDFloatingPointExceptionHandler(data.Frame);
|
||||
break;
|
||||
}
|
||||
case CPU::x86::Virtualization:
|
||||
{
|
||||
VirtualizationExceptionHandler(data.Frame);
|
||||
break;
|
||||
}
|
||||
case CPU::x86::Security:
|
||||
{
|
||||
SecurityExceptionHandler(data.Frame);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
UnknownExceptionHandler(data.Frame);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
switch (data.Frame->InterruptNumber)
|
||||
{
|
||||
case CPU::x86::DivideByZero:
|
||||
{
|
||||
DivideByZeroExceptionHandler(data.Frame);
|
||||
break;
|
||||
}
|
||||
case CPU::x86::Debug:
|
||||
{
|
||||
DebugExceptionHandler(data.Frame);
|
||||
break;
|
||||
}
|
||||
case CPU::x86::NonMaskableInterrupt:
|
||||
{
|
||||
NonMaskableInterruptExceptionHandler(data.Frame);
|
||||
break;
|
||||
}
|
||||
case CPU::x86::Breakpoint:
|
||||
{
|
||||
BreakpointExceptionHandler(data.Frame);
|
||||
break;
|
||||
}
|
||||
case CPU::x86::Overflow:
|
||||
{
|
||||
OverflowExceptionHandler(data.Frame);
|
||||
break;
|
||||
}
|
||||
case CPU::x86::BoundRange:
|
||||
{
|
||||
BoundRangeExceptionHandler(data.Frame);
|
||||
break;
|
||||
}
|
||||
case CPU::x86::InvalidOpcode:
|
||||
{
|
||||
InvalidOpcodeExceptionHandler(data.Frame);
|
||||
break;
|
||||
}
|
||||
case CPU::x86::DeviceNotAvailable:
|
||||
{
|
||||
DeviceNotAvailableExceptionHandler(data.Frame);
|
||||
break;
|
||||
}
|
||||
case CPU::x86::DoubleFault:
|
||||
{
|
||||
DoubleFaultExceptionHandler(data.Frame);
|
||||
break;
|
||||
}
|
||||
case CPU::x86::CoprocessorSegmentOverrun:
|
||||
{
|
||||
CoprocessorSegmentOverrunExceptionHandler(data.Frame);
|
||||
break;
|
||||
}
|
||||
case CPU::x86::InvalidTSS:
|
||||
{
|
||||
InvalidTSSExceptionHandler(data.Frame);
|
||||
break;
|
||||
}
|
||||
case CPU::x86::SegmentNotPresent:
|
||||
{
|
||||
SegmentNotPresentExceptionHandler(data.Frame);
|
||||
break;
|
||||
}
|
||||
case CPU::x86::StackSegmentFault:
|
||||
{
|
||||
StackFaultExceptionHandler(data.Frame);
|
||||
break;
|
||||
}
|
||||
case CPU::x86::GeneralProtectionFault:
|
||||
{
|
||||
GeneralProtectionExceptionHandler(data.Frame);
|
||||
break;
|
||||
}
|
||||
case CPU::x86::PageFault:
|
||||
{
|
||||
PageFaultExceptionHandler(data.Frame);
|
||||
break;
|
||||
}
|
||||
case CPU::x86::x87FloatingPoint:
|
||||
{
|
||||
x87FloatingPointExceptionHandler(data.Frame);
|
||||
break;
|
||||
}
|
||||
case CPU::x86::AlignmentCheck:
|
||||
{
|
||||
AlignmentCheckExceptionHandler(data.Frame);
|
||||
break;
|
||||
}
|
||||
case CPU::x86::MachineCheck:
|
||||
{
|
||||
MachineCheckExceptionHandler(data.Frame);
|
||||
break;
|
||||
}
|
||||
case CPU::x86::SIMDFloatingPoint:
|
||||
{
|
||||
SIMDFloatingPointExceptionHandler(data.Frame);
|
||||
break;
|
||||
}
|
||||
case CPU::x86::Virtualization:
|
||||
{
|
||||
VirtualizationExceptionHandler(data.Frame);
|
||||
break;
|
||||
}
|
||||
case CPU::x86::Security:
|
||||
{
|
||||
SecurityExceptionHandler(data.Frame);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
UnknownExceptionHandler(data.Frame);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -33,358 +33,358 @@
|
||||
#include "../../../kernel.h"
|
||||
|
||||
static const char *PagefaultDescriptions[8] = {
|
||||
"Supervisory process tried to read a non-present page entry\n",
|
||||
"Supervisory process tried to read a page and caused a protection fault\n",
|
||||
"Supervisory process tried to write to a non-present page entry\n",
|
||||
"Supervisory process tried to write a page and caused a protection fault\n",
|
||||
"User process tried to read a non-present page entry\n",
|
||||
"User process tried to read a page and caused a protection fault\n",
|
||||
"User process tried to write to a non-present page entry\n",
|
||||
"User process tried to write a page and caused a protection fault\n"};
|
||||
"Supervisory process tried to read a non-present page entry\n",
|
||||
"Supervisory process tried to read a page and caused a protection fault\n",
|
||||
"Supervisory process tried to write to a non-present page entry\n",
|
||||
"Supervisory process tried to write a page and caused a protection fault\n",
|
||||
"User process tried to read a non-present page entry\n",
|
||||
"User process tried to read a page and caused a protection fault\n",
|
||||
"User process tried to write to a non-present page entry\n",
|
||||
"User process tried to write a page and caused a protection fault\n"};
|
||||
|
||||
namespace CrashHandler
|
||||
{
|
||||
SafeFunction void DisplayMainScreen(CRData data)
|
||||
{
|
||||
CHArchTrapFrame *Frame = data.Frame;
|
||||
SafeFunction void DisplayMainScreen(CRData data)
|
||||
{
|
||||
CHArchTrapFrame *Frame = data.Frame;
|
||||
|
||||
/*
|
||||
/*
|
||||
_______ ___ ___ _______ _______ _______ _______ ______ ______ _______ _______ _______ _______ _____
|
||||
| __| | | __|_ _| ___| | | | | __ \ _ | __| | | ___| \
|
||||
|__ |\ /|__ | | | | ___| | | ---| < |__ | | ___| -- |
|
||||
|_______| |___| |_______| |___| |_______|__|_|__| |______|___|__|___|___|_______|___|___|_______|_____/
|
||||
*/
|
||||
EHPrint("\eFF5500 _______ ___ ___ _______ _______ _______ _______ ______ ______ _______ _______ _______ _______ _____ \n");
|
||||
EHPrint("| __| | | __|_ _| ___| | | | | __ \\ _ | __| | | ___| \\ \n");
|
||||
EHPrint("|__ |\\ /|__ | | | | ___| | | ---| < |__ | | ___| -- |\n");
|
||||
EHPrint("|_______| |___| |_______| |___| |_______|__|_|__| |______|___|__|___|___|_______|___|___|_______|_____/ \n\eFAFAFA");
|
||||
*/
|
||||
EHPrint("\eFF5500 _______ ___ ___ _______ _______ _______ _______ ______ ______ _______ _______ _______ _______ _____ \n");
|
||||
EHPrint("| __| | | __|_ _| ___| | | | | __ \\ _ | __| | | ___| \\ \n");
|
||||
EHPrint("|__ |\\ /|__ | | | | ___| | | ---| < |__ | | ___| -- |\n");
|
||||
EHPrint("|_______| |___| |_______| |___| |_______|__|_|__| |______|___|__|___|___|_______|___|___|_______|_____/ \n\eFAFAFA");
|
||||
|
||||
switch (Frame->InterruptNumber)
|
||||
{
|
||||
case CPU::x86::DivideByZero:
|
||||
{
|
||||
EHPrint("Exception: Divide By Zero\n");
|
||||
EHPrint("The processor attempted to divide a number by zero.\n");
|
||||
break;
|
||||
}
|
||||
case CPU::x86::Debug:
|
||||
{
|
||||
EHPrint("Exception: Debug\n");
|
||||
EHPrint("A debug exception has occurred.\n");
|
||||
break;
|
||||
}
|
||||
case CPU::x86::NonMaskableInterrupt:
|
||||
{
|
||||
EHPrint("Exception: Non-Maskable Interrupt\n");
|
||||
EHPrint("A non-maskable interrupt was received.\n");
|
||||
break;
|
||||
}
|
||||
case CPU::x86::Breakpoint:
|
||||
{
|
||||
EHPrint("Exception: Breakpoint\n");
|
||||
EHPrint("The processor encountered a breakpoint.\n");
|
||||
break;
|
||||
}
|
||||
case CPU::x86::Overflow:
|
||||
{
|
||||
EHPrint("Exception: Overflow\n");
|
||||
EHPrint("The processor attempted to add a number to a number that was too large.\n");
|
||||
break;
|
||||
}
|
||||
case CPU::x86::BoundRange:
|
||||
{
|
||||
EHPrint("Exception: Bound Range\n");
|
||||
EHPrint("The processor attempted to access an array element that is out of bounds.\n");
|
||||
break;
|
||||
}
|
||||
case CPU::x86::InvalidOpcode:
|
||||
{
|
||||
EHPrint("Exception: Invalid Opcode\n");
|
||||
EHPrint("The processor attempted to execute an invalid opcode.\n");
|
||||
break;
|
||||
}
|
||||
case CPU::x86::DeviceNotAvailable:
|
||||
{
|
||||
EHPrint("Exception: Device Not Available\n");
|
||||
EHPrint("The processor attempted to use a device that is not available.\n");
|
||||
break;
|
||||
}
|
||||
case CPU::x86::DoubleFault:
|
||||
{
|
||||
EHPrint("Exception: Double Fault\n");
|
||||
EHPrint("The processor encountered a double fault.\n");
|
||||
break;
|
||||
}
|
||||
case CPU::x86::CoprocessorSegmentOverrun:
|
||||
{
|
||||
EHPrint("Exception: Coprocessor Segment Overrun\n");
|
||||
EHPrint("The processor attempted to access a segment that is not available.\n");
|
||||
break;
|
||||
}
|
||||
case CPU::x86::InvalidTSS:
|
||||
{
|
||||
EHPrint("Exception: Invalid TSS\n");
|
||||
EHPrint("The processor attempted to access a task state segment that is not available or valid.\n");
|
||||
CPU::x64::SelectorErrorCode SelCode = {.raw = Frame->ErrorCode};
|
||||
EHPrint("External? %s\n", SelCode.External ? "Yes" : "No");
|
||||
EHPrint("GDT IDT LDT IDT\n");
|
||||
switch (SelCode.Table)
|
||||
{
|
||||
case 0b00:
|
||||
{
|
||||
EHPrint(" ^ \n");
|
||||
EHPrint(" | \n");
|
||||
EHPrint(" %ld\n", SelCode.Idx);
|
||||
break;
|
||||
}
|
||||
case 0b01:
|
||||
{
|
||||
EHPrint(" ^ \n");
|
||||
EHPrint(" | \n");
|
||||
EHPrint(" %ld\n", SelCode.Idx);
|
||||
break;
|
||||
}
|
||||
case 0b10:
|
||||
{
|
||||
EHPrint(" ^ \n");
|
||||
EHPrint(" | \n");
|
||||
EHPrint(" %ld\n", SelCode.Idx);
|
||||
break;
|
||||
}
|
||||
case 0b11:
|
||||
{
|
||||
EHPrint(" ^ \n");
|
||||
EHPrint(" | \n");
|
||||
EHPrint(" %ld\n", SelCode.Idx);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
EHPrint(" ? \n");
|
||||
EHPrint(" ? \n");
|
||||
EHPrint(" %ld\n", SelCode.Idx);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CPU::x86::SegmentNotPresent:
|
||||
{
|
||||
EHPrint("Exception: Segment Not Present\n");
|
||||
EHPrint("The processor attempted to access a segment that is not present.\n");
|
||||
CPU::x64::SelectorErrorCode SelCode = {.raw = Frame->ErrorCode};
|
||||
EHPrint("External? %s\n", SelCode.External ? "Yes" : "No");
|
||||
EHPrint("GDT IDT LDT IDT\n");
|
||||
switch (SelCode.Table)
|
||||
{
|
||||
case 0b00:
|
||||
{
|
||||
EHPrint(" ^ \n");
|
||||
EHPrint(" | \n");
|
||||
EHPrint(" %ld\n", SelCode.Idx);
|
||||
break;
|
||||
}
|
||||
case 0b01:
|
||||
{
|
||||
EHPrint(" ^ \n");
|
||||
EHPrint(" | \n");
|
||||
EHPrint(" %ld\n", SelCode.Idx);
|
||||
break;
|
||||
}
|
||||
case 0b10:
|
||||
{
|
||||
EHPrint(" ^ \n");
|
||||
EHPrint(" | \n");
|
||||
EHPrint(" %ld\n", SelCode.Idx);
|
||||
break;
|
||||
}
|
||||
case 0b11:
|
||||
{
|
||||
EHPrint(" ^ \n");
|
||||
EHPrint(" | \n");
|
||||
EHPrint(" %ld\n", SelCode.Idx);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
EHPrint(" ? \n");
|
||||
EHPrint(" ? \n");
|
||||
EHPrint(" %ld\n", SelCode.Idx);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CPU::x86::StackSegmentFault:
|
||||
{
|
||||
EHPrint("Exception: Stack Segment Fault\n");
|
||||
CPU::x64::SelectorErrorCode SelCode = {.raw = Frame->ErrorCode};
|
||||
EHPrint("External? %s\n", SelCode.External ? "Yes" : "No");
|
||||
EHPrint("GDT IDT LDT IDT\n");
|
||||
switch (SelCode.Table)
|
||||
{
|
||||
case 0b00:
|
||||
{
|
||||
EHPrint(" ^ \n");
|
||||
EHPrint(" | \n");
|
||||
EHPrint(" %ld\n", SelCode.Idx);
|
||||
break;
|
||||
}
|
||||
case 0b01:
|
||||
{
|
||||
EHPrint(" ^ \n");
|
||||
EHPrint(" | \n");
|
||||
EHPrint(" %ld\n", SelCode.Idx);
|
||||
break;
|
||||
}
|
||||
case 0b10:
|
||||
{
|
||||
EHPrint(" ^ \n");
|
||||
EHPrint(" | \n");
|
||||
EHPrint(" %ld\n", SelCode.Idx);
|
||||
break;
|
||||
}
|
||||
case 0b11:
|
||||
{
|
||||
EHPrint(" ^ \n");
|
||||
EHPrint(" | \n");
|
||||
EHPrint(" %ld\n", SelCode.Idx);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
EHPrint(" ? \n");
|
||||
EHPrint(" ? \n");
|
||||
EHPrint(" %ld\n", SelCode.Idx);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CPU::x86::GeneralProtectionFault:
|
||||
{
|
||||
EHPrint("Exception: General Protection Fault\n");
|
||||
EHPrint("Kernel performed an illegal operation.\n");
|
||||
CPU::x64::SelectorErrorCode SelCode = {.raw = Frame->ErrorCode};
|
||||
EHPrint("External? %s\n", SelCode.External ? "Yes" : "No");
|
||||
EHPrint("GDT IDT LDT IDT\n");
|
||||
switch (SelCode.Table)
|
||||
{
|
||||
case 0b00:
|
||||
{
|
||||
EHPrint(" ^ \n");
|
||||
EHPrint(" | \n");
|
||||
EHPrint(" %ld\n", SelCode.Idx);
|
||||
break;
|
||||
}
|
||||
case 0b01:
|
||||
{
|
||||
EHPrint(" ^ \n");
|
||||
EHPrint(" | \n");
|
||||
EHPrint(" %ld\n", SelCode.Idx);
|
||||
break;
|
||||
}
|
||||
case 0b10:
|
||||
{
|
||||
EHPrint(" ^ \n");
|
||||
EHPrint(" | \n");
|
||||
EHPrint(" %ld\n", SelCode.Idx);
|
||||
break;
|
||||
}
|
||||
case 0b11:
|
||||
{
|
||||
EHPrint(" ^ \n");
|
||||
EHPrint(" | \n");
|
||||
EHPrint(" %ld\n", SelCode.Idx);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
EHPrint(" ? \n");
|
||||
EHPrint(" ? \n");
|
||||
EHPrint(" %ld\n", SelCode.Idx);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CPU::x86::PageFault:
|
||||
{
|
||||
EHPrint("Exception: Page Fault\n");
|
||||
EHPrint("The processor attempted to access a page that is not present/accessible.\n");
|
||||
switch (Frame->InterruptNumber)
|
||||
{
|
||||
case CPU::x86::DivideByZero:
|
||||
{
|
||||
EHPrint("Exception: Divide By Zero\n");
|
||||
EHPrint("The processor attempted to divide a number by zero.\n");
|
||||
break;
|
||||
}
|
||||
case CPU::x86::Debug:
|
||||
{
|
||||
EHPrint("Exception: Debug\n");
|
||||
EHPrint("A debug exception has occurred.\n");
|
||||
break;
|
||||
}
|
||||
case CPU::x86::NonMaskableInterrupt:
|
||||
{
|
||||
EHPrint("Exception: Non-Maskable Interrupt\n");
|
||||
EHPrint("A non-maskable interrupt was received.\n");
|
||||
break;
|
||||
}
|
||||
case CPU::x86::Breakpoint:
|
||||
{
|
||||
EHPrint("Exception: Breakpoint\n");
|
||||
EHPrint("The processor encountered a breakpoint.\n");
|
||||
break;
|
||||
}
|
||||
case CPU::x86::Overflow:
|
||||
{
|
||||
EHPrint("Exception: Overflow\n");
|
||||
EHPrint("The processor attempted to add a number to a number that was too large.\n");
|
||||
break;
|
||||
}
|
||||
case CPU::x86::BoundRange:
|
||||
{
|
||||
EHPrint("Exception: Bound Range\n");
|
||||
EHPrint("The processor attempted to access an array element that is out of bounds.\n");
|
||||
break;
|
||||
}
|
||||
case CPU::x86::InvalidOpcode:
|
||||
{
|
||||
EHPrint("Exception: Invalid Opcode\n");
|
||||
EHPrint("The processor attempted to execute an invalid opcode.\n");
|
||||
break;
|
||||
}
|
||||
case CPU::x86::DeviceNotAvailable:
|
||||
{
|
||||
EHPrint("Exception: Device Not Available\n");
|
||||
EHPrint("The processor attempted to use a device that is not available.\n");
|
||||
break;
|
||||
}
|
||||
case CPU::x86::DoubleFault:
|
||||
{
|
||||
EHPrint("Exception: Double Fault\n");
|
||||
EHPrint("The processor encountered a double fault.\n");
|
||||
break;
|
||||
}
|
||||
case CPU::x86::CoprocessorSegmentOverrun:
|
||||
{
|
||||
EHPrint("Exception: Coprocessor Segment Overrun\n");
|
||||
EHPrint("The processor attempted to access a segment that is not available.\n");
|
||||
break;
|
||||
}
|
||||
case CPU::x86::InvalidTSS:
|
||||
{
|
||||
EHPrint("Exception: Invalid TSS\n");
|
||||
EHPrint("The processor attempted to access a task state segment that is not available or valid.\n");
|
||||
CPU::x64::SelectorErrorCode SelCode = {.raw = Frame->ErrorCode};
|
||||
EHPrint("External? %s\n", SelCode.External ? "Yes" : "No");
|
||||
EHPrint("GDT IDT LDT IDT\n");
|
||||
switch (SelCode.Table)
|
||||
{
|
||||
case 0b00:
|
||||
{
|
||||
EHPrint(" ^ \n");
|
||||
EHPrint(" | \n");
|
||||
EHPrint(" %ld\n", SelCode.Idx);
|
||||
break;
|
||||
}
|
||||
case 0b01:
|
||||
{
|
||||
EHPrint(" ^ \n");
|
||||
EHPrint(" | \n");
|
||||
EHPrint(" %ld\n", SelCode.Idx);
|
||||
break;
|
||||
}
|
||||
case 0b10:
|
||||
{
|
||||
EHPrint(" ^ \n");
|
||||
EHPrint(" | \n");
|
||||
EHPrint(" %ld\n", SelCode.Idx);
|
||||
break;
|
||||
}
|
||||
case 0b11:
|
||||
{
|
||||
EHPrint(" ^ \n");
|
||||
EHPrint(" | \n");
|
||||
EHPrint(" %ld\n", SelCode.Idx);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
EHPrint(" ? \n");
|
||||
EHPrint(" ? \n");
|
||||
EHPrint(" %ld\n", SelCode.Idx);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CPU::x86::SegmentNotPresent:
|
||||
{
|
||||
EHPrint("Exception: Segment Not Present\n");
|
||||
EHPrint("The processor attempted to access a segment that is not present.\n");
|
||||
CPU::x64::SelectorErrorCode SelCode = {.raw = Frame->ErrorCode};
|
||||
EHPrint("External? %s\n", SelCode.External ? "Yes" : "No");
|
||||
EHPrint("GDT IDT LDT IDT\n");
|
||||
switch (SelCode.Table)
|
||||
{
|
||||
case 0b00:
|
||||
{
|
||||
EHPrint(" ^ \n");
|
||||
EHPrint(" | \n");
|
||||
EHPrint(" %ld\n", SelCode.Idx);
|
||||
break;
|
||||
}
|
||||
case 0b01:
|
||||
{
|
||||
EHPrint(" ^ \n");
|
||||
EHPrint(" | \n");
|
||||
EHPrint(" %ld\n", SelCode.Idx);
|
||||
break;
|
||||
}
|
||||
case 0b10:
|
||||
{
|
||||
EHPrint(" ^ \n");
|
||||
EHPrint(" | \n");
|
||||
EHPrint(" %ld\n", SelCode.Idx);
|
||||
break;
|
||||
}
|
||||
case 0b11:
|
||||
{
|
||||
EHPrint(" ^ \n");
|
||||
EHPrint(" | \n");
|
||||
EHPrint(" %ld\n", SelCode.Idx);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
EHPrint(" ? \n");
|
||||
EHPrint(" ? \n");
|
||||
EHPrint(" %ld\n", SelCode.Idx);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CPU::x86::StackSegmentFault:
|
||||
{
|
||||
EHPrint("Exception: Stack Segment Fault\n");
|
||||
CPU::x64::SelectorErrorCode SelCode = {.raw = Frame->ErrorCode};
|
||||
EHPrint("External? %s\n", SelCode.External ? "Yes" : "No");
|
||||
EHPrint("GDT IDT LDT IDT\n");
|
||||
switch (SelCode.Table)
|
||||
{
|
||||
case 0b00:
|
||||
{
|
||||
EHPrint(" ^ \n");
|
||||
EHPrint(" | \n");
|
||||
EHPrint(" %ld\n", SelCode.Idx);
|
||||
break;
|
||||
}
|
||||
case 0b01:
|
||||
{
|
||||
EHPrint(" ^ \n");
|
||||
EHPrint(" | \n");
|
||||
EHPrint(" %ld\n", SelCode.Idx);
|
||||
break;
|
||||
}
|
||||
case 0b10:
|
||||
{
|
||||
EHPrint(" ^ \n");
|
||||
EHPrint(" | \n");
|
||||
EHPrint(" %ld\n", SelCode.Idx);
|
||||
break;
|
||||
}
|
||||
case 0b11:
|
||||
{
|
||||
EHPrint(" ^ \n");
|
||||
EHPrint(" | \n");
|
||||
EHPrint(" %ld\n", SelCode.Idx);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
EHPrint(" ? \n");
|
||||
EHPrint(" ? \n");
|
||||
EHPrint(" %ld\n", SelCode.Idx);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CPU::x86::GeneralProtectionFault:
|
||||
{
|
||||
EHPrint("Exception: General Protection Fault\n");
|
||||
EHPrint("Kernel performed an illegal operation.\n");
|
||||
CPU::x64::SelectorErrorCode SelCode = {.raw = Frame->ErrorCode};
|
||||
EHPrint("External? %s\n", SelCode.External ? "Yes" : "No");
|
||||
EHPrint("GDT IDT LDT IDT\n");
|
||||
switch (SelCode.Table)
|
||||
{
|
||||
case 0b00:
|
||||
{
|
||||
EHPrint(" ^ \n");
|
||||
EHPrint(" | \n");
|
||||
EHPrint(" %ld\n", SelCode.Idx);
|
||||
break;
|
||||
}
|
||||
case 0b01:
|
||||
{
|
||||
EHPrint(" ^ \n");
|
||||
EHPrint(" | \n");
|
||||
EHPrint(" %ld\n", SelCode.Idx);
|
||||
break;
|
||||
}
|
||||
case 0b10:
|
||||
{
|
||||
EHPrint(" ^ \n");
|
||||
EHPrint(" | \n");
|
||||
EHPrint(" %ld\n", SelCode.Idx);
|
||||
break;
|
||||
}
|
||||
case 0b11:
|
||||
{
|
||||
EHPrint(" ^ \n");
|
||||
EHPrint(" | \n");
|
||||
EHPrint(" %ld\n", SelCode.Idx);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
EHPrint(" ? \n");
|
||||
EHPrint(" ? \n");
|
||||
EHPrint(" %ld\n", SelCode.Idx);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CPU::x86::PageFault:
|
||||
{
|
||||
EHPrint("Exception: Page Fault\n");
|
||||
EHPrint("The processor attempted to access a page that is not present/accessible.\n");
|
||||
|
||||
CPU::x64::PageFaultErrorCode params = {.raw = (uint32_t)Frame->ErrorCode};
|
||||
CPU::x64::PageFaultErrorCode params = {.raw = (uint32_t)Frame->ErrorCode};
|
||||
#if defined(a64)
|
||||
EHPrint("At \e8888FF%#lx \eFAFAFAby \e8888FF%#lx\eFAFAFA\n", PageFaultAddress, Frame->rip);
|
||||
EHPrint("At \e8888FF%#lx \eFAFAFAby \e8888FF%#lx\eFAFAFA\n", PageFaultAddress, Frame->rip);
|
||||
#elif defined(a32)
|
||||
EHPrint("At \e8888FF%#lx \eFAFAFAby \e8888FF%#lx\eFAFAFA\n", PageFaultAddress, Frame->eip);
|
||||
EHPrint("At \e8888FF%#lx \eFAFAFAby \e8888FF%#lx\eFAFAFA\n", PageFaultAddress, Frame->eip);
|
||||
#elif defined(aa64)
|
||||
#endif
|
||||
EHPrint("Page: %s\eFAFAFA\n", params.P ? "\e058C19Present" : "\eE85230Not Present");
|
||||
EHPrint("Write Operation: \e8888FF%s\eFAFAFA\n", params.W ? "Read-Only" : "Read-Write");
|
||||
EHPrint("Processor Mode: \e8888FF%s\eFAFAFA\n", params.U ? "User-Mode" : "Kernel-Mode");
|
||||
EHPrint("CPU Reserved Bits: %s\eFAFAFA\n", params.R ? "\eE85230Reserved" : "\e058C19Unreserved");
|
||||
EHPrint("Caused By An Instruction Fetch: %s\eFAFAFA\n", params.I ? "\eE85230Yes" : "\e058C19No");
|
||||
EHPrint("Caused By A Protection-Key Violation: %s\eFAFAFA\n", params.PK ? "\eE85230Yes" : "\e058C19No");
|
||||
EHPrint("Caused By A Shadow Stack Access: %s\eFAFAFA\n", params.SS ? "\eE85230Yes" : "\e058C19No");
|
||||
EHPrint("Caused By An SGX Violation: %s\eFAFAFA\n", params.SGX ? "\eE85230Yes" : "\e058C19No");
|
||||
EHPrint("More Info: \e8888FF");
|
||||
if (Frame->ErrorCode & 0x00000008)
|
||||
EHPrint("One or more page directory entries contain reserved bits which are set to 1.\n");
|
||||
else
|
||||
EHPrint(PagefaultDescriptions[Frame->ErrorCode & 0b111]);
|
||||
EHPrint("\eFAFAFA");
|
||||
break;
|
||||
}
|
||||
case CPU::x86::x87FloatingPoint:
|
||||
{
|
||||
EHPrint("Exception: x87 Floating Point\n");
|
||||
EHPrint("The x87 FPU generated an error.\n");
|
||||
break;
|
||||
}
|
||||
case CPU::x86::AlignmentCheck:
|
||||
{
|
||||
EHPrint("Exception: Alignment Check\n");
|
||||
EHPrint("The CPU detected an unaligned memory access.\n");
|
||||
break;
|
||||
}
|
||||
case CPU::x86::MachineCheck:
|
||||
{
|
||||
EHPrint("Exception: Machine Check\n");
|
||||
EHPrint("The CPU detected a hardware error.\n");
|
||||
break;
|
||||
}
|
||||
case CPU::x86::SIMDFloatingPoint:
|
||||
{
|
||||
EHPrint("Exception: SIMD Floating Point\n");
|
||||
EHPrint("The CPU detected an error in the SIMD unit.\n");
|
||||
break;
|
||||
}
|
||||
case CPU::x86::Virtualization:
|
||||
{
|
||||
EHPrint("Exception: Virtualization\n");
|
||||
EHPrint("The CPU detected a virtualization error.\n");
|
||||
break;
|
||||
}
|
||||
case CPU::x86::Security:
|
||||
{
|
||||
EHPrint("Exception: Security\n");
|
||||
EHPrint("The CPU detected a security violation.\n");
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
EHPrint("Exception: Unknown\n");
|
||||
EHPrint("The CPU generated an unknown exception.\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
EHPrint("Page: %s\eFAFAFA\n", params.P ? "\e058C19Present" : "\eE85230Not Present");
|
||||
EHPrint("Write Operation: \e8888FF%s\eFAFAFA\n", params.W ? "Read-Only" : "Read-Write");
|
||||
EHPrint("Processor Mode: \e8888FF%s\eFAFAFA\n", params.U ? "User-Mode" : "Kernel-Mode");
|
||||
EHPrint("CPU Reserved Bits: %s\eFAFAFA\n", params.R ? "\eE85230Reserved" : "\e058C19Unreserved");
|
||||
EHPrint("Caused By An Instruction Fetch: %s\eFAFAFA\n", params.I ? "\eE85230Yes" : "\e058C19No");
|
||||
EHPrint("Caused By A Protection-Key Violation: %s\eFAFAFA\n", params.PK ? "\eE85230Yes" : "\e058C19No");
|
||||
EHPrint("Caused By A Shadow Stack Access: %s\eFAFAFA\n", params.SS ? "\eE85230Yes" : "\e058C19No");
|
||||
EHPrint("Caused By An SGX Violation: %s\eFAFAFA\n", params.SGX ? "\eE85230Yes" : "\e058C19No");
|
||||
EHPrint("More Info: \e8888FF");
|
||||
if (Frame->ErrorCode & 0x00000008)
|
||||
EHPrint("One or more page directory entries contain reserved bits which are set to 1.\n");
|
||||
else
|
||||
EHPrint(PagefaultDescriptions[Frame->ErrorCode & 0b111]);
|
||||
EHPrint("\eFAFAFA");
|
||||
break;
|
||||
}
|
||||
case CPU::x86::x87FloatingPoint:
|
||||
{
|
||||
EHPrint("Exception: x87 Floating Point\n");
|
||||
EHPrint("The x87 FPU generated an error.\n");
|
||||
break;
|
||||
}
|
||||
case CPU::x86::AlignmentCheck:
|
||||
{
|
||||
EHPrint("Exception: Alignment Check\n");
|
||||
EHPrint("The CPU detected an unaligned memory access.\n");
|
||||
break;
|
||||
}
|
||||
case CPU::x86::MachineCheck:
|
||||
{
|
||||
EHPrint("Exception: Machine Check\n");
|
||||
EHPrint("The CPU detected a hardware error.\n");
|
||||
break;
|
||||
}
|
||||
case CPU::x86::SIMDFloatingPoint:
|
||||
{
|
||||
EHPrint("Exception: SIMD Floating Point\n");
|
||||
EHPrint("The CPU detected an error in the SIMD unit.\n");
|
||||
break;
|
||||
}
|
||||
case CPU::x86::Virtualization:
|
||||
{
|
||||
EHPrint("Exception: Virtualization\n");
|
||||
EHPrint("The CPU detected a virtualization error.\n");
|
||||
break;
|
||||
}
|
||||
case CPU::x86::Security:
|
||||
{
|
||||
EHPrint("Exception: Security\n");
|
||||
EHPrint("The CPU detected a security violation.\n");
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
EHPrint("Exception: Unknown\n");
|
||||
EHPrint("The CPU generated an unknown exception.\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(a64)
|
||||
EHPrint("The exception happened at \e8888FF%#lx\eFAFAFA\n", Frame->rip);
|
||||
EHPrint("The exception happened at \e8888FF%#lx\eFAFAFA\n", Frame->rip);
|
||||
#elif defined(a32)
|
||||
EHPrint("The exception happened at \e8888FF%#lx\eFAFAFA\n", Frame->eip);
|
||||
EHPrint("The exception happened at \e8888FF%#lx\eFAFAFA\n", Frame->eip);
|
||||
#elif defined(aa64)
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -35,65 +35,44 @@
|
||||
|
||||
namespace CrashHandler
|
||||
{
|
||||
SafeFunction void DisplayStackFrameScreen(CRData data)
|
||||
{
|
||||
EHPrint("\eFAFAFATracing 10 frames...");
|
||||
TraceFrames(data, 10, KernelSymbolTable, true);
|
||||
if (data.Process)
|
||||
{
|
||||
EHPrint("\n\eFAFAFATracing 10 process frames...");
|
||||
SymbolResolver::Symbols *sh = data.Process->ELFSymbolTable;
|
||||
if (!sh)
|
||||
EHPrint("\n\eFF0000< No symbol table available. >\n");
|
||||
else
|
||||
TraceFrames(data, 10, sh, false);
|
||||
}
|
||||
EHPrint("\n\eFAFAFATracing interrupt frames...");
|
||||
for (short i = 0; i < 8; i++)
|
||||
{
|
||||
if (EHIntFrames[i])
|
||||
{
|
||||
if (!Memory::Virtual().Check(EHIntFrames[i]))
|
||||
continue;
|
||||
EHPrint("\n\e2565CC%p", EHIntFrames[i]);
|
||||
EHPrint("\e7925CC-");
|
||||
SafeFunction void DisplayStackFrameScreen(CRData data)
|
||||
{
|
||||
EHPrint("\eFAFAFATracing 10 frames...");
|
||||
TraceFrames(data, 10, KernelSymbolTable, true);
|
||||
if (data.Process)
|
||||
{
|
||||
EHPrint("\n\eFAFAFATracing 10 process frames...");
|
||||
SymbolResolver::Symbols *pSt = data.Process->ELFSymbolTable;
|
||||
debug("pSt = %#lx", pSt);
|
||||
if (!pSt || !pSt->SymTableExists)
|
||||
EHPrint("\n\eFF0000< No symbol table available. >\n");
|
||||
else
|
||||
TraceFrames(data, 10, pSt, false);
|
||||
}
|
||||
EHPrint("\n\eFAFAFATracing interrupt frames...");
|
||||
for (short i = 0; i < 8; i++)
|
||||
{
|
||||
if (EHIntFrames[i])
|
||||
{
|
||||
if (!Memory::Virtual().Check(EHIntFrames[i]))
|
||||
continue;
|
||||
EHPrint("\n\e2565CC%p", EHIntFrames[i]);
|
||||
EHPrint("\e7925CC-");
|
||||
#if defined(a64)
|
||||
if ((uintptr_t)EHIntFrames[i] >= 0xFFFFFFFF80000000 && (uintptr_t)EHIntFrames[i] <= (uintptr_t)&_kernel_end)
|
||||
if ((uintptr_t)EHIntFrames[i] >= 0xFFFFFFFF80000000 &&
|
||||
(uintptr_t)EHIntFrames[i] <= (uintptr_t)&_kernel_end)
|
||||
#elif defined(a32)
|
||||
if ((uintptr_t)EHIntFrames[i] >= 0xC0000000 && (uintptr_t)EHIntFrames[i] <= (uintptr_t)&_kernel_end)
|
||||
if ((uintptr_t)EHIntFrames[i] >= 0xC0000000 &&
|
||||
(uintptr_t)EHIntFrames[i] <= (uintptr_t)&_kernel_end)
|
||||
#elif defined(aa64)
|
||||
if ((uintptr_t)EHIntFrames[i] >= 0xFFFFFFFF80000000 && (uintptr_t)EHIntFrames[i] <= (uintptr_t)&_kernel_end)
|
||||
if ((uintptr_t)EHIntFrames[i] >= 0xFFFFFFFF80000000 &&
|
||||
(uintptr_t)EHIntFrames[i] <= (uintptr_t)&_kernel_end)
|
||||
#endif
|
||||
EHPrint("\e25CCC9%s", KernelSymbolTable->GetSymbolFromAddress((uintptr_t)EHIntFrames[i]));
|
||||
else
|
||||
EHPrint("\eFF4CA9Outside Kernel");
|
||||
}
|
||||
}
|
||||
if (data.Process && data.Thread)
|
||||
{
|
||||
EHPrint("\n\n\eFAFAFATracing thread instruction pointer history...");
|
||||
SymbolResolver::Symbols *sh = data.Process->ELFSymbolTable;
|
||||
if (!sh)
|
||||
EHPrint("\n\eFFA500Warning: No symbol table available.");
|
||||
int SameItr = 0;
|
||||
uintptr_t LastRIP = 0;
|
||||
for (size_t i = 0; i < sizeof(data.Thread->IPHistory) / sizeof(data.Thread->IPHistory[0]); i++)
|
||||
{
|
||||
if (data.Thread->IPHistory[i] == LastRIP)
|
||||
{
|
||||
SameItr++;
|
||||
if (SameItr > 2)
|
||||
continue;
|
||||
}
|
||||
else
|
||||
SameItr = 0;
|
||||
LastRIP = data.Thread->IPHistory[i];
|
||||
if (!sh)
|
||||
EHPrint("\n\eCCCCCC%d: \e2565CC%p", i, data.Thread->IPHistory[i]);
|
||||
else
|
||||
EHPrint("\n\eCCCCCC%d: \e2565CC%p\e7925CC-\e25CCC9%s", i, data.Thread->IPHistory[i], sh->GetSymbolFromAddress(data.Thread->IPHistory[i]));
|
||||
}
|
||||
EHPrint("\n\e7925CCNote: \e2565CCSame instruction pointers are not shown more than 3 times.\n");
|
||||
}
|
||||
}
|
||||
EHPrint("\e25CCC9%s",
|
||||
KernelSymbolTable->GetSymbol((uintptr_t)EHIntFrames[i]));
|
||||
else
|
||||
EHPrint("\eFF4CA9Outside Kernel");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,18 +1,18 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
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 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.
|
||||
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/>.
|
||||
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 "../../crashhandler.hpp"
|
||||
@ -34,64 +34,66 @@
|
||||
|
||||
namespace CrashHandler
|
||||
{
|
||||
SafeFunction void DisplayTasksScreen(CRData data)
|
||||
{
|
||||
const char *StatusColor[9] = {
|
||||
"FF0000", // Unknown
|
||||
"AAFF00", // Ready
|
||||
"00AA00", // Running
|
||||
"FFAA00", // Sleeping
|
||||
"FFAA00", // Blocked
|
||||
"FFAA00", // Stopped
|
||||
"FFAA00", // Waiting
|
||||
SafeFunction void DisplayTasksScreen(CRData data)
|
||||
{
|
||||
const char *StatusColor[] = {
|
||||
"FF0000", // Unknown
|
||||
"AAFF00", // Ready
|
||||
"00AA00", // Running
|
||||
"FFAA00", // Sleeping
|
||||
"FFAA00", // Blocked
|
||||
"FFAA00", // Stopped
|
||||
"FFAA00", // Waiting
|
||||
|
||||
"FF0088", // Zombie
|
||||
"FF0000", // Terminated
|
||||
};
|
||||
"FF00FF", // Core dump
|
||||
"FF0088", // Zombie
|
||||
"FF0000", // Terminated
|
||||
};
|
||||
|
||||
const char *StatusString[9] = {
|
||||
"Unknown", // Unknown
|
||||
"Ready", // Ready
|
||||
"Running", // Running
|
||||
"Sleeping", // Sleeping
|
||||
"Blocked", // Blocked
|
||||
"Stopped", // Stopped
|
||||
"Waiting", // Waiting
|
||||
const char *StatusString[] = {
|
||||
"Unknown", // Unknown
|
||||
"Ready", // Ready
|
||||
"Running", // Running
|
||||
"Sleeping", // Sleeping
|
||||
"Blocked", // Blocked
|
||||
"Stopped", // Stopped
|
||||
"Waiting", // Waiting
|
||||
|
||||
"Zombie", // Zombie
|
||||
"Terminated", // Terminated
|
||||
};
|
||||
"CoreDump", // Core dump
|
||||
"Zombie", // Zombie
|
||||
"Terminated", // Terminated
|
||||
};
|
||||
|
||||
if (TaskManager)
|
||||
{
|
||||
std::vector<Tasking::PCB *> Plist = TaskManager->GetProcessList();
|
||||
if (TaskManager)
|
||||
{
|
||||
std::list<Tasking::PCB *> Plist = TaskManager->GetProcessList();
|
||||
|
||||
if (data.Thread)
|
||||
if (data.Thread)
|
||||
#if defined(a64)
|
||||
EHPrint("\eFAFAFACrash occurred in thread \eAA0F0F%s\eFAFAFA(%ld) at \e00AAAA%#lx\n",
|
||||
data.Thread->Name, data.Thread->ID, data.Frame->rip);
|
||||
EHPrint("\eFAFAFACrash occurred in thread \eAA0F0F%s\eFAFAFA(%ld) at \e00AAAA%#lx\n",
|
||||
data.Thread->Name, data.Thread->ID, data.Frame->rip);
|
||||
#elif defined(a32)
|
||||
EHPrint("\eFAFAFACrash occurred in thread \eAA0F0F%s\eFAFAFA(%ld) at \e00AAAA%#lx\n",
|
||||
data.Thread->Name, data.Thread->ID, data.Frame->eip);
|
||||
EHPrint("\eFAFAFACrash occurred in thread \eAA0F0F%s\eFAFAFA(%ld) at \e00AAAA%#lx\n",
|
||||
data.Thread->Name, data.Thread->ID, data.Frame->eip);
|
||||
#elif defined(aa64)
|
||||
#endif
|
||||
|
||||
EHPrint("\eFAFAFAProcess list (%ld):\n", Plist.size());
|
||||
foreach (auto Process in Plist)
|
||||
{
|
||||
EHPrint("\e%s-> \eFAFAFA%s\eCCCCCC(%ld) \e00AAAA%s\eFAFAFA PT:\e00AAAA%#lx\n",
|
||||
StatusColor[Process->State.load()], Process->Name,
|
||||
Process->ID, StatusString[Process->State.load()],
|
||||
Process->PageTable);
|
||||
EHPrint("\eFAFAFAProcess list (%ld):\n", Plist.size());
|
||||
foreach (auto Process in Plist)
|
||||
{
|
||||
EHPrint("\e%s-> \eFAFAFA%s\eCCCCCC(%ld) \e00AAAA%s\eFAFAFA PT:\e00AAAA%#lx\n",
|
||||
StatusColor[Process->State.load()], Process->Name,
|
||||
Process->ID, StatusString[Process->State.load()],
|
||||
Process->PageTable);
|
||||
|
||||
foreach (auto Thread in Process->Threads)
|
||||
EHPrint("\e%s -> \eFAFAFA%s\eCCCCCC(%ld) \e00AAAA%s\eFAFAFA Stack:\e00AAAA%#lx\n",
|
||||
StatusColor[Thread->State.load()], Thread->Name,
|
||||
Thread->ID, StatusString[Thread->State.load()],
|
||||
Thread->Stack);
|
||||
}
|
||||
}
|
||||
else
|
||||
EHPrint("\eFAFAFATaskManager is not initialized!\n");
|
||||
}
|
||||
foreach (auto Thread in Process->Threads)
|
||||
EHPrint("\e%s -> \eFAFAFA%s\eCCCCCC(%ld) \e00AAAA%s\eFAFAFA Stack:\e00AAAA%#lx\n",
|
||||
StatusColor[Thread->State.load()], Thread->Name,
|
||||
Thread->ID, StatusString[Thread->State.load()],
|
||||
Thread->Stack);
|
||||
}
|
||||
}
|
||||
else
|
||||
EHPrint("\eFAFAFATaskManager is not initialized!\n");
|
||||
}
|
||||
}
|
||||
|
@ -32,117 +32,144 @@
|
||||
|
||||
#include "../../kernel.h"
|
||||
|
||||
#define AddrToStr(addr) SymHandle->GetSymbol(addr)
|
||||
|
||||
namespace CrashHandler
|
||||
{
|
||||
struct StackFrame
|
||||
{
|
||||
struct StackFrame *rbp;
|
||||
uintptr_t rip;
|
||||
};
|
||||
struct StackFrame
|
||||
{
|
||||
struct StackFrame *rbp;
|
||||
uintptr_t rip;
|
||||
};
|
||||
|
||||
SafeFunction void TraceFrames(CRData data, int Count, SymbolResolver::Symbols *SymHandle, bool Kernel)
|
||||
{
|
||||
if (!Memory::Virtual().Check(data.Frame))
|
||||
{
|
||||
EHPrint("Invalid frame pointer: %p\n", data.Frame);
|
||||
return;
|
||||
}
|
||||
SafeFunction void TraceFrames(CRData data, int Count,
|
||||
SymbolResolver::Symbols *SymHandle,
|
||||
bool Kernel)
|
||||
{
|
||||
Memory::Virtual vmm;
|
||||
|
||||
if (!Memory::Virtual().Check(SymHandle))
|
||||
{
|
||||
EHPrint("Invalid symbol handle: %p\n", SymHandle);
|
||||
return;
|
||||
}
|
||||
if (!vmm.Check(data.Frame))
|
||||
{
|
||||
EHPrint("Invalid frame pointer: %p\n", data.Frame);
|
||||
return;
|
||||
}
|
||||
|
||||
bool TriedRetryBP = false;
|
||||
struct StackFrame *frames = nullptr;
|
||||
RetryBP:
|
||||
#if defined(a64)
|
||||
if (TriedRetryBP == false)
|
||||
frames = (struct StackFrame *)data.Frame->rbp;
|
||||
#elif defined(a32)
|
||||
if (TriedRetryBP == false)
|
||||
frames = (struct StackFrame *)data.Frame->ebp;
|
||||
#elif defined(aa64)
|
||||
#endif
|
||||
if (!Memory::Virtual().Check((void *)frames))
|
||||
{
|
||||
if (TriedRetryBP == false)
|
||||
{
|
||||
frames = (struct StackFrame *)Memory::Virtual(data.Process->PageTable).GetPhysical((void *)frames);
|
||||
TriedRetryBP = true;
|
||||
goto RetryBP;
|
||||
}
|
||||
#if defined(a64)
|
||||
EHPrint("Invalid rbp pointer: %p\n", data.Frame->rbp);
|
||||
#elif defined(a32)
|
||||
EHPrint("Invalid ebp pointer: %p\n", data.Frame->ebp);
|
||||
#elif defined(aa64)
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
if (!vmm.Check(SymHandle))
|
||||
{
|
||||
EHPrint("Invalid symbol handle: %p\n", SymHandle);
|
||||
return;
|
||||
}
|
||||
|
||||
debug("\nStack tracing... %p %d %p %d", data.Frame, Count, frames, Kernel);
|
||||
EHPrint("\e7981FC\nStack Trace:\n");
|
||||
if (!frames || !frames->rip || !frames->rbp)
|
||||
{
|
||||
bool TriedRetryBP = false;
|
||||
struct StackFrame *frames = nullptr;
|
||||
RetryBP:
|
||||
#if defined(a64)
|
||||
EHPrint("\e2565CC%p", (void *)data.Frame->rip);
|
||||
if (TriedRetryBP == false)
|
||||
frames = (struct StackFrame *)data.Frame->rbp;
|
||||
#elif defined(a32)
|
||||
EHPrint("\e2565CC%p", (void *)data.Frame->eip);
|
||||
if (TriedRetryBP == false)
|
||||
frames = (struct StackFrame *)data.Frame->ebp;
|
||||
#elif defined(aa64)
|
||||
#endif
|
||||
EHPrint("\e7925CC-");
|
||||
if (!vmm.Check((void *)frames))
|
||||
{
|
||||
if (TriedRetryBP == false)
|
||||
{
|
||||
Memory::Virtual vma(data.Process->PageTable);
|
||||
debug("Invalid frame pointer: %p", frames);
|
||||
frames = (struct StackFrame *)data.Process->PageTable->Get((void *)frames);
|
||||
debug("Physical frame pointer: %p", frames);
|
||||
TriedRetryBP = true;
|
||||
goto RetryBP;
|
||||
}
|
||||
#if defined(a64)
|
||||
EHPrint("\eAA25CC%s", SymHandle->GetSymbolFromAddress(data.Frame->rip));
|
||||
EHPrint("Invalid rbp pointer: %p\n", data.Frame->rbp);
|
||||
#elif defined(a32)
|
||||
EHPrint("\eAA25CC%s", SymHandle->GetSymbolFromAddress(data.Frame->eip));
|
||||
EHPrint("Invalid ebp pointer: %p\n", data.Frame->ebp);
|
||||
#elif defined(aa64)
|
||||
#endif
|
||||
EHPrint("\e7981FC <- Exception");
|
||||
EHPrint("\eFF0000\n< No stack trace available. >\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
#if defined(a64)
|
||||
EHPrint("\e2565CC%p", (void *)data.Frame->rip);
|
||||
EHPrint("\e7925CC-");
|
||||
if ((data.Frame->rip >= 0xFFFFFFFF80000000 && data.Frame->rip <= (uintptr_t)&_kernel_end) || !Kernel)
|
||||
EHPrint("\eAA25CC%s", SymHandle->GetSymbolFromAddress(data.Frame->rip));
|
||||
else
|
||||
EHPrint("Outside Kernel");
|
||||
#elif defined(a32)
|
||||
EHPrint("\e2565CC%p", (void *)data.Frame->eip);
|
||||
EHPrint("\e7925CC-");
|
||||
if ((data.Frame->eip >= 0xC0000000 && data.Frame->eip <= (uintptr_t)&_kernel_end) || !Kernel)
|
||||
EHPrint("\eAA25CC%s", SymHandle->GetSymbolFromAddress(data.Frame->eip));
|
||||
else
|
||||
EHPrint("Outside Kernel");
|
||||
#elif defined(aa64)
|
||||
#endif
|
||||
EHPrint("\e7981FC <- Exception");
|
||||
for (int frame = 0; frame < Count; ++frame)
|
||||
{
|
||||
if (!frames->rip)
|
||||
break;
|
||||
EHPrint("\n\e2565CC%p", (void *)frames->rip);
|
||||
EHPrint("\e7925CC-");
|
||||
#if defined(a64)
|
||||
if ((frames->rip >= 0xFFFFFFFF80000000 && frames->rip <= (uintptr_t)&_kernel_end) || !Kernel)
|
||||
#elif defined(a32)
|
||||
if ((frames->rip >= 0xC0000000 && frames->rip <= (uintptr_t)&_kernel_end) || !Kernel)
|
||||
#elif defined(aa64)
|
||||
if ((frames->rip >= 0xFFFFFFFF80000000 && frames->rip <= (uintptr_t)&_kernel_end) || !Kernel)
|
||||
#endif
|
||||
EHPrint("\e25CCC9%s", SymHandle->GetSymbolFromAddress(frames->rip));
|
||||
else
|
||||
EHPrint("\eFF4CA9Outside Kernel");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Memory::Virtual().Check(frames->rbp))
|
||||
return;
|
||||
frames = frames->rbp;
|
||||
}
|
||||
}
|
||||
EHPrint("\n");
|
||||
}
|
||||
debug("Stack tracing... %p %d %p %d",
|
||||
data.Frame, Count, frames, Kernel);
|
||||
EHPrint("\e7981FC\nStack Trace:\n");
|
||||
if (!frames || !frames->rip || !frames->rbp)
|
||||
{
|
||||
#if defined(a64)
|
||||
EHPrint("\e2565CC%p", (void *)data.Frame->rip);
|
||||
#elif defined(a32)
|
||||
EHPrint("\e2565CC%p", (void *)data.Frame->eip);
|
||||
#elif defined(aa64)
|
||||
#endif
|
||||
EHPrint("\e7925CC-");
|
||||
#if defined(a64)
|
||||
EHPrint("\eAA25CC%s", AddrToStr(data.Frame->rip));
|
||||
#elif defined(a32)
|
||||
EHPrint("\eAA25CC%s", AddrToStr(data.Frame->eip));
|
||||
#elif defined(aa64)
|
||||
#endif
|
||||
EHPrint("\e7981FC <- Exception");
|
||||
EHPrint("\eFF0000\n< No stack trace available. >\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
#if defined(a64)
|
||||
debug("Exception in function %s(%p)",
|
||||
AddrToStr(data.Frame->rip),
|
||||
data.Frame->rip);
|
||||
EHPrint("\e2565CC%p", (void *)data.Frame->rip);
|
||||
EHPrint("\e7925CC-");
|
||||
if ((data.Frame->rip >= 0xFFFFFFFF80000000 &&
|
||||
data.Frame->rip <= (uintptr_t)&_kernel_end) ||
|
||||
Kernel == false)
|
||||
{
|
||||
EHPrint("\eAA25CC%s", AddrToStr(data.Frame->rip));
|
||||
}
|
||||
else
|
||||
EHPrint("Outside Kernel");
|
||||
#elif defined(a32)
|
||||
EHPrint("\e2565CC%p", (void *)data.Frame->eip);
|
||||
EHPrint("\e7925CC-");
|
||||
if ((data.Frame->eip >= 0xC0000000 &&
|
||||
data.Frame->eip <= (uintptr_t)&_kernel_end) ||
|
||||
Kernel == false)
|
||||
{
|
||||
EHPrint("\eAA25CC%s", AddrToStr(data.Frame->eip));
|
||||
}
|
||||
else
|
||||
EHPrint("Outside Kernel");
|
||||
#elif defined(aa64)
|
||||
#endif
|
||||
EHPrint("\e7981FC <- Exception");
|
||||
for (int frame = 0; frame < Count; ++frame)
|
||||
{
|
||||
if (!frames->rip)
|
||||
break;
|
||||
EHPrint("\n\e2565CC%p", (void *)frames->rip);
|
||||
EHPrint("\e7925CC-");
|
||||
#if defined(a64)
|
||||
if ((frames->rip >= 0xFFFFFFFF80000000 &&
|
||||
frames->rip <= (uintptr_t)&_kernel_end) ||
|
||||
Kernel == false)
|
||||
#elif defined(a32)
|
||||
if ((frames->rip >= 0xC0000000 &&
|
||||
frames->rip <= (uintptr_t)&_kernel_end) ||
|
||||
Kernel == false)
|
||||
#elif defined(aa64)
|
||||
if ((frames->rip >= 0xFFFFFFFF80000000 &&
|
||||
frames->rip <= (uintptr_t)&_kernel_end) ||
|
||||
Kernel == false)
|
||||
#endif
|
||||
EHPrint("\e25CCC9%s", AddrToStr(frames->rip));
|
||||
else
|
||||
EHPrint("\eFF4CA9Outside Kernel");
|
||||
|
||||
if (!vmm.Check(frames->rbp))
|
||||
return;
|
||||
frames = frames->rbp;
|
||||
}
|
||||
}
|
||||
EHPrint("\n");
|
||||
}
|
||||
}
|
||||
|
@ -34,8 +34,12 @@
|
||||
|
||||
SafeFunction bool UserModeExceptionHandler(CHArchTrapFrame *Frame)
|
||||
{
|
||||
thisThread->State = Tasking::TaskState::Waiting;
|
||||
CPUData *CurCPU = GetCurrentCPU();
|
||||
Tasking::PCB *CurProc = CurCPU->CurrentProcess;
|
||||
Tasking::TCB *CurThread = CurCPU->CurrentThread;
|
||||
debug("Current process %s(%d) and thread %s(%d)",
|
||||
CurProc->Name, CurProc->ID, CurThread->Name, CurThread->ID);
|
||||
CurThread->SetState(Tasking::Waiting);
|
||||
|
||||
#ifdef DEBUG
|
||||
{
|
||||
@ -153,37 +157,59 @@ SafeFunction bool UserModeExceptionHandler(CHArchTrapFrame *Frame)
|
||||
{
|
||||
bool Handled = false;
|
||||
|
||||
Handled = CurCPU->CurrentProcess->vma->HandleCoW(CrashHandler::PageFaultAddress);
|
||||
Handled = CurProc->vma->HandleCoW(CrashHandler::PageFaultAddress);
|
||||
if (!Handled)
|
||||
Handled = CurCPU->CurrentThread->Stack->Expand(CrashHandler::PageFaultAddress);
|
||||
Handled = CurThread->Stack->Expand(CrashHandler::PageFaultAddress);
|
||||
|
||||
if (Handled)
|
||||
{
|
||||
debug("Page fault handled");
|
||||
thisThread->State = Tasking::TaskState::Ready;
|
||||
CurThread->SetState(Tasking::Ready);
|
||||
return true;
|
||||
}
|
||||
|
||||
CurProc->Signals->SendSignal(SIGSEGV,
|
||||
{Tasking::KILL_CRASH});
|
||||
break;
|
||||
}
|
||||
case CPU::x86::Debug:
|
||||
case CPU::x86::Breakpoint:
|
||||
{
|
||||
CurProc->Signals->SendSignal(SIGTRAP,
|
||||
{Tasking::KILL_CRASH});
|
||||
break;
|
||||
}
|
||||
case CPU::x86::DivideByZero:
|
||||
case CPU::x86::Debug:
|
||||
case CPU::x86::NonMaskableInterrupt:
|
||||
case CPU::x86::Breakpoint:
|
||||
case CPU::x86::Overflow:
|
||||
case CPU::x86::BoundRange:
|
||||
case CPU::x86::x87FloatingPoint:
|
||||
case CPU::x86::SIMDFloatingPoint:
|
||||
{
|
||||
CurProc->Signals->SendSignal(SIGFPE,
|
||||
{Tasking::KILL_CRASH});
|
||||
break;
|
||||
}
|
||||
case CPU::x86::InvalidOpcode:
|
||||
case CPU::x86::GeneralProtectionFault:
|
||||
{
|
||||
CurProc->Signals->SendSignal(SIGILL,
|
||||
{Tasking::KILL_CRASH});
|
||||
break;
|
||||
}
|
||||
case CPU::x86::DeviceNotAvailable:
|
||||
{
|
||||
CurProc->Signals->SendSignal(SIGBUS,
|
||||
{Tasking::KILL_CRASH});
|
||||
break;
|
||||
}
|
||||
case CPU::x86::NonMaskableInterrupt:
|
||||
case CPU::x86::DoubleFault:
|
||||
case CPU::x86::CoprocessorSegmentOverrun:
|
||||
case CPU::x86::InvalidTSS:
|
||||
case CPU::x86::SegmentNotPresent:
|
||||
case CPU::x86::StackSegmentFault:
|
||||
case CPU::x86::GeneralProtectionFault:
|
||||
case CPU::x86::x87FloatingPoint:
|
||||
case CPU::x86::AlignmentCheck:
|
||||
case CPU::x86::MachineCheck:
|
||||
case CPU::x86::SIMDFloatingPoint:
|
||||
case CPU::x86::Virtualization:
|
||||
case CPU::x86::Security:
|
||||
default:
|
||||
|
@ -25,11 +25,11 @@
|
||||
|
||||
namespace CrashHandler
|
||||
{
|
||||
extern uintptr_t PageFaultAddress;
|
||||
extern void *EHIntFrames[INT_FRAMES_MAX];
|
||||
extern uintptr_t PageFaultAddress;
|
||||
extern void *EHIntFrames[INT_FRAMES_MAX];
|
||||
|
||||
void EHPrint(const char *Format, ...);
|
||||
void Handle(void *Data);
|
||||
void EHPrint(const char *Format, ...);
|
||||
void Handle(void *Data);
|
||||
}
|
||||
|
||||
#endif // !__FENNIX_KERNEL_CRASH_HANDLER_H__
|
||||
|
@ -21,11 +21,13 @@
|
||||
#include <lock.hpp>
|
||||
#include <io.h>
|
||||
|
||||
#include "../kernel.h"
|
||||
|
||||
NewLock(DebuggerLock);
|
||||
|
||||
extern bool serialports[8];
|
||||
|
||||
static inline NIF void uart_wrapper(char c, void *unused)
|
||||
EXTERNC NIF void uart_wrapper(char c, void *unused)
|
||||
{
|
||||
static int once = 0;
|
||||
if (unlikely(!once++))
|
||||
|
@ -21,18 +21,17 @@
|
||||
#include <printf.h>
|
||||
|
||||
#include "../kernel.h"
|
||||
#include "../mapi.hpp"
|
||||
#include "../Fex.hpp"
|
||||
|
||||
namespace Disk
|
||||
{
|
||||
void Manager::FetchDisks(unsigned long modUniqueID)
|
||||
{
|
||||
KernelCallback callback{};
|
||||
callback.Reason = QueryReason;
|
||||
ModuleManager->IOCB(modUniqueID, &callback);
|
||||
this->AvailablePorts = callback.DiskCallback.Fetch.Ports;
|
||||
this->BytesPerSector = callback.DiskCallback.Fetch.BytesPerSector;
|
||||
/* KernelCallback */
|
||||
// KernelCallback callback{};
|
||||
// callback.Reason = QueryReason;
|
||||
// DriverManager->IOCB(modUniqueID, &callback);
|
||||
// this->AvailablePorts = callback.DiskCallback.Fetch.Ports;
|
||||
// this->BytesPerSector = callback.DiskCallback.Fetch.BytesPerSector;
|
||||
debug("AvailablePorts:%ld BytesPerSector:%ld", this->AvailablePorts, this->BytesPerSector);
|
||||
|
||||
if (this->AvailablePorts <= 0)
|
||||
@ -49,15 +48,16 @@ namespace Disk
|
||||
drive->MechanicalDisk = true;
|
||||
|
||||
memset(RWBuffer, 0, this->BytesPerSector);
|
||||
callback.Reason = ReceiveReason;
|
||||
callback.DiskCallback.RW = {
|
||||
.Sector = 0,
|
||||
.SectorCount = 2,
|
||||
.Port = ItrPort,
|
||||
.Buffer = RWBuffer,
|
||||
.Write = false,
|
||||
};
|
||||
ModuleManager->IOCB(modUniqueID, &callback);
|
||||
/* KernelCallback */
|
||||
// callback.Reason = ReceiveReason;
|
||||
// callback.DiskCallback.RW = {
|
||||
// .Sector = 0,
|
||||
// .SectorCount = 2,
|
||||
// .Port = ItrPort,
|
||||
// .Buffer = RWBuffer,
|
||||
// .Write = false,
|
||||
// };
|
||||
// DriverManager->IOCB(modUniqueID, &callback);
|
||||
memcpy(&drive->Table, RWBuffer, sizeof(PartitionTable));
|
||||
|
||||
/*
|
||||
@ -72,15 +72,16 @@ namespace Disk
|
||||
for (uint32_t Block = 0; Block < Sectors; Block++)
|
||||
{
|
||||
memset(RWBuffer, 0, this->BytesPerSector);
|
||||
callback.Reason = ReceiveReason;
|
||||
callback.DiskCallback.RW = {
|
||||
.Sector = 2 + Block,
|
||||
.SectorCount = 1,
|
||||
.Port = ItrPort,
|
||||
.Buffer = RWBuffer,
|
||||
.Write = false,
|
||||
};
|
||||
ModuleManager->IOCB(modUniqueID, &callback);
|
||||
/* KernelCallback */
|
||||
// callback.Reason = ReceiveReason;
|
||||
// callback.DiskCallback.RW = {
|
||||
// .Sector = 2 + Block,
|
||||
// .SectorCount = 1,
|
||||
// .Port = ItrPort,
|
||||
// .Buffer = RWBuffer,
|
||||
// .Write = false,
|
||||
// };
|
||||
// DriverManager->IOCB(modUniqueID, &callback);
|
||||
|
||||
for (uint32_t e = 0; e < Entries; e++)
|
||||
{
|
||||
|
939
core/driver/api.cpp
Normal file
939
core/driver/api.cpp
Normal file
@ -0,0 +1,939 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <driver.hpp>
|
||||
|
||||
#include "../../kernel.h"
|
||||
#include "../../driver.h"
|
||||
|
||||
// #define DEBUG_API
|
||||
|
||||
#ifdef DEBUG_API
|
||||
#define dbg_api(Format, ...) function(Format, ##__VA_ARGS__)
|
||||
#else
|
||||
#define dbg_api(Format, ...)
|
||||
#endif
|
||||
|
||||
using enum PCI::PCICommands;
|
||||
|
||||
#define VMWARE_MAGIC 0x564D5868 /* hXMV */
|
||||
#define VMWARE_PORT 0x5658
|
||||
#define CMD_GETVERSION 0xA
|
||||
|
||||
namespace Driver
|
||||
{
|
||||
int RegisterFunction(dev_t MajorID, void *Function, __driverRegFunc Type)
|
||||
{
|
||||
dbg_api("%d, %#lx, %d", MajorID, (uintptr_t)Function, Type);
|
||||
|
||||
std::unordered_map<dev_t, DriverObject> &Drivers =
|
||||
DriverManager->GetDrivers();
|
||||
|
||||
auto itr = Drivers.find(MajorID);
|
||||
if (itr == Drivers.end())
|
||||
return -EINVAL;
|
||||
|
||||
DriverObject *drv = &itr->second;
|
||||
|
||||
switch (Type)
|
||||
{
|
||||
case _drf_Entry:
|
||||
drv->Entry = (int (*)())Function;
|
||||
debug("Entry %#lx for %s", (uintptr_t)Function, drv->Path);
|
||||
break;
|
||||
case _drf_Final:
|
||||
drv->Final = (int (*)())Function;
|
||||
debug("Finalize %#lx for %s", (uintptr_t)Function, drv->Path);
|
||||
break;
|
||||
case _drf_Panic:
|
||||
drv->Panic = (int (*)())Function;
|
||||
debug("Panic %#lx for %s", (uintptr_t)Function, drv->Path);
|
||||
break;
|
||||
case _drf_Probe:
|
||||
drv->Probe = (int (*)())Function;
|
||||
debug("Probe %#lx for %s", (uintptr_t)Function, drv->Path);
|
||||
break;
|
||||
default:
|
||||
assert(!"Invalid driver function type");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int GetDriverInfo(dev_t MajorID, const char *Name, const char *Description, const char *Author, const char *Version, const char *License)
|
||||
{
|
||||
dbg_api("%d, %s, %s, %s, %s, %s", MajorID, Name, Description, Author, Version, License);
|
||||
|
||||
std::unordered_map<dev_t, DriverObject> &Drivers =
|
||||
DriverManager->GetDrivers();
|
||||
|
||||
auto itr = Drivers.find(MajorID);
|
||||
if (itr == Drivers.end())
|
||||
return -EINVAL;
|
||||
|
||||
DriverObject *drv = &itr->second;
|
||||
|
||||
strncpy(drv->Name, Name, sizeof(drv->Name));
|
||||
strncpy(drv->Description, Description, sizeof(drv->Description));
|
||||
strncpy(drv->Author, Author, sizeof(drv->Author));
|
||||
strncpy(drv->Version, Version, sizeof(drv->Version));
|
||||
strncpy(drv->License, License, sizeof(drv->License));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* --------- */
|
||||
|
||||
int RegisterInterruptHandler(dev_t MajorID, uint8_t IRQ, void *Handler)
|
||||
{
|
||||
dbg_api("%d, %d, %#lx", MajorID, IRQ, Handler);
|
||||
|
||||
std::unordered_map<dev_t, DriverObject> &Drivers =
|
||||
DriverManager->GetDrivers();
|
||||
|
||||
auto itr = Drivers.find(MajorID);
|
||||
if (itr == Drivers.end())
|
||||
return -EINVAL;
|
||||
|
||||
DriverObject *drv = &itr->second;
|
||||
|
||||
if (drv->InterruptHandlers->contains(IRQ))
|
||||
return -EEXIST;
|
||||
|
||||
Interrupts::AddHandler((void (*)(CPU::TrapFrame *))Handler, IRQ);
|
||||
drv->InterruptHandlers->insert(std::pair<uint8_t, void *>(IRQ, Handler));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int OverrideInterruptHandler(dev_t MajorID, uint8_t IRQ, void *Handler)
|
||||
{
|
||||
dbg_api("%d, %d, %#lx", MajorID, IRQ, Handler);
|
||||
|
||||
debug("Overriding IRQ %d with %#lx", IRQ, Handler);
|
||||
|
||||
std::unordered_map<dev_t, DriverObject> &Drivers =
|
||||
DriverManager->GetDrivers();
|
||||
|
||||
foreach (auto &var in Drivers)
|
||||
{
|
||||
DriverObject *drv = &var.second;
|
||||
|
||||
foreach (auto &ih in * drv->InterruptHandlers)
|
||||
{
|
||||
if (ih.first == IRQ)
|
||||
{
|
||||
debug("Removing IRQ %d: %#lx for %s", IRQ, (uintptr_t)ih.second, drv->Path);
|
||||
Interrupts::RemoveHandler((void (*)(CPU::TrapFrame *))ih.second, IRQ);
|
||||
drv->InterruptHandlers->erase(IRQ);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return RegisterInterruptHandler(MajorID, IRQ, Handler);
|
||||
}
|
||||
|
||||
int UnregisterInterruptHandler(dev_t MajorID, uint8_t IRQ, void *Handler)
|
||||
{
|
||||
dbg_api("%d, %d, %#lx", MajorID, IRQ, Handler);
|
||||
|
||||
std::unordered_map<dev_t, DriverObject> &Drivers =
|
||||
DriverManager->GetDrivers();
|
||||
|
||||
auto itr = Drivers.find(MajorID);
|
||||
if (itr == Drivers.end())
|
||||
return -EINVAL;
|
||||
|
||||
DriverObject *drv = &itr->second;
|
||||
Interrupts::RemoveHandler((void (*)(CPU::TrapFrame *))Handler, IRQ);
|
||||
drv->InterruptHandlers->erase(IRQ);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int UnregisterAllInterruptHandlers(dev_t MajorID, void *Handler)
|
||||
{
|
||||
dbg_api("%d, %#lx", MajorID, Handler);
|
||||
|
||||
std::unordered_map<dev_t, DriverObject> &Drivers =
|
||||
DriverManager->GetDrivers();
|
||||
|
||||
auto itr = Drivers.find(MajorID);
|
||||
if (itr == Drivers.end())
|
||||
return -EINVAL;
|
||||
|
||||
DriverObject *drv = &itr->second;
|
||||
foreach (auto &i in * drv->InterruptHandlers)
|
||||
{
|
||||
Interrupts::RemoveHandler((void (*)(CPU::TrapFrame *))Handler, i.first);
|
||||
debug("Removed IRQ %d: %#lx for %s", i.first, (uintptr_t)Handler, drv->Path);
|
||||
}
|
||||
drv->InterruptHandlers->clear();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* --------- */
|
||||
|
||||
dev_t RegisterInputDevice(dev_t MajorID, DeviceDriverType Type)
|
||||
{
|
||||
dbg_api("%d, %d", MajorID, Type);
|
||||
|
||||
switch (Type)
|
||||
{
|
||||
case ddt_Keyboard:
|
||||
return DriverManager->InputKeyboardDev->Register(MajorID);
|
||||
case ddt_Mouse:
|
||||
return DriverManager->InputMouseDev->Register(MajorID);
|
||||
/* ... */
|
||||
default:
|
||||
assert(!"Invalid input device type");
|
||||
}
|
||||
}
|
||||
|
||||
int UnregisterInputDevice(dev_t MajorID, dev_t MinorID, DeviceDriverType Type)
|
||||
{
|
||||
dbg_api("%d, %d, %d", MajorID, MinorID, Type);
|
||||
|
||||
switch (Type)
|
||||
{
|
||||
case ddt_Keyboard:
|
||||
return DriverManager->InputKeyboardDev->Unregister(MajorID, MinorID);
|
||||
case ddt_Mouse:
|
||||
return DriverManager->InputMouseDev->Unregister(MajorID, MinorID);
|
||||
/* ... */
|
||||
default:
|
||||
assert(!"Invalid input device type");
|
||||
}
|
||||
}
|
||||
|
||||
int ReportKeyboardEvent(dev_t MajorID, dev_t MinorID, uint8_t ScanCode)
|
||||
{
|
||||
dbg_api("%d, %d, %d", MajorID, MinorID, ScanCode);
|
||||
|
||||
return DriverManager->InputKeyboardDev->ReportKeyEvent(MajorID, MinorID, ScanCode);
|
||||
}
|
||||
|
||||
int ReportRelativeMouseEvent(dev_t MajorID, dev_t MinorID, __MouseButtons Button, int X, int Y, int8_t Z)
|
||||
{
|
||||
dbg_api("%d, %d, %d, %d, %d, %d", MajorID, MinorID, Button, X, Y, Z);
|
||||
|
||||
return DriverManager->InputMouseDev->ReportMouseEvent(MajorID, MinorID,
|
||||
Button.LeftButton, Button.RightButton, Button.MiddleButton,
|
||||
Button.Button4, Button.Button5, Button.Button6, Button.Button7, Button.Button8,
|
||||
X, Y, Z, true);
|
||||
}
|
||||
|
||||
int ReportAbsoluteMouseEvent(dev_t MajorID, dev_t MinorID, __MouseButtons Button, uintptr_t X, uintptr_t Y, int8_t Z)
|
||||
{
|
||||
dbg_api("%d, %d, %d, %d, %d, %d", MajorID, MinorID, Button, X, Y, Z);
|
||||
|
||||
return DriverManager->InputMouseDev->ReportMouseEvent(MajorID, MinorID,
|
||||
Button.LeftButton, Button.RightButton, Button.MiddleButton,
|
||||
Button.Button4, Button.Button5, Button.Button6, Button.Button7, Button.Button8,
|
||||
X, Y, Z, false);
|
||||
}
|
||||
|
||||
/* --------- */
|
||||
|
||||
dev_t RegisterBlockDevice(dev_t MajorID, DeviceDriverType Type, void *Open, void *Close, void *Read, void *Write, void *Ioctl)
|
||||
{
|
||||
dbg_api("%d, %d, %#lx, %#lx, %#lx, %#lx, %#lx", MajorID, Type, Open, Close, Read, Write, Ioctl);
|
||||
|
||||
switch (Type)
|
||||
{
|
||||
case ddt_SATA:
|
||||
{
|
||||
dev_t ret = DriverManager->BlockSATADev->Register(MajorID);
|
||||
DriverManager->BlockSATADev->NewBlock(MajorID, ret,
|
||||
(SlaveDeviceFile::drvOpen_t)Open,
|
||||
(SlaveDeviceFile::drvClose_t)Close,
|
||||
(SlaveDeviceFile::drvRead_t)Read,
|
||||
(SlaveDeviceFile::drvWrite_t)Write,
|
||||
(SlaveDeviceFile::drvIoctl_t)Ioctl);
|
||||
return ret;
|
||||
}
|
||||
case ddt_ATA:
|
||||
{
|
||||
dev_t ret = DriverManager->BlockHDDev->Register(MajorID);
|
||||
DriverManager->BlockHDDev->NewBlock(MajorID, ret,
|
||||
(SlaveDeviceFile::drvOpen_t)Open,
|
||||
(SlaveDeviceFile::drvClose_t)Close,
|
||||
(SlaveDeviceFile::drvRead_t)Read,
|
||||
(SlaveDeviceFile::drvWrite_t)Write,
|
||||
(SlaveDeviceFile::drvIoctl_t)Ioctl);
|
||||
return ret;
|
||||
}
|
||||
case ddt_NVMe:
|
||||
{
|
||||
dev_t ret = DriverManager->BlockNVMeDev->Register(MajorID);
|
||||
DriverManager->BlockNVMeDev->NewBlock(MajorID, ret,
|
||||
(SlaveDeviceFile::drvOpen_t)Open,
|
||||
(SlaveDeviceFile::drvClose_t)Close,
|
||||
(SlaveDeviceFile::drvRead_t)Read,
|
||||
(SlaveDeviceFile::drvWrite_t)Write,
|
||||
(SlaveDeviceFile::drvIoctl_t)Ioctl);
|
||||
return ret;
|
||||
}
|
||||
/* ... */
|
||||
default:
|
||||
assert(!"Invalid storage device type");
|
||||
}
|
||||
}
|
||||
|
||||
int UnregisterBlockDevice(dev_t MajorID, dev_t MinorID, DeviceDriverType Type)
|
||||
{
|
||||
dbg_api("%d, %d, %d", MajorID, MinorID, Type);
|
||||
|
||||
switch (Type)
|
||||
{
|
||||
case ddt_SATA:
|
||||
return DriverManager->BlockSATADev->Unregister(MajorID, MinorID);
|
||||
case ddt_ATA:
|
||||
return DriverManager->BlockHDDev->Unregister(MajorID, MinorID);
|
||||
case ddt_NVMe:
|
||||
return DriverManager->BlockNVMeDev->Unregister(MajorID, MinorID);
|
||||
/* ... */
|
||||
default:
|
||||
assert(!"Invalid storage device type");
|
||||
}
|
||||
}
|
||||
|
||||
/* --------- */
|
||||
|
||||
dev_t RegisterAudioDevice(dev_t MajorID, DeviceDriverType Type, void *Open, void *Close, void *Read, void *Write, void *Ioctl)
|
||||
{
|
||||
dbg_api("%d, %d, %#lx, %#lx, %#lx, %#lx, %#lx", MajorID, Type, Open, Close, Read, Write, Ioctl);
|
||||
|
||||
switch (Type)
|
||||
{
|
||||
case ddt_Audio:
|
||||
{
|
||||
dev_t ret = DriverManager->AudioDev->Register(MajorID);
|
||||
DriverManager->AudioDev->NewAudio(MajorID, ret,
|
||||
(SlaveDeviceFile::drvOpen_t)Open,
|
||||
(SlaveDeviceFile::drvClose_t)Close,
|
||||
(SlaveDeviceFile::drvRead_t)Read,
|
||||
(SlaveDeviceFile::drvWrite_t)Write,
|
||||
(SlaveDeviceFile::drvIoctl_t)Ioctl);
|
||||
return ret;
|
||||
}
|
||||
/* ... */
|
||||
default:
|
||||
assert(!"Invalid audio device type");
|
||||
}
|
||||
}
|
||||
|
||||
int UnregisterAudioDevice(dev_t MajorID, dev_t MinorID, DeviceDriverType Type)
|
||||
{
|
||||
dbg_api("%d, %d, %d", MajorID, MinorID, Type);
|
||||
|
||||
switch (Type)
|
||||
{
|
||||
case ddt_Audio:
|
||||
return DriverManager->AudioDev->Unregister(MajorID, MinorID);
|
||||
/* ... */
|
||||
default:
|
||||
assert(!"Invalid audio device type");
|
||||
}
|
||||
}
|
||||
|
||||
/* --------- */
|
||||
|
||||
dev_t RegisterNetDevice(dev_t MajorID, DeviceDriverType Type, void *Open, void *Close, void *Read, void *Write, void *Ioctl)
|
||||
{
|
||||
dbg_api("%d, %d, %#lx, %#lx, %#lx, %#lx, %#lx", MajorID, Type, Open, Close, Read, Write, Ioctl);
|
||||
|
||||
switch (Type)
|
||||
{
|
||||
case ddt_Network:
|
||||
{
|
||||
dev_t ret = DriverManager->NetDev->Register(MajorID);
|
||||
DriverManager->NetDev->NewNet(MajorID, ret,
|
||||
(SlaveDeviceFile::drvOpen_t)Open,
|
||||
(SlaveDeviceFile::drvClose_t)Close,
|
||||
(SlaveDeviceFile::drvRead_t)Read,
|
||||
(SlaveDeviceFile::drvWrite_t)Write,
|
||||
(SlaveDeviceFile::drvIoctl_t)Ioctl);
|
||||
return ret;
|
||||
}
|
||||
/* ... */
|
||||
default:
|
||||
assert(!"Invalid audio device type");
|
||||
}
|
||||
}
|
||||
|
||||
int UnregisterNetDevice(dev_t MajorID, dev_t MinorID, DeviceDriverType Type)
|
||||
{
|
||||
dbg_api("%d, %d, %d", MajorID, MinorID, Type);
|
||||
|
||||
switch (Type)
|
||||
{
|
||||
case ddt_Network:
|
||||
return DriverManager->NetDev->Unregister(MajorID, MinorID);
|
||||
/* ... */
|
||||
default:
|
||||
assert(!"Invalid audio device type");
|
||||
}
|
||||
}
|
||||
|
||||
int ReportNetworkPacket(dev_t MajorID, dev_t MinorID, void *Buffer, size_t Size)
|
||||
{
|
||||
dbg_api("%d, %d, %#lx, %d", MajorID, MinorID, Buffer, Size);
|
||||
|
||||
return DriverManager->NetDev->ReportNetworkPacket(MajorID, MinorID, Buffer, Size);
|
||||
}
|
||||
|
||||
/* --------- */
|
||||
|
||||
void d_KPrint(dev_t MajorID, const char *Format, va_list args)
|
||||
{
|
||||
dbg_api("%d %s, %#lx", MajorID, Format, args);
|
||||
|
||||
_KPrint(Format, args);
|
||||
}
|
||||
|
||||
void KernelLog(dev_t MajorID, const char *Format, va_list args)
|
||||
{
|
||||
dbg_api("%d, %s, %#lx", MajorID, Format, args);
|
||||
|
||||
fctprintf(uart_wrapper, nullptr, "DRVER| %ld: ", MajorID);
|
||||
vfctprintf(uart_wrapper, nullptr, Format, args);
|
||||
uart_wrapper('\n', nullptr);
|
||||
}
|
||||
|
||||
/* --------- */
|
||||
|
||||
void *RequestPages(dev_t MajorID, size_t Pages)
|
||||
{
|
||||
dbg_api("%d, %d", MajorID, Pages);
|
||||
|
||||
std::unordered_map<dev_t, DriverObject> &Drivers =
|
||||
DriverManager->GetDrivers();
|
||||
auto itr = Drivers.find(MajorID);
|
||||
assert(itr != Drivers.end());
|
||||
|
||||
return itr->second.vma->RequestPages(Pages);
|
||||
}
|
||||
|
||||
void FreePages(dev_t MajorID, void *Pointer, size_t Pages)
|
||||
{
|
||||
dbg_api("%d, %#lx, %d", MajorID, Pointer, Pages);
|
||||
|
||||
std::unordered_map<dev_t, DriverObject> &Drivers =
|
||||
DriverManager->GetDrivers();
|
||||
|
||||
auto itr = Drivers.find(MajorID);
|
||||
assert(itr != Drivers.end());
|
||||
|
||||
itr->second.vma->FreePages(Pointer, Pages);
|
||||
}
|
||||
|
||||
/* --------- */
|
||||
|
||||
void AppendMapFlag(dev_t MajorID, void *Address, PageMapFlags Flag)
|
||||
{
|
||||
dbg_api("%d, %#lx, %d", MajorID, Address, Flag);
|
||||
|
||||
Memory::Virtual vmm(KernelPageTable);
|
||||
vmm.GetPTE(Address)->raw |= Flag;
|
||||
}
|
||||
|
||||
void RemoveMapFlag(dev_t MajorID, void *Address, PageMapFlags Flag)
|
||||
{
|
||||
dbg_api("%d, %#lx, %d", MajorID, Address, Flag);
|
||||
|
||||
Memory::Virtual vmm(KernelPageTable);
|
||||
vmm.GetPTE(Address)->raw &= ~Flag;
|
||||
}
|
||||
|
||||
void MapPages(dev_t MajorID, void *PhysicalAddress, void *VirtualAddress, size_t Pages, uint32_t Flags)
|
||||
{
|
||||
dbg_api("%d, %#lx, %#lx, %d, %d", MajorID, PhysicalAddress, VirtualAddress, Pages, Flags);
|
||||
|
||||
Memory::Virtual vmm(KernelPageTable);
|
||||
vmm.Map(VirtualAddress, PhysicalAddress, Pages, Flags);
|
||||
}
|
||||
|
||||
void UnmapPages(dev_t MajorID, void *VirtualAddress, size_t Pages)
|
||||
{
|
||||
dbg_api("%d, %#lx, %d", MajorID, VirtualAddress, Pages);
|
||||
|
||||
Memory::Virtual vmm(KernelPageTable);
|
||||
vmm.Unmap(VirtualAddress, Pages);
|
||||
}
|
||||
|
||||
/* --------- */
|
||||
|
||||
pid_t CreateKernelProcess(dev_t MajorID, const char *Name)
|
||||
{
|
||||
dbg_api("%d, %s", MajorID, Name);
|
||||
|
||||
Tasking::PCB *pcb = TaskManager->CreateProcess(nullptr,
|
||||
Name, Tasking::System,
|
||||
nullptr, true, 0, 0);
|
||||
|
||||
return pcb->ID;
|
||||
}
|
||||
|
||||
pid_t CreateKernelThread(dev_t MajorID, pid_t pId, const char *Name, void *EntryPoint, void *Argument)
|
||||
{
|
||||
dbg_api("%d, %d, %s, %#lx, %#lx", MajorID, pId, Name, EntryPoint, Argument);
|
||||
|
||||
Tasking::PCB *parent = TaskManager->GetProcessByID(pId);
|
||||
if (!parent)
|
||||
return -EINVAL;
|
||||
|
||||
CriticalSection cs;
|
||||
Tasking::TCB *tcb = TaskManager->CreateThread(parent, (Tasking::IP)EntryPoint);
|
||||
if (Argument)
|
||||
tcb->SYSV_ABI_Call((uintptr_t)Argument);
|
||||
tcb->Rename(Name);
|
||||
return tcb->ID;
|
||||
}
|
||||
|
||||
int KillProcess(dev_t MajorID, pid_t pId, int ExitCode)
|
||||
{
|
||||
dbg_api("%d, %d, %d", MajorID, pId, ExitCode);
|
||||
|
||||
Tasking::PCB *pcb = TaskManager->GetProcessByID(pId);
|
||||
if (!pcb)
|
||||
return -EINVAL;
|
||||
TaskManager->KillProcess(pcb, (Tasking::KillCode)ExitCode);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int KillThread(dev_t MajorID, pid_t tId, int ExitCode)
|
||||
{
|
||||
dbg_api("%d, %d, %d", MajorID, tId, ExitCode);
|
||||
|
||||
Tasking::TCB *tcb = TaskManager->GetThreadByID(tId);
|
||||
if (!tcb)
|
||||
return -EINVAL;
|
||||
TaskManager->KillThread(tcb, (Tasking::KillCode)ExitCode);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Yield(dev_t MajorID)
|
||||
{
|
||||
dbg_api("%d", MajorID);
|
||||
|
||||
TaskManager->Yield();
|
||||
}
|
||||
|
||||
void Sleep(dev_t MajorID, uint64_t Milliseconds)
|
||||
{
|
||||
dbg_api("%d, %d", MajorID, Milliseconds);
|
||||
|
||||
TaskManager->Sleep(Milliseconds);
|
||||
}
|
||||
|
||||
/* --------- */
|
||||
|
||||
__PCIArray *GetPCIDevices(dev_t MajorID, uint16_t _Vendors[], uint16_t _Devices[])
|
||||
{
|
||||
dbg_api("%d, %#lx, %#lx", MajorID, _Vendors, _Devices);
|
||||
|
||||
std::unordered_map<dev_t, DriverObject> &Drivers =
|
||||
DriverManager->GetDrivers();
|
||||
|
||||
auto itr = Drivers.find(MajorID);
|
||||
if (itr == Drivers.end())
|
||||
return nullptr;
|
||||
|
||||
std::list<uint16_t> VendorIDs;
|
||||
for (int i = 0; _Vendors[i] != 0x0; i++)
|
||||
VendorIDs.push_back(_Vendors[i]);
|
||||
|
||||
std::list<uint16_t> DeviceIDs;
|
||||
for (int i = 0; _Devices[i] != 0x0; i++)
|
||||
DeviceIDs.push_back(_Devices[i]);
|
||||
|
||||
std::list<PCI::PCIDevice> Devices = PCIManager->FindPCIDevice(VendorIDs, DeviceIDs);
|
||||
if (Devices.empty())
|
||||
return nullptr;
|
||||
|
||||
Memory::VirtualMemoryArea *vma = itr->second.vma;
|
||||
__PCIArray *head = nullptr;
|
||||
__PCIArray *array = nullptr;
|
||||
|
||||
foreach (auto &dev in Devices)
|
||||
{
|
||||
/* TODO: optimize memory allocation */
|
||||
PCI::PCIDevice *dptr = (PCI::PCIDevice *)vma->RequestPages(TO_PAGES(sizeof(PCI::PCIDevice)));
|
||||
memcpy(dptr, &dev, sizeof(PCI::PCIDevice));
|
||||
|
||||
__PCIArray *newArray = (__PCIArray *)vma->RequestPages(TO_PAGES(sizeof(__PCIArray)));
|
||||
|
||||
if (unlikely(head == nullptr))
|
||||
{
|
||||
head = newArray;
|
||||
array = head;
|
||||
}
|
||||
else
|
||||
{
|
||||
array->Next = newArray;
|
||||
array = newArray;
|
||||
}
|
||||
|
||||
array->Device = dptr;
|
||||
array->Next = nullptr;
|
||||
|
||||
debug("Found %02x.%02x.%02x: %04x:%04x",
|
||||
dev.Bus, dev.Device, dev.Function,
|
||||
dev.Header->VendorID, dev.Header->DeviceID);
|
||||
}
|
||||
|
||||
return head;
|
||||
}
|
||||
|
||||
void InitializePCI(dev_t MajorID, void *_Header)
|
||||
{
|
||||
dbg_api("%d, %#lx", MajorID, _Header);
|
||||
|
||||
PCI::PCIDeviceHeader *Header = (PCI::PCIDeviceHeader *)_Header;
|
||||
|
||||
debug("Header Type: %d", Header->HeaderType);
|
||||
switch (Header->HeaderType)
|
||||
{
|
||||
case 128:
|
||||
warn("Unknown header type %d! Guessing PCI Header 0",
|
||||
Header->HeaderType);
|
||||
[[fallthrough]];
|
||||
case 0: /* PCI Header 0 */
|
||||
{
|
||||
PCI::PCIHeader0 *hdr0 = (PCI::PCIHeader0 *)Header;
|
||||
|
||||
uint32_t BAR[6];
|
||||
size_t BARsSize[6];
|
||||
|
||||
BAR[0] = hdr0->BAR0;
|
||||
BAR[1] = hdr0->BAR1;
|
||||
BAR[2] = hdr0->BAR2;
|
||||
BAR[3] = hdr0->BAR3;
|
||||
BAR[4] = hdr0->BAR4;
|
||||
BAR[5] = hdr0->BAR5;
|
||||
|
||||
debug("Type: %d; IOBase: %#lx; MemoryBase: %#lx",
|
||||
BAR[0] & 1, BAR[1] & (~3), BAR[0] & (~15));
|
||||
|
||||
/* BARs Size */
|
||||
for (short i = 0; i < 6; i++)
|
||||
{
|
||||
if (BAR[i] == 0)
|
||||
continue;
|
||||
|
||||
size_t size;
|
||||
if ((BAR[i] & 1) == 0) /* Memory Base */
|
||||
{
|
||||
hdr0->BAR0 = 0xFFFFFFFF;
|
||||
size = hdr0->BAR0;
|
||||
hdr0->BAR0 = BAR[i];
|
||||
BARsSize[i] = size & (~15);
|
||||
BARsSize[i] = ~BARsSize[i] + 1;
|
||||
BARsSize[i] = BARsSize[i] & 0xFFFFFFFF;
|
||||
debug("BAR%d %#lx size: %d",
|
||||
i, BAR[i], BARsSize[i]);
|
||||
}
|
||||
else if ((BAR[i] & 1) == 1) /* I/O Base */
|
||||
{
|
||||
hdr0->BAR1 = 0xFFFFFFFF;
|
||||
size = hdr0->BAR1;
|
||||
hdr0->BAR1 = BAR[i];
|
||||
BARsSize[i] = size & (~3);
|
||||
BARsSize[i] = ~BARsSize[i] + 1;
|
||||
BARsSize[i] = BARsSize[i] & 0xFFFF;
|
||||
debug("BAR%d %#lx size: %d",
|
||||
i, BAR[i], BARsSize[i]);
|
||||
}
|
||||
}
|
||||
|
||||
Memory::Virtual vmm(KernelPageTable);
|
||||
|
||||
/* Mapping the BARs */
|
||||
for (short i = 0; i < 6; i++)
|
||||
{
|
||||
if (BAR[i] == 0)
|
||||
continue;
|
||||
|
||||
if ((BAR[i] & 1) == 0) /* Memory Base */
|
||||
{
|
||||
uintptr_t BARBase = BAR[i] & (~15);
|
||||
size_t BARSize = BARsSize[i];
|
||||
|
||||
debug("Mapping BAR%d %#lx-%#lx",
|
||||
i, BARBase, BARBase + BARSize);
|
||||
|
||||
if (BARSize == 0)
|
||||
{
|
||||
warn("BAR%d size is zero!", i);
|
||||
BARSize++;
|
||||
}
|
||||
|
||||
vmm.Map((void *)BARBase, (void *)BARBase,
|
||||
BARSize, Memory::RW | Memory::PWT | Memory::PCD);
|
||||
}
|
||||
else if ((BAR[i] & 1) == 1) /* I/O Base */
|
||||
{
|
||||
uintptr_t BARBase = BAR[i] & (~3);
|
||||
size_t BARSize = BARsSize[i];
|
||||
|
||||
debug("Mapping BAR%d %#x-%#x",
|
||||
i, BARBase, BARBase + BARSize);
|
||||
|
||||
if (BARSize == 0)
|
||||
{
|
||||
warn("BAR%d size is zero!", i);
|
||||
BARSize++;
|
||||
}
|
||||
|
||||
vmm.Map((void *)BARBase, (void *)BARBase,
|
||||
BARSize, Memory::RW | Memory::PWT | Memory::PCD);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 1: /* PCI Header 1 (PCI-to-PCI Bridge) */
|
||||
{
|
||||
fixme("PCI Header 1 (PCI-to-PCI Bridge) not implemented yet");
|
||||
break;
|
||||
}
|
||||
case 2: /* PCI Header 2 (PCI-to-CardBus Bridge) */
|
||||
{
|
||||
fixme("PCI Header 2 (PCI-to-CardBus Bridge) not implemented yet");
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
error("Unknown header type %d", Header->HeaderType);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Header->Command |= PCI_COMMAND_MASTER |
|
||||
PCI_COMMAND_IO |
|
||||
PCI_COMMAND_MEMORY;
|
||||
Header->Command &= ~PCI_COMMAND_INTX_DISABLE;
|
||||
}
|
||||
|
||||
uint32_t GetBAR(dev_t MajorID, uint8_t i, void *_Header)
|
||||
{
|
||||
dbg_api("%d, %d, %#lx", MajorID, i, _Header);
|
||||
|
||||
PCI::PCIDeviceHeader *Header = (PCI::PCIDeviceHeader *)_Header;
|
||||
|
||||
switch (Header->HeaderType)
|
||||
{
|
||||
case 128:
|
||||
warn("Unknown header type %d! Guessing PCI Header 0",
|
||||
Header->HeaderType);
|
||||
[[fallthrough]];
|
||||
case 0: /* PCI Header 0 */
|
||||
{
|
||||
PCI::PCIHeader0 *hdr0 =
|
||||
(PCI::PCIHeader0 *)Header;
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
return hdr0->BAR0;
|
||||
case 1:
|
||||
return hdr0->BAR1;
|
||||
case 2:
|
||||
return hdr0->BAR2;
|
||||
case 3:
|
||||
return hdr0->BAR3;
|
||||
case 4:
|
||||
return hdr0->BAR4;
|
||||
case 5:
|
||||
return hdr0->BAR5;
|
||||
default:
|
||||
assert(!"Invalid BAR index");
|
||||
}
|
||||
}
|
||||
case 1: /* PCI Header 1 (PCI-to-PCI Bridge) */
|
||||
{
|
||||
PCI::PCIHeader1 *hdr1 =
|
||||
(PCI::PCIHeader1 *)Header;
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
return hdr1->BAR0;
|
||||
case 1:
|
||||
return hdr1->BAR1;
|
||||
default:
|
||||
assert(!"Invalid BAR index");
|
||||
}
|
||||
}
|
||||
case 2: /* PCI Header 2 (PCI-to-CardBus Bridge) */
|
||||
{
|
||||
assert(!"PCI-to-CardBus Bridge not supported");
|
||||
}
|
||||
default:
|
||||
assert(!"Invalid PCI header type");
|
||||
}
|
||||
}
|
||||
|
||||
/* --------- */
|
||||
|
||||
void *api__memcpy(dev_t MajorID, void *Destination, const void *Source, size_t Length)
|
||||
{
|
||||
dbg_api("%d, %#lx, %#lx, %d", MajorID, Destination, Source, Length);
|
||||
|
||||
return memcpy(Destination, Source, Length);
|
||||
}
|
||||
|
||||
void *api__memset(dev_t MajorID, void *Destination, int Value, size_t Length)
|
||||
{
|
||||
dbg_api("%d, %#lx, %d, %d", MajorID, Destination, Value, Length);
|
||||
|
||||
return memset(Destination, Value, Length);
|
||||
}
|
||||
|
||||
void *api__memmove(dev_t MajorID, void *Destination, const void *Source, size_t Length)
|
||||
{
|
||||
dbg_api("%d, %#lx, %#lx, %d", MajorID, Destination, Source, Length);
|
||||
|
||||
return memmove(Destination, Source, Length);
|
||||
}
|
||||
|
||||
int api__memcmp(dev_t MajorID, const void *Left, const void *Right, size_t Length)
|
||||
{
|
||||
dbg_api("%d, %#lx, %#lx, %d", MajorID, Left, Right, Length);
|
||||
|
||||
return memcmp(Left, Right, Length);
|
||||
}
|
||||
|
||||
size_t api__strlen(dev_t MajorID, const char *String)
|
||||
{
|
||||
dbg_api("%d, %s", MajorID, String);
|
||||
|
||||
return strlen(String);
|
||||
}
|
||||
|
||||
char *api__strcpy(dev_t MajorID, char *Destination, const char *Source)
|
||||
{
|
||||
dbg_api("%d, %#lx, %s", MajorID, Destination, Source);
|
||||
|
||||
return strcpy(Destination, Source);
|
||||
}
|
||||
|
||||
char *api__strcat(dev_t MajorID, char *Destination, const char *Source)
|
||||
{
|
||||
dbg_api("%d, %#lx, %s", MajorID, Destination, Source);
|
||||
|
||||
return strcat(Destination, Source);
|
||||
}
|
||||
|
||||
int api__strcmp(dev_t MajorID, const char *Left, const char *Right)
|
||||
{
|
||||
dbg_api("%d, %s, %s", MajorID, Left, Right);
|
||||
|
||||
return strcmp(Left, Right);
|
||||
}
|
||||
|
||||
int api__strncmp(dev_t MajorID, const char *Left, const char *Right, size_t Length)
|
||||
{
|
||||
dbg_api("%d, %s, %s, %d", MajorID, Left, Right, Length);
|
||||
|
||||
return strncmp(Left, Right, Length);
|
||||
}
|
||||
|
||||
char *api__strchr(dev_t MajorID, const char *String, int Character)
|
||||
{
|
||||
dbg_api("%d, %s, %d", MajorID, String, Character);
|
||||
|
||||
return strchr(String, Character);
|
||||
}
|
||||
|
||||
char *api__strrchr(dev_t MajorID, const char *String, int Character)
|
||||
{
|
||||
dbg_api("%d, %s, %d", MajorID, String, Character);
|
||||
|
||||
stub;
|
||||
return nullptr;
|
||||
// return strrchr(String, Character);
|
||||
}
|
||||
|
||||
char *api__strstr(dev_t MajorID, const char *Haystack, const char *Needle)
|
||||
{
|
||||
dbg_api("%d, %s, %s", MajorID, Haystack, Needle);
|
||||
|
||||
return strstr(Haystack, Needle);
|
||||
}
|
||||
|
||||
/* --------- */
|
||||
|
||||
void PopulateDriverAPI(void *API)
|
||||
{
|
||||
__driverAPI *api = (__driverAPI *)API;
|
||||
|
||||
api->RegisterFunction = RegisterFunction;
|
||||
api->GetDriverInfo = GetDriverInfo;
|
||||
|
||||
api->RegisterInterruptHandler = RegisterInterruptHandler;
|
||||
api->OverrideInterruptHandler = OverrideInterruptHandler;
|
||||
api->UnregisterInterruptHandler = UnregisterInterruptHandler;
|
||||
api->UnregisterAllInterruptHandlers = UnregisterAllInterruptHandlers;
|
||||
|
||||
api->RegisterInputDevice = RegisterInputDevice;
|
||||
api->UnregisterInputDevice = UnregisterInputDevice;
|
||||
api->ReportKeyboardEvent = ReportKeyboardEvent;
|
||||
api->ReportRelativeMouseEvent = ReportRelativeMouseEvent;
|
||||
api->ReportAbsoluteMouseEvent = ReportAbsoluteMouseEvent;
|
||||
|
||||
api->RegisterBlockDevice = RegisterBlockDevice;
|
||||
api->UnregisterBlockDevice = UnregisterBlockDevice;
|
||||
|
||||
api->RegisterAudioDevice = RegisterAudioDevice;
|
||||
api->UnregisterAudioDevice = UnregisterAudioDevice;
|
||||
|
||||
api->RegisterNetDevice = RegisterNetDevice;
|
||||
api->UnregisterNetDevice = UnregisterNetDevice;
|
||||
api->ReportNetworkPacket = ReportNetworkPacket;
|
||||
|
||||
api->KPrint = d_KPrint;
|
||||
api->KernelLog = KernelLog;
|
||||
|
||||
api->RequestPages = RequestPages;
|
||||
api->FreePages = FreePages;
|
||||
|
||||
api->AppendMapFlag = AppendMapFlag;
|
||||
api->RemoveMapFlag = RemoveMapFlag;
|
||||
api->MapPages = MapPages;
|
||||
api->UnmapPages = UnmapPages;
|
||||
|
||||
api->CreateKernelProcess = CreateKernelProcess;
|
||||
api->CreateKernelThread = CreateKernelThread;
|
||||
api->KillProcess = KillProcess;
|
||||
api->KillThread = KillThread;
|
||||
api->Yield = Yield;
|
||||
api->Sleep = Sleep;
|
||||
|
||||
api->GetPCIDevices = GetPCIDevices;
|
||||
api->InitializePCI = InitializePCI;
|
||||
api->GetBAR = GetBAR;
|
||||
|
||||
api->memcpy = api__memcpy;
|
||||
api->memset = api__memset;
|
||||
api->memmove = api__memmove;
|
||||
api->memcmp = api__memcmp;
|
||||
api->strlen = api__strlen;
|
||||
api->strcpy = api__strcpy;
|
||||
api->strcat = api__strcat;
|
||||
api->strcmp = api__strcmp;
|
||||
api->strncmp = api__strncmp;
|
||||
api->strchr = api__strchr;
|
||||
api->strrchr = api__strrchr;
|
||||
api->strstr = api__strstr;
|
||||
}
|
||||
}
|
325
core/driver/devfile/master.cpp
Normal file
325
core/driver/devfile/master.cpp
Normal file
@ -0,0 +1,325 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <driver.hpp>
|
||||
|
||||
#include <memory.hpp>
|
||||
#include <ints.hpp>
|
||||
#include <task.hpp>
|
||||
#include <printf.h>
|
||||
#include <exec.hpp>
|
||||
#include <cwalk.h>
|
||||
#include <md5.h>
|
||||
|
||||
#include "../../../kernel.h"
|
||||
#include "../../../driver.h"
|
||||
|
||||
using namespace vfs;
|
||||
|
||||
namespace Driver
|
||||
{
|
||||
int MasterDeviceFile::open(int Flags, mode_t Mode)
|
||||
{
|
||||
switch (this->DeviceType)
|
||||
{
|
||||
default:
|
||||
if (this->SlavesMap.empty())
|
||||
return -ENOSYS;
|
||||
Slaves slave = this->SlavesMap.begin()->second;
|
||||
return slave->begin()->second->open(Flags, Mode);
|
||||
}
|
||||
}
|
||||
|
||||
int MasterDeviceFile::close()
|
||||
{
|
||||
switch (this->DeviceType)
|
||||
{
|
||||
default:
|
||||
if (this->SlavesMap.empty())
|
||||
return -ENOSYS;
|
||||
Slaves slave = this->SlavesMap.begin()->second;
|
||||
return slave->begin()->second->close();
|
||||
}
|
||||
}
|
||||
|
||||
size_t MasterDeviceFile::read(uint8_t *Buffer,
|
||||
size_t Size,
|
||||
off_t Offset)
|
||||
{
|
||||
switch (this->DeviceType)
|
||||
{
|
||||
case ddt_Keyboard:
|
||||
{
|
||||
while (KeyQueue.empty())
|
||||
TaskManager->Yield();
|
||||
|
||||
/* Request scancode */
|
||||
if (Size == 2 && Buffer[1] == 0x00)
|
||||
{
|
||||
if (RawKeyQueue.empty())
|
||||
return 0;
|
||||
|
||||
Buffer[0] = RawKeyQueue.front();
|
||||
RawKeyQueue.pop_front();
|
||||
return 1;
|
||||
}
|
||||
|
||||
Buffer[0] = KeyQueue.front();
|
||||
KeyQueue.pop_front();
|
||||
return 1;
|
||||
}
|
||||
default:
|
||||
if (this->SlavesMap.empty())
|
||||
return 0;
|
||||
Slaves slave = this->SlavesMap.begin()->second;
|
||||
return slave->begin()->second->read(Buffer, Size, Offset);
|
||||
}
|
||||
}
|
||||
|
||||
size_t MasterDeviceFile::write(uint8_t *Buffer,
|
||||
size_t Size,
|
||||
off_t Offset)
|
||||
{
|
||||
switch (this->DeviceType)
|
||||
{
|
||||
default:
|
||||
if (this->SlavesMap.empty())
|
||||
return 0;
|
||||
Slaves slave = this->SlavesMap.begin()->second;
|
||||
return slave->begin()->second->write(Buffer, Size, Offset);
|
||||
}
|
||||
}
|
||||
|
||||
int MasterDeviceFile::ioctl(unsigned long Request,
|
||||
void *Argp)
|
||||
{
|
||||
switch (this->DeviceType)
|
||||
{
|
||||
default:
|
||||
if (this->SlavesMap.empty())
|
||||
return -ENOSYS;
|
||||
Slaves slave = this->SlavesMap.begin()->second;
|
||||
return slave->begin()->second->ioctl(Request, Argp);
|
||||
}
|
||||
}
|
||||
|
||||
void MasterDeviceFile::ClearBuffers()
|
||||
{
|
||||
this->RawKeyQueue.clear();
|
||||
this->KeyQueue.clear();
|
||||
/* ... */
|
||||
|
||||
foreach (auto &sm in this->SlavesMap)
|
||||
{
|
||||
Slaves slave = sm.second;
|
||||
foreach (auto &sdf in *slave)
|
||||
sdf.second->ClearBuffers();
|
||||
}
|
||||
}
|
||||
|
||||
int MasterDeviceFile::ReportKeyEvent(maj_t ID, min_t MinorID, uint8_t ScanCode)
|
||||
{
|
||||
debug("New key event: %02x", ScanCode);
|
||||
if (this->SlavesMap.find(ID) == this->SlavesMap.end())
|
||||
return -EINVAL;
|
||||
|
||||
std::unordered_map<min_t, SlaveDeviceFile *> *slave = this->SlavesMap[ID];
|
||||
if ((*slave).find(MinorID) == (*slave).end())
|
||||
return -EINVAL;
|
||||
|
||||
/* We are master, keep a copy of the scancode and
|
||||
converted key */
|
||||
|
||||
if (RawKeyQueue.size() > 16)
|
||||
RawKeyQueue.pop_front();
|
||||
RawKeyQueue.push_back(ScanCode);
|
||||
|
||||
if (KeyQueue.size() > 16)
|
||||
KeyQueue.pop_front();
|
||||
|
||||
switch (ScanCode & ~KEY_PRESSED)
|
||||
{
|
||||
case KEY_LEFT_SHIFT:
|
||||
case KEY_RIGHT_SHIFT:
|
||||
{
|
||||
if (ScanCode & KEY_PRESSED)
|
||||
UpperCase = true;
|
||||
else
|
||||
UpperCase = false;
|
||||
break;
|
||||
}
|
||||
case KEY_CAPS_LOCK:
|
||||
{
|
||||
if (ScanCode & KEY_PRESSED)
|
||||
CapsLock = !CapsLock;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
KeyQueue.push_back(GetScanCode(ScanCode, UpperCase || CapsLock));
|
||||
|
||||
SlaveDeviceFile *sdf = (*slave)[MinorID];
|
||||
return sdf->ReportKeyEvent(ScanCode);
|
||||
}
|
||||
|
||||
int MasterDeviceFile::ReportMouseEvent(maj_t ID, min_t MinorID,
|
||||
bool LeftButton, bool RightButton, bool MiddleButton,
|
||||
bool Button4, bool Button5, bool Button6, bool Button7, bool Button8,
|
||||
uintptr_t X, uintptr_t Y, int8_t Z, bool Relative)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
int MasterDeviceFile::ReportNetworkPacket(maj_t ID, min_t MinorID, void *Buffer, size_t Size)
|
||||
{
|
||||
/* TODO: Buffer must be allocated by the kernel */
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
int MasterDeviceFile::NewBlock(maj_t ID, min_t MinorID, drvOpen_t Open, drvClose_t Close,
|
||||
drvRead_t Read, drvWrite_t Write, drvIoctl_t Ioctl)
|
||||
{
|
||||
assert(this->SlavesMap.find(ID) != this->SlavesMap.end());
|
||||
Slaves slave = this->SlavesMap[ID];
|
||||
assert((*slave).find(MinorID) != (*slave).end());
|
||||
SlaveDeviceFile *sdf = (*slave)[MinorID];
|
||||
sdf->Open = Open;
|
||||
sdf->Close = Close;
|
||||
sdf->Read = Read;
|
||||
sdf->Write = Write;
|
||||
sdf->Ioctl = Ioctl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int MasterDeviceFile::NewAudio(maj_t ID, min_t MinorID, drvOpen_t Open, drvClose_t Close,
|
||||
drvRead_t Read, drvWrite_t Write, drvIoctl_t Ioctl)
|
||||
{
|
||||
assert(this->SlavesMap.find(ID) != this->SlavesMap.end());
|
||||
Slaves slave = this->SlavesMap[ID];
|
||||
assert((*slave).find(MinorID) != (*slave).end());
|
||||
SlaveDeviceFile *sdf = (*slave)[MinorID];
|
||||
sdf->Open = Open;
|
||||
sdf->Close = Close;
|
||||
sdf->Read = Read;
|
||||
sdf->Write = Write;
|
||||
sdf->Ioctl = Ioctl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int MasterDeviceFile::NewNet(maj_t ID, min_t MinorID, drvOpen_t Open, drvClose_t Close,
|
||||
drvRead_t Read, drvWrite_t Write, drvIoctl_t Ioctl)
|
||||
{
|
||||
assert(this->SlavesMap.find(ID) != this->SlavesMap.end());
|
||||
Slaves slave = this->SlavesMap[ID];
|
||||
assert((*slave).find(MinorID) != (*slave).end());
|
||||
SlaveDeviceFile *sdf = (*slave)[MinorID];
|
||||
sdf->Open = Open;
|
||||
sdf->Close = Close;
|
||||
sdf->Read = Read;
|
||||
sdf->Write = Write;
|
||||
sdf->Ioctl = Ioctl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
dev_t MasterDeviceFile::Register(maj_t ID)
|
||||
{
|
||||
debug("Registering slave device %d", ID);
|
||||
Slaves slave;
|
||||
if (this->SlavesMap.find(ID) != this->SlavesMap.end())
|
||||
slave = this->SlavesMap[ID];
|
||||
else
|
||||
slave = new std::unordered_map<min_t, SlaveDeviceFile *>();
|
||||
|
||||
char name[24];
|
||||
sprintf(name, "%s%ld", this->SlaveName, this->SlaveIDCounter);
|
||||
SlaveDeviceFile *sdf = new SlaveDeviceFile(name,
|
||||
this->SlaveParent,
|
||||
this->DeviceType,
|
||||
this->Type);
|
||||
|
||||
sdf->DeviceMajor = ID;
|
||||
sdf->DeviceMinor = this->SlaveIDCounter;
|
||||
|
||||
(*slave)[this->SlaveIDCounter] = sdf;
|
||||
this->SlavesMap[ID] = slave;
|
||||
return this->SlaveIDCounter++;
|
||||
}
|
||||
|
||||
int MasterDeviceFile::Unregister(maj_t ID, min_t MinorID)
|
||||
{
|
||||
debug("Unregistering slave device %d:%d", ID, MinorID);
|
||||
if (this->SlavesMap.find(ID) == this->SlavesMap.end())
|
||||
return -EINVAL;
|
||||
|
||||
std::unordered_map<min_t, SlaveDeviceFile *> *slave = this->SlavesMap[ID];
|
||||
if ((*slave).find(MinorID) == (*slave).end())
|
||||
return -EINVAL;
|
||||
|
||||
SlaveDeviceFile *sdf = (*slave)[MinorID];
|
||||
delete sdf;
|
||||
slave->erase(MinorID);
|
||||
if (slave->empty())
|
||||
{
|
||||
delete slave;
|
||||
this->SlavesMap.erase(ID);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
MasterDeviceFile::MasterDeviceFile(const char *MasterName,
|
||||
const char *_SlaveName,
|
||||
Node *Parent,
|
||||
int Type)
|
||||
: Node(Parent, MasterName, NodeType::FILE)
|
||||
{
|
||||
strncpy(this->SlaveName, _SlaveName, sizeof(this->Name));
|
||||
this->DeviceType = Type;
|
||||
this->SlaveParent = Parent;
|
||||
|
||||
switch (Type)
|
||||
{
|
||||
case ddt_Keyboard:
|
||||
case ddt_Mouse:
|
||||
case ddt_Joystick:
|
||||
case ddt_Gamepad:
|
||||
case ddt_Touchpad:
|
||||
case ddt_Touchscreen:
|
||||
this->Type = NodeType::CHARDEVICE;
|
||||
break;
|
||||
case ddt_SATA:
|
||||
case ddt_ATA:
|
||||
case ddt_NVMe:
|
||||
this->Type = NodeType::BLOCKDEVICE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
MasterDeviceFile::~MasterDeviceFile()
|
||||
{
|
||||
foreach (auto &sm in this->SlavesMap)
|
||||
{
|
||||
Slaves slave = sm.second;
|
||||
foreach (auto &sdf in *slave)
|
||||
delete sdf.second;
|
||||
delete slave;
|
||||
}
|
||||
this->SlavesMap.clear();
|
||||
}
|
||||
}
|
131
core/driver/devfile/slave.cpp
Normal file
131
core/driver/devfile/slave.cpp
Normal file
@ -0,0 +1,131 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <driver.hpp>
|
||||
|
||||
#include <memory.hpp>
|
||||
#include <ints.hpp>
|
||||
#include <task.hpp>
|
||||
#include <printf.h>
|
||||
#include <exec.hpp>
|
||||
#include <cwalk.h>
|
||||
#include <md5.h>
|
||||
|
||||
#include "../../../kernel.h"
|
||||
#include "../../../driver.h"
|
||||
|
||||
using namespace vfs;
|
||||
|
||||
namespace Driver
|
||||
{
|
||||
int SlaveDeviceFile::open(int Flags, mode_t Mode)
|
||||
{
|
||||
switch (this->DeviceType)
|
||||
{
|
||||
default:
|
||||
if (this->Open)
|
||||
return this->Open(this->DeviceMajor, this->DeviceMinor,
|
||||
Flags, Mode);
|
||||
return -ENOSYS;
|
||||
}
|
||||
}
|
||||
|
||||
int SlaveDeviceFile::close()
|
||||
{
|
||||
switch (this->DeviceType)
|
||||
{
|
||||
default:
|
||||
if (this->Close)
|
||||
return this->Close(this->DeviceMajor, this->DeviceMinor);
|
||||
return -ENOSYS;
|
||||
}
|
||||
}
|
||||
|
||||
size_t SlaveDeviceFile::read(uint8_t *Buffer,
|
||||
size_t Size,
|
||||
off_t Offset)
|
||||
{
|
||||
switch (this->DeviceType)
|
||||
{
|
||||
case ddt_Keyboard:
|
||||
{
|
||||
while (KeyQueue.empty())
|
||||
TaskManager->Yield();
|
||||
|
||||
Buffer[0] = KeyQueue.front();
|
||||
KeyQueue.pop_front();
|
||||
return 1;
|
||||
}
|
||||
default:
|
||||
if (this->Read)
|
||||
return this->Read(this->DeviceMajor, this->DeviceMinor,
|
||||
Buffer, Size, Offset);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
size_t SlaveDeviceFile::write(uint8_t *Buffer,
|
||||
size_t Size,
|
||||
off_t Offset)
|
||||
{
|
||||
switch (this->DeviceType)
|
||||
{
|
||||
default:
|
||||
if (this->Write)
|
||||
return this->Write(this->DeviceMajor, this->DeviceMinor,
|
||||
Buffer, Size, Offset);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int SlaveDeviceFile::ioctl(unsigned long Request,
|
||||
void *Argp)
|
||||
{
|
||||
switch (this->DeviceType)
|
||||
{
|
||||
default:
|
||||
if (this->Ioctl)
|
||||
return this->Ioctl(this->DeviceMajor, this->DeviceMinor,
|
||||
Request, Argp);
|
||||
return -ENOSYS;
|
||||
}
|
||||
}
|
||||
|
||||
void SlaveDeviceFile::ClearBuffers()
|
||||
{
|
||||
KeyQueue.clear();
|
||||
/* ... */
|
||||
}
|
||||
|
||||
int SlaveDeviceFile::ReportKeyEvent(uint8_t ScanCode)
|
||||
{
|
||||
if (KeyQueue.size() > 16)
|
||||
KeyQueue.pop_front();
|
||||
KeyQueue.push_back(ScanCode);
|
||||
return 0;
|
||||
}
|
||||
|
||||
SlaveDeviceFile::SlaveDeviceFile(const char *Name, vfs::Node *Parent, int Type, vfs::NodeType NType)
|
||||
: Node(Parent, Name, NType)
|
||||
{
|
||||
this->DeviceType = Type;
|
||||
}
|
||||
|
||||
SlaveDeviceFile::~SlaveDeviceFile()
|
||||
{
|
||||
}
|
||||
}
|
582
core/driver/driver.cpp
Normal file
582
core/driver/driver.cpp
Normal file
@ -0,0 +1,582 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <driver.hpp>
|
||||
|
||||
#include <memory.hpp>
|
||||
#include <ints.hpp>
|
||||
#include <task.hpp>
|
||||
#include <printf.h>
|
||||
#include <exec.hpp>
|
||||
#include <cwalk.h>
|
||||
#include <md5.h>
|
||||
|
||||
#include "../../kernel.h"
|
||||
#include "../../driver.h"
|
||||
|
||||
using namespace vfs;
|
||||
|
||||
namespace Driver
|
||||
{
|
||||
void Manager::LoadAllDrivers()
|
||||
{
|
||||
foreach (auto &var in Drivers)
|
||||
{
|
||||
DriverObject *Drv = &var.second;
|
||||
size_t dapiPgs = TO_PAGES(sizeof(__driverAPI));
|
||||
__driverAPI *dApi = (__driverAPI *)Drv->vma->RequestPages(dapiPgs);
|
||||
debug("Driver API at %#lx-%#lx", dApi, dApi + sizeof(__driverAPI));
|
||||
|
||||
fixme("api version");
|
||||
dApi->APIVersion.Major = 0;
|
||||
dApi->APIVersion.Minor = 0;
|
||||
dApi->APIVersion.Patch = 0;
|
||||
|
||||
dApi->MajorID = var.first;
|
||||
dApi->Base = Drv->BaseAddress;
|
||||
PopulateDriverAPI(dApi);
|
||||
|
||||
debug("Calling driver %s at %#lx", Drv->Path, Drv->EntryPoint);
|
||||
int (*DrvInit)(__driverAPI *) = (int (*)(__driverAPI *))Drv->EntryPoint;
|
||||
Drv->ErrorCode = DrvInit(dApi);
|
||||
if (Drv->ErrorCode < 0)
|
||||
{
|
||||
KPrint("FATAL: _start() failed for %s: %s",
|
||||
Drv->Name, strerror(Drv->ErrorCode));
|
||||
error("Failed to load driver %s: %s",
|
||||
Drv->Path, strerror(Drv->ErrorCode));
|
||||
|
||||
Drv->vma->FreeAllPages();
|
||||
continue;
|
||||
}
|
||||
|
||||
KPrint("Loading driver %s", Drv->Name);
|
||||
|
||||
debug("Calling Probe()=%#lx on driver %s",
|
||||
Drv->Probe, Drv->Path);
|
||||
Drv->ErrorCode = Drv->Probe();
|
||||
if (Drv->ErrorCode < 0)
|
||||
{
|
||||
KPrint("Probe() failed for %s: %s",
|
||||
Drv->Name, strerror(Drv->ErrorCode));
|
||||
error("Failed to probe driver %s: %s",
|
||||
Drv->Path, strerror(Drv->ErrorCode));
|
||||
|
||||
Drv->vma->FreeAllPages();
|
||||
continue;
|
||||
}
|
||||
|
||||
debug("Calling driver Entry()=%#lx function on driver %s",
|
||||
Drv->Entry, Drv->Path);
|
||||
Drv->ErrorCode = Drv->Entry();
|
||||
if (Drv->ErrorCode < 0)
|
||||
{
|
||||
KPrint("Entry() failed for %s: %s",
|
||||
Drv->Name, strerror(Drv->ErrorCode));
|
||||
error("Failed to initialize driver %s: %s",
|
||||
Drv->Path, strerror(Drv->ErrorCode));
|
||||
|
||||
Drv->vma->FreeAllPages();
|
||||
continue;
|
||||
}
|
||||
|
||||
debug("Loaded driver %s", Drv->Path);
|
||||
Drv->Initialized = true;
|
||||
}
|
||||
|
||||
InputMouseDev->ClearBuffers();
|
||||
InputKeyboardDev->ClearBuffers();
|
||||
|
||||
BlockSATADev->ClearBuffers();
|
||||
BlockHDDev->ClearBuffers();
|
||||
BlockNVMeDev->ClearBuffers();
|
||||
|
||||
AudioDev->ClearBuffers();
|
||||
|
||||
NetDev->ClearBuffers();
|
||||
/* ... */
|
||||
}
|
||||
|
||||
void Manager::UnloadAllDrivers()
|
||||
{
|
||||
foreach (auto &var in Drivers)
|
||||
{
|
||||
DriverObject *Drv = &var.second;
|
||||
if (!Drv->Initialized)
|
||||
continue;
|
||||
|
||||
debug("Unloading driver %s", Drv->Name);
|
||||
int err = Drv->Final();
|
||||
if (err < 0)
|
||||
{
|
||||
warn("Failed to unload driver %s: %s",
|
||||
Drv->Name, strerror(err));
|
||||
}
|
||||
|
||||
if (!Drv->InterruptHandlers->empty())
|
||||
{
|
||||
foreach (auto &rInt in * Drv->InterruptHandlers)
|
||||
{
|
||||
Interrupts::RemoveHandler((void (*)(CPU::TrapFrame *))rInt.second);
|
||||
}
|
||||
Drv->InterruptHandlers->clear();
|
||||
}
|
||||
|
||||
delete Drv->vma, Drv->vma = nullptr;
|
||||
delete Drv->InterruptHandlers, Drv->InterruptHandlers = nullptr;
|
||||
}
|
||||
Drivers.clear();
|
||||
}
|
||||
|
||||
void Manager::Panic()
|
||||
{
|
||||
Memory::Virtual vmm;
|
||||
foreach (auto Driver in Drivers)
|
||||
{
|
||||
if (!Driver.second.Initialized)
|
||||
continue;
|
||||
|
||||
trace("Panic on driver %s", Driver.second.Name);
|
||||
debug("%#lx", Driver.second.Panic);
|
||||
|
||||
/* Crash while probing? */
|
||||
if (Driver.second.Panic && vmm.Check((void *)Driver.second.Panic))
|
||||
Driver.second.Panic();
|
||||
else
|
||||
error("No panic function for driver %s",
|
||||
Driver.second.Name);
|
||||
}
|
||||
}
|
||||
|
||||
int Manager::LoadDriverFile(uintptr_t &EntryPoint,
|
||||
uintptr_t &BaseAddress,
|
||||
Memory::VirtualMemoryArea *dVma,
|
||||
RefNode *rDrv)
|
||||
{
|
||||
Elf64_Ehdr ELFHeader;
|
||||
rDrv->seek(0, SEEK_SET);
|
||||
rDrv->read((uint8_t *)&ELFHeader, sizeof(Elf64_Ehdr));
|
||||
if (ELFHeader.e_type != ET_DYN)
|
||||
{
|
||||
error("Driver %s is not a shared object", rDrv->node->FullPath);
|
||||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
trace("Loading driver %s in memory", rDrv->node->Name);
|
||||
|
||||
BaseAddress = 0;
|
||||
{
|
||||
Elf64_Phdr ProgramBreakHeader{};
|
||||
Elf64_Phdr ProgramHeader;
|
||||
|
||||
size_t SegmentsSize = 0;
|
||||
for (Elf64_Half i = 0; i < ELFHeader.e_phnum; i++)
|
||||
{
|
||||
rDrv->seek(ELFHeader.e_phoff + (i * sizeof(Elf64_Phdr)), SEEK_SET);
|
||||
rDrv->read((uint8_t *)&ProgramHeader, sizeof(Elf64_Phdr));
|
||||
|
||||
if (ProgramHeader.p_type == PT_LOAD ||
|
||||
ProgramHeader.p_type == PT_DYNAMIC)
|
||||
{
|
||||
if (SegmentsSize < ProgramHeader.p_vaddr + ProgramHeader.p_memsz)
|
||||
{
|
||||
SegmentsSize = ProgramHeader.p_vaddr + ProgramHeader.p_memsz;
|
||||
ProgramBreakHeader = ProgramHeader;
|
||||
}
|
||||
}
|
||||
}
|
||||
debug("SegmentsSize: %#lx", SegmentsSize);
|
||||
|
||||
/* TODO: Check if this is correct and/or it needs more
|
||||
complex calculations & allocations */
|
||||
void *SegmentsAddress = dVma->RequestPages(TO_PAGES(SegmentsSize) + 1, true);
|
||||
BaseAddress = (uintptr_t)SegmentsAddress;
|
||||
debug("BaseAddress: %#lx, End: %#lx (%#lx)", BaseAddress,
|
||||
BaseAddress + FROM_PAGES(TO_PAGES(SegmentsSize)),
|
||||
SegmentsSize);
|
||||
|
||||
for (Elf64_Half i = 0; i < ELFHeader.e_phnum; i++)
|
||||
{
|
||||
rDrv->seek(ELFHeader.e_phoff + (i * sizeof(Elf64_Phdr)), SEEK_SET);
|
||||
rDrv->read((uint8_t *)&ProgramHeader, sizeof(Elf64_Phdr));
|
||||
|
||||
switch (ProgramHeader.p_type)
|
||||
{
|
||||
case PT_LOAD:
|
||||
{
|
||||
/* Because this is ET_DYN, we can load the segments
|
||||
anywhere we want. */
|
||||
uintptr_t SegmentDestination = BaseAddress + ProgramHeader.p_vaddr;
|
||||
|
||||
if (ProgramHeader.p_memsz == 0)
|
||||
continue;
|
||||
|
||||
debug("Copying PT_LOAD to %#lx-%#lx (%ld file bytes, %ld mem bytes)",
|
||||
SegmentDestination, SegmentDestination + ProgramHeader.p_memsz,
|
||||
ProgramHeader.p_filesz, ProgramHeader.p_memsz);
|
||||
|
||||
if (ProgramHeader.p_filesz > 0)
|
||||
{
|
||||
rDrv->seek(ProgramHeader.p_offset, SEEK_SET);
|
||||
rDrv->read((uint8_t *)SegmentDestination, ProgramHeader.p_filesz);
|
||||
}
|
||||
|
||||
if (ProgramHeader.p_memsz - ProgramHeader.p_filesz > 0)
|
||||
{
|
||||
void *zAddr = (void *)(SegmentDestination + ProgramHeader.p_filesz);
|
||||
memset(zAddr, 0, ProgramHeader.p_memsz - ProgramHeader.p_filesz);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PT_DYNAMIC:
|
||||
{
|
||||
/* PT_DYNAMIC contains the dynamic linking information for the
|
||||
executable or shared library. */
|
||||
|
||||
uintptr_t DynamicSegmentDestination = BaseAddress + ProgramHeader.p_vaddr;
|
||||
|
||||
if (ProgramHeader.p_memsz == 0)
|
||||
continue;
|
||||
|
||||
debug("Copying PT_DYNAMIC to %#lx-%#lx (%ld file bytes, %ld mem bytes)",
|
||||
DynamicSegmentDestination, DynamicSegmentDestination + ProgramHeader.p_memsz,
|
||||
ProgramHeader.p_filesz, ProgramHeader.p_memsz);
|
||||
|
||||
if (ProgramHeader.p_filesz > 0)
|
||||
{
|
||||
rDrv->seek(ProgramHeader.p_offset, SEEK_SET);
|
||||
rDrv->read((uint8_t *)DynamicSegmentDestination, ProgramHeader.p_filesz);
|
||||
}
|
||||
|
||||
if (ProgramHeader.p_memsz - ProgramHeader.p_filesz > 0)
|
||||
{
|
||||
void *zAddr = (void *)(DynamicSegmentDestination + ProgramHeader.p_filesz);
|
||||
memset(zAddr, 0, ProgramHeader.p_memsz - ProgramHeader.p_filesz);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
fixme("Unhandled program header type: %#lx",
|
||||
ProgramHeader.p_type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Elf64_Phdr ProgramHeader;
|
||||
for (Elf64_Half i = 0; i < ELFHeader.e_phnum; i++)
|
||||
{
|
||||
rDrv->seek(ELFHeader.e_phoff + (i * sizeof(Elf64_Phdr)), SEEK_SET);
|
||||
rDrv->read((uint8_t *)&ProgramHeader, sizeof(Elf64_Phdr));
|
||||
|
||||
if (ProgramHeader.p_type == PT_DYNAMIC)
|
||||
{
|
||||
Elf64_Dyn *Dynamic = (Elf64_Dyn *)(BaseAddress + ProgramHeader.p_vaddr);
|
||||
Elf64_Dyn *RelaSize = nullptr;
|
||||
Elf64_Dyn *PltRelSize = nullptr;
|
||||
|
||||
while (Dynamic->d_tag != DT_NULL)
|
||||
{
|
||||
switch (Dynamic->d_tag)
|
||||
{
|
||||
case DT_RELASZ:
|
||||
RelaSize = Dynamic;
|
||||
debug("RELA Size: %d", RelaSize->d_un.d_val / sizeof(Elf64_Rela));
|
||||
|
||||
break;
|
||||
case DT_PLTRELSZ:
|
||||
PltRelSize = Dynamic;
|
||||
debug("PLTRELSZ: %d", PltRelSize->d_un.d_val / sizeof(Elf64_Rela));
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
Dynamic++;
|
||||
}
|
||||
Dynamic = (Elf64_Dyn *)(BaseAddress + ProgramHeader.p_vaddr);
|
||||
|
||||
while (Dynamic->d_tag != DT_NULL)
|
||||
{
|
||||
switch (Dynamic->d_tag)
|
||||
{
|
||||
case DT_RELA: /* .rela.dyn */
|
||||
{
|
||||
if (!RelaSize)
|
||||
{
|
||||
error("DT_RELASZ is not set");
|
||||
break;
|
||||
}
|
||||
|
||||
Elf64_Rela *Rela = (Elf64_Rela *)(BaseAddress + Dynamic->d_un.d_ptr);
|
||||
for (size_t i = 0; i < (RelaSize->d_un.d_val / sizeof(Elf64_Rela)); i++)
|
||||
{
|
||||
Elf64_Rela *r = &Rela[i];
|
||||
uintptr_t *RelocationAddress = (uintptr_t *)(BaseAddress + r->r_offset);
|
||||
uintptr_t RelocationTarget = 0;
|
||||
|
||||
switch (ELF64_R_TYPE(r->r_info))
|
||||
{
|
||||
case R_X86_64_GLOB_DAT:
|
||||
case R_X86_64_JUMP_SLOT:
|
||||
{
|
||||
RelocationTarget = BaseAddress;
|
||||
break;
|
||||
}
|
||||
case R_X86_64_RELATIVE:
|
||||
case R_X86_64_64:
|
||||
{
|
||||
RelocationTarget = BaseAddress + r->r_addend;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
fixme("Unhandled relocation type: %#lx",
|
||||
ELF64_R_TYPE(r->r_info));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
*RelocationAddress = RelocationTarget;
|
||||
|
||||
debug("Relocated %#lx to %#lx",
|
||||
r->r_offset, *RelocationAddress);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DT_PLTREL:
|
||||
{
|
||||
if (Dynamic->d_un.d_val != DT_RELA)
|
||||
error("DT_PLTREL is not DT_RELA");
|
||||
break;
|
||||
}
|
||||
case DT_JMPREL: /* .rela.plt */
|
||||
{
|
||||
if (!PltRelSize)
|
||||
{
|
||||
error("DT_PLTRELSZ is not set");
|
||||
break;
|
||||
}
|
||||
|
||||
int fd = fopen(rDrv->node->FullPath, "r");
|
||||
|
||||
std::vector<Elf64_Dyn> SymTab = Execute::ELFGetDynamicTag_x86_64(fd, DT_SYMTAB);
|
||||
std::vector<Elf64_Dyn> StrTab = Execute::ELFGetDynamicTag_x86_64(fd, DT_STRTAB);
|
||||
Elf64_Sym *_SymTab = (Elf64_Sym *)((uintptr_t)BaseAddress + SymTab[0].d_un.d_ptr);
|
||||
char *DynStr = (char *)((uintptr_t)BaseAddress + StrTab[0].d_un.d_ptr);
|
||||
UNUSED(DynStr);
|
||||
fclose(fd);
|
||||
|
||||
Elf64_Rela *Rela = (Elf64_Rela *)(BaseAddress + Dynamic->d_un.d_ptr);
|
||||
for (size_t i = 0; i < (PltRelSize->d_un.d_val / sizeof(Elf64_Rela)); i++)
|
||||
{
|
||||
Elf64_Rela *r = &Rela[i];
|
||||
uintptr_t *RelocationAddress = (uintptr_t *)(BaseAddress + r->r_offset);
|
||||
uintptr_t RelocationTarget = 0;
|
||||
|
||||
switch (ELF64_R_TYPE(r->r_info))
|
||||
{
|
||||
case R_X86_64_JUMP_SLOT:
|
||||
{
|
||||
Elf64_Xword SymIndex = ELF64_R_SYM(r->r_info);
|
||||
Elf64_Sym *Sym = _SymTab + SymIndex;
|
||||
|
||||
#ifdef DEBUG
|
||||
const char *SymbolName = DynStr + Sym->st_name;
|
||||
debug("Symbol %s at %#lx", SymbolName, Sym->st_value);
|
||||
#endif
|
||||
|
||||
RelocationTarget = BaseAddress + Sym->st_value;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
fixme("Unhandled relocation type: %#lx",
|
||||
ELF64_R_TYPE(r->r_info));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
*RelocationAddress = RelocationTarget;
|
||||
|
||||
debug("Relocated %#lx to %#lx",
|
||||
r->r_offset, *RelocationAddress);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DT_SYMTAB:
|
||||
{
|
||||
fixme("DT_SYMTAB");
|
||||
break;
|
||||
int fd = fopen(rDrv->node->FullPath, "r");
|
||||
|
||||
std::vector<Elf64_Dyn> SymTab = Execute::ELFGetDynamicTag_x86_64(fd, DT_SYMTAB);
|
||||
std::vector<Elf64_Dyn> StrTab = Execute::ELFGetDynamicTag_x86_64(fd, DT_STRTAB);
|
||||
Elf64_Sym *_SymTab = (Elf64_Sym *)((uintptr_t)BaseAddress + SymTab[0].d_un.d_ptr);
|
||||
char *DynStr = (char *)((uintptr_t)BaseAddress + StrTab[0].d_un.d_ptr);
|
||||
UNUSED(DynStr);
|
||||
fclose(fd);
|
||||
|
||||
size_t symtabEntrySize = 0;
|
||||
Elf64_Dyn *entrySizeDyn = Dynamic;
|
||||
while (entrySizeDyn->d_tag != DT_NULL)
|
||||
{
|
||||
if (entrySizeDyn->d_tag == DT_SYMENT)
|
||||
{
|
||||
symtabEntrySize = entrySizeDyn->d_un.d_val;
|
||||
break;
|
||||
}
|
||||
entrySizeDyn++;
|
||||
}
|
||||
|
||||
if (symtabEntrySize == 0)
|
||||
{
|
||||
fixme("No information about symbol entry size");
|
||||
break;
|
||||
}
|
||||
|
||||
size_t numSymbols = Dynamic->d_un.d_val / symtabEntrySize;
|
||||
|
||||
for (size_t i = 0; i < numSymbols; i++)
|
||||
{
|
||||
Elf64_Sym *s = &_SymTab[i];
|
||||
if (s->st_name == 0)
|
||||
continue;
|
||||
|
||||
#ifdef DEBUG
|
||||
const char *SymbolName = (const char *)(DynStr + s->st_name);
|
||||
debug("%d: Symbol %s at %#lx", i, SymbolName, s->st_value);
|
||||
#endif
|
||||
/** TODO: search for symbols and link */
|
||||
/** good use but it will not work only
|
||||
* if we specify to default visibility but
|
||||
* this will create more issues :/ */
|
||||
// if (strcmp(SymbolName, "DriverProbe") == 0)
|
||||
// {
|
||||
// Drivers[MajorIDCounter].Probe = (int (*)())(BaseAddress + s->st_value);
|
||||
// debug("Found probe function at %#lx", Drivers[MajorIDCounter].Probe);
|
||||
// }
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
fixme("Unhandled dynamic tag: %#lx",
|
||||
Dynamic->d_tag);
|
||||
break;
|
||||
}
|
||||
}
|
||||
Dynamic++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EntryPoint = ELFHeader.e_entry;
|
||||
EntryPoint += BaseAddress;
|
||||
|
||||
debug("Driver %s has entry point %#lx and base %#lx",
|
||||
rDrv->node->FullPath, EntryPoint, BaseAddress);
|
||||
|
||||
/* FIXME: Do not add to the KernelSymbolTable! */
|
||||
// Memory::SmartHeap sh(rDrv->Size);
|
||||
// rDrv->seek(0, SEEK_SET);
|
||||
// rDrv->read((uint8_t *)sh.Get(), rDrv->Size);
|
||||
// KernelSymbolTable->AppendSymbols((uintptr_t)sh.Get(), BaseAddress);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Manager::Manager()
|
||||
{
|
||||
debug("Initializing driver manager");
|
||||
const char *DriverDirectory = Config.DriverDirectory;
|
||||
RefNode *rn = fs->Open(DriverDirectory);
|
||||
if (!rn)
|
||||
{
|
||||
error("Failed to open driver directory %s", DriverDirectory);
|
||||
KPrint("Failed to open driver directory %s", DriverDirectory);
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (auto drvNode in rn->node->Children)
|
||||
{
|
||||
if (drvNode->Type != vfs::FILE)
|
||||
continue;
|
||||
|
||||
if (Execute::GetBinaryType(drvNode->FullPath) != Execute::BinTypeELF)
|
||||
{
|
||||
error("Driver %s is not an ELF binary", drvNode->FullPath);
|
||||
continue;
|
||||
}
|
||||
|
||||
RefNode *rDrv = drvNode->CreateReference();
|
||||
|
||||
Memory::VirtualMemoryArea *dVma =
|
||||
new Memory::VirtualMemoryArea(thisProcess->PageTable);
|
||||
|
||||
uintptr_t EntryPoint, BaseAddress;
|
||||
int err = this->LoadDriverFile(EntryPoint, BaseAddress, dVma, rDrv);
|
||||
debug("err = %d (%s)", err, strerror(err));
|
||||
if (err != 0)
|
||||
{
|
||||
error("Failed to load driver %s: %s",
|
||||
drvNode->FullPath, strerror(err));
|
||||
|
||||
delete rDrv;
|
||||
delete dVma;
|
||||
continue;
|
||||
}
|
||||
delete rDrv;
|
||||
|
||||
Drivers[MajorIDCounter++] = {
|
||||
.BaseAddress = BaseAddress,
|
||||
.EntryPoint = EntryPoint,
|
||||
.vma = dVma,
|
||||
.Path = drvNode->FullPath,
|
||||
.InterruptHandlers = new std::unordered_map<uint8_t, void *>};
|
||||
|
||||
dev_t countr = MajorIDCounter - 1;
|
||||
const char *drvName;
|
||||
size_t drvNameLen;
|
||||
cwk_path_get_basename(drvNode->FullPath, &drvName, &drvNameLen);
|
||||
strncpy(Drivers[countr].Name, drvName, sizeof(Drivers[countr].Name));
|
||||
}
|
||||
|
||||
delete rn;
|
||||
|
||||
InputMouseDev = new MasterDeviceFile("mice", "mouse", DevFS, ddt_Mouse);
|
||||
InputKeyboardDev = new MasterDeviceFile("key", "kbd", DevFS, ddt_Keyboard);
|
||||
|
||||
BlockSATADev = new MasterDeviceFile("sd", "sd", DevFS, ddt_SATA);
|
||||
BlockHDDev = new MasterDeviceFile("hd", "hd", DevFS, ddt_ATA);
|
||||
BlockNVMeDev = new MasterDeviceFile("nvme", "nvme", DevFS, ddt_NVMe);
|
||||
|
||||
AudioDev = new MasterDeviceFile("audio", "snd", DevFS, ddt_Audio);
|
||||
|
||||
NetDev = new MasterDeviceFile("network", "net", DevFS, ddt_Network);
|
||||
}
|
||||
|
||||
Manager::~Manager()
|
||||
{
|
||||
debug("Unloading drivers");
|
||||
UnloadAllDrivers();
|
||||
delete InputMouseDev;
|
||||
delete InputKeyboardDev;
|
||||
}
|
||||
}
|
369
core/driver/scancode.cpp
Normal file
369
core/driver/scancode.cpp
Normal file
@ -0,0 +1,369 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <driver.hpp>
|
||||
|
||||
#include "../../driver.h"
|
||||
|
||||
static char ScanCodeConversionTableLower[] = {
|
||||
[KEY_1] = '1',
|
||||
[KEY_2] = '2',
|
||||
[KEY_3] = '3',
|
||||
[KEY_4] = '4',
|
||||
[KEY_5] = '5',
|
||||
[KEY_6] = '6',
|
||||
[KEY_7] = '7',
|
||||
[KEY_8] = '8',
|
||||
[KEY_9] = '9',
|
||||
[KEY_0] = '0',
|
||||
|
||||
[KEY_Q] = 'q',
|
||||
[KEY_W] = 'w',
|
||||
[KEY_E] = 'e',
|
||||
[KEY_R] = 'r',
|
||||
[KEY_T] = 't',
|
||||
[KEY_Y] = 'y',
|
||||
[KEY_U] = 'u',
|
||||
[KEY_I] = 'i',
|
||||
[KEY_O] = 'o',
|
||||
[KEY_P] = 'p',
|
||||
[KEY_A] = 'a',
|
||||
[KEY_S] = 's',
|
||||
[KEY_D] = 'd',
|
||||
[KEY_F] = 'f',
|
||||
[KEY_G] = 'g',
|
||||
[KEY_H] = 'h',
|
||||
[KEY_J] = 'j',
|
||||
[KEY_K] = 'k',
|
||||
[KEY_L] = 'l',
|
||||
[KEY_Z] = 'z',
|
||||
[KEY_X] = 'x',
|
||||
[KEY_C] = 'c',
|
||||
[KEY_V] = 'v',
|
||||
[KEY_B] = 'b',
|
||||
[KEY_N] = 'n',
|
||||
[KEY_M] = 'm',
|
||||
|
||||
[KEY_F1] = 0x00,
|
||||
[KEY_F2] = 0x00,
|
||||
[KEY_F3] = 0x00,
|
||||
[KEY_F4] = 0x00,
|
||||
[KEY_F5] = 0x00,
|
||||
[KEY_F6] = 0x00,
|
||||
[KEY_F7] = 0x00,
|
||||
[KEY_F8] = 0x00,
|
||||
[KEY_F9] = 0x00,
|
||||
[KEY_F10] = 0x00,
|
||||
[KEY_F11] = 0x00,
|
||||
[KEY_F12] = 0x00,
|
||||
|
||||
[KEYPAD_7] = '7',
|
||||
[KEYPAD_8] = '8',
|
||||
[KEYPAD_9] = '9',
|
||||
[KEYPAD_MINUS] = '-',
|
||||
[KEYPAD_4] = '4',
|
||||
[KEYPAD_5] = '5',
|
||||
[KEYPAD_6] = '6',
|
||||
[KEYPAD_PLUS] = '+',
|
||||
[KEYPAD_1] = '1',
|
||||
[KEYPAD_2] = '2',
|
||||
[KEYPAD_3] = '3',
|
||||
[KEYPAD_0] = '0',
|
||||
[KEYPAD_PERIOD] = '.',
|
||||
[KEYPAD_RETURN] = '\n',
|
||||
[KEYPAD_ASTERISK] = '*',
|
||||
[KEYPAD_SLASH] = '/',
|
||||
|
||||
[KEY_LEFT_CTRL] = 0x00,
|
||||
[KEY_RIGHT_CTRL] = 0x00,
|
||||
[KEY_LEFT_SHIFT] = 0x00,
|
||||
[KEY_RIGHT_SHIFT] = 0x00,
|
||||
[KEY_LEFT_ALT] = 0x00,
|
||||
[KEY_RIGHT_ALT] = 0x00,
|
||||
[KEY_ESCAPE] = '\e',
|
||||
[KEY_MINUS] = '-',
|
||||
[KEY_EQUAL] = '=',
|
||||
[KEY_BACKSPACE] = '\b',
|
||||
[KEY_TAB] = '\t',
|
||||
[KEY_LEFT_BRACKET] = '[',
|
||||
[KEY_RIGHT_BRACKET] = ']',
|
||||
[KEY_RETURN] = '\n',
|
||||
[KEY_SEMICOLON] = ';',
|
||||
[KEY_APOSTROPHE] = '\'',
|
||||
[KEY_BACK_TICK] = '`',
|
||||
[KEY_BACKSLASH] = '\\',
|
||||
[KEY_COMMA] = ',',
|
||||
[KEY_PERIOD] = '.',
|
||||
[KEY_SLASH] = '/',
|
||||
[KEY_SPACE] = ' ',
|
||||
[KEY_CAPS_LOCK] = 0x00,
|
||||
[KEY_NUM_LOCK] = 0x00,
|
||||
[KEY_SCROLL_LOCK] = 0x00,
|
||||
[KEY_PRINT_SCREEN] = 0x00,
|
||||
|
||||
[KEY_HOME] = 0x00,
|
||||
[KEY_UP_ARROW] = 0x00,
|
||||
[KEY_LEFT_ARROW] = 0x00,
|
||||
[KEY_RIGHT_ARROW] = 0x00,
|
||||
[KEY_DOWN_ARROW] = 0x00,
|
||||
[KEY_PAGE_UP] = 0x00,
|
||||
[KEY_PAGE_DOWN] = 0x00,
|
||||
[KEY_END] = 0x00,
|
||||
[KEY_INSERT] = 0x00,
|
||||
[KEY_DELETE] = 0x00,
|
||||
[KEY_LEFT_GUI] = 0x00,
|
||||
[KEY_RIGHT_GUI] = 0x00,
|
||||
[KEY_APPS] = 0x00,
|
||||
|
||||
[KEY_MULTIMEDIA_PREV_TRACK] = 0x00,
|
||||
[KEY_MULTIMEDIA_NEXT_TRACK] = 0x00,
|
||||
[KEY_MULTIMEDIA_MUTE] = 0x00,
|
||||
[KEY_MULTIMEDIA_CALCULATOR] = 0x00,
|
||||
[KEY_MULTIMEDIA_PLAY] = 0x00,
|
||||
[KEY_MULTIMEDIA_STOP] = 0x00,
|
||||
[KEY_MULTIMEDIA_VOL_DOWN] = 0x00,
|
||||
[KEY_MULTIMEDIA_VOL_UP] = 0x00,
|
||||
[KEY_MULTIMEDIA_WWW_HOME] = 0x00,
|
||||
[KEY_MULTIMEDIA_WWW_SEARCH] = 0x00,
|
||||
[KEY_MULTIMEDIA_WWW_FAVORITES] = 0x00,
|
||||
[KEY_MULTIMEDIA_WWW_REFRESH] = 0x00,
|
||||
[KEY_MULTIMEDIA_WWW_STOP] = 0x00,
|
||||
[KEY_MULTIMEDIA_WWW_FORWARD] = 0x00,
|
||||
[KEY_MULTIMEDIA_WWW_BACK] = 0x00,
|
||||
[KEY_MULTIMEDIA_MY_COMPUTER] = 0x00,
|
||||
[KEY_MULTIMEDIA_EMAIL] = 0x00,
|
||||
[KEY_MULTIMEDIA_MEDIA_SELECT] = 0x00,
|
||||
|
||||
[KEY_ACPI_POWER] = 0x00,
|
||||
[KEY_ACPI_SLEEP] = 0x00,
|
||||
[KEY_ACPI_WAKE] = 0x00};
|
||||
|
||||
static char ScanCodeConversionTableUpper[] = {
|
||||
[KEY_1] = '!',
|
||||
[KEY_2] = '@',
|
||||
[KEY_3] = '#',
|
||||
[KEY_4] = '$',
|
||||
[KEY_5] = '%',
|
||||
[KEY_6] = '^',
|
||||
[KEY_7] = '&',
|
||||
[KEY_8] = '*',
|
||||
[KEY_9] = '(',
|
||||
[KEY_0] = ')',
|
||||
|
||||
[KEY_Q] = 'Q',
|
||||
[KEY_W] = 'W',
|
||||
[KEY_E] = 'E',
|
||||
[KEY_R] = 'R',
|
||||
[KEY_T] = 'T',
|
||||
[KEY_Y] = 'Y',
|
||||
[KEY_U] = 'U',
|
||||
[KEY_I] = 'I',
|
||||
[KEY_O] = 'O',
|
||||
[KEY_P] = 'P',
|
||||
[KEY_A] = 'A',
|
||||
[KEY_S] = 'S',
|
||||
[KEY_D] = 'D',
|
||||
[KEY_F] = 'F',
|
||||
[KEY_G] = 'G',
|
||||
[KEY_H] = 'H',
|
||||
[KEY_J] = 'J',
|
||||
[KEY_K] = 'K',
|
||||
[KEY_L] = 'L',
|
||||
[KEY_Z] = 'Z',
|
||||
[KEY_X] = 'X',
|
||||
[KEY_C] = 'C',
|
||||
[KEY_V] = 'V',
|
||||
[KEY_B] = 'B',
|
||||
[KEY_N] = 'N',
|
||||
[KEY_M] = 'M',
|
||||
|
||||
[KEY_F1] = 0x00,
|
||||
[KEY_F2] = 0x00,
|
||||
[KEY_F3] = 0x00,
|
||||
[KEY_F4] = 0x00,
|
||||
[KEY_F5] = 0x00,
|
||||
[KEY_F6] = 0x00,
|
||||
[KEY_F7] = 0x00,
|
||||
[KEY_F8] = 0x00,
|
||||
[KEY_F9] = 0x00,
|
||||
[KEY_F10] = 0x00,
|
||||
[KEY_F11] = 0x00,
|
||||
[KEY_F12] = 0x00,
|
||||
|
||||
[KEYPAD_7] = '7',
|
||||
[KEYPAD_8] = '8',
|
||||
[KEYPAD_9] = '9',
|
||||
[KEYPAD_MINUS] = '-',
|
||||
[KEYPAD_4] = '4',
|
||||
[KEYPAD_5] = '5',
|
||||
[KEYPAD_6] = '6',
|
||||
[KEYPAD_PLUS] = '+',
|
||||
[KEYPAD_1] = '1',
|
||||
[KEYPAD_2] = '2',
|
||||
[KEYPAD_3] = '3',
|
||||
[KEYPAD_0] = '0',
|
||||
[KEYPAD_PERIOD] = '.',
|
||||
[KEYPAD_RETURN] = '\n',
|
||||
[KEYPAD_ASTERISK] = '*',
|
||||
[KEYPAD_SLASH] = '/',
|
||||
|
||||
[KEY_LEFT_CTRL] = 0x00,
|
||||
[KEY_RIGHT_CTRL] = 0x00,
|
||||
[KEY_LEFT_SHIFT] = 0x00,
|
||||
[KEY_RIGHT_SHIFT] = 0x00,
|
||||
[KEY_LEFT_ALT] = 0x00,
|
||||
[KEY_RIGHT_ALT] = 0x00,
|
||||
[KEY_ESCAPE] = '\e',
|
||||
[KEY_MINUS] = '_',
|
||||
[KEY_EQUAL] = '+',
|
||||
[KEY_BACKSPACE] = '\b',
|
||||
[KEY_TAB] = '\t',
|
||||
[KEY_LEFT_BRACKET] = '{',
|
||||
[KEY_RIGHT_BRACKET] = '}',
|
||||
[KEY_RETURN] = '\n',
|
||||
[KEY_SEMICOLON] = ':',
|
||||
[KEY_APOSTROPHE] = '\"',
|
||||
[KEY_BACK_TICK] = '~',
|
||||
[KEY_BACKSLASH] = '|',
|
||||
[KEY_COMMA] = '<',
|
||||
[KEY_PERIOD] = '>',
|
||||
[KEY_SLASH] = '/',
|
||||
[KEY_SPACE] = ' ',
|
||||
[KEY_CAPS_LOCK] = 0x00,
|
||||
[KEY_NUM_LOCK] = 0x00,
|
||||
[KEY_SCROLL_LOCK] = 0x00,
|
||||
[KEY_PRINT_SCREEN] = 0x00,
|
||||
|
||||
[KEY_HOME] = 0x00,
|
||||
[KEY_UP_ARROW] = 0x00,
|
||||
[KEY_LEFT_ARROW] = 0x00,
|
||||
[KEY_RIGHT_ARROW] = 0x00,
|
||||
[KEY_DOWN_ARROW] = 0x00,
|
||||
[KEY_PAGE_UP] = 0x00,
|
||||
[KEY_PAGE_DOWN] = 0x00,
|
||||
[KEY_END] = 0x00,
|
||||
[KEY_INSERT] = 0x00,
|
||||
[KEY_DELETE] = 0x00,
|
||||
[KEY_LEFT_GUI] = 0x00,
|
||||
[KEY_RIGHT_GUI] = 0x00,
|
||||
[KEY_APPS] = 0x00,
|
||||
|
||||
[KEY_MULTIMEDIA_PREV_TRACK] = 0x00,
|
||||
[KEY_MULTIMEDIA_NEXT_TRACK] = 0x00,
|
||||
[KEY_MULTIMEDIA_MUTE] = 0x00,
|
||||
[KEY_MULTIMEDIA_CALCULATOR] = 0x00,
|
||||
[KEY_MULTIMEDIA_PLAY] = 0x00,
|
||||
[KEY_MULTIMEDIA_STOP] = 0x00,
|
||||
[KEY_MULTIMEDIA_VOL_DOWN] = 0x00,
|
||||
[KEY_MULTIMEDIA_VOL_UP] = 0x00,
|
||||
[KEY_MULTIMEDIA_WWW_HOME] = 0x00,
|
||||
[KEY_MULTIMEDIA_WWW_SEARCH] = 0x00,
|
||||
[KEY_MULTIMEDIA_WWW_FAVORITES] = 0x00,
|
||||
[KEY_MULTIMEDIA_WWW_REFRESH] = 0x00,
|
||||
[KEY_MULTIMEDIA_WWW_STOP] = 0x00,
|
||||
[KEY_MULTIMEDIA_WWW_FORWARD] = 0x00,
|
||||
[KEY_MULTIMEDIA_WWW_BACK] = 0x00,
|
||||
[KEY_MULTIMEDIA_MY_COMPUTER] = 0x00,
|
||||
[KEY_MULTIMEDIA_EMAIL] = 0x00,
|
||||
[KEY_MULTIMEDIA_MEDIA_SELECT] = 0x00,
|
||||
|
||||
[KEY_ACPI_POWER] = 0x00,
|
||||
[KEY_ACPI_SLEEP] = 0x00,
|
||||
[KEY_ACPI_WAKE] = 0x00};
|
||||
|
||||
#ifdef DEBUG
|
||||
static const char *ScanCodeDebugNames[] = {
|
||||
"KEY_1", "KEY_2", "KEY_3", "KEY_4", "KEY_5", "KEY_6", "KEY_7", "KEY_8",
|
||||
"KEY_9", "KEY_0", "KEY_Q", "KEY_W", "KEY_E", "KEY_R", "KEY_T", "KEY_Y",
|
||||
"KEY_U", "KEY_I", "KEY_O", "KEY_P", "KEY_A", "KEY_S", "KEY_D", "KEY_F",
|
||||
"KEY_G", "KEY_H", "KEY_J", "KEY_K", "KEY_L", "KEY_Z", "KEY_X", "KEY_C",
|
||||
"KEY_V", "KEY_B", "KEY_N", "KEY_M", "KEY_F1", "KEY_F2", "KEY_F3", "KEY_F4",
|
||||
"KEY_F5", "KEY_F6", "KEY_F7", "KEY_F8", "KEY_F9", "KEY_F10", "KEY_F11",
|
||||
"KEY_F12", "KEYPAD_7", "KEYPAD_8", "KEYPAD_9", "KEYPAD_MINUS", "KEYPAD_4",
|
||||
"KEYPAD_5", "KEYPAD_6", "KEYPAD_PLUS", "KEYPAD_1", "KEYPAD_2", "KEYPAD_3",
|
||||
"KEYPAD_0", "KEYPAD_PERIOD", "KEYPAD_RETURN", "KEYPAD_ASTERISK", "KEYPAD_SLASH",
|
||||
"KEY_LEFT_CTRL", "KEY_RIGHT_CTRL", "KEY_LEFT_SHIFT", "KEY_RIGHT_SHIFT",
|
||||
"KEY_LEFT_ALT", "KEY_RIGHT_ALT", "KEY_ESCAPE", "KEY_MINUS", "KEY_EQUAL",
|
||||
"KEY_BACKSPACE", "KEY_TAB", "KEY_LEFT_BRACKET", "KEY_RIGHT_BRACKET",
|
||||
"KEY_RETURN", "KEY_SEMICOLON", "KEY_APOSTROPHE", "KEY_BACK_TICK",
|
||||
"KEY_BACKSLASH", "KEY_COMMA", "KEY_PERIOD", "KEY_SLASH", "KEY_SPACE",
|
||||
"KEY_CAPS_LOCK", "KEY_NUM_LOCK", "KEY_SCROLL_LOCK", "KEY_PRINT_SCREEN",
|
||||
"KEY_HOME", "KEY_UP_ARROW", "KEY_LEFT_ARROW", "KEY_RIGHT_ARROW",
|
||||
"KEY_DOWN_ARROW", "KEY_PAGE_UP", "KEY_PAGE_DOWN", "KEY_END", "KEY_INSERT",
|
||||
"KEY_DELETE", "KEY_LEFT_GUI", "KEY_RIGHT_GUI", "KEY_APPS",
|
||||
"KEY_MULTIMEDIA_PREV_TRACK", "KEY_MULTIMEDIA_NEXT_TRACK", "KEY_MULTIMEDIA_MUTE",
|
||||
"KEY_MULTIMEDIA_CALCULATOR", "KEY_MULTIMEDIA_PLAY", "KEY_MULTIMEDIA_STOP",
|
||||
"KEY_MULTIMEDIA_VOL_DOWN", "KEY_MULTIMEDIA_VOL_UP", "KEY_MULTIMEDIA_WWW_HOME",
|
||||
"KEY_MULTIMEDIA_WWW_SEARCH", "KEY_MULTIMEDIA_WWW_FAVORITES",
|
||||
"KEY_MULTIMEDIA_WWW_REFRESH", "KEY_MULTIMEDIA_WWW_STOP",
|
||||
"KEY_MULTIMEDIA_WWW_FORWARD", "KEY_MULTIMEDIA_WWW_BACK",
|
||||
"KEY_MULTIMEDIA_MY_COMPUTER", "KEY_MULTIMEDIA_EMAIL",
|
||||
"KEY_MULTIMEDIA_MEDIA_SELECT", "KEY_ACPI_POWER", "KEY_ACPI_SLEEP", "KEY_ACPI_WAKE"};
|
||||
#endif
|
||||
|
||||
namespace Driver
|
||||
{
|
||||
char GetScanCode(uint8_t ScanCode, bool Upper)
|
||||
{
|
||||
ScanCode &= 0x7F; /* Remove KEY_PRESSED bit */
|
||||
if (ScanCode >= sizeof(ScanCodeConversionTableLower))
|
||||
{
|
||||
warn("Unknown scancode %x", ScanCode);
|
||||
return 0x00;
|
||||
}
|
||||
|
||||
// debug("Scancode %x (%s)", ScanCode, ScanCodeDebugNames[ScanCode]);
|
||||
return Upper
|
||||
? ScanCodeConversionTableUpper[ScanCode]
|
||||
: ScanCodeConversionTableLower[ScanCode];
|
||||
}
|
||||
|
||||
bool IsValidChar(uint8_t ScanCode)
|
||||
{
|
||||
ScanCode &= 0x7F; /* Remove KEY_PRESSED bit */
|
||||
if (ScanCode >= sizeof(ScanCodeConversionTableLower))
|
||||
return false;
|
||||
|
||||
if (ScanCode > KEY_M)
|
||||
{
|
||||
if (ScanCode < KEYPAD_7)
|
||||
return false; /* F1 - F12 */
|
||||
|
||||
switch (ScanCode)
|
||||
{
|
||||
case KEY_MINUS:
|
||||
case KEY_EQUAL:
|
||||
case KEY_LEFT_BRACKET:
|
||||
case KEY_RIGHT_BRACKET:
|
||||
case KEY_RETURN:
|
||||
case KEY_SEMICOLON:
|
||||
case KEY_APOSTROPHE:
|
||||
case KEY_BACK_TICK:
|
||||
case KEY_BACKSLASH:
|
||||
case KEY_COMMA:
|
||||
case KEY_PERIOD:
|
||||
case KEY_SLASH:
|
||||
case KEY_SPACE:
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
132
core/dsdt.cpp
132
core/dsdt.cpp
@ -54,11 +54,7 @@ namespace ACPI
|
||||
#define ACPI_GAS_IO 1
|
||||
#define ACPI_GAS_PCI 2
|
||||
|
||||
#if defined(a64)
|
||||
void DSDT::OnInterruptReceived(CPU::x64::TrapFrame *)
|
||||
#elif defined(a32)
|
||||
void DSDT::OnInterruptReceived(CPU::x32::TrapFrame *)
|
||||
#endif
|
||||
void DSDT::OnInterruptReceived(CPU::TrapFrame *)
|
||||
{
|
||||
debug("SCI Handle Triggered");
|
||||
uint16_t Event = 0;
|
||||
@ -77,7 +73,27 @@ namespace ACPI
|
||||
Event = a | b;
|
||||
}
|
||||
|
||||
debug("SCI Event: %#lx", Event);
|
||||
#ifdef DEBUG
|
||||
char dbgEvStr[128];
|
||||
dbgEvStr[0] = '\0';
|
||||
if (Event & ACPI_BUSMASTER)
|
||||
strcat(dbgEvStr, "BUSMASTER ");
|
||||
if (Event & ACPI_GLOBAL)
|
||||
strcat(dbgEvStr, "GLOBAL ");
|
||||
if (Event & ACPI_POWER_BUTTON)
|
||||
strcat(dbgEvStr, "POWER_BUTTON ");
|
||||
if (Event & ACPI_SLEEP_BUTTON)
|
||||
strcat(dbgEvStr, "SLEEP_BUTTON ");
|
||||
if (Event & ACPI_RTC_ALARM)
|
||||
strcat(dbgEvStr, "RTC_ALARM ");
|
||||
if (Event & ACPI_PCIE_WAKE)
|
||||
strcat(dbgEvStr, "PCIE_WAKE ");
|
||||
if (Event & ACPI_WAKE)
|
||||
strcat(dbgEvStr, "WAKE ");
|
||||
if (Event & ACPI_TIMER)
|
||||
strcat(dbgEvStr, "ACPI_TIMER ");
|
||||
KPrint("SCI Event: %s", dbgEvStr);
|
||||
#endif
|
||||
if (Event & ACPI_BUSMASTER)
|
||||
{
|
||||
fixme("ACPI Busmaster");
|
||||
@ -88,12 +104,13 @@ namespace ACPI
|
||||
}
|
||||
else if (Event & ACPI_POWER_BUTTON)
|
||||
{
|
||||
if (TaskManager && !TaskManager->IsPanic())
|
||||
Tasking::PCB *pcb = thisProcess;
|
||||
if (pcb && !pcb->GetContext()->IsPanic())
|
||||
{
|
||||
TaskManager->CreateThread(TaskManager->CreateProcess(nullptr,
|
||||
"Shutdown",
|
||||
Tasking::TaskExecutionMode::Kernel),
|
||||
Tasking::IP(KST_Shutdown));
|
||||
Tasking::Task *ctx = pcb->GetContext();
|
||||
ctx->CreateThread(ctx->GetKernelProcess(),
|
||||
Tasking::IP(KST_Shutdown))
|
||||
->Rename("Shutdown");
|
||||
}
|
||||
else
|
||||
KernelShutdownThread(false);
|
||||
@ -120,35 +137,56 @@ namespace ACPI
|
||||
}
|
||||
else
|
||||
{
|
||||
error("ACPI unknown event %#lx on CPU %d", Event, GetCurrentCPU()->ID);
|
||||
CPU::Stop();
|
||||
error("ACPI unknown event %#lx on CPU %d",
|
||||
Event, GetCurrentCPU()->ID);
|
||||
KPrint("ACPI unknown event %#lx on CPU %d",
|
||||
Event, GetCurrentCPU()->ID);
|
||||
}
|
||||
}
|
||||
|
||||
void DSDT::Shutdown()
|
||||
{
|
||||
trace("Shutting down...");
|
||||
if (SCI_EN == 1)
|
||||
if (SCI_EN != 1)
|
||||
{
|
||||
outw(s_cst(uint16_t, acpi->FADT->PM1aControlBlock),
|
||||
s_cst(uint16_t,
|
||||
(inw(s_cst(uint16_t,
|
||||
acpi->FADT->PM1aControlBlock)) &
|
||||
0xE3FF) |
|
||||
((SLP_TYPa << 10) | ACPI_SLEEP)));
|
||||
|
||||
if (acpi->FADT->PM1bControlBlock)
|
||||
outw(s_cst(uint16_t, acpi->FADT->PM1bControlBlock),
|
||||
s_cst(uint16_t,
|
||||
(inw(
|
||||
s_cst(uint16_t, acpi->FADT->PM1bControlBlock)) &
|
||||
0xE3FF) |
|
||||
((SLP_TYPb << 10) | ACPI_SLEEP)));
|
||||
|
||||
outw(s_cst(uint16_t, PM1a_CNT), SLP_TYPa | SLP_EN);
|
||||
if (PM1b_CNT)
|
||||
outw(s_cst(uint16_t, PM1b_CNT), SLP_TYPb | SLP_EN);
|
||||
error("ACPI Shutdown not supported");
|
||||
return;
|
||||
}
|
||||
|
||||
if (inw(s_cst(uint16_t, PM1a_CNT) & SCI_EN) == 0)
|
||||
{
|
||||
KPrint("ACPI was disabled, enabling...");
|
||||
if (SMI_CMD == 0 || ACPI_ENABLE == 0)
|
||||
{
|
||||
error("ACPI Shutdown not supported");
|
||||
KPrint("ACPI Shutdown not supported");
|
||||
return;
|
||||
}
|
||||
|
||||
outb(s_cst(uint16_t, SMI_CMD), ACPI_ENABLE);
|
||||
|
||||
uint16_t Timeout = 3000;
|
||||
while ((inw(s_cst(uint16_t, PM1a_CNT)) & SCI_EN) == 0 && Timeout-- > 0)
|
||||
;
|
||||
|
||||
if (Timeout == 0)
|
||||
{
|
||||
error("ACPI Shutdown not supported");
|
||||
KPrint("ACPI Shutdown not supported");
|
||||
return;
|
||||
}
|
||||
|
||||
if (PM1b_CNT)
|
||||
{
|
||||
Timeout = 3000;
|
||||
while ((inw(s_cst(uint16_t, PM1b_CNT)) & SCI_EN) == 0 && Timeout-- > 0)
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
outw(s_cst(uint16_t, PM1a_CNT), SLP_TYPa | SLP_EN);
|
||||
if (PM1b_CNT)
|
||||
outw(s_cst(uint16_t, PM1b_CNT), SLP_TYPb | SLP_EN);
|
||||
}
|
||||
|
||||
void DSDT::Reboot()
|
||||
@ -187,21 +225,24 @@ namespace ACPI
|
||||
}
|
||||
}
|
||||
|
||||
DSDT::DSDT(ACPI *acpi) : Interrupts::Handler(acpi->FADT->SCI_Interrupt)
|
||||
DSDT::DSDT(ACPI *acpi) : Interrupts::Handler(acpi->FADT->SCI_Interrupt, true)
|
||||
{
|
||||
/* TODO: AML Interpreter */
|
||||
|
||||
this->acpi = acpi;
|
||||
uint64_t Address = ((IsCanonical(acpi->FADT->X_Dsdt) && acpi->XSDTSupported) ? acpi->FADT->X_Dsdt : acpi->FADT->Dsdt);
|
||||
uint8_t *S5Address = (uint8_t *)(Address) + 36;
|
||||
ACPI::ACPI::ACPIHeader *Header = (ACPI::ACPI::ACPIHeader *)Address;
|
||||
if (!Memory::Virtual().Check(Header))
|
||||
Memory::Virtual vmm;
|
||||
if (!vmm.Check(Header))
|
||||
{
|
||||
warn("DSDT is not mapped");
|
||||
debug("DSDT: %#lx", Address);
|
||||
Memory::Virtual().Map(Header, Header, Memory::RW);
|
||||
vmm.Map(Header, Header, Memory::RW);
|
||||
}
|
||||
|
||||
size_t Length = Header->Length;
|
||||
Memory::Virtual().Map(Header, Header, Length, Memory::RW);
|
||||
vmm.Map(Header, Header, Length, Memory::RW);
|
||||
|
||||
while (Length-- > 0)
|
||||
{
|
||||
@ -212,20 +253,27 @@ namespace ACPI
|
||||
|
||||
if (Length <= 0)
|
||||
{
|
||||
warn("_S5 not present in ACPI");
|
||||
warn("_S5_ not present in ACPI");
|
||||
return;
|
||||
}
|
||||
|
||||
if ((*(S5Address - 1) == 0x08 || (*(S5Address - 2) == 0x08 && *(S5Address - 1) == '\\')) && *(S5Address + 4) == 0x12)
|
||||
if ((*(S5Address - 1) == 0x08 ||
|
||||
(*(S5Address - 2) == 0x08 &&
|
||||
*(S5Address - 1) == '\\')) &&
|
||||
*(S5Address + 4) == 0x12)
|
||||
{
|
||||
S5Address += 5;
|
||||
S5Address += ((*S5Address & 0xC0) >> 6) + 2;
|
||||
|
||||
if (*S5Address == 0x0A)
|
||||
S5Address++;
|
||||
|
||||
SLP_TYPa = s_cst(uint16_t, *(S5Address) << 10);
|
||||
S5Address++;
|
||||
|
||||
if (*S5Address == 0x0A)
|
||||
S5Address++;
|
||||
|
||||
SLP_TYPb = s_cst(uint16_t, *(S5Address) << 10);
|
||||
SMI_CMD = acpi->FADT->SMI_CommandPort;
|
||||
ACPI_ENABLE = acpi->FADT->AcpiEnable;
|
||||
@ -235,11 +283,13 @@ namespace ACPI
|
||||
PM1_CNT_LEN = acpi->FADT->PM1ControlLength;
|
||||
SLP_EN = 1 << 13;
|
||||
SCI_EN = 1;
|
||||
trace("ACPI Shutdown is supported");
|
||||
KPrint("ACPI Shutdown is supported");
|
||||
ACPIShutdownSupported = true;
|
||||
|
||||
{
|
||||
uint16_t value = ACPI_POWER_BUTTON | ACPI_SLEEP_BUTTON | ACPI_WAKE;
|
||||
const uint16_t value = /*ACPI_TIMER |*/ ACPI_BUSMASTER | ACPI_GLOBAL |
|
||||
ACPI_POWER_BUTTON | ACPI_SLEEP_BUTTON | ACPI_RTC_ALARM |
|
||||
ACPI_PCIE_WAKE | ACPI_WAKE;
|
||||
uint16_t a = s_cst(uint16_t, acpi->FADT->PM1aEventBlock + (acpi->FADT->PM1EventLength / 2));
|
||||
uint16_t b = s_cst(uint16_t, acpi->FADT->PM1bEventBlock + (acpi->FADT->PM1EventLength / 2));
|
||||
debug("SCI Event: %#x [a:%#x b:%#x]", value, a, b);
|
||||
@ -266,7 +316,7 @@ namespace ACPI
|
||||
((APIC::APIC *)Interrupts::apic[0])->RedirectIRQ(0, uint8_t(acpi->FADT->SCI_Interrupt), 1);
|
||||
return;
|
||||
}
|
||||
warn("Failed to parse _S5 in ACPI");
|
||||
warn("Failed to parse _S5_ in ACPI");
|
||||
SCI_EN = 0;
|
||||
}
|
||||
|
||||
|
@ -46,10 +46,64 @@ namespace Interrupts
|
||||
{
|
||||
struct Event
|
||||
{
|
||||
int ID;
|
||||
/** Interrupt number */
|
||||
int IRQ;
|
||||
|
||||
/** Raw pointer to the Handler */
|
||||
void *Data;
|
||||
|
||||
/** Is this a handler? */
|
||||
bool IsHandler;
|
||||
|
||||
/**
|
||||
* Function to call if this is not a Handler
|
||||
*
|
||||
* Used for C-style callbacks.
|
||||
*/
|
||||
void (*Callback)(CPU::TrapFrame *);
|
||||
|
||||
/**
|
||||
* Context for the callback
|
||||
*
|
||||
* Used for C-style callbacks if the callback needs a context.
|
||||
* (e.g. a driver)
|
||||
*/
|
||||
void *Context;
|
||||
|
||||
/**
|
||||
* Priority of the event
|
||||
*
|
||||
* Used for sorting the events.
|
||||
*
|
||||
* This is incremented every time the event is called.
|
||||
*
|
||||
* This will improve performance by reducing the time
|
||||
* spent on searching for the event.
|
||||
*/
|
||||
unsigned long Priority;
|
||||
|
||||
/**
|
||||
* If this is true, the event is critical.
|
||||
*
|
||||
* This will make sure that the event will not be
|
||||
* removed by the kernel.
|
||||
*
|
||||
* This is used to prevent the kernel from removing
|
||||
* ACPI related handlers. (SCI interrupts)
|
||||
*/
|
||||
bool Critical;
|
||||
};
|
||||
std::vector<Event> RegisteredEvents;
|
||||
std::list<Event> RegisteredEvents;
|
||||
|
||||
#ifdef DEBUG
|
||||
#define SORT_DIVIDER 10
|
||||
#else
|
||||
#define SORT_DIVIDER 1
|
||||
#endif
|
||||
|
||||
#define SORT_START 10000
|
||||
std::atomic_uint SortEvents = SORT_START / SORT_DIVIDER;
|
||||
constexpr uint32_t SORT_ITR = (SORT_START * 100) / SORT_DIVIDER;
|
||||
|
||||
#if defined(a86)
|
||||
/* APIC::APIC */ void *apic[MAX_CPU];
|
||||
@ -120,6 +174,7 @@ namespace Interrupts
|
||||
#elif defined(aa64)
|
||||
warn("aarch64 is not supported yet");
|
||||
#endif
|
||||
CPU::Interrupts(CPU::Enable);
|
||||
}
|
||||
|
||||
void InitializeTimer(int Core)
|
||||
@ -139,7 +194,90 @@ namespace Interrupts
|
||||
|
||||
SafeFunction void RemoveAll()
|
||||
{
|
||||
RegisteredEvents.clear();
|
||||
forItr(itr, RegisteredEvents)
|
||||
{
|
||||
if (itr->Critical)
|
||||
continue;
|
||||
RegisteredEvents.erase(itr);
|
||||
}
|
||||
}
|
||||
|
||||
void AddHandler(void (*Callback)(CPU::TrapFrame *),
|
||||
int InterruptNumber,
|
||||
void *ctx, bool Critical)
|
||||
{
|
||||
/* Just log a warning if the interrupt is already registered. */
|
||||
foreach (auto ev in RegisteredEvents)
|
||||
{
|
||||
if (ev.IRQ == InterruptNumber &&
|
||||
ev.Callback == Callback)
|
||||
{
|
||||
warn("IRQ%d is already registered.",
|
||||
InterruptNumber);
|
||||
}
|
||||
}
|
||||
|
||||
Event newEvent =
|
||||
{InterruptNumber, /* IRQ */
|
||||
nullptr, /* Data */
|
||||
false, /* IsHandler */
|
||||
Callback, /* Callback */
|
||||
ctx, /* Context */
|
||||
0, /* Priority */
|
||||
Critical}; /* Critical */
|
||||
RegisteredEvents.push_back(newEvent);
|
||||
debug("Registered interrupt handler for IRQ%d to %#lx",
|
||||
InterruptNumber, Callback);
|
||||
}
|
||||
|
||||
void RemoveHandler(void (*Callback)(CPU::TrapFrame *), int InterruptNumber)
|
||||
{
|
||||
forItr(itr, RegisteredEvents)
|
||||
{
|
||||
if (itr->IRQ == InterruptNumber &&
|
||||
itr->Callback == Callback)
|
||||
{
|
||||
RegisteredEvents.erase(itr);
|
||||
debug("Unregistered interrupt handler for IRQ%d to %#lx",
|
||||
InterruptNumber, Callback);
|
||||
return;
|
||||
}
|
||||
}
|
||||
warn("Event %d not found.", InterruptNumber);
|
||||
}
|
||||
|
||||
void RemoveHandler(void (*Callback)(CPU::TrapFrame *))
|
||||
{
|
||||
forItr(itr, RegisteredEvents)
|
||||
{
|
||||
if (itr->Callback == Callback)
|
||||
{
|
||||
debug("Removing handle %d %#lx", itr->IRQ,
|
||||
itr->IsHandler
|
||||
? itr->Data
|
||||
: (void *)itr->Callback);
|
||||
|
||||
RegisteredEvents.erase(itr);
|
||||
}
|
||||
}
|
||||
warn("Handle not found.");
|
||||
}
|
||||
|
||||
void RemoveHandler(int InterruptNumber)
|
||||
{
|
||||
forItr(itr, RegisteredEvents)
|
||||
{
|
||||
if (itr->IRQ == InterruptNumber)
|
||||
{
|
||||
debug("Removing handle %d %#lx", itr->IRQ,
|
||||
itr->IsHandler
|
||||
? itr->Data
|
||||
: (void *)itr->Callback);
|
||||
|
||||
RegisteredEvents.erase(itr);
|
||||
}
|
||||
}
|
||||
warn("IRQ%d not found.", InterruptNumber);
|
||||
}
|
||||
|
||||
extern "C" SafeFunction void MainInterruptHandler(void *Data)
|
||||
@ -170,77 +308,126 @@ namespace Interrupts
|
||||
Core = CoreData->ID;
|
||||
|
||||
/* If this is false, we have a big problem. */
|
||||
if (likely(Frame->InterruptNumber < CPU::x86::IRQ223 &&
|
||||
Frame->InterruptNumber > CPU::x86::ISR0))
|
||||
{
|
||||
/* Halt core interrupt */
|
||||
if (unlikely(Frame->InterruptNumber == CPU::x86::IRQ29))
|
||||
CPU::Stop();
|
||||
|
||||
bool InterruptHandled = false;
|
||||
foreach (auto ev in RegisteredEvents)
|
||||
{
|
||||
#if defined(a86)
|
||||
if ((ev.ID + CPU::x86::IRQ0) == s_cst(int, Frame->InterruptNumber))
|
||||
#elif defined(aa64)
|
||||
if (ev.ID == s_cst(int, Frame->InterruptNumber))
|
||||
#endif
|
||||
{
|
||||
Handler *hnd = (Handler *)ev.Data;
|
||||
hnd->OnInterruptReceived(Frame);
|
||||
InterruptHandled = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!InterruptHandled)
|
||||
{
|
||||
error("IRQ%d is unhandled on CPU %d.",
|
||||
Frame->InterruptNumber - 32, Core);
|
||||
if (Frame->InterruptNumber == CPU::x86::IRQ1)
|
||||
{
|
||||
uint8_t scancode = inb(0x60);
|
||||
warn("IRQ1 is the keyboard interrupt. Scancode: %#x", scancode);
|
||||
}
|
||||
}
|
||||
|
||||
if (likely(apic[Core]))
|
||||
{
|
||||
APIC::APIC *this_apic = (APIC::APIC *)apic[Core];
|
||||
this_apic->EOI();
|
||||
// TODO: Handle PIC too
|
||||
return;
|
||||
}
|
||||
else
|
||||
fixme("APIC not found for core %d", Core);
|
||||
// TODO: PIC
|
||||
}
|
||||
else
|
||||
if (unlikely(Frame->InterruptNumber >= CPU::x86::IRQ223 ||
|
||||
Frame->InterruptNumber <= CPU::x86::ISR0))
|
||||
{
|
||||
error("Interrupt number %d is out of range.",
|
||||
Frame->InterruptNumber);
|
||||
assert(!"Interrupt number is out of range.");
|
||||
}
|
||||
|
||||
error("HALT HALT HALT HALT HALT HALT HALT HALT HALT [IRQ%d]",
|
||||
Frame->InterruptNumber - 32);
|
||||
/* Halt core interrupt */
|
||||
if (unlikely(Frame->InterruptNumber == CPU::x86::IRQ31))
|
||||
CPU::Stop();
|
||||
|
||||
bool InterruptHandled = false;
|
||||
foreach (auto &ev in RegisteredEvents)
|
||||
{
|
||||
#if defined(a86)
|
||||
int iEvNum = ev.IRQ + CPU::x86::IRQ0;
|
||||
#elif defined(aa64)
|
||||
int iEvNum = ev.IRQ;
|
||||
#endif
|
||||
if (iEvNum == s_cst(int, Frame->InterruptNumber))
|
||||
{
|
||||
if (ev.IsHandler)
|
||||
{
|
||||
Handler *hnd = (Handler *)ev.Data;
|
||||
hnd->OnInterruptReceived(Frame);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ev.Context != nullptr)
|
||||
ev.Callback((CPU::TrapFrame *)ev.Context);
|
||||
else
|
||||
ev.Callback(Frame);
|
||||
}
|
||||
ev.Priority++;
|
||||
InterruptHandled = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (unlikely(!InterruptHandled))
|
||||
{
|
||||
error("IRQ%d is unhandled on CPU %d.",
|
||||
Frame->InterruptNumber - 32, Core);
|
||||
}
|
||||
|
||||
/* TODO: This should be done when the os is idle */
|
||||
if (SortEvents++ > SORT_ITR)
|
||||
{
|
||||
debug("Sorting events");
|
||||
SortEvents = 0;
|
||||
RegisteredEvents.sort([](const Event &a, const Event &b)
|
||||
{ return a.Priority < b.Priority; });
|
||||
|
||||
#ifdef DEBUG
|
||||
foreach (auto ev in RegisteredEvents)
|
||||
{
|
||||
void *func = ev.IsHandler
|
||||
? ev.Data
|
||||
: (void *)ev.Callback;
|
||||
const char *symbol = ev.IsHandler
|
||||
? "class"
|
||||
: KernelSymbolTable->GetSymbol((uintptr_t)func);
|
||||
|
||||
debug("Event IRQ%d [%#lx %s] has priority %ld",
|
||||
ev.IRQ, func, symbol, ev.Priority);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (likely(apic[Core]))
|
||||
{
|
||||
APIC::APIC *this_apic = (APIC::APIC *)apic[Core];
|
||||
this_apic->EOI();
|
||||
// TODO: Handle PIC too
|
||||
return;
|
||||
}
|
||||
else
|
||||
fixme("APIC not found for core %d", Core);
|
||||
// TODO: PIC
|
||||
|
||||
assert(!"Interrupt EOI not handled.");
|
||||
CPU::Stop();
|
||||
}
|
||||
|
||||
Handler::Handler(int InterruptNumber)
|
||||
Handler::Handler(int InterruptNumber, bool Critical)
|
||||
{
|
||||
foreach (auto ev in RegisteredEvents)
|
||||
{
|
||||
if (ev.ID == InterruptNumber)
|
||||
if (ev.IRQ == InterruptNumber)
|
||||
{
|
||||
warn("IRQ%d is already registered.",
|
||||
InterruptNumber);
|
||||
}
|
||||
}
|
||||
|
||||
debug("Registering interrupt handler for IRQ%d.",
|
||||
InterruptNumber);
|
||||
|
||||
this->InterruptNumber = InterruptNumber;
|
||||
RegisteredEvents.push_back({InterruptNumber, this});
|
||||
|
||||
Event newEvent =
|
||||
{InterruptNumber, /* IRQ */
|
||||
this, /* Data */
|
||||
true, /* IsHandler */
|
||||
nullptr, /* Callback */
|
||||
nullptr, /* Context */
|
||||
0, /* Priority */
|
||||
Critical}; /* Critical */
|
||||
RegisteredEvents.push_back(newEvent);
|
||||
debug("Registered interrupt handler for IRQ%d.",
|
||||
InterruptNumber);
|
||||
}
|
||||
|
||||
Handler::Handler(PCI::PCIDevice Device, bool Critical)
|
||||
{
|
||||
PCI::PCIHeader0 *hdr0 =
|
||||
(PCI::PCIHeader0 *)Device.Header;
|
||||
Handler(hdr0->InterruptLine, Critical);
|
||||
}
|
||||
|
||||
Handler::Handler()
|
||||
{
|
||||
debug("Empty interrupt handler.");
|
||||
}
|
||||
|
||||
Handler::~Handler()
|
||||
@ -250,7 +437,7 @@ namespace Interrupts
|
||||
|
||||
forItr(itr, RegisteredEvents)
|
||||
{
|
||||
if (itr->ID == this->InterruptNumber)
|
||||
if (itr->IRQ == this->InterruptNumber)
|
||||
{
|
||||
RegisteredEvents.erase(itr);
|
||||
return;
|
||||
@ -259,21 +446,9 @@ namespace Interrupts
|
||||
warn("Event %d not found.", this->InterruptNumber);
|
||||
}
|
||||
|
||||
#if defined(a64)
|
||||
void Handler::OnInterruptReceived(CPU::x64::TrapFrame *Frame)
|
||||
void Handler::OnInterruptReceived(CPU::TrapFrame *Frame)
|
||||
{
|
||||
trace("Unhandled interrupt IRQ%d",
|
||||
Frame->InterruptNumber - 32);
|
||||
#elif defined(a32)
|
||||
void Handler::OnInterruptReceived(CPU::x32::TrapFrame *Frame)
|
||||
{
|
||||
trace("Unhandled interrupt IRQ%d",
|
||||
Frame->InterruptNumber - 32);
|
||||
#elif defined(aa64)
|
||||
void Handler::OnInterruptReceived(CPU::aarch64::TrapFrame *Frame)
|
||||
{
|
||||
trace("Unhandled interrupt IRQ%d",
|
||||
trace("Unhandled interrupt %d",
|
||||
Frame->InterruptNumber);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
137
core/lock.cpp
137
core/lock.cpp
@ -22,76 +22,71 @@
|
||||
|
||||
#include "../kernel.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
/* This might end up in a deadlock in the deadlock handler.
|
||||
Nobody can escape the deadlock, not even the
|
||||
deadlock handler itself. */
|
||||
|
||||
// #define PRINT_BACKTRACE
|
||||
#endif
|
||||
// #define PRINT_BACKTRACE 1
|
||||
|
||||
#ifdef PRINT_BACKTRACE
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wframe-address"
|
||||
|
||||
void PrintStacktrace(LockClass::SpinLockData *Lock)
|
||||
{
|
||||
if (KernelSymbolTable)
|
||||
if (!KernelSymbolTable)
|
||||
{
|
||||
struct StackFrame
|
||||
{
|
||||
uintptr_t BasePointer;
|
||||
uintptr_t ReturnAddress;
|
||||
};
|
||||
|
||||
// char DbgAttempt[1024] = "\0";
|
||||
// char DbgHolder[1024] = "\0";
|
||||
|
||||
std::string DbgAttempt = "\0";
|
||||
std::string DbgHolder = "\0";
|
||||
|
||||
StackFrame *FrameAttempt = (StackFrame *)Lock->StackPointerAttempt.load();
|
||||
StackFrame *FrameHolder = (StackFrame *)Lock->StackPointerHolder.load();
|
||||
|
||||
while (Memory::Virtual().Check(FrameAttempt))
|
||||
{
|
||||
DbgAttempt.concat(KernelSymbolTable->GetSymbolFromAddress(FrameAttempt->ReturnAddress));
|
||||
DbgAttempt.concat("<-");
|
||||
FrameAttempt = (StackFrame *)FrameAttempt->BasePointer;
|
||||
}
|
||||
debug("Attempt: %s", DbgAttempt.c_str());
|
||||
|
||||
while (Memory::Virtual().Check(FrameHolder))
|
||||
{
|
||||
DbgHolder.concat(KernelSymbolTable->GetSymbolFromAddress(FrameHolder->ReturnAddress));
|
||||
DbgHolder.concat("<-");
|
||||
FrameHolder = (StackFrame *)FrameHolder->BasePointer;
|
||||
}
|
||||
|
||||
debug("Holder: %s", DbgHolder.c_str());
|
||||
|
||||
// debug("\t\t%s<-%s<-%s<-%s<-%s<-%s<-%s<-%s<-%s<-%s",
|
||||
// KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)),
|
||||
// KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(1)),
|
||||
// KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(2)),
|
||||
// KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(3)),
|
||||
// KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(4)),
|
||||
// KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(5)),
|
||||
// KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(6)),
|
||||
// KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(7)),
|
||||
// KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(8)),
|
||||
// KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(9)));
|
||||
warn("Symbol table not available.");
|
||||
return;
|
||||
}
|
||||
|
||||
struct StackFrame
|
||||
{
|
||||
uintptr_t BasePointer;
|
||||
uintptr_t ReturnAddress;
|
||||
};
|
||||
|
||||
// char DbgAttempt[1024] = "\0";
|
||||
// char DbgHolder[1024] = "\0";
|
||||
std::string DbgAttempt = "\0";
|
||||
std::string DbgHolder = "\0";
|
||||
|
||||
StackFrame *FrameAttempt = (StackFrame *)Lock->StackPointerAttempt.load();
|
||||
StackFrame *FrameHolder = (StackFrame *)Lock->StackPointerHolder.load();
|
||||
|
||||
while (Memory::Virtual().Check(FrameAttempt))
|
||||
{
|
||||
DbgAttempt.concat(KernelSymbolTable->GetSymbol(FrameAttempt->ReturnAddress));
|
||||
DbgAttempt.concat("<-");
|
||||
FrameAttempt = (StackFrame *)FrameAttempt->BasePointer;
|
||||
}
|
||||
warn("Attempt: %s", DbgAttempt.c_str());
|
||||
|
||||
while (Memory::Virtual().Check(FrameHolder))
|
||||
{
|
||||
DbgHolder.concat(KernelSymbolTable->GetSymbol(FrameHolder->ReturnAddress));
|
||||
DbgHolder.concat("<-");
|
||||
FrameHolder = (StackFrame *)FrameHolder->BasePointer;
|
||||
}
|
||||
|
||||
warn("Holder: %s", DbgHolder.c_str());
|
||||
|
||||
// warn("\t\t%s<-%s<-%s<-%s<-%s<-%s<-%s<-%s<-%s<-%s",
|
||||
// KernelSymbolTable->GetSymbol((uintptr_t)__builtin_return_address(0)),
|
||||
// KernelSymbolTable->GetSymbol((uintptr_t)__builtin_return_address(1)),
|
||||
// KernelSymbolTable->GetSymbol((uintptr_t)__builtin_return_address(2)),
|
||||
// KernelSymbolTable->GetSymbol((uintptr_t)__builtin_return_address(3)),
|
||||
// KernelSymbolTable->GetSymbol((uintptr_t)__builtin_return_address(4)),
|
||||
// KernelSymbolTable->GetSymbol((uintptr_t)__builtin_return_address(5)),
|
||||
// KernelSymbolTable->GetSymbol((uintptr_t)__builtin_return_address(6)),
|
||||
// KernelSymbolTable->GetSymbol((uintptr_t)__builtin_return_address(7)),
|
||||
// KernelSymbolTable->GetSymbol((uintptr_t)__builtin_return_address(8)),
|
||||
// KernelSymbolTable->GetSymbol((uintptr_t)__builtin_return_address(9)));
|
||||
}
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
#define DEADLOCK_TIMEOUT 0x100000
|
||||
#define DEADLOCK_TIMEOUT_DEBUGGER 0x1000
|
||||
#define DEADLOCK_TIMEOUT 0x1000
|
||||
#else
|
||||
#define DEADLOCK_TIMEOUT 0x10000000
|
||||
#define DEADLOCK_TIMEOUT_DEBUGGER 0x100000
|
||||
#endif
|
||||
|
||||
bool ForceUnlock = false;
|
||||
@ -159,26 +154,26 @@ int LockClass::Lock(const char *FunctionName)
|
||||
Retry:
|
||||
int i = 0;
|
||||
while (IsLocked.exchange(true, std::memory_order_acquire) &&
|
||||
++i < (DebuggerIsAttached ? DEADLOCK_TIMEOUT_DEBUGGER : DEADLOCK_TIMEOUT))
|
||||
++i < DEADLOCK_TIMEOUT)
|
||||
{
|
||||
this->Yield();
|
||||
}
|
||||
|
||||
if (i >= (DebuggerIsAttached ? DEADLOCK_TIMEOUT_DEBUGGER : DEADLOCK_TIMEOUT))
|
||||
if (i >= DEADLOCK_TIMEOUT)
|
||||
{
|
||||
DeadLock(LockData);
|
||||
goto Retry;
|
||||
}
|
||||
|
||||
LockData.Count++;
|
||||
LockData.CurrentHolder = FunctionName;
|
||||
LockData.StackPointerHolder = (uintptr_t)__builtin_frame_address(0);
|
||||
LockData.Count.fetch_add(1);
|
||||
LockData.CurrentHolder.store(FunctionName);
|
||||
LockData.StackPointerHolder.store((uintptr_t)__builtin_frame_address(0));
|
||||
|
||||
CPUData *CoreData = GetCurrentCPU();
|
||||
if (CoreData != nullptr)
|
||||
LockData.Core = CoreData->ID;
|
||||
LockData.Core.store(CoreData->ID);
|
||||
|
||||
LocksCount++;
|
||||
LocksCount.fetch_add(1);
|
||||
|
||||
__sync;
|
||||
return 0;
|
||||
@ -189,8 +184,8 @@ int LockClass::Unlock()
|
||||
__sync;
|
||||
|
||||
IsLocked.store(false, std::memory_order_release);
|
||||
LockData.Count--;
|
||||
LocksCount--;
|
||||
LockData.Count.fetch_sub(1);
|
||||
LocksCount.fetch_sub(1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -230,19 +225,19 @@ int LockClass::TimeoutLock(const char *FunctionName, uint64_t Timeout)
|
||||
if (!TimeManager)
|
||||
return Lock(FunctionName);
|
||||
|
||||
LockData.AttemptingToGet = FunctionName;
|
||||
LockData.StackPointerAttempt = (uintptr_t)__builtin_frame_address(0);
|
||||
LockData.AttemptingToGet.store(FunctionName);
|
||||
LockData.StackPointerAttempt.store((uintptr_t)__builtin_frame_address(0));
|
||||
|
||||
std::atomic_uint64_t Target = 0;
|
||||
Retry:
|
||||
int i = 0;
|
||||
while (IsLocked.exchange(true, std::memory_order_acquire) &&
|
||||
++i < (DebuggerIsAttached ? DEADLOCK_TIMEOUT_DEBUGGER : DEADLOCK_TIMEOUT))
|
||||
++i < DEADLOCK_TIMEOUT)
|
||||
{
|
||||
this->Yield();
|
||||
}
|
||||
|
||||
if (i >= (DebuggerIsAttached ? DEADLOCK_TIMEOUT_DEBUGGER : DEADLOCK_TIMEOUT))
|
||||
if (i >= DEADLOCK_TIMEOUT)
|
||||
{
|
||||
if (Target.load() == 0)
|
||||
Target.store(TimeManager->CalculateTarget(Timeout,
|
||||
@ -251,15 +246,15 @@ Retry:
|
||||
goto Retry;
|
||||
}
|
||||
|
||||
LockData.Count++;
|
||||
LockData.CurrentHolder = FunctionName;
|
||||
LockData.StackPointerHolder = (uintptr_t)__builtin_frame_address(0);
|
||||
LockData.Count.fetch_add(1);
|
||||
LockData.CurrentHolder.store(FunctionName);
|
||||
LockData.StackPointerHolder.store((uintptr_t)__builtin_frame_address(0));
|
||||
|
||||
CPUData *CoreData = GetCurrentCPU();
|
||||
if (CoreData != nullptr)
|
||||
LockData.Core = CoreData->ID;
|
||||
LockData.Core.store(CoreData->ID);
|
||||
|
||||
LocksCount++;
|
||||
LocksCount.fetch_add(1);
|
||||
|
||||
__sync;
|
||||
return 0;
|
||||
|
@ -38,39 +38,45 @@ namespace Memory
|
||||
|
||||
/* Check if the address is valid. */
|
||||
if ((uintptr_t)Address < HeapStart)
|
||||
{
|
||||
debug("Address %#lx is less than HeapStart %#lx", Address, HeapStart);
|
||||
return (void *)-ENOMEM;
|
||||
}
|
||||
|
||||
Virtual vmm = Virtual(this->Table);
|
||||
Virtual vmm(this->Table);
|
||||
|
||||
if ((uintptr_t)Address > Break)
|
||||
{
|
||||
/* Allocate more memory. */
|
||||
size_t Pages = TO_PAGES(uintptr_t(Address) - Break);
|
||||
ssize_t Pages = TO_PAGES(uintptr_t(Address) - Break);
|
||||
void *Allocated = vma->RequestPages(Pages);
|
||||
if (Allocated == nullptr)
|
||||
return (void *)-ENOMEM;
|
||||
|
||||
/* Map the allocated pages. */
|
||||
for (size_t i = 0; i < Pages; i++)
|
||||
for (ssize_t i = 0; i < Pages; i++)
|
||||
{
|
||||
void *VirtAddr = (void *)(Break + (i * PAGE_SIZE));
|
||||
void *PhysAddr = (void *)(uintptr_t(Allocated) + (i * PAGE_SIZE));
|
||||
debug("Mapping %#lx to %#lx", VirtAddr, PhysAddr);
|
||||
vmm.Map(VirtAddr, PhysAddr, RW | US);
|
||||
}
|
||||
|
||||
Break = (uint64_t)Address;
|
||||
return (void *)Break;
|
||||
Break = ROUND_UP(uintptr_t(Address), PAGE_SIZE);
|
||||
debug("Round up %#lx to %#lx", Address, Break);
|
||||
return Address;
|
||||
}
|
||||
|
||||
/* Free memory. */
|
||||
size_t Pages = TO_PAGES(uintptr_t(Address) - Break);
|
||||
ssize_t Pages = TO_PAGES(Break - uintptr_t(Address));
|
||||
vma->FreePages((void *)Break, Pages);
|
||||
|
||||
/* Unmap the freed pages. */
|
||||
for (size_t i = 0; i < Pages; i++)
|
||||
for (ssize_t i = 0; i < Pages; i++)
|
||||
{
|
||||
uint64_t Page = Break - (i * 0x1000);
|
||||
vmm.Remap((void *)Page, (void *)Page, PTFlag::P | PTFlag::RW);
|
||||
vmm.Remap((void *)Page, (void *)Page, RW);
|
||||
debug("Unmapping %#lx", Page);
|
||||
}
|
||||
|
||||
Break = (uint64_t)Address;
|
||||
@ -82,12 +88,16 @@ namespace Memory
|
||||
assert(Table != nullptr);
|
||||
assert(vma != nullptr);
|
||||
|
||||
debug("+ %#lx", this);
|
||||
|
||||
this->Table = Table;
|
||||
this->vma = vma;
|
||||
}
|
||||
|
||||
ProgramBreak::~ProgramBreak()
|
||||
{
|
||||
debug("- %#lx", this);
|
||||
|
||||
/* Do nothing because VirtualMemoryArea
|
||||
will be destroyed later. */
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include "liballoc_1_1.h"
|
||||
#include <convert.h>
|
||||
|
||||
#pragma GCC diagnostic ignored "-Wconversion"
|
||||
#pragma GCC diagnostic ignored "-Wsign-conversion"
|
||||
@ -104,6 +105,7 @@ static long long l_possibleOverruns = 0; ///< Number of possible overruns
|
||||
|
||||
__no_sanitize("undefined") static void *liballoc_memset(void *s, int c, size_t n)
|
||||
{
|
||||
return memset(s, c, n);
|
||||
unsigned int i;
|
||||
for (i = 0; i < n; i++)
|
||||
((char *)s)[i] = c;
|
||||
@ -112,6 +114,7 @@ __no_sanitize("undefined") static void *liballoc_memset(void *s, int c, size_t n
|
||||
}
|
||||
__no_sanitize("undefined") static void *liballoc_memcpy(void *s1, const void *s2, size_t n)
|
||||
{
|
||||
return memcpy(s1, s2, n);
|
||||
char *cdest;
|
||||
char *csrc;
|
||||
unsigned int *ldest = (unsigned int *)s1;
|
||||
|
@ -24,46 +24,46 @@ extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/** This function is supposed to lock the memory data structures. It
|
||||
* could be as simple as disabling interrupts or acquiring a spinlock.
|
||||
* It's up to you to decide.
|
||||
*
|
||||
* \return 0 if the lock was acquired successfully. Anything else is
|
||||
* failure.
|
||||
*/
|
||||
extern int liballoc_lock();
|
||||
/** This function is supposed to lock the memory data structures. It
|
||||
* could be as simple as disabling interrupts or acquiring a spinlock.
|
||||
* It's up to you to decide.
|
||||
*
|
||||
* \return 0 if the lock was acquired successfully. Anything else is
|
||||
* failure.
|
||||
*/
|
||||
extern int liballoc_lock();
|
||||
|
||||
/** This function unlocks what was previously locked by the liballoc_lock
|
||||
* function. If it disabled interrupts, it enables interrupts. If it
|
||||
* had acquiried a spinlock, it releases the spinlock. etc.
|
||||
*
|
||||
* \return 0 if the lock was successfully released.
|
||||
*/
|
||||
extern int liballoc_unlock();
|
||||
/** This function unlocks what was previously locked by the liballoc_lock
|
||||
* function. If it disabled interrupts, it enables interrupts. If it
|
||||
* had acquiried a spinlock, it releases the spinlock. etc.
|
||||
*
|
||||
* \return 0 if the lock was successfully released.
|
||||
*/
|
||||
extern int liballoc_unlock();
|
||||
|
||||
/** This is the hook into the local system which allocates pages. It
|
||||
* accepts an integer parameter which is the number of pages
|
||||
* required. The page size was set up in the liballoc_init function.
|
||||
*
|
||||
* \return NULL if the pages were not allocated.
|
||||
* \return A pointer to the allocated memory.
|
||||
*/
|
||||
extern void *liballoc_alloc(size_t);
|
||||
/** This is the hook into the local system which allocates pages. It
|
||||
* accepts an integer parameter which is the number of pages
|
||||
* required. The page size was set up in the liballoc_init function.
|
||||
*
|
||||
* \return NULL if the pages were not allocated.
|
||||
* \return A pointer to the allocated memory.
|
||||
*/
|
||||
extern void *liballoc_alloc(size_t);
|
||||
|
||||
/** This frees previously allocated memory. The void* parameter passed
|
||||
* to the function is the exact same value returned from a previous
|
||||
* liballoc_alloc call.
|
||||
*
|
||||
* The integer value is the number of pages to free.
|
||||
*
|
||||
* \return 0 if the memory was successfully freed.
|
||||
*/
|
||||
extern int liballoc_free(void *, size_t);
|
||||
/** This frees previously allocated memory. The void* parameter passed
|
||||
* to the function is the exact same value returned from a previous
|
||||
* liballoc_alloc call.
|
||||
*
|
||||
* The integer value is the number of pages to free.
|
||||
*
|
||||
* \return 0 if the memory was successfully freed.
|
||||
*/
|
||||
extern int liballoc_free(void *, size_t);
|
||||
|
||||
extern void *PREFIX(malloc)(size_t); ///< The standard function.
|
||||
extern void *PREFIX(realloc)(void *, size_t); ///< The standard function.
|
||||
extern void *PREFIX(calloc)(size_t, size_t); ///< The standard function.
|
||||
extern void PREFIX(free)(void *); ///< The standard function.
|
||||
extern void *PREFIX(malloc)(size_t); ///< The standard function.
|
||||
extern void *PREFIX(realloc)(void *, size_t); ///< The standard function.
|
||||
extern void *PREFIX(calloc)(size_t, size_t); ///< The standard function.
|
||||
extern void PREFIX(free)(void *); ///< The standard function.
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -16,11 +16,14 @@ EXTERNC int liballoc_unlock()
|
||||
|
||||
EXTERNC void *liballoc_alloc(size_t Pages)
|
||||
{
|
||||
return KernelAllocator.RequestPages(Pages);
|
||||
void *ret = KernelAllocator.RequestPages(Pages);
|
||||
debug("(%d) = %#lx", Pages, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
EXTERNC int liballoc_free(void *Address, size_t Pages)
|
||||
{
|
||||
debug("(%#lx, %d)", Address, Pages);
|
||||
KernelAllocator.FreePages(Address, Pages);
|
||||
return 0;
|
||||
}
|
||||
|
3597
core/memory/heap_allocators/rpmalloc/rpmalloc.c
Normal file
3597
core/memory/heap_allocators/rpmalloc/rpmalloc.c
Normal file
File diff suppressed because it is too large
Load Diff
371
core/memory/heap_allocators/rpmalloc/rpmalloc.h
Normal file
371
core/memory/heap_allocators/rpmalloc/rpmalloc.h
Normal file
@ -0,0 +1,371 @@
|
||||
/* rpmalloc.h - Memory allocator - Public Domain - 2016 Mattias Jansson
|
||||
*
|
||||
* This library provides a cross-platform lock free thread caching malloc implementation in C11.
|
||||
* The latest source code is always available at
|
||||
*
|
||||
* https://github.com/mjansson/rpmalloc
|
||||
*
|
||||
* This library is put in the public domain; you can redistribute it and/or modify it without any restrictions.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#if defined(__clang__) || defined(__GNUC__)
|
||||
#define RPMALLOC_EXPORT __attribute__((visibility("default")))
|
||||
#define RPMALLOC_ALLOCATOR
|
||||
#if (defined(__clang_major__) && (__clang_major__ < 4)) || (defined(__GNUC__) && defined(ENABLE_PRELOAD) && ENABLE_PRELOAD)
|
||||
#define RPMALLOC_ATTRIB_MALLOC
|
||||
#define RPMALLOC_ATTRIB_ALLOC_SIZE(size)
|
||||
#define RPMALLOC_ATTRIB_ALLOC_SIZE2(count, size)
|
||||
#else
|
||||
#define RPMALLOC_ATTRIB_MALLOC __attribute__((__malloc__))
|
||||
#define RPMALLOC_ATTRIB_ALLOC_SIZE(size) __attribute__((alloc_size(size)))
|
||||
#define RPMALLOC_ATTRIB_ALLOC_SIZE2(count, size) __attribute__((alloc_size(count, size)))
|
||||
#endif
|
||||
#define RPMALLOC_CDECL
|
||||
#elif defined(_MSC_VER)
|
||||
#define RPMALLOC_EXPORT
|
||||
#define RPMALLOC_ALLOCATOR __declspec(allocator) __declspec(restrict)
|
||||
#define RPMALLOC_ATTRIB_MALLOC
|
||||
#define RPMALLOC_ATTRIB_ALLOC_SIZE(size)
|
||||
#define RPMALLOC_ATTRIB_ALLOC_SIZE2(count, size)
|
||||
#define RPMALLOC_CDECL __cdecl
|
||||
#else
|
||||
#define RPMALLOC_EXPORT
|
||||
#define RPMALLOC_ALLOCATOR
|
||||
#define RPMALLOC_ATTRIB_MALLOC
|
||||
#define RPMALLOC_ATTRIB_ALLOC_SIZE(size)
|
||||
#define RPMALLOC_ATTRIB_ALLOC_SIZE2(count, size)
|
||||
#define RPMALLOC_CDECL
|
||||
#endif
|
||||
|
||||
//! Define RPMALLOC_CONFIGURABLE to enable configuring sizes. Will introduce
|
||||
// a very small overhead due to some size calculations not being compile time constants
|
||||
#ifndef RPMALLOC_CONFIGURABLE
|
||||
#define RPMALLOC_CONFIGURABLE 1
|
||||
#endif
|
||||
|
||||
//! Define RPMALLOC_FIRST_CLASS_HEAPS to enable heap based API (rpmalloc_heap_* functions).
|
||||
// Will introduce a very small overhead to track fully allocated spans in heaps
|
||||
#ifndef RPMALLOC_FIRST_CLASS_HEAPS
|
||||
#define RPMALLOC_FIRST_CLASS_HEAPS 0
|
||||
#endif
|
||||
|
||||
//! Flag to rpaligned_realloc to not preserve content in reallocation
|
||||
#define RPMALLOC_NO_PRESERVE 1
|
||||
//! Flag to rpaligned_realloc to fail and return null pointer if grow cannot be done in-place,
|
||||
// in which case the original pointer is still valid (just like a call to realloc which failes to allocate
|
||||
// a new block).
|
||||
#define RPMALLOC_GROW_OR_FAIL 2
|
||||
|
||||
typedef struct rpmalloc_global_statistics_t
|
||||
{
|
||||
//! Current amount of virtual memory mapped, all of which might not have been committed (only if ENABLE_STATISTICS=1)
|
||||
size_t mapped;
|
||||
//! Peak amount of virtual memory mapped, all of which might not have been committed (only if ENABLE_STATISTICS=1)
|
||||
size_t mapped_peak;
|
||||
//! Current amount of memory in global caches for small and medium sizes (<32KiB)
|
||||
size_t cached;
|
||||
//! Current amount of memory allocated in huge allocations, i.e larger than LARGE_SIZE_LIMIT which is 2MiB by default (only if ENABLE_STATISTICS=1)
|
||||
size_t huge_alloc;
|
||||
//! Peak amount of memory allocated in huge allocations, i.e larger than LARGE_SIZE_LIMIT which is 2MiB by default (only if ENABLE_STATISTICS=1)
|
||||
size_t huge_alloc_peak;
|
||||
//! Total amount of memory mapped since initialization (only if ENABLE_STATISTICS=1)
|
||||
size_t mapped_total;
|
||||
//! Total amount of memory unmapped since initialization (only if ENABLE_STATISTICS=1)
|
||||
size_t unmapped_total;
|
||||
} rpmalloc_global_statistics_t;
|
||||
|
||||
typedef struct rpmalloc_thread_statistics_t
|
||||
{
|
||||
//! Current number of bytes available in thread size class caches for small and medium sizes (<32KiB)
|
||||
size_t sizecache;
|
||||
//! Current number of bytes available in thread span caches for small and medium sizes (<32KiB)
|
||||
size_t spancache;
|
||||
//! Total number of bytes transitioned from thread cache to global cache (only if ENABLE_STATISTICS=1)
|
||||
size_t thread_to_global;
|
||||
//! Total number of bytes transitioned from global cache to thread cache (only if ENABLE_STATISTICS=1)
|
||||
size_t global_to_thread;
|
||||
//! Per span count statistics (only if ENABLE_STATISTICS=1)
|
||||
struct
|
||||
{
|
||||
//! Currently used number of spans
|
||||
size_t current;
|
||||
//! High water mark of spans used
|
||||
size_t peak;
|
||||
//! Number of spans transitioned to global cache
|
||||
size_t to_global;
|
||||
//! Number of spans transitioned from global cache
|
||||
size_t from_global;
|
||||
//! Number of spans transitioned to thread cache
|
||||
size_t to_cache;
|
||||
//! Number of spans transitioned from thread cache
|
||||
size_t from_cache;
|
||||
//! Number of spans transitioned to reserved state
|
||||
size_t to_reserved;
|
||||
//! Number of spans transitioned from reserved state
|
||||
size_t from_reserved;
|
||||
//! Number of raw memory map calls (not hitting the reserve spans but resulting in actual OS mmap calls)
|
||||
size_t map_calls;
|
||||
} span_use[64];
|
||||
//! Per size class statistics (only if ENABLE_STATISTICS=1)
|
||||
struct
|
||||
{
|
||||
//! Current number of allocations
|
||||
size_t alloc_current;
|
||||
//! Peak number of allocations
|
||||
size_t alloc_peak;
|
||||
//! Total number of allocations
|
||||
size_t alloc_total;
|
||||
//! Total number of frees
|
||||
size_t free_total;
|
||||
//! Number of spans transitioned to cache
|
||||
size_t spans_to_cache;
|
||||
//! Number of spans transitioned from cache
|
||||
size_t spans_from_cache;
|
||||
//! Number of spans transitioned from reserved state
|
||||
size_t spans_from_reserved;
|
||||
//! Number of raw memory map calls (not hitting the reserve spans but resulting in actual OS mmap calls)
|
||||
size_t map_calls;
|
||||
} size_use[128];
|
||||
} rpmalloc_thread_statistics_t;
|
||||
|
||||
typedef struct rpmalloc_config_t
|
||||
{
|
||||
//! Map memory pages for the given number of bytes. The returned address MUST be
|
||||
// aligned to the rpmalloc span size, which will always be a power of two.
|
||||
// Optionally the function can store an alignment offset in the offset variable
|
||||
// in case it performs alignment and the returned pointer is offset from the
|
||||
// actual start of the memory region due to this alignment. The alignment offset
|
||||
// will be passed to the memory unmap function. The alignment offset MUST NOT be
|
||||
// larger than 65535 (storable in an uint16_t), if it is you must use natural
|
||||
// alignment to shift it into 16 bits. If you set a memory_map function, you
|
||||
// must also set a memory_unmap function or else the default implementation will
|
||||
// be used for both. This function must be thread safe, it can be called by
|
||||
// multiple threads simultaneously.
|
||||
void *(*memory_map)(size_t size, size_t *offset);
|
||||
//! Unmap the memory pages starting at address and spanning the given number of bytes.
|
||||
// If release is set to non-zero, the unmap is for an entire span range as returned by
|
||||
// a previous call to memory_map and that the entire range should be released. The
|
||||
// release argument holds the size of the entire span range. If release is set to 0,
|
||||
// the unmap is a partial decommit of a subset of the mapped memory range.
|
||||
// If you set a memory_unmap function, you must also set a memory_map function or
|
||||
// else the default implementation will be used for both. This function must be thread
|
||||
// safe, it can be called by multiple threads simultaneously.
|
||||
void (*memory_unmap)(void *address, size_t size, size_t offset, size_t release);
|
||||
//! Called when an assert fails, if asserts are enabled. Will use the standard assert()
|
||||
// if this is not set.
|
||||
void (*error_callback)(const char *message);
|
||||
//! Called when a call to map memory pages fails (out of memory). If this callback is
|
||||
// not set or returns zero the library will return a null pointer in the allocation
|
||||
// call. If this callback returns non-zero the map call will be retried. The argument
|
||||
// passed is the number of bytes that was requested in the map call. Only used if
|
||||
// the default system memory map function is used (memory_map callback is not set).
|
||||
int (*map_fail_callback)(size_t size);
|
||||
//! Size of memory pages. The page size MUST be a power of two. All memory mapping
|
||||
// requests to memory_map will be made with size set to a multiple of the page size.
|
||||
// Used if RPMALLOC_CONFIGURABLE is defined to 1, otherwise system page size is used.
|
||||
size_t page_size;
|
||||
//! Size of a span of memory blocks. MUST be a power of two, and in [4096,262144]
|
||||
// range (unless 0 - set to 0 to use the default span size). Used if RPMALLOC_CONFIGURABLE
|
||||
// is defined to 1.
|
||||
size_t span_size;
|
||||
//! Number of spans to map at each request to map new virtual memory blocks. This can
|
||||
// be used to minimize the system call overhead at the cost of virtual memory address
|
||||
// space. The extra mapped pages will not be written until actually used, so physical
|
||||
// committed memory should not be affected in the default implementation. Will be
|
||||
// aligned to a multiple of spans that match memory page size in case of huge pages.
|
||||
size_t span_map_count;
|
||||
//! Enable use of large/huge pages. If this flag is set to non-zero and page size is
|
||||
// zero, the allocator will try to enable huge pages and auto detect the configuration.
|
||||
// If this is set to non-zero and page_size is also non-zero, the allocator will
|
||||
// assume huge pages have been configured and enabled prior to initializing the
|
||||
// allocator.
|
||||
// For Windows, see https://docs.microsoft.com/en-us/windows/desktop/memory/large-page-support
|
||||
// For Linux, see https://www.kernel.org/doc/Documentation/vm/hugetlbpage.txt
|
||||
int enable_huge_pages;
|
||||
//! Respectively allocated pages and huge allocated pages names for systems
|
||||
// supporting it to be able to distinguish among anonymous regions.
|
||||
const char *page_name;
|
||||
const char *huge_page_name;
|
||||
} rpmalloc_config_t;
|
||||
|
||||
//! Initialize allocator with default configuration
|
||||
RPMALLOC_EXPORT int
|
||||
rpmalloc_initialize(void);
|
||||
|
||||
//! Initialize allocator with given configuration
|
||||
RPMALLOC_EXPORT int
|
||||
rpmalloc_initialize_config(const rpmalloc_config_t *config);
|
||||
|
||||
//! Get allocator configuration
|
||||
RPMALLOC_EXPORT const rpmalloc_config_t *
|
||||
rpmalloc_config(void);
|
||||
|
||||
//! Finalize allocator
|
||||
RPMALLOC_EXPORT void
|
||||
rpmalloc_finalize(void);
|
||||
|
||||
//! Initialize allocator for calling thread
|
||||
RPMALLOC_EXPORT void
|
||||
rpmalloc_thread_initialize(void);
|
||||
|
||||
//! Finalize allocator for calling thread
|
||||
RPMALLOC_EXPORT void
|
||||
rpmalloc_thread_finalize(int release_caches);
|
||||
|
||||
//! Perform deferred deallocations pending for the calling thread heap
|
||||
RPMALLOC_EXPORT void
|
||||
rpmalloc_thread_collect(void);
|
||||
|
||||
//! Query if allocator is initialized for calling thread
|
||||
RPMALLOC_EXPORT int
|
||||
rpmalloc_is_thread_initialized(void);
|
||||
|
||||
//! Get per-thread statistics
|
||||
RPMALLOC_EXPORT void
|
||||
rpmalloc_thread_statistics(rpmalloc_thread_statistics_t *stats);
|
||||
|
||||
//! Get global statistics
|
||||
RPMALLOC_EXPORT void
|
||||
rpmalloc_global_statistics(rpmalloc_global_statistics_t *stats);
|
||||
|
||||
//! Dump all statistics in human readable format to file (should be a FILE*)
|
||||
RPMALLOC_EXPORT void
|
||||
rpmalloc_dump_statistics(void *file);
|
||||
|
||||
//! Allocate a memory block of at least the given size
|
||||
RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void *
|
||||
rpmalloc(size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(1);
|
||||
|
||||
//! Free the given memory block
|
||||
RPMALLOC_EXPORT void
|
||||
rpfree(void *ptr);
|
||||
|
||||
//! Allocate a memory block of at least the given size and zero initialize it
|
||||
RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void *
|
||||
rpcalloc(size_t num, size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE2(1, 2);
|
||||
|
||||
//! Reallocate the given block to at least the given size
|
||||
RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void *
|
||||
rprealloc(void *ptr, size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(2);
|
||||
|
||||
//! Reallocate the given block to at least the given size and alignment,
|
||||
// with optional control flags (see RPMALLOC_NO_PRESERVE).
|
||||
// Alignment must be a power of two and a multiple of sizeof(void*),
|
||||
// and should ideally be less than memory page size. A caveat of rpmalloc
|
||||
// internals is that this must also be strictly less than the span size (default 64KiB)
|
||||
RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void *
|
||||
rpaligned_realloc(void *ptr, size_t alignment, size_t size, size_t oldsize, unsigned int flags) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(3);
|
||||
|
||||
//! Allocate a memory block of at least the given size and alignment.
|
||||
// Alignment must be a power of two and a multiple of sizeof(void*),
|
||||
// and should ideally be less than memory page size. A caveat of rpmalloc
|
||||
// internals is that this must also be strictly less than the span size (default 64KiB)
|
||||
RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void *
|
||||
rpaligned_alloc(size_t alignment, size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(2);
|
||||
|
||||
//! Allocate a memory block of at least the given size and alignment, and zero initialize it.
|
||||
// Alignment must be a power of two and a multiple of sizeof(void*),
|
||||
// and should ideally be less than memory page size. A caveat of rpmalloc
|
||||
// internals is that this must also be strictly less than the span size (default 64KiB)
|
||||
RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void *
|
||||
rpaligned_calloc(size_t alignment, size_t num, size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE2(2, 3);
|
||||
|
||||
//! Allocate a memory block of at least the given size and alignment.
|
||||
// Alignment must be a power of two and a multiple of sizeof(void*),
|
||||
// and should ideally be less than memory page size. A caveat of rpmalloc
|
||||
// internals is that this must also be strictly less than the span size (default 64KiB)
|
||||
RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void *
|
||||
rpmemalign(size_t alignment, size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(2);
|
||||
|
||||
//! Allocate a memory block of at least the given size and alignment.
|
||||
// Alignment must be a power of two and a multiple of sizeof(void*),
|
||||
// and should ideally be less than memory page size. A caveat of rpmalloc
|
||||
// internals is that this must also be strictly less than the span size (default 64KiB)
|
||||
RPMALLOC_EXPORT int
|
||||
rpposix_memalign(void **memptr, size_t alignment, size_t size);
|
||||
|
||||
//! Query the usable size of the given memory block (from given pointer to the end of block)
|
||||
RPMALLOC_EXPORT size_t
|
||||
rpmalloc_usable_size(void *ptr);
|
||||
|
||||
#if RPMALLOC_FIRST_CLASS_HEAPS
|
||||
|
||||
//! Heap type
|
||||
typedef struct heap_t rpmalloc_heap_t;
|
||||
|
||||
//! Acquire a new heap. Will reuse existing released heaps or allocate memory for a new heap
|
||||
// if none available. Heap API is implemented with the strict assumption that only one single
|
||||
// thread will call heap functions for a given heap at any given time, no functions are thread safe.
|
||||
RPMALLOC_EXPORT rpmalloc_heap_t *
|
||||
rpmalloc_heap_acquire(void);
|
||||
|
||||
//! Release a heap (does NOT free the memory allocated by the heap, use rpmalloc_heap_free_all before destroying the heap).
|
||||
// Releasing a heap will enable it to be reused by other threads. Safe to pass a null pointer.
|
||||
RPMALLOC_EXPORT void
|
||||
rpmalloc_heap_release(rpmalloc_heap_t *heap);
|
||||
|
||||
//! Allocate a memory block of at least the given size using the given heap.
|
||||
RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void *
|
||||
rpmalloc_heap_alloc(rpmalloc_heap_t *heap, size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(2);
|
||||
|
||||
//! Allocate a memory block of at least the given size using the given heap. The returned
|
||||
// block will have the requested alignment. Alignment must be a power of two and a multiple of sizeof(void*),
|
||||
// and should ideally be less than memory page size. A caveat of rpmalloc
|
||||
// internals is that this must also be strictly less than the span size (default 64KiB).
|
||||
RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void *
|
||||
rpmalloc_heap_aligned_alloc(rpmalloc_heap_t *heap, size_t alignment, size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(3);
|
||||
|
||||
//! Allocate a memory block of at least the given size using the given heap and zero initialize it.
|
||||
RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void *
|
||||
rpmalloc_heap_calloc(rpmalloc_heap_t *heap, size_t num, size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE2(2, 3);
|
||||
|
||||
//! Allocate a memory block of at least the given size using the given heap and zero initialize it. The returned
|
||||
// block will have the requested alignment. Alignment must either be zero, or a power of two and a multiple of sizeof(void*),
|
||||
// and should ideally be less than memory page size. A caveat of rpmalloc
|
||||
// internals is that this must also be strictly less than the span size (default 64KiB).
|
||||
RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void *
|
||||
rpmalloc_heap_aligned_calloc(rpmalloc_heap_t *heap, size_t alignment, size_t num, size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE2(2, 3);
|
||||
|
||||
//! Reallocate the given block to at least the given size. The memory block MUST be allocated
|
||||
// by the same heap given to this function.
|
||||
RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void *
|
||||
rpmalloc_heap_realloc(rpmalloc_heap_t *heap, void *ptr, size_t size, unsigned int flags) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(3);
|
||||
|
||||
//! Reallocate the given block to at least the given size. The memory block MUST be allocated
|
||||
// by the same heap given to this function. The returned block will have the requested alignment.
|
||||
// Alignment must be either zero, or a power of two and a multiple of sizeof(void*), and should ideally be
|
||||
// less than memory page size. A caveat of rpmalloc internals is that this must also be strictly less than
|
||||
// the span size (default 64KiB).
|
||||
RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void *
|
||||
rpmalloc_heap_aligned_realloc(rpmalloc_heap_t *heap, void *ptr, size_t alignment, size_t size, unsigned int flags) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(4);
|
||||
|
||||
//! Free the given memory block from the given heap. The memory block MUST be allocated
|
||||
// by the same heap given to this function.
|
||||
RPMALLOC_EXPORT void
|
||||
rpmalloc_heap_free(rpmalloc_heap_t *heap, void *ptr);
|
||||
|
||||
//! Free all memory allocated by the heap
|
||||
RPMALLOC_EXPORT void
|
||||
rpmalloc_heap_free_all(rpmalloc_heap_t *heap);
|
||||
|
||||
//! Set the given heap as the current heap for the calling thread. A heap MUST only be current heap
|
||||
// for a single thread, a heap can never be shared between multiple threads. The previous
|
||||
// current heap for the calling thread is released to be reused by other threads.
|
||||
RPMALLOC_EXPORT void
|
||||
rpmalloc_heap_thread_set_current(rpmalloc_heap_t *heap);
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
91
core/memory/heap_allocators/rpmalloc/rpmalloc_compat.cpp
Normal file
91
core/memory/heap_allocators/rpmalloc/rpmalloc_compat.cpp
Normal file
@ -0,0 +1,91 @@
|
||||
/*
|
||||
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 <memory/macro.hpp>
|
||||
#include <sys/mman.h>
|
||||
#include <memory.hpp>
|
||||
#include <assert.h>
|
||||
#include <unistd.h>
|
||||
|
||||
// #include "rpmalloc.c"
|
||||
#include "../../../../kernel.h"
|
||||
|
||||
struct heap_t
|
||||
{
|
||||
char pad[56408];
|
||||
};
|
||||
|
||||
static heap_t *__rpmalloc_tls_heap = nullptr;
|
||||
EXTERNC heap_t **__memory_thread_heap(void)
|
||||
{
|
||||
if (unlikely(!TaskManager || !thisThread))
|
||||
{
|
||||
if (unlikely(!__rpmalloc_tls_heap))
|
||||
{
|
||||
__rpmalloc_tls_heap = (heap_t *)KernelAllocator.RequestPages(TO_PAGES(sizeof(heap_t)));
|
||||
debug("rpmalloc TLS heap: %#lx", __rpmalloc_tls_heap);
|
||||
memset(__rpmalloc_tls_heap, 0, sizeof(heap_t));
|
||||
assert(__rpmalloc_tls_heap);
|
||||
}
|
||||
return &__rpmalloc_tls_heap;
|
||||
}
|
||||
return &__rpmalloc_tls_heap;
|
||||
heap_t *heap = (heap_t *)thisThread->TLS.pBase;
|
||||
return (heap_t **)heap;
|
||||
}
|
||||
|
||||
EXTERNC uintptr_t __get_tid(void)
|
||||
{
|
||||
if (unlikely(!TaskManager || !thisThread))
|
||||
return (uintptr_t)-1;
|
||||
return thisThread->ID;
|
||||
}
|
||||
|
||||
EXTERNC long __rpmalloc_sysconf(int name)
|
||||
{
|
||||
switch (name)
|
||||
{
|
||||
case _SC_PAGESIZE:
|
||||
return PAGE_SIZE;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
EXTERNC void *__rpmalloc_mmap(void *addr, size_t length, int, int, int fd, off_t offset)
|
||||
{
|
||||
assert(addr == 0 && fd == -1 && offset == 0);
|
||||
|
||||
void *ptr = KernelAllocator.RequestPages(TO_PAGES(length));
|
||||
debug("Requested %d pages, got %p", TO_PAGES(length), ptr);
|
||||
if (ptr == nullptr)
|
||||
return MAP_FAILED;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
EXTERNC int __rpmalloc_munmap(void *addr, size_t length)
|
||||
{
|
||||
KernelAllocator.FreePages(addr, TO_PAGES(length));
|
||||
debug("Freed %d pages at %p", TO_PAGES(length), addr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXTERNC int __rpmalloc_posix_madvise(void *addr, size_t length, int advice)
|
||||
{
|
||||
function("%#lx %d %d", addr, length, advice);
|
||||
return 0;
|
||||
}
|
@ -26,6 +26,7 @@
|
||||
|
||||
#include "heap_allocators/Xalloc/Xalloc.hpp"
|
||||
#include "heap_allocators/liballoc_1_1/liballoc_1_1.h"
|
||||
#include "heap_allocators/rpmalloc/rpmalloc.h"
|
||||
#include "../../kernel.h"
|
||||
|
||||
// #define DEBUG_ALLOCATIONS 1
|
||||
@ -72,7 +73,7 @@ NIF void tracepagetable(PageTable *pt)
|
||||
NIF void MapFromZero(PageTable *PT)
|
||||
{
|
||||
debug("Mapping from 0x0 to %#llx", bInfo.Memory.Size);
|
||||
Virtual va = Virtual(PT);
|
||||
Virtual vmm = Virtual(PT);
|
||||
size_t MemSize = bInfo.Memory.Size;
|
||||
|
||||
if (Page1GBSupport && PSESupport)
|
||||
@ -80,29 +81,29 @@ NIF void MapFromZero(PageTable *PT)
|
||||
/* Map the first 100MB of memory as 4KB pages */
|
||||
|
||||
// uintptr_t Physical4KBSectionStart = 0x10000000;
|
||||
// va.Map((void *)0,
|
||||
// vmm.Map((void *)0,
|
||||
// (void *)0,
|
||||
// Physical4KBSectionStart,
|
||||
// PTFlag::RW);
|
||||
// RW);
|
||||
|
||||
// va.Map((void *)Physical4KBSectionStart,
|
||||
// vmm.Map((void *)Physical4KBSectionStart,
|
||||
// (void *)Physical4KBSectionStart,
|
||||
// MemSize - Physical4KBSectionStart,
|
||||
// PTFlag::RW,
|
||||
// RW,
|
||||
// Virtual::MapType::OneGiB);
|
||||
|
||||
va.Map((void *)0, (void *)0, MemSize, PTFlag::RW);
|
||||
vmm.Map((void *)0, (void *)0, MemSize, RW);
|
||||
}
|
||||
else
|
||||
va.Map((void *)0, (void *)0, MemSize, PTFlag::RW);
|
||||
vmm.Map((void *)0, (void *)0, MemSize, RW);
|
||||
|
||||
va.Unmap((void *)0);
|
||||
vmm.Unmap((void *)0);
|
||||
}
|
||||
|
||||
NIF void MapFramebuffer(PageTable *PT, bool PSE, bool OneGB)
|
||||
NIF void MapFramebuffer(PageTable *PT)
|
||||
{
|
||||
debug("Mapping Framebuffer");
|
||||
Virtual va = Virtual(PT);
|
||||
Virtual vmm = Virtual(PT);
|
||||
int itrfb = 0;
|
||||
while (1)
|
||||
{
|
||||
@ -111,17 +112,17 @@ NIF void MapFramebuffer(PageTable *PT, bool PSE, bool OneGB)
|
||||
|
||||
size_t fbSize = bInfo.Framebuffer[itrfb].Pitch * bInfo.Framebuffer[itrfb].Height;
|
||||
|
||||
if (PSE && OneGB)
|
||||
if (PSESupport && Page1GBSupport)
|
||||
{
|
||||
va.OptimizedMap(bInfo.Framebuffer[itrfb].BaseAddress,
|
||||
bInfo.Framebuffer[itrfb].BaseAddress,
|
||||
fbSize, PTFlag::RW | PTFlag::US | PTFlag::G);
|
||||
vmm.OptimizedMap(bInfo.Framebuffer[itrfb].BaseAddress,
|
||||
bInfo.Framebuffer[itrfb].BaseAddress,
|
||||
fbSize, RW | US | G);
|
||||
}
|
||||
else
|
||||
{
|
||||
va.Map(bInfo.Framebuffer[itrfb].BaseAddress,
|
||||
bInfo.Framebuffer[itrfb].BaseAddress,
|
||||
fbSize, PTFlag::RW | PTFlag::US | PTFlag::G);
|
||||
vmm.Map(bInfo.Framebuffer[itrfb].BaseAddress,
|
||||
bInfo.Framebuffer[itrfb].BaseAddress,
|
||||
fbSize, RW | US | G);
|
||||
}
|
||||
itrfb++;
|
||||
}
|
||||
@ -176,14 +177,14 @@ NIF void MapKernel(PageTable *PT)
|
||||
uintptr_t BaseKernelMapAddress = (uintptr_t)bInfo.Kernel.PhysicalBase;
|
||||
debug("Base kernel map address: %#lx", BaseKernelMapAddress);
|
||||
uintptr_t k;
|
||||
Virtual va = Virtual(PT);
|
||||
Virtual vmm = Virtual(PT);
|
||||
|
||||
/* Bootstrap section */
|
||||
if (BaseKernelMapAddress == BootstrapStart)
|
||||
{
|
||||
for (k = BootstrapStart; k < BootstrapEnd; k += PAGE_SIZE)
|
||||
{
|
||||
va.Map((void *)k, (void *)BaseKernelMapAddress, PTFlag::RW | PTFlag::G);
|
||||
vmm.Map((void *)k, (void *)BaseKernelMapAddress, RW | G);
|
||||
KernelAllocator.ReservePage((void *)BaseKernelMapAddress);
|
||||
BaseKernelMapAddress += PAGE_SIZE;
|
||||
}
|
||||
@ -197,7 +198,7 @@ NIF void MapKernel(PageTable *PT)
|
||||
/* Text section */
|
||||
for (k = KernelTextStart; k < KernelTextEnd; k += PAGE_SIZE)
|
||||
{
|
||||
va.Map((void *)k, (void *)BaseKernelMapAddress, PTFlag::RW | PTFlag::G);
|
||||
vmm.Map((void *)k, (void *)BaseKernelMapAddress, RW | G);
|
||||
KernelAllocator.ReservePage((void *)BaseKernelMapAddress);
|
||||
BaseKernelMapAddress += PAGE_SIZE;
|
||||
}
|
||||
@ -205,7 +206,7 @@ NIF void MapKernel(PageTable *PT)
|
||||
/* Data section */
|
||||
for (k = KernelDataStart; k < KernelDataEnd; k += PAGE_SIZE)
|
||||
{
|
||||
va.Map((void *)k, (void *)BaseKernelMapAddress, PTFlag::RW | PTFlag::G);
|
||||
vmm.Map((void *)k, (void *)BaseKernelMapAddress, RW | G);
|
||||
KernelAllocator.ReservePage((void *)BaseKernelMapAddress);
|
||||
BaseKernelMapAddress += PAGE_SIZE;
|
||||
}
|
||||
@ -213,7 +214,7 @@ NIF void MapKernel(PageTable *PT)
|
||||
/* Read only data section */
|
||||
for (k = KernelRoDataStart; k < KernelRoDataEnd; k += PAGE_SIZE)
|
||||
{
|
||||
va.Map((void *)k, (void *)BaseKernelMapAddress, PTFlag::G);
|
||||
vmm.Map((void *)k, (void *)BaseKernelMapAddress, G);
|
||||
KernelAllocator.ReservePage((void *)BaseKernelMapAddress);
|
||||
BaseKernelMapAddress += PAGE_SIZE;
|
||||
}
|
||||
@ -221,7 +222,7 @@ NIF void MapKernel(PageTable *PT)
|
||||
/* Block starting symbol section */
|
||||
for (k = KernelBssStart; k < KernelBssEnd; k += PAGE_SIZE)
|
||||
{
|
||||
va.Map((void *)k, (void *)BaseKernelMapAddress, PTFlag::RW | PTFlag::G);
|
||||
vmm.Map((void *)k, (void *)BaseKernelMapAddress, RW | G);
|
||||
KernelAllocator.ReservePage((void *)BaseKernelMapAddress);
|
||||
BaseKernelMapAddress += PAGE_SIZE;
|
||||
}
|
||||
@ -233,10 +234,63 @@ NIF void MapKernel(PageTable *PT)
|
||||
{
|
||||
for (k = KernelFileStart; k < KernelFileEnd; k += PAGE_SIZE)
|
||||
{
|
||||
va.Map((void *)k, (void *)k, PTFlag::G);
|
||||
vmm.Map((void *)k, (void *)k, G);
|
||||
KernelAllocator.ReservePage((void *)k);
|
||||
}
|
||||
}
|
||||
else
|
||||
info("Cannot determine kernel file address. Ignoring.");
|
||||
}
|
||||
|
||||
NIF void CreatePageTable(PageTable *pt)
|
||||
{
|
||||
static int check_cpuid = 0;
|
||||
|
||||
if (!check_cpuid++)
|
||||
{
|
||||
if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_AMD) == 0)
|
||||
{
|
||||
CPU::x86::AMD::CPUID0x80000001 cpuid;
|
||||
cpuid.Get();
|
||||
PSESupport = cpuid.EDX.PSE;
|
||||
Page1GBSupport = cpuid.EDX.Page1GB;
|
||||
}
|
||||
else if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_INTEL) == 0)
|
||||
{
|
||||
CPU::x86::Intel::CPUID0x00000001 cpuid;
|
||||
cpuid.Get();
|
||||
PSESupport = cpuid.EDX.PSE;
|
||||
}
|
||||
|
||||
if (PSESupport)
|
||||
{
|
||||
#if defined(a64)
|
||||
CPU::x64::CR4 cr4 = CPU::x64::readcr4();
|
||||
cr4.PSE = 1;
|
||||
CPU::x64::writecr4(cr4);
|
||||
#elif defined(a32)
|
||||
CPU::x32::CR4 cr4 = CPU::x32::readcr4();
|
||||
cr4.PSE = 1;
|
||||
CPU::x32::writecr4(cr4);
|
||||
#elif defined(aa64)
|
||||
#endif
|
||||
trace("PSE Support Enabled");
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
if (Page1GBSupport)
|
||||
debug("1GB Page Support Enabled");
|
||||
#endif
|
||||
}
|
||||
|
||||
/* TODO: Map faster */
|
||||
MapFromZero(pt);
|
||||
MapFramebuffer(pt);
|
||||
MapKernel(pt);
|
||||
|
||||
#ifdef DEBUG
|
||||
tracepagetable(pt);
|
||||
#endif
|
||||
}
|
||||
|
||||
NIF void InitializeMemoryManagement()
|
||||
@ -312,58 +366,59 @@ NIF void InitializeMemoryManagement()
|
||||
KernelPageTable = (PageTable *)KernelAllocator.RequestPages(TO_PAGES(PAGE_SIZE + 1));
|
||||
memset(KernelPageTable, 0, PAGE_SIZE);
|
||||
|
||||
if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_AMD) == 0)
|
||||
{
|
||||
CPU::x86::AMD::CPUID0x80000001 cpuid;
|
||||
cpuid.Get();
|
||||
PSESupport = cpuid.EDX.PSE;
|
||||
Page1GBSupport = cpuid.EDX.Page1GB;
|
||||
}
|
||||
else if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_INTEL) == 0)
|
||||
{
|
||||
CPU::x86::Intel::CPUID0x00000001 cpuid;
|
||||
cpuid.Get();
|
||||
PSESupport = cpuid.EDX.PSE;
|
||||
}
|
||||
CreatePageTable(KernelPageTable);
|
||||
|
||||
if (PSESupport)
|
||||
{
|
||||
#if defined(a64)
|
||||
CPU::x64::CR4 cr4 = CPU::x64::readcr4();
|
||||
cr4.PSE = 1;
|
||||
CPU::x64::writecr4(cr4);
|
||||
#elif defined(a32)
|
||||
CPU::x32::CR4 cr4 = CPU::x32::readcr4();
|
||||
cr4.PSE = 1;
|
||||
CPU::x32::writecr4(cr4);
|
||||
#elif defined(aa64)
|
||||
#endif
|
||||
trace("PSE Support Enabled");
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
if (Page1GBSupport)
|
||||
debug("1GB Page Support Enabled");
|
||||
#endif
|
||||
|
||||
MapFromZero(KernelPageTable);
|
||||
MapFramebuffer(KernelPageTable, PSESupport, Page1GBSupport);
|
||||
MapKernel(KernelPageTable);
|
||||
|
||||
trace("Applying new page table from address %#lx", KernelPageTable);
|
||||
#ifdef DEBUG
|
||||
tracepagetable(KernelPageTable);
|
||||
#endif
|
||||
trace("Applying new page table from address %#lx",
|
||||
KernelPageTable);
|
||||
CPU::PageTable(KernelPageTable);
|
||||
debug("Page table updated.");
|
||||
|
||||
XallocV1Allocator = new Xalloc::V1((void *)KERNEL_HEAP_BASE, false, false);
|
||||
XallocV2Allocator = new Xalloc::V2((void *)KERNEL_HEAP_BASE);
|
||||
trace("XallocV1 Allocator initialized at %#lx", XallocV1Allocator);
|
||||
trace("XallocV2 Allocator initialized at %#lx", XallocV2Allocator);
|
||||
/* FIXME: Read kernel params */
|
||||
AllocatorType = Config.AllocatorType;
|
||||
|
||||
/* FIXME: Read kernel config */
|
||||
AllocatorType = MemoryAllocatorType::liballoc11;
|
||||
switch (AllocatorType)
|
||||
{
|
||||
case MemoryAllocatorType::Pages:
|
||||
break;
|
||||
case MemoryAllocatorType::XallocV1:
|
||||
{
|
||||
XallocV1Allocator = new Xalloc::V1((void *)KERNEL_HEAP_BASE, false, false);
|
||||
trace("XallocV1 Allocator initialized at %#lx", XallocV1Allocator);
|
||||
break;
|
||||
}
|
||||
case MemoryAllocatorType::XallocV2:
|
||||
{
|
||||
XallocV2Allocator = new Xalloc::V2((void *)KERNEL_HEAP_BASE);
|
||||
trace("XallocV2 Allocator initialized at %#lx", XallocV2Allocator);
|
||||
break;
|
||||
}
|
||||
case MemoryAllocatorType::liballoc11:
|
||||
break;
|
||||
case MemoryAllocatorType::rpmalloc_:
|
||||
{
|
||||
trace("Using rpmalloc allocator");
|
||||
rpmalloc_initialize();
|
||||
break;
|
||||
rpmalloc_config_t config = {
|
||||
.memory_map = nullptr,
|
||||
.memory_unmap = nullptr,
|
||||
.error_callback = nullptr,
|
||||
.map_fail_callback = nullptr,
|
||||
.page_size = PAGE_SIZE,
|
||||
.span_size = 4 * 1024, /* 4 KiB */
|
||||
.span_map_count = 1,
|
||||
.enable_huge_pages = 0,
|
||||
.page_name = nullptr,
|
||||
.huge_page_name = nullptr};
|
||||
rpmalloc_initialize_config(&config);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
error("Unknown allocator type %d", AllocatorType);
|
||||
CPU::Stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void *malloc(size_t Size)
|
||||
@ -371,7 +426,7 @@ void *malloc(size_t Size)
|
||||
assert(Size > 0);
|
||||
|
||||
memdbg("malloc(%d)->[%s]", Size,
|
||||
KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0))
|
||||
KernelSymbolTable ? KernelSymbolTable->GetSymbol((uintptr_t)__builtin_return_address(0))
|
||||
: "Unknown");
|
||||
|
||||
void *ret = nullptr;
|
||||
@ -397,6 +452,11 @@ void *malloc(size_t Size)
|
||||
ret = PREFIX(malloc)(Size);
|
||||
break;
|
||||
}
|
||||
case MemoryAllocatorType::rpmalloc_:
|
||||
{
|
||||
ret = rpmalloc(Size);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
error("Unknown allocator type %d", AllocatorType);
|
||||
@ -413,7 +473,7 @@ void *calloc(size_t n, size_t Size)
|
||||
assert(Size > 0);
|
||||
|
||||
memdbg("calloc(%d, %d)->[%s]", n, Size,
|
||||
KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0))
|
||||
KernelSymbolTable ? KernelSymbolTable->GetSymbol((uintptr_t)__builtin_return_address(0))
|
||||
: "Unknown");
|
||||
|
||||
void *ret = nullptr;
|
||||
@ -439,6 +499,11 @@ void *calloc(size_t n, size_t Size)
|
||||
void *ret = PREFIX(calloc)(n, Size);
|
||||
return ret;
|
||||
}
|
||||
case MemoryAllocatorType::rpmalloc_:
|
||||
{
|
||||
ret = rpcalloc(n, Size);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
error("Unknown allocator type %d", AllocatorType);
|
||||
@ -455,7 +520,7 @@ void *realloc(void *Address, size_t Size)
|
||||
assert(Size > 0);
|
||||
|
||||
memdbg("realloc(%#lx, %d)->[%s]", Address, Size,
|
||||
KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0))
|
||||
KernelSymbolTable ? KernelSymbolTable->GetSymbol((uintptr_t)__builtin_return_address(0))
|
||||
: "Unknown");
|
||||
|
||||
void *ret = nullptr;
|
||||
@ -481,6 +546,11 @@ void *realloc(void *Address, size_t Size)
|
||||
void *ret = PREFIX(realloc)(Address, Size);
|
||||
return ret;
|
||||
}
|
||||
case MemoryAllocatorType::rpmalloc_:
|
||||
{
|
||||
ret = rprealloc(Address, Size);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
error("Unknown allocator type %d", AllocatorType);
|
||||
@ -497,7 +567,7 @@ void free(void *Address)
|
||||
assert(Address != nullptr);
|
||||
|
||||
memdbg("free(%#lx)->[%s]", Address,
|
||||
KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0))
|
||||
KernelSymbolTable ? KernelSymbolTable->GetSymbol((uintptr_t)__builtin_return_address(0))
|
||||
: "Unknown");
|
||||
|
||||
switch (AllocatorType)
|
||||
@ -523,6 +593,11 @@ void free(void *Address)
|
||||
(Address);
|
||||
break;
|
||||
}
|
||||
case MemoryAllocatorType::rpmalloc_:
|
||||
{
|
||||
rpfree(Address);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
error("Unknown allocator type %d", AllocatorType);
|
||||
@ -536,7 +611,7 @@ void *operator new(std::size_t Size)
|
||||
assert(Size > 0);
|
||||
|
||||
memdbg("new(%d)->[%s]", Size,
|
||||
KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0))
|
||||
KernelSymbolTable ? KernelSymbolTable->GetSymbol((uintptr_t)__builtin_return_address(0))
|
||||
: "Unknown");
|
||||
|
||||
void *ret = malloc(Size);
|
||||
@ -548,7 +623,7 @@ void *operator new[](std::size_t Size)
|
||||
assert(Size > 0);
|
||||
|
||||
memdbg("new[](%d)->[%s]", Size,
|
||||
KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0))
|
||||
KernelSymbolTable ? KernelSymbolTable->GetSymbol((uintptr_t)__builtin_return_address(0))
|
||||
: "Unknown");
|
||||
|
||||
void *ret = malloc(Size);
|
||||
@ -560,7 +635,7 @@ void *operator new(std::size_t Size, std::align_val_t Alignment)
|
||||
assert(Size > 0);
|
||||
|
||||
memdbg("new(%d, %d)->[%s]", Size, Alignment,
|
||||
KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0))
|
||||
KernelSymbolTable ? KernelSymbolTable->GetSymbol((uintptr_t)__builtin_return_address(0))
|
||||
: "Unknown");
|
||||
|
||||
fixme("operator new with alignment(%#lx) is not implemented",
|
||||
@ -575,7 +650,7 @@ void operator delete(void *Pointer)
|
||||
assert(Pointer != nullptr);
|
||||
|
||||
memdbg("delete(%#lx)->[%s]", Pointer,
|
||||
KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0))
|
||||
KernelSymbolTable ? KernelSymbolTable->GetSymbol((uintptr_t)__builtin_return_address(0))
|
||||
: "Unknown");
|
||||
|
||||
free(Pointer);
|
||||
@ -586,7 +661,7 @@ void operator delete[](void *Pointer)
|
||||
assert(Pointer != nullptr);
|
||||
|
||||
memdbg("delete[](%#lx)->[%s]", Pointer,
|
||||
KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0))
|
||||
KernelSymbolTable ? KernelSymbolTable->GetSymbol((uintptr_t)__builtin_return_address(0))
|
||||
: "Unknown");
|
||||
|
||||
free(Pointer);
|
||||
@ -599,7 +674,7 @@ void operator delete(void *Pointer, long unsigned int Size)
|
||||
|
||||
memdbg("delete(%#lx, %d)->[%s]",
|
||||
Pointer, Size,
|
||||
KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0))
|
||||
KernelSymbolTable ? KernelSymbolTable->GetSymbol((uintptr_t)__builtin_return_address(0))
|
||||
: "Unknown");
|
||||
|
||||
free(Pointer);
|
||||
@ -612,7 +687,7 @@ void operator delete[](void *Pointer, long unsigned int Size)
|
||||
|
||||
memdbg("delete[](%#lx, %d)->[%s]",
|
||||
Pointer, Size,
|
||||
KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0))
|
||||
KernelSymbolTable ? KernelSymbolTable->GetSymbol((uintptr_t)__builtin_return_address(0))
|
||||
: "Unknown");
|
||||
|
||||
free(Pointer);
|
||||
|
@ -1,6 +1,9 @@
|
||||
#include <memory.hpp>
|
||||
|
||||
#include <filesystem.hpp>
|
||||
#include <signal.hpp>
|
||||
#include <utsname.h>
|
||||
#include <time.h>
|
||||
|
||||
namespace Memory
|
||||
{
|
||||
@ -13,29 +16,75 @@ namespace Memory
|
||||
#endif
|
||||
}
|
||||
|
||||
PageTable PageTable::Fork()
|
||||
PageTable *PageTable::Fork()
|
||||
{
|
||||
PageTable NewTable;
|
||||
memcpy(&NewTable, this, sizeof(PageTable));
|
||||
PageTable *NewTable = (PageTable *)KernelAllocator.RequestPages(TO_PAGES(sizeof(PageTable)));
|
||||
// memset(NewTable, 0, sizeof(PageTable));
|
||||
// CreatePageTable(NewTable);
|
||||
memcpy(NewTable, this, sizeof(PageTable));
|
||||
|
||||
debug("Forking page table %#lx to %#lx", this, NewTable);
|
||||
#if defined(a64)
|
||||
for (size_t i = 0; i < sizeof(Entries) / sizeof(Entries[0]); i++)
|
||||
{
|
||||
PageMapLevel4 *PML4 = &Entries[i];
|
||||
PageMapLevel4 *NewPML4 = &NewTable->Entries[i];
|
||||
if (!PML4->Present)
|
||||
continue;
|
||||
|
||||
PageDirectoryPointerTableEntryPtr *ptrPDPT = (PageDirectoryPointerTableEntryPtr *)(PML4->GetAddress() << 12);
|
||||
PageDirectoryPointerTableEntryPtr *ptrNewPDPT = (PageDirectoryPointerTableEntryPtr *)KernelAllocator.RequestPage();
|
||||
NewPML4->SetAddress((uintptr_t)ptrNewPDPT >> 12);
|
||||
for (size_t j = 0; j < sizeof(ptrPDPT->Entries) / sizeof(ptrPDPT->Entries[0]); j++)
|
||||
{
|
||||
PageDirectoryPointerTableEntry *PDPT = &ptrPDPT->Entries[j];
|
||||
PageDirectoryPointerTableEntry *NewPDPT = &ptrNewPDPT->Entries[j];
|
||||
*NewPDPT = *PDPT;
|
||||
|
||||
if (!PDPT->Present)
|
||||
continue;
|
||||
if (PDPT->PageSize)
|
||||
continue;
|
||||
|
||||
PageDirectoryEntryPtr *ptrPDE = (PageDirectoryEntryPtr *)(PDPT->GetAddress() << 12);
|
||||
PageDirectoryEntryPtr *ptrNewPDE = (PageDirectoryEntryPtr *)KernelAllocator.RequestPage();
|
||||
NewPDPT->SetAddress((uintptr_t)ptrNewPDE >> 12);
|
||||
for (size_t k = 0; k < sizeof(ptrPDE->Entries) / sizeof(ptrPDE->Entries[0]); k++)
|
||||
{
|
||||
PageDirectoryEntry *PDE = &ptrPDE->Entries[k];
|
||||
PageDirectoryEntry *NewPDE = &ptrNewPDE->Entries[k];
|
||||
*NewPDE = *PDE;
|
||||
|
||||
if (!PDE->Present)
|
||||
continue;
|
||||
if (PDE->PageSize)
|
||||
continue;
|
||||
|
||||
PageTableEntryPtr *ptrPTE = (PageTableEntryPtr *)(PDE->GetAddress() << 12);
|
||||
PageTableEntryPtr *ptrNewPTE = (PageTableEntryPtr *)KernelAllocator.RequestPage();
|
||||
NewPDE->SetAddress((uintptr_t)ptrNewPTE >> 12);
|
||||
for (size_t l = 0; l < sizeof(ptrPTE->Entries) / sizeof(ptrPTE->Entries[0]); l++)
|
||||
{
|
||||
PageTableEntry *PTE = &ptrPTE->Entries[l];
|
||||
PageTableEntry *NewPTE = &ptrNewPTE->Entries[l];
|
||||
*NewPTE = *PTE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
#error "PageTable::Fork() not implemented for other architectures"
|
||||
#endif
|
||||
|
||||
debug("Forked page table %#lx to %#lx", this, NewTable);
|
||||
return NewTable;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T PageTable::Get(T Address)
|
||||
/* We can't have Memory::Virtual in the header */
|
||||
void *PageTable::__getPhysical(void *Address)
|
||||
{
|
||||
Virtual vmm = Virtual(this);
|
||||
Virtual vmm(this);
|
||||
void *PhysAddr = vmm.GetPhysical((void *)Address);
|
||||
uintptr_t Diff = uintptr_t(Address);
|
||||
Diff &= 0xFFF;
|
||||
Diff = uintptr_t(PhysAddr) + Diff;
|
||||
return (T)Diff;
|
||||
return PhysAddr;
|
||||
}
|
||||
|
||||
/* Templates */
|
||||
template struct stat *PageTable::Get<struct stat *>(struct stat *);
|
||||
template const char *PageTable::Get<const char *>(const char *);
|
||||
template const void *PageTable::Get<const void *>(const void *);
|
||||
template uintptr_t PageTable::Get<uintptr_t>(uintptr_t);
|
||||
template void *PageTable::Get<void *>(void *);
|
||||
/* ... */
|
||||
}
|
||||
|
@ -107,9 +107,11 @@ namespace Memory
|
||||
}
|
||||
|
||||
error("Out of memory! (Free: %ld MiB; Used: %ld MiB; Reserved: %ld MiB)",
|
||||
TO_MiB(FreeMemory), TO_MiB(UsedMemory), TO_MiB(ReservedMemory));
|
||||
TO_MiB(FreeMemory.load()), TO_MiB(UsedMemory.load()), TO_MiB(ReservedMemory.load()));
|
||||
KPrint("Out of memory! (Free: %ld MiB; Used: %ld MiB; Reserved: %ld MiB)",
|
||||
TO_MiB(FreeMemory), TO_MiB(UsedMemory), TO_MiB(ReservedMemory));
|
||||
TO_MiB(FreeMemory.load()), TO_MiB(UsedMemory.load()), TO_MiB(ReservedMemory.load()));
|
||||
debug("Raw values: free %#lx used %#lx reserved %#lx",
|
||||
FreeMemory.load(), UsedMemory.load(), ReservedMemory.load());
|
||||
CPU::Stop();
|
||||
__builtin_unreachable();
|
||||
}
|
||||
@ -157,9 +159,11 @@ namespace Memory
|
||||
}
|
||||
|
||||
error("Out of memory! (Free: %ld MiB; Used: %ld MiB; Reserved: %ld MiB)",
|
||||
TO_MiB(FreeMemory), TO_MiB(UsedMemory), TO_MiB(ReservedMemory));
|
||||
TO_MiB(FreeMemory.load()), TO_MiB(UsedMemory.load()), TO_MiB(ReservedMemory.load()));
|
||||
KPrint("Out of memory! (Free: %ld MiB; Used: %ld MiB; Reserved: %ld MiB)",
|
||||
TO_MiB(FreeMemory), TO_MiB(UsedMemory), TO_MiB(ReservedMemory));
|
||||
TO_MiB(FreeMemory.load()), TO_MiB(UsedMemory.load()), TO_MiB(ReservedMemory.load()));
|
||||
debug("Raw values: free %#lx used %#lx reserved %#lx",
|
||||
FreeMemory.load(), UsedMemory.load(), ReservedMemory.load());
|
||||
CPU::Halt(true);
|
||||
__builtin_unreachable();
|
||||
}
|
||||
@ -185,8 +189,8 @@ namespace Memory
|
||||
|
||||
if (PageBitmap.Set(Index, false))
|
||||
{
|
||||
FreeMemory += PAGE_SIZE;
|
||||
UsedMemory -= PAGE_SIZE;
|
||||
FreeMemory.fetch_add(PAGE_SIZE);
|
||||
UsedMemory.fetch_sub(PAGE_SIZE);
|
||||
if (PageBitmapIndex > Index)
|
||||
PageBitmapIndex = Index;
|
||||
}
|
||||
@ -215,8 +219,8 @@ namespace Memory
|
||||
|
||||
if (PageBitmap.Set(Index, true))
|
||||
{
|
||||
FreeMemory -= PAGE_SIZE;
|
||||
UsedMemory += PAGE_SIZE;
|
||||
FreeMemory.fetch_sub(PAGE_SIZE);
|
||||
UsedMemory.fetch_add(PAGE_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -243,8 +247,8 @@ namespace Memory
|
||||
|
||||
if (PageBitmap.Set(Index, true))
|
||||
{
|
||||
FreeMemory -= PAGE_SIZE;
|
||||
ReservedMemory += PAGE_SIZE;
|
||||
FreeMemory.fetch_sub(PAGE_SIZE);
|
||||
ReservedMemory.fetch_add(PAGE_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -264,8 +268,8 @@ namespace Memory
|
||||
|
||||
if (PageBitmap.Set(Index, true))
|
||||
{
|
||||
FreeMemory -= PAGE_SIZE;
|
||||
ReservedMemory += PAGE_SIZE;
|
||||
FreeMemory.fetch_sub(PAGE_SIZE);
|
||||
ReservedMemory.fetch_add(PAGE_SIZE);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -282,8 +286,8 @@ namespace Memory
|
||||
|
||||
if (PageBitmap.Set(Index, false))
|
||||
{
|
||||
FreeMemory += PAGE_SIZE;
|
||||
ReservedMemory -= PAGE_SIZE;
|
||||
FreeMemory.fetch_add(PAGE_SIZE);
|
||||
ReservedMemory.fetch_sub(PAGE_SIZE);
|
||||
if (PageBitmapIndex > Index)
|
||||
PageBitmapIndex = Index;
|
||||
}
|
||||
@ -305,8 +309,8 @@ namespace Memory
|
||||
|
||||
if (PageBitmap.Set(Index, false))
|
||||
{
|
||||
FreeMemory += PAGE_SIZE;
|
||||
ReservedMemory -= PAGE_SIZE;
|
||||
FreeMemory.fetch_add(PAGE_SIZE);
|
||||
ReservedMemory.fetch_sub(PAGE_SIZE);
|
||||
if (PageBitmapIndex > Index)
|
||||
PageBitmapIndex = Index;
|
||||
}
|
||||
@ -320,8 +324,8 @@ namespace Memory
|
||||
uint64_t MemorySize = bInfo.Memory.Size;
|
||||
debug("Memory size: %lld bytes (%ld pages)",
|
||||
MemorySize, TO_PAGES(MemorySize));
|
||||
TotalMemory = MemorySize;
|
||||
FreeMemory = MemorySize;
|
||||
TotalMemory.store(MemorySize);
|
||||
FreeMemory.store(MemorySize);
|
||||
|
||||
size_t BitmapSize = (size_t)(MemorySize / PAGE_SIZE) / 8 + 1;
|
||||
uintptr_t BitmapAddress = 0x0;
|
||||
|
@ -80,7 +80,7 @@ namespace Memory
|
||||
if (this->UserMode)
|
||||
{
|
||||
std::vector<AllocatedPages> ParentAllocatedPages = Parent->GetAllocatedPages();
|
||||
Virtual vma = Virtual(this->vma->GetTable());
|
||||
Virtual vma(this->vma->GetTable());
|
||||
foreach (auto Page in ParentAllocatedPages)
|
||||
{
|
||||
void *NewPhysical = this->vma->RequestPages(1);
|
||||
@ -162,6 +162,7 @@ namespace Memory
|
||||
}
|
||||
|
||||
debug("Allocated stack at %#lx", this->StackBottom);
|
||||
debug("Stack Range: %#lx - %#lx", this->StackBottom, this->StackTop);
|
||||
}
|
||||
|
||||
StackGuard::~StackGuard()
|
||||
|
@ -74,6 +74,8 @@ namespace Memory
|
||||
bool VirtualMemoryArea::Add(void *Address, size_t Count)
|
||||
{
|
||||
SmartLock(MgrLock);
|
||||
function("%#lx, %lld", Address, Count);
|
||||
|
||||
if (Address == nullptr)
|
||||
{
|
||||
error("Address is null!");
|
||||
@ -118,7 +120,10 @@ namespace Memory
|
||||
void *VirtualMemoryArea::RequestPages(size_t Count, bool User)
|
||||
{
|
||||
SmartLock(MgrLock);
|
||||
function("%lld, %s", Count, User ? "true" : "false");
|
||||
|
||||
void *Address = KernelAllocator.RequestPages(Count);
|
||||
memset(Address, 0, Count * PAGE_SIZE);
|
||||
for (size_t i = 0; i < Count; i++)
|
||||
{
|
||||
int Flags = Memory::PTFlag::RW;
|
||||
@ -127,23 +132,19 @@ namespace Memory
|
||||
|
||||
void *AddressToMap = (void *)((uintptr_t)Address + (i * PAGE_SIZE));
|
||||
|
||||
Memory::Virtual vmm = Memory::Virtual(this->Table);
|
||||
vmm.Remap(AddressToMap, AddressToMap, Flags);
|
||||
Memory::Virtual vmm(this->Table);
|
||||
vmm.Map(AddressToMap, AddressToMap, Flags);
|
||||
}
|
||||
|
||||
AllocatedPagesList.push_back({Address, Count});
|
||||
|
||||
/* For security reasons, we clear the allocated page
|
||||
if it's a user page. */
|
||||
if (User)
|
||||
memset(Address, 0, Count * PAGE_SIZE);
|
||||
|
||||
return Address;
|
||||
}
|
||||
|
||||
void VirtualMemoryArea::FreePages(void *Address, size_t Count)
|
||||
{
|
||||
SmartLock(MgrLock);
|
||||
function("%#lx, %lld", Address, Count);
|
||||
|
||||
forItr(itr, AllocatedPagesList)
|
||||
{
|
||||
if (itr->Address == Address)
|
||||
@ -162,7 +163,7 @@ namespace Memory
|
||||
|
||||
KernelAllocator.FreePages(Address, Count);
|
||||
|
||||
Memory::Virtual vmm = Memory::Virtual(this->Table);
|
||||
Memory::Virtual vmm(this->Table);
|
||||
for (size_t i = 0; i < Count; i++)
|
||||
{
|
||||
void *AddressToMap = (void *)((uintptr_t)Address + (i * PAGE_SIZE));
|
||||
@ -178,6 +179,8 @@ namespace Memory
|
||||
void VirtualMemoryArea::DetachAddress(void *Address)
|
||||
{
|
||||
SmartLock(MgrLock);
|
||||
function("%#lx", Address);
|
||||
|
||||
forItr(itr, AllocatedPagesList)
|
||||
{
|
||||
if (itr->Address == Address)
|
||||
@ -193,7 +196,14 @@ namespace Memory
|
||||
bool Read, bool Write, bool Exec,
|
||||
bool Fixed, bool Shared)
|
||||
{
|
||||
Memory::Virtual vmm = Memory::Virtual(this->Table);
|
||||
function("%#lx, %lld, %s, %s, %s, %s, %s", Address, Length,
|
||||
Read ? "true" : "false",
|
||||
Write ? "true" : "false",
|
||||
Exec ? "true" : "false",
|
||||
Fixed ? "true" : "false",
|
||||
Shared ? "true" : "false");
|
||||
|
||||
Memory::Virtual vmm(this->Table);
|
||||
|
||||
// FIXME
|
||||
// for (uintptr_t j = uintptr_t(Address);
|
||||
@ -209,20 +219,21 @@ namespace Memory
|
||||
// }
|
||||
|
||||
bool AnyAddress = Address == nullptr;
|
||||
debug("AnyAddress: %s", AnyAddress ? "true" : "false");
|
||||
|
||||
if (AnyAddress)
|
||||
{
|
||||
Address = this->RequestPages(1);
|
||||
if (Address == nullptr)
|
||||
return nullptr;
|
||||
memset(Address, 0, PAGE_SIZE);
|
||||
Address = this->RequestPages(TO_PAGES(Length), true);
|
||||
debug("Allocated %#lx-%#lx for pt %#lx",
|
||||
Address, (uintptr_t)Address + Length, this->Table);
|
||||
return Address;
|
||||
}
|
||||
|
||||
SmartLock(MgrLock);
|
||||
vmm.Unmap(Address, Length);
|
||||
vmm.Map(Address, nullptr, Length, PTFlag::CoW);
|
||||
|
||||
if (AnyAddress)
|
||||
vmm.Remap(Address, Address, PTFlag::RW | PTFlag::US);
|
||||
debug("CoW region created at range %#lx-%#lx for pt %#lx",
|
||||
Address, (uintptr_t)Address + Length, this->Table);
|
||||
|
||||
SharedRegion sr{
|
||||
.Address = Address,
|
||||
@ -235,13 +246,15 @@ namespace Memory
|
||||
.ReferenceCount = 0,
|
||||
};
|
||||
SharedRegions.push_back(sr);
|
||||
debug("CoW region created at %#lx for pt %#lx",
|
||||
Address, this->Table);
|
||||
return Address;
|
||||
}
|
||||
|
||||
bool VirtualMemoryArea::HandleCoW(uintptr_t PFA)
|
||||
{
|
||||
function("%#lx", PFA);
|
||||
Memory::Virtual vmm = Memory::Virtual(this->Table);
|
||||
Memory::Virtual vmm(this->Table);
|
||||
Memory::PageTableEntry *pte = vmm.GetPTE((void *)PFA);
|
||||
|
||||
if (!pte)
|
||||
@ -260,6 +273,9 @@ namespace Memory
|
||||
|
||||
if (PFA >= Start && PFA < End)
|
||||
{
|
||||
debug("Start: %#lx, End: %#lx (PFA: %#lx)",
|
||||
Start, End, PFA);
|
||||
|
||||
if (sr.Shared)
|
||||
{
|
||||
fixme("Shared CoW");
|
||||
@ -272,30 +288,117 @@ namespace Memory
|
||||
return false;
|
||||
memset(pAddr, 0, PAGE_SIZE);
|
||||
|
||||
uint64_t Flags = 0;
|
||||
if (sr.Read)
|
||||
Flags |= PTFlag::US;
|
||||
if (sr.Write)
|
||||
Flags |= PTFlag::RW;
|
||||
// if (sr.Exec)
|
||||
// Flags |= PTFlag::XD;
|
||||
assert(pte->Present == true);
|
||||
pte->ReadWrite = sr.Write;
|
||||
pte->UserSupervisor = sr.Read;
|
||||
pte->ExecuteDisable = sr.Exec;
|
||||
|
||||
vmm.Remap((void *)PFA, pAddr, Flags);
|
||||
pte->CopyOnWrite = false;
|
||||
debug("PFA %#lx is CoW (pt %#lx, flags %#lx)",
|
||||
PFA, this->Table, pte->raw);
|
||||
#if defined(a64)
|
||||
CPU::x64::invlpg((void *)PFA);
|
||||
#elif defined(a32)
|
||||
CPU::x32::invlpg((void *)PFA);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
debug("PFA %#lx is not CoW", PFA);
|
||||
debug("PFA %#lx is not CoW (pt %#lx)",
|
||||
PFA, this->Table);
|
||||
return false;
|
||||
}
|
||||
|
||||
void VirtualMemoryArea::FreeAllPages()
|
||||
{
|
||||
SmartLock(MgrLock);
|
||||
foreach (auto ap in AllocatedPagesList)
|
||||
{
|
||||
KernelAllocator.FreePages(ap.Address, ap.PageCount);
|
||||
Memory::Virtual vmm(this->Table);
|
||||
for (size_t i = 0; i < ap.PageCount; i++)
|
||||
vmm.Remap((void *)((uintptr_t)ap.Address + (i * PAGE_SIZE)),
|
||||
(void *)((uintptr_t)ap.Address + (i * PAGE_SIZE)),
|
||||
Memory::PTFlag::RW);
|
||||
}
|
||||
AllocatedPagesList.clear();
|
||||
}
|
||||
|
||||
void VirtualMemoryArea::Fork(VirtualMemoryArea *Parent)
|
||||
{
|
||||
function("%#lx", Parent);
|
||||
|
||||
if (Parent == nullptr)
|
||||
{
|
||||
error("Parent is null!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (Parent->Table == nullptr)
|
||||
{
|
||||
error("Parent's table is null!");
|
||||
return;
|
||||
}
|
||||
|
||||
Memory::Virtual vmm(this->Table);
|
||||
SmartLock(MgrLock);
|
||||
foreach (auto ap in Parent->GetAllocatedPagesList())
|
||||
{
|
||||
MgrLock.Unlock();
|
||||
void *Address = this->RequestPages(ap.PageCount);
|
||||
MgrLock.Lock(__FUNCTION__);
|
||||
if (Address == nullptr)
|
||||
return;
|
||||
|
||||
memcpy(Address, ap.Address, ap.PageCount * PAGE_SIZE);
|
||||
|
||||
// map these new allocated pages to be the same as the parent
|
||||
for (size_t i = 0; i < ap.PageCount; i++)
|
||||
{
|
||||
void *AddressToMap = (void *)((uintptr_t)ap.Address + (i * PAGE_SIZE));
|
||||
void *RealAddress = (void *)((uintptr_t)Address + (i * PAGE_SIZE));
|
||||
|
||||
#if defined(a86)
|
||||
Memory::PageTableEntry *pte = vmm.GetPTE(AddressToMap);
|
||||
uintptr_t Flags = 0;
|
||||
Flags |= pte->Present ? 1UL : 0;
|
||||
Flags |= pte->ReadWrite ? 2UL : 0;
|
||||
Flags |= pte->UserSupervisor ? 4UL : 0;
|
||||
Flags |= pte->CopyOnWrite ? 512UL : 0;
|
||||
|
||||
debug("Mapping %#lx to %#lx (flags %s/%s/%s/%s)",
|
||||
RealAddress, AddressToMap,
|
||||
Flags & PTFlag::P ? "P" : "-",
|
||||
Flags & PTFlag::RW ? "RW" : "-",
|
||||
Flags & PTFlag::US ? "US" : "-",
|
||||
Flags & PTFlag::CoW ? "CoW" : "-");
|
||||
vmm.Map(AddressToMap, RealAddress, Flags);
|
||||
#else
|
||||
#warning "Not implemented"
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
foreach (auto sr in Parent->GetSharedRegions())
|
||||
{
|
||||
MgrLock.Unlock();
|
||||
void *Address = this->CreateCoWRegion(sr.Address, sr.Length,
|
||||
sr.Read, sr.Write, sr.Exec,
|
||||
sr.Fixed, sr.Shared);
|
||||
MgrLock.Lock(__FUNCTION__);
|
||||
if (Address == nullptr)
|
||||
return;
|
||||
memcpy(Address, sr.Address, sr.Length);
|
||||
}
|
||||
}
|
||||
|
||||
VirtualMemoryArea::VirtualMemoryArea(PageTable *Table)
|
||||
{
|
||||
debug("+ %#lx %s", this,
|
||||
KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "");
|
||||
KernelSymbolTable ? KernelSymbolTable->GetSymbol((uintptr_t)__builtin_return_address(0)) : "");
|
||||
|
||||
SmartLock(MgrLock);
|
||||
if (Table)
|
||||
@ -316,12 +419,22 @@ namespace Memory
|
||||
VirtualMemoryArea::~VirtualMemoryArea()
|
||||
{
|
||||
debug("- %#lx %s", this,
|
||||
KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "");
|
||||
KernelSymbolTable ? KernelSymbolTable->GetSymbol((uintptr_t)__builtin_return_address(0)) : "");
|
||||
|
||||
#ifdef DEBUG
|
||||
if (this->Table == KernelPageTable)
|
||||
debug("Not remapping kernel page table allocated pages.");
|
||||
#endif
|
||||
|
||||
SmartLock(MgrLock);
|
||||
Memory::Virtual vmm(this->Table);
|
||||
foreach (auto ap in AllocatedPagesList)
|
||||
{
|
||||
KernelAllocator.FreePages(ap.Address, ap.PageCount);
|
||||
Memory::Virtual vmm = Memory::Virtual(this->Table);
|
||||
|
||||
if (this->Table == KernelPageTable)
|
||||
continue;
|
||||
|
||||
for (size_t i = 0; i < ap.PageCount; i++)
|
||||
vmm.Remap((void *)((uintptr_t)ap.Address + (i * PAGE_SIZE)),
|
||||
(void *)((uintptr_t)ap.Address + (i * PAGE_SIZE)),
|
||||
|
@ -20,15 +20,25 @@
|
||||
#include <convert.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include "../../kernel.h"
|
||||
|
||||
namespace Memory
|
||||
{
|
||||
Virtual::Virtual(PageTable *Table)
|
||||
{
|
||||
if (Table)
|
||||
this->Table = Table;
|
||||
else
|
||||
this->Table = (PageTable *)CPU::PageTable();
|
||||
}
|
||||
Virtual::Virtual(PageTable *Table)
|
||||
{
|
||||
if (Table)
|
||||
this->pTable = Table;
|
||||
else
|
||||
this->pTable = thisPageTable;
|
||||
|
||||
Virtual::~Virtual() {}
|
||||
// debug("+ %#lx (PT: %#lx) %s", this, this->pTable,
|
||||
// KernelSymbolTable
|
||||
// ? KernelSymbolTable->GetSymbol((uintptr_t)__builtin_return_address(0))
|
||||
// : "Unknown");
|
||||
}
|
||||
|
||||
Virtual::~Virtual()
|
||||
{
|
||||
// debug("- %#lx", this);
|
||||
}
|
||||
}
|
||||
|
@ -1,347 +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 <module.hpp>
|
||||
|
||||
#include <memory.hpp>
|
||||
#include <ints.hpp>
|
||||
#include <task.hpp>
|
||||
#include <printf.h>
|
||||
#include <cwalk.h>
|
||||
#include <md5.h>
|
||||
|
||||
#include "../../modules/mod.hpp"
|
||||
#include "../../kernel.h"
|
||||
#include "../../mapi.hpp"
|
||||
#include "../../Fex.hpp"
|
||||
#include "api.hpp"
|
||||
|
||||
using vfs::RefNode;
|
||||
|
||||
namespace Module
|
||||
{
|
||||
void Module::Panic()
|
||||
{
|
||||
debug("%ld modules loaded, [modUIDs: %ld]", Modules.size(), modUIDs - 1);
|
||||
|
||||
foreach (auto Drv in Modules)
|
||||
{
|
||||
KernelCallback callback{};
|
||||
callback.Reason = StopReason;
|
||||
ModuleManager->IOCB(Drv.modUniqueID, &callback);
|
||||
|
||||
for (size_t j = 0; j < sizeof(Drv.InterruptHook) / sizeof(Drv.InterruptHook[0]); j++)
|
||||
{
|
||||
if (!Drv.InterruptHook[j])
|
||||
continue;
|
||||
|
||||
Drv.InterruptHook[j]->Disable();
|
||||
debug("Interrupt hook %#lx disabled", Drv.InterruptHook[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Module::UnloadAllModules()
|
||||
{
|
||||
debug("%ld modules loaded, [modUIDs: %ld]", Modules.size(), modUIDs - 1);
|
||||
|
||||
foreach (auto Drv in Modules)
|
||||
{
|
||||
KernelCallback callback{};
|
||||
callback.Reason = StopReason;
|
||||
debug("Stopping & unloading module %ld [%#lx]", Drv.modUniqueID, Drv.Address);
|
||||
ModuleManager->IOCB(Drv.modUniqueID, &callback);
|
||||
|
||||
for (size_t j = 0; j < sizeof(Drv.InterruptHook) / sizeof(Drv.InterruptHook[0]); j++)
|
||||
{
|
||||
if (!Drv.InterruptHook[j])
|
||||
continue;
|
||||
|
||||
debug("Interrupt hook %#lx", Drv.InterruptHook[j]);
|
||||
delete Drv.InterruptHook[j], Drv.InterruptHook[j] = nullptr;
|
||||
}
|
||||
|
||||
if (Drv.vma)
|
||||
delete Drv.vma, Drv.vma = nullptr;
|
||||
}
|
||||
Modules.clear();
|
||||
}
|
||||
|
||||
bool Module::UnloadModule(unsigned long id)
|
||||
{
|
||||
debug("Searching for module %ld", id);
|
||||
|
||||
forItr(Drv, Modules)
|
||||
{
|
||||
if (Drv->modUniqueID != id)
|
||||
continue;
|
||||
|
||||
KernelCallback callback{};
|
||||
callback.Reason = StopReason;
|
||||
debug("Stopping & unloading module %ld [%#lx]", Drv->modUniqueID, Drv->Address);
|
||||
this->IOCB(Drv->modUniqueID, &callback);
|
||||
|
||||
for (size_t j = 0; j < sizeof(Drv->InterruptHook) / sizeof(Drv->InterruptHook[0]); j++)
|
||||
{
|
||||
if (!Drv->InterruptHook[j])
|
||||
continue;
|
||||
|
||||
debug("Interrupt hook %#lx", Drv->InterruptHook[j]);
|
||||
delete Drv->InterruptHook[j], Drv->InterruptHook[j] = nullptr;
|
||||
}
|
||||
|
||||
if (Drv->vma)
|
||||
delete Drv->vma, Drv->vma = nullptr;
|
||||
|
||||
Modules.erase(Drv);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int Module::IOCB(unsigned long id, void *KCB)
|
||||
{
|
||||
foreach (auto Drv in Modules)
|
||||
{
|
||||
if (Drv.modUniqueID != id)
|
||||
continue;
|
||||
|
||||
FexExtended *fexE = (FexExtended *)Drv.ExtendedHeaderAddress;
|
||||
return ((int (*)(void *))((uintptr_t)fexE->Module.Callback + (uintptr_t)Drv.Address))(KCB);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
ModuleCode Module::CallModuleEntryPoint(void *fex, bool BuiltIn)
|
||||
{
|
||||
ModuleCode ret{};
|
||||
KernelAPI modKAPI = KernelAPITemplate;
|
||||
|
||||
modKAPI.Info.modUniqueID = modUIDs++;
|
||||
modKAPI.Info.KernelDebug = DebuggerIsAttached;
|
||||
|
||||
debug("Calling module entry point ( %#lx %ld )", (unsigned long)fex, modKAPI.Info.modUniqueID);
|
||||
|
||||
if (!BuiltIn)
|
||||
{
|
||||
modKAPI.Info.Offset = (unsigned long)fex;
|
||||
|
||||
debug("MODULE: %s HAS MODULE ID %ld",
|
||||
((FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS))->Module.Name,
|
||||
modKAPI.Info.modUniqueID);
|
||||
ret = ((ModuleCode(*)(KernelAPI *))((uintptr_t)((Fex *)fex)->EntryPoint + (uintptr_t)fex))(((KernelAPI *)&modKAPI));
|
||||
}
|
||||
else
|
||||
{
|
||||
debug("MODULE: BUILTIN HAS MODULE ID %ld", modKAPI.Info.modUniqueID);
|
||||
ret = ((ModuleCode(*)(KernelAPI *))((uintptr_t)fex))(((KernelAPI *)&modKAPI));
|
||||
}
|
||||
|
||||
if (ModuleCode::OK != ret)
|
||||
{
|
||||
modUIDs--;
|
||||
return ret;
|
||||
}
|
||||
return ModuleCode::OK;
|
||||
}
|
||||
|
||||
ModuleCode Module::LoadModule(vfs::Node *fildes)
|
||||
{
|
||||
Fex DrvHdr;
|
||||
fildes->read((uint8_t *)&DrvHdr, sizeof(Fex), 0);
|
||||
|
||||
if (DrvHdr.Magic[0] != 'F' || DrvHdr.Magic[1] != 'E' || DrvHdr.Magic[2] != 'X' || DrvHdr.Magic[3] != '\0')
|
||||
return ModuleCode::INVALID_FEX_HEADER;
|
||||
|
||||
debug("Fex Magic: \"%s\"; Type: %d; OS: %d; EntryPoint: %#lx", DrvHdr.Magic, DrvHdr.Type, DrvHdr.OS, DrvHdr.EntryPoint);
|
||||
|
||||
if (DrvHdr.Type != FexFormatType::FexFormatType_Module)
|
||||
return ModuleCode::NOT_MODULE;
|
||||
|
||||
FexExtended fexE;
|
||||
fildes->read((uint8_t *)&fexE, sizeof(FexExtended), EXTENDED_SECTION_ADDRESS);
|
||||
|
||||
debug("Name: \"%s\"; Type: %d; Callback: %#lx", fexE.Module.Name, fexE.Module.Type, fexE.Module.Callback);
|
||||
|
||||
Memory::SmartHeap ModuleAddress(fildes->Size);
|
||||
fildes->read(ModuleAddress, fildes->Size, 0);
|
||||
|
||||
switch (fexE.Module.Bind.Type)
|
||||
{
|
||||
case ModuleBindType::BIND_PCI:
|
||||
return this->ModuleLoadBindPCI(ModuleAddress, fildes->Size);
|
||||
case ModuleBindType::BIND_INTERRUPT:
|
||||
return this->ModuleLoadBindInterrupt(ModuleAddress, fildes->Size);
|
||||
case ModuleBindType::BIND_PROCESS:
|
||||
return this->ModuleLoadBindProcess(ModuleAddress, fildes->Size);
|
||||
case ModuleBindType::BIND_INPUT:
|
||||
return this->ModuleLoadBindInput(ModuleAddress, fildes->Size);
|
||||
default:
|
||||
{
|
||||
error("Unknown module bind type: %d", fexE.Module.Bind.Type);
|
||||
return ModuleCode::UNKNOWN_MODULE_BIND_TYPE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Module::LoadModules()
|
||||
{
|
||||
SmartCriticalSection(ModuleInitLock);
|
||||
|
||||
const char *ModuleConfigFile = new char[256];
|
||||
assert(strlen(Config.ModuleDirectory) < 255 - 12);
|
||||
strcpy((char *)ModuleConfigFile, Config.ModuleDirectory);
|
||||
strcat((char *)ModuleConfigFile, "/config.ini");
|
||||
fixme("Loading module config file: %s", ModuleConfigFile);
|
||||
delete[] ModuleConfigFile;
|
||||
|
||||
debug("Loading built-in modules");
|
||||
StartBuiltInModules();
|
||||
|
||||
RefNode *ModuleDirectory = fs->Open(Config.ModuleDirectory);
|
||||
if (!ModuleDirectory)
|
||||
{
|
||||
KPrint("\eE85230Failed to open %s: %d)",
|
||||
Config.ModuleDirectory, errno);
|
||||
return;
|
||||
}
|
||||
|
||||
debug("Loading modules from %s", Config.ModuleDirectory);
|
||||
foreach (auto DrvFile in ModuleDirectory->node->Children)
|
||||
{
|
||||
if (DrvFile->Type != vfs::NodeType::FILE)
|
||||
continue;
|
||||
|
||||
if (cwk_path_has_extension(DrvFile->Name))
|
||||
{
|
||||
const char *extension;
|
||||
size_t extension_length;
|
||||
cwk_path_get_extension(DrvFile->Name, &extension, &extension_length);
|
||||
debug("File: %s; Extension: %s", DrvFile->Name, extension);
|
||||
if (strcmp(extension, ".fex") == 0)
|
||||
{
|
||||
uintptr_t ret = this->LoadModule(DrvFile);
|
||||
char *RetString = new char[256];
|
||||
if (ret == ModuleCode::OK)
|
||||
strcpy(RetString, "\e058C19OK");
|
||||
else if (ret == ModuleCode::NOT_AVAILABLE)
|
||||
strcpy(RetString, "\eFF7900NOT AVAILABLE");
|
||||
else
|
||||
strcpy(RetString, "\eE85230FAILED");
|
||||
KPrint("%s %s %#lx", DrvFile->Name, RetString, ret);
|
||||
delete[] RetString;
|
||||
}
|
||||
}
|
||||
}
|
||||
delete ModuleDirectory;
|
||||
}
|
||||
|
||||
Module::Module() {}
|
||||
|
||||
Module::~Module()
|
||||
{
|
||||
debug("Destructor called");
|
||||
this->UnloadAllModules();
|
||||
}
|
||||
|
||||
#if defined(a64)
|
||||
SafeFunction void ModuleInterruptHook::OnInterruptReceived(CPU::x64::TrapFrame *Frame)
|
||||
#elif defined(a32)
|
||||
SafeFunction void ModuleInterruptHook::OnInterruptReceived(CPU::x32::TrapFrame *Frame)
|
||||
#elif defined(aa64)
|
||||
SafeFunction void ModuleInterruptHook::OnInterruptReceived(CPU::aarch64::TrapFrame *Frame)
|
||||
#endif
|
||||
{
|
||||
SmartLock(DriverInterruptLock); /* Lock in case of multiple interrupts firing at the same time */
|
||||
if (!this->Enabled)
|
||||
{
|
||||
debug("Interrupt hook is not enabled (%#lx, IRQ%d)",
|
||||
Frame->InterruptNumber,
|
||||
Frame->InterruptNumber - 32);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Handle.InterruptCallback)
|
||||
{
|
||||
#if defined(a86)
|
||||
uint64_t IntNum = Frame->InterruptNumber - 32;
|
||||
#elif defined(aa64)
|
||||
uint64_t IntNum = Frame->InterruptNumber;
|
||||
#endif
|
||||
warn("Interrupt callback for %ld is not set for module %ld!",
|
||||
IntNum, Handle.modUniqueID);
|
||||
return;
|
||||
}
|
||||
CPURegisters regs;
|
||||
#if defined(a64)
|
||||
regs.r15 = Frame->r15;
|
||||
regs.r14 = Frame->r14;
|
||||
regs.r13 = Frame->r13;
|
||||
regs.r12 = Frame->r12;
|
||||
regs.r11 = Frame->r11;
|
||||
regs.r10 = Frame->r10;
|
||||
regs.r9 = Frame->r9;
|
||||
regs.r8 = Frame->r8;
|
||||
|
||||
regs.rbp = Frame->rbp;
|
||||
regs.rdi = Frame->rdi;
|
||||
regs.rsi = Frame->rsi;
|
||||
regs.rdx = Frame->rdx;
|
||||
regs.rcx = Frame->rcx;
|
||||
regs.rbx = Frame->rbx;
|
||||
regs.rax = Frame->rax;
|
||||
|
||||
regs.InterruptNumber = Frame->InterruptNumber;
|
||||
regs.ErrorCode = Frame->ErrorCode;
|
||||
regs.rip = Frame->rip;
|
||||
regs.cs = Frame->cs;
|
||||
regs.rflags = Frame->rflags.raw;
|
||||
regs.rsp = Frame->rsp;
|
||||
regs.ss = Frame->ss;
|
||||
#elif defined(a32)
|
||||
regs.edi = Frame->edi;
|
||||
regs.esi = Frame->esi;
|
||||
regs.ebp = Frame->ebp;
|
||||
regs.esp = Frame->esp;
|
||||
regs.ebx = Frame->ebx;
|
||||
regs.edx = Frame->edx;
|
||||
regs.ecx = Frame->ecx;
|
||||
regs.eax = Frame->eax;
|
||||
|
||||
regs.InterruptNumber = Frame->InterruptNumber;
|
||||
regs.ErrorCode = Frame->ErrorCode;
|
||||
regs.eip = Frame->eip;
|
||||
regs.cs = Frame->cs;
|
||||
regs.eflags = Frame->eflags.raw;
|
||||
regs.r3_esp = Frame->r3_esp;
|
||||
regs.r3_ss = Frame->r3_ss;
|
||||
#elif defined(aa64)
|
||||
#endif
|
||||
((int (*)(void *))(Handle.InterruptCallback))(®s);
|
||||
UNUSED(Frame);
|
||||
}
|
||||
|
||||
ModuleInterruptHook::ModuleInterruptHook(int Interrupt, ModuleFile Handle) : Interrupts::Handler(Interrupt)
|
||||
{
|
||||
this->Handle = Handle;
|
||||
#if defined(a86)
|
||||
trace("Interrupt %d hooked to module %ld", Interrupt, Handle.modUniqueID);
|
||||
#elif defined(aa64)
|
||||
trace("Interrupt %d hooked to module %ld", Interrupt, Handle.modUniqueID);
|
||||
#endif
|
||||
}
|
||||
}
|
@ -1,226 +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 <module.hpp>
|
||||
|
||||
#include <dumper.hpp>
|
||||
#include <lock.hpp>
|
||||
|
||||
#include "../../kernel.h"
|
||||
#include "../../Fex.hpp"
|
||||
#include "api.hpp"
|
||||
|
||||
// show debug messages
|
||||
// #define DEBUG_MODULE_API 1
|
||||
|
||||
#ifdef DEBUG_MODULE_API
|
||||
#define modbg(m, ...) debug(m, ##__VA_ARGS__)
|
||||
#else
|
||||
#define modbg(m, ...)
|
||||
#endif
|
||||
|
||||
NewLock(ModuleDisplayPrintLock);
|
||||
|
||||
void ModuleDebugPrint(char *String, __UINT64_TYPE__ modUniqueID)
|
||||
{
|
||||
trace("[%ld] %s", modUniqueID, String);
|
||||
}
|
||||
|
||||
void ModuleDisplayPrint(char *String)
|
||||
{
|
||||
SmartLock(ModuleDisplayPrintLock);
|
||||
for (__UINT64_TYPE__ i = 0; i < strlen(String); i++)
|
||||
Display->Print(String[i], 0, true);
|
||||
}
|
||||
|
||||
void *RequestPage(__UINT64_TYPE__ Size)
|
||||
{
|
||||
void *ret = KernelAllocator.RequestPages(size_t(Size + 1));
|
||||
modbg("Allocated %ld pages (%#lx-%#lx)",
|
||||
Size, (__UINT64_TYPE__)ret,
|
||||
(__UINT64_TYPE__)ret + FROM_PAGES(Size));
|
||||
return ret;
|
||||
}
|
||||
|
||||
void FreePage(void *Page, __UINT64_TYPE__ Size)
|
||||
{
|
||||
modbg("Freeing %ld pages (%#lx-%#lx)",
|
||||
Size, (__UINT64_TYPE__)Page,
|
||||
(__UINT64_TYPE__)Page + FROM_PAGES(Size));
|
||||
KernelAllocator.FreePages(Page, size_t(Size + 1));
|
||||
}
|
||||
|
||||
void MapMemory(void *VirtualAddress, void *PhysicalAddress, __UINT64_TYPE__ Flags)
|
||||
{
|
||||
SmartLock(ModuleDisplayPrintLock);
|
||||
modbg("Mapping %#lx to %#lx with flags %#lx...",
|
||||
(__UINT64_TYPE__)VirtualAddress,
|
||||
(__UINT64_TYPE__)PhysicalAddress, Flags);
|
||||
Memory::Virtual(KernelPageTable).Map(VirtualAddress, PhysicalAddress, Flags);
|
||||
}
|
||||
|
||||
void UnmapMemory(void *VirtualAddress)
|
||||
{
|
||||
SmartLock(ModuleDisplayPrintLock);
|
||||
modbg("Unmapping %#lx...",
|
||||
(__UINT64_TYPE__)VirtualAddress);
|
||||
Memory::Virtual(KernelPageTable).Unmap(VirtualAddress);
|
||||
}
|
||||
|
||||
void *Modulememcpy(void *Destination, void *Source, __UINT64_TYPE__ Size)
|
||||
{
|
||||
SmartLock(ModuleDisplayPrintLock);
|
||||
modbg("Copying %ld bytes from %#lx-%#lx to %#lx-%#lx...", Size,
|
||||
(__UINT64_TYPE__)Source, (__UINT64_TYPE__)Source + Size,
|
||||
(__UINT64_TYPE__)Destination, (__UINT64_TYPE__)Destination + Size);
|
||||
return memcpy(Destination, Source, size_t(Size));
|
||||
}
|
||||
|
||||
void *Modulememset(void *Destination, int Value, __UINT64_TYPE__ Size)
|
||||
{
|
||||
SmartLock(ModuleDisplayPrintLock);
|
||||
modbg("Setting value %#x at %#lx-%#lx (%ld bytes)...", Value,
|
||||
(__UINT64_TYPE__)Destination,
|
||||
(__UINT64_TYPE__)Destination + Size, Size);
|
||||
return memset(Destination, Value, size_t(Size));
|
||||
}
|
||||
|
||||
void ModuleNetSend(__UINT32_TYPE__ ModuleID,
|
||||
__UINT8_TYPE__ *Data,
|
||||
__UINT16_TYPE__ Size)
|
||||
{
|
||||
// This is useless I guess...
|
||||
if (NIManager)
|
||||
NIManager->DrvSend(ModuleID, Data, Size);
|
||||
}
|
||||
|
||||
void ModuleNetReceive(__UINT32_TYPE__ ModuleID,
|
||||
__UINT8_TYPE__ *Data,
|
||||
__UINT16_TYPE__ Size)
|
||||
{
|
||||
if (NIManager)
|
||||
NIManager->DrvReceive(ModuleID, Data, Size);
|
||||
}
|
||||
|
||||
void ModuleAHCIDiskRead(__UINT32_TYPE__ ModuleID,
|
||||
__UINT64_TYPE__ Sector,
|
||||
__UINT8_TYPE__ *Data,
|
||||
__UINT32_TYPE__ SectorCount,
|
||||
__UINT8_TYPE__ Port)
|
||||
{
|
||||
DumpData("ModuleDiskRead", Data, SectorCount * 512);
|
||||
UNUSED(ModuleID);
|
||||
UNUSED(Sector);
|
||||
UNUSED(Port);
|
||||
}
|
||||
|
||||
void ModuleAHCIDiskWrite(__UINT32_TYPE__ ModuleID,
|
||||
__UINT64_TYPE__ Sector,
|
||||
__UINT8_TYPE__ *Data,
|
||||
__UINT32_TYPE__ SectorCount,
|
||||
__UINT8_TYPE__ Port)
|
||||
{
|
||||
DumpData("ModuleDiskWrite",
|
||||
Data, SectorCount * 512);
|
||||
UNUSED(ModuleID);
|
||||
UNUSED(Sector);
|
||||
UNUSED(Port);
|
||||
}
|
||||
|
||||
char *ModulePCIGetDeviceName(__UINT32_TYPE__ VendorID,
|
||||
__UINT32_TYPE__ DeviceID)
|
||||
{
|
||||
UNUSED(VendorID);
|
||||
UNUSED(DeviceID);
|
||||
return (char *)"Unknown";
|
||||
}
|
||||
|
||||
__UINT32_TYPE__ ModuleGetWidth()
|
||||
{
|
||||
return Display->GetBuffer(0)->Width;
|
||||
}
|
||||
|
||||
__UINT32_TYPE__ ModuleGetHeight()
|
||||
{
|
||||
return Display->GetBuffer(0)->Height;
|
||||
}
|
||||
|
||||
void ModuleSleep(__UINT64_TYPE__ Milliseconds)
|
||||
{
|
||||
SmartLock(ModuleDisplayPrintLock);
|
||||
modbg("Sleeping for %ld milliseconds...", Milliseconds);
|
||||
if (TaskManager)
|
||||
TaskManager->Sleep(Milliseconds);
|
||||
else
|
||||
TimeManager->Sleep(size_t(Milliseconds),
|
||||
Time::Units::Milliseconds);
|
||||
}
|
||||
|
||||
int Modulesprintf(char *Buffer, const char *Format, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, Format);
|
||||
int ret = vsprintf(Buffer, Format, args);
|
||||
va_end(args);
|
||||
return ret;
|
||||
}
|
||||
|
||||
KernelAPI KernelAPITemplate = {
|
||||
.Version = {
|
||||
.Major = 0,
|
||||
.Minor = 0,
|
||||
.Patch = 1},
|
||||
.Info = {
|
||||
.Offset = 0,
|
||||
.modUniqueID = 0,
|
||||
.KernelDebug = false,
|
||||
},
|
||||
.Memory = {
|
||||
.PageSize = PAGE_SIZE,
|
||||
.RequestPage = RequestPage,
|
||||
.FreePage = FreePage,
|
||||
.Map = MapMemory,
|
||||
.Unmap = UnmapMemory,
|
||||
},
|
||||
.PCI = {
|
||||
.GetDeviceName = ModulePCIGetDeviceName,
|
||||
},
|
||||
.Util = {
|
||||
.DebugPrint = ModuleDebugPrint,
|
||||
.DisplayPrint = ModuleDisplayPrint,
|
||||
.memcpy = Modulememcpy,
|
||||
.memset = Modulememset,
|
||||
.Sleep = ModuleSleep,
|
||||
.sprintf = Modulesprintf,
|
||||
},
|
||||
.Command = {
|
||||
.Network = {
|
||||
.SendPacket = ModuleNetSend,
|
||||
.ReceivePacket = ModuleNetReceive,
|
||||
},
|
||||
.Disk = {
|
||||
.AHCI = {
|
||||
.ReadSector = ModuleAHCIDiskRead,
|
||||
.WriteSector = ModuleAHCIDiskWrite,
|
||||
},
|
||||
},
|
||||
},
|
||||
.Display = {
|
||||
.GetWidth = ModuleGetWidth,
|
||||
.GetHeight = ModuleGetHeight,
|
||||
},
|
||||
};
|
@ -1,118 +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 "../api.hpp"
|
||||
|
||||
#include <ints.hpp>
|
||||
#include <memory.hpp>
|
||||
#include <task.hpp>
|
||||
#include <lock.hpp>
|
||||
#include <printf.h>
|
||||
#include <cwalk.h>
|
||||
#include <md5.h>
|
||||
|
||||
#include "../../../kernel.h"
|
||||
#include "../../../mapi.hpp"
|
||||
#include "../../../Fex.hpp"
|
||||
|
||||
namespace Module
|
||||
{
|
||||
ModuleCode Module::ModuleLoadBindInterrupt(uintptr_t ModuleAddress, size_t Size, bool IsBuiltIn)
|
||||
{
|
||||
Memory::VirtualMemoryArea *vma = new Memory::VirtualMemoryArea(nullptr);
|
||||
|
||||
BuiltInModuleInfo *bidi = (BuiltInModuleInfo *)ModuleAddress;
|
||||
Fex *fex = nullptr;
|
||||
if (!IsBuiltIn)
|
||||
{
|
||||
fex = (Fex *)vma->RequestPages(TO_PAGES(Size + 1));
|
||||
memcpy(fex, (void *)ModuleAddress, Size);
|
||||
debug("Module allocated at %#lx-%#lx", fex, (uintptr_t)fex + Size);
|
||||
}
|
||||
else
|
||||
fex = (Fex *)bidi->EntryPoint;
|
||||
ModuleCode ret = CallModuleEntryPoint(fex, IsBuiltIn);
|
||||
if (ret != ModuleCode::OK)
|
||||
{
|
||||
delete vma;
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (IsBuiltIn)
|
||||
fex = 0x0; /* Addresses are absolute if built-in. */
|
||||
|
||||
FexExtended *fexE = IsBuiltIn ? (FexExtended *)bidi->ExtendedHeader : (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
|
||||
|
||||
debug("Starting driver %s", fexE->Module.Name);
|
||||
|
||||
switch (fexE->Module.Type)
|
||||
{
|
||||
case FexModuleType::FexModuleType_Generic:
|
||||
case FexModuleType::FexModuleType_Display:
|
||||
case FexModuleType::FexModuleType_Network:
|
||||
case FexModuleType::FexModuleType_Storage:
|
||||
case FexModuleType::FexModuleType_FileSystem:
|
||||
case FexModuleType::FexModuleType_Input:
|
||||
case FexModuleType::FexModuleType_Audio:
|
||||
{
|
||||
FexExtended *DriverExtendedHeader = (FexExtended *)vma->RequestPages(TO_PAGES(sizeof(FexExtended) + 1));
|
||||
memcpy(DriverExtendedHeader, fexE, sizeof(FexExtended));
|
||||
|
||||
ModuleFile DrvFile = {
|
||||
.Enabled = true,
|
||||
.BuiltIn = IsBuiltIn,
|
||||
.modUniqueID = this->modUIDs - 1,
|
||||
.Address = (void *)fex,
|
||||
.ExtendedHeaderAddress = (void *)DriverExtendedHeader,
|
||||
.InterruptCallback = (void *)((uintptr_t)fex + (uintptr_t)fexE->Module.InterruptCallback),
|
||||
.vma = vma,
|
||||
};
|
||||
|
||||
if (fexE->Module.InterruptCallback)
|
||||
{
|
||||
for (uint16_t i = 0; i < sizeof(fexE->Module.Bind.Interrupt.Vector) / sizeof(fexE->Module.Bind.Interrupt.Vector[0]); i++)
|
||||
{
|
||||
if (fexE->Module.Bind.Interrupt.Vector[i] == 0)
|
||||
break;
|
||||
DrvFile.InterruptHook[i] = new ModuleInterruptHook(fexE->Module.Bind.Interrupt.Vector[i], DrvFile);
|
||||
}
|
||||
}
|
||||
|
||||
KernelCallback KCallback{};
|
||||
KCallback.RawPtr = nullptr;
|
||||
KCallback.Reason = CallbackReason::ConfigurationReason;
|
||||
ModuleCode CallbackRet = ((ModuleCode(*)(KernelCallback *))((uintptr_t)fexE->Module.Callback + (uintptr_t)fex))(&KCallback);
|
||||
|
||||
if (CallbackRet != ModuleCode::OK)
|
||||
{
|
||||
error("Module %s returned error %d", fexE->Module.Name, CallbackRet);
|
||||
delete vma;
|
||||
return CallbackRet;
|
||||
}
|
||||
|
||||
Modules.push_back(DrvFile);
|
||||
return ModuleCode::OK;
|
||||
}
|
||||
default:
|
||||
{
|
||||
warn("Unknown driver type: %d", fexE->Module.Type);
|
||||
delete vma;
|
||||
return ModuleCode::UNKNOWN_MODULE_TYPE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,145 +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 "../api.hpp"
|
||||
|
||||
#include <ints.hpp>
|
||||
#include <memory.hpp>
|
||||
#include <task.hpp>
|
||||
#include <lock.hpp>
|
||||
#include <printf.h>
|
||||
#include <cwalk.h>
|
||||
#include <md5.h>
|
||||
|
||||
#include "../../../kernel.h"
|
||||
#include "../../../mapi.hpp"
|
||||
#include "../../../Fex.hpp"
|
||||
|
||||
namespace Module
|
||||
{
|
||||
ModuleCode Module::ModuleLoadBindPCI(uintptr_t ModuleAddress, size_t Size, bool IsBuiltIn)
|
||||
{
|
||||
FexExtended *DrvExtHdr = (FexExtended *)(ModuleAddress + EXTENDED_SECTION_ADDRESS);
|
||||
if (IsBuiltIn)
|
||||
DrvExtHdr = (FexExtended *)(((BuiltInModuleInfo *)ModuleAddress)->ExtendedHeader);
|
||||
|
||||
uint16_t SizeOfVendorID = sizeof(DrvExtHdr->Module.Bind.PCI.VendorID) /
|
||||
sizeof(DrvExtHdr->Module.Bind.PCI.VendorID[0]);
|
||||
uint16_t SizeOfDeviceID = sizeof(DrvExtHdr->Module.Bind.PCI.DeviceID) /
|
||||
sizeof(DrvExtHdr->Module.Bind.PCI.DeviceID[0]);
|
||||
|
||||
for (uint16_t vID = 0; vID < SizeOfVendorID; vID++)
|
||||
{
|
||||
for (uint16_t dID = 0; dID < SizeOfDeviceID; dID++)
|
||||
{
|
||||
if (DrvExtHdr->Module.Bind.PCI.VendorID[vID] == 0 ||
|
||||
DrvExtHdr->Module.Bind.PCI.DeviceID[dID] == 0)
|
||||
continue;
|
||||
|
||||
std::vector<PCI::PCIDevice> devices =
|
||||
PCIManager->FindPCIDevice(DrvExtHdr->Module.Bind.PCI.VendorID[vID],
|
||||
DrvExtHdr->Module.Bind.PCI.DeviceID[dID]);
|
||||
if (devices.size() == 0)
|
||||
continue;
|
||||
|
||||
foreach (auto Device in devices)
|
||||
{
|
||||
debug("[%ld] VendorID: %#x; DeviceID: %#x",
|
||||
devices.size(), Device.Header->VendorID,
|
||||
Device.Header->DeviceID);
|
||||
|
||||
Memory::VirtualMemoryArea *vma = new Memory::VirtualMemoryArea(nullptr);
|
||||
|
||||
BuiltInModuleInfo *bidi = (BuiltInModuleInfo *)ModuleAddress;
|
||||
Fex *fex = nullptr;
|
||||
if (!IsBuiltIn)
|
||||
{
|
||||
fex = (Fex *)vma->RequestPages(TO_PAGES(Size + 1));
|
||||
memcpy(fex, (void *)ModuleAddress, Size);
|
||||
debug("Module allocated at %#lx-%#lx", fex, (uintptr_t)fex + Size);
|
||||
}
|
||||
else
|
||||
fex = (Fex *)bidi->EntryPoint;
|
||||
ModuleCode ret = CallModuleEntryPoint(fex, IsBuiltIn);
|
||||
if (ret != ModuleCode::OK)
|
||||
{
|
||||
delete vma;
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (IsBuiltIn)
|
||||
fex = 0x0; /* Addresses are absolute if built-in. */
|
||||
|
||||
FexExtended *fexE = IsBuiltIn ? (FexExtended *)bidi->ExtendedHeader : (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
|
||||
debug("Starting driver %s", fexE->Module.Name);
|
||||
|
||||
PCIManager->MapPCIAddresses(Device);
|
||||
|
||||
switch (fexE->Module.Type)
|
||||
{
|
||||
case FexModuleType::FexModuleType_Generic:
|
||||
case FexModuleType::FexModuleType_Display:
|
||||
case FexModuleType::FexModuleType_Network:
|
||||
case FexModuleType::FexModuleType_Storage:
|
||||
case FexModuleType::FexModuleType_FileSystem:
|
||||
case FexModuleType::FexModuleType_Input:
|
||||
case FexModuleType::FexModuleType_Audio:
|
||||
{
|
||||
FexExtended *DriverExtendedHeader = (FexExtended *)vma->RequestPages(TO_PAGES(sizeof(FexExtended) + 1));
|
||||
memcpy(DriverExtendedHeader, fexE, sizeof(FexExtended));
|
||||
|
||||
ModuleFile DrvFile = {
|
||||
.Enabled = true,
|
||||
.BuiltIn = IsBuiltIn,
|
||||
.modUniqueID = this->modUIDs - 1,
|
||||
.Address = (void *)fex,
|
||||
.ExtendedHeaderAddress = (void *)DriverExtendedHeader,
|
||||
.InterruptCallback = (void *)((uintptr_t)fex + (uintptr_t)fexE->Module.InterruptCallback),
|
||||
.vma = vma,
|
||||
};
|
||||
|
||||
if (fexE->Module.InterruptCallback)
|
||||
DrvFile.InterruptHook[0] = new ModuleInterruptHook(((int)((PCI::PCIHeader0 *)Device.Header)->InterruptLine), DrvFile);
|
||||
|
||||
KernelCallback KCallback{};
|
||||
KCallback.RawPtr = Device.Header;
|
||||
KCallback.Reason = CallbackReason::ConfigurationReason;
|
||||
ModuleCode CallbackRet = ((ModuleCode(*)(KernelCallback *))((uintptr_t)fexE->Module.Callback + (uintptr_t)fex))(&KCallback);
|
||||
|
||||
if (CallbackRet != ModuleCode::OK)
|
||||
{
|
||||
error("Module %s returned error %d", fexE->Module.Name, CallbackRet);
|
||||
delete vma;
|
||||
return CallbackRet;
|
||||
}
|
||||
|
||||
Modules.push_back(DrvFile);
|
||||
return ModuleCode::OK;
|
||||
}
|
||||
default:
|
||||
{
|
||||
warn("Unknown driver type: %d", fexE->Module.Type);
|
||||
delete vma;
|
||||
return ModuleCode::UNKNOWN_MODULE_TYPE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ModuleCode::PCI_DEVICE_NOT_FOUND;
|
||||
}
|
||||
}
|
@ -1,42 +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 "../api.hpp"
|
||||
|
||||
#include <ints.hpp>
|
||||
#include <memory.hpp>
|
||||
#include <task.hpp>
|
||||
#include <lock.hpp>
|
||||
#include <printf.h>
|
||||
#include <cwalk.h>
|
||||
#include <md5.h>
|
||||
|
||||
#include "../../../kernel.h"
|
||||
#include "../../../mapi.hpp"
|
||||
#include "../../../Fex.hpp"
|
||||
|
||||
namespace Module
|
||||
{
|
||||
ModuleCode Module::ModuleLoadBindProcess(uintptr_t ModuleAddress, size_t Size, bool IsBuiltIn)
|
||||
{
|
||||
stub;
|
||||
UNUSED(ModuleAddress);
|
||||
UNUSED(Size);
|
||||
UNUSED(IsBuiltIn);
|
||||
return ModuleCode::NOT_IMPLEMENTED;
|
||||
}
|
||||
}
|
204
core/pci.cpp
204
core/pci.cpp
@ -279,6 +279,10 @@ namespace PCI
|
||||
{
|
||||
switch (VendorID)
|
||||
{
|
||||
case 0x106B:
|
||||
return "Apple Inc.";
|
||||
case 0x104B:
|
||||
return "Bus Logic";
|
||||
case 0x1000:
|
||||
return "Symbios Logic";
|
||||
case 0x1B36:
|
||||
@ -317,12 +321,36 @@ namespace PCI
|
||||
{
|
||||
switch (VendorID)
|
||||
{
|
||||
case Apple:
|
||||
{
|
||||
switch (DeviceID)
|
||||
{
|
||||
case 0x3f:
|
||||
return "KeyLargo/Intrepid USB";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case BusLogic:
|
||||
{
|
||||
switch (DeviceID)
|
||||
{
|
||||
case 0x1040:
|
||||
return "BT-946C (BA80C30) [MultiMaster 10]";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SymbiosLogic:
|
||||
{
|
||||
switch (DeviceID)
|
||||
{
|
||||
case 0x30:
|
||||
return "53c1030 PCI-X Fusion-MPT Dual Ultra320 SCSI";
|
||||
case 0x54:
|
||||
return "SAS1068 PCI-X Fusion-MPT SAS";
|
||||
case 0x1000:
|
||||
return "63C815";
|
||||
default:
|
||||
@ -420,6 +448,12 @@ namespace PCI
|
||||
return "RTL-8029(AS)";
|
||||
case 0x8139:
|
||||
return "RTL-8139/8139C/8139C+ Ethernet Controller";
|
||||
case 0x8161:
|
||||
return "RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller";
|
||||
case 0x8168:
|
||||
return "RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller";
|
||||
case 0xC821:
|
||||
return "RTL8821CE 802.11ac PCIe Wireless Network Adapter";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -503,6 +537,8 @@ namespace PCI
|
||||
return "82557/8/9/0/1 Ethernet Pro 100";
|
||||
case 0x1209:
|
||||
return "8255xER/82551IT Fast Ethernet Controller";
|
||||
case 0x1004:
|
||||
return "82543GC Gigabit Ethernet Controller (Copper)";
|
||||
case 0x100E:
|
||||
return "82540EM Gigabit Ethernet Controller";
|
||||
case 0x7190:
|
||||
@ -519,6 +555,10 @@ namespace PCI
|
||||
return "7 Series/C210 Series Chipset Family USB xHCI Host Controller";
|
||||
case 0x100F:
|
||||
return "82545EM Gigabit Ethernet Controller (Copper)";
|
||||
case 0x1903:
|
||||
return "Xeon E3-1200 v5/E3-1500 v5/6th Gen Core Processor Thermal Subsystem";
|
||||
case 0x1911:
|
||||
return "Xeon E3-1200 v5/v6 / E3-1500 v5 / 6th/7th Gen Core Processor Gaussian Mixture Model";
|
||||
case 0x1371:
|
||||
return "ES1371/ES1373 / Creative Labs CT2518";
|
||||
case 0x27b9:
|
||||
@ -537,6 +577,8 @@ namespace PCI
|
||||
return "82801I (ICH9 Family) USB UHCI Controller #1";
|
||||
case 0x2668:
|
||||
return "82801FB/FBM/FR/FW/FRW (ICH6 Family) High Definition Audio Controller";
|
||||
case 0x265C:
|
||||
return "82801FB/FBM/FR/FW/FRW (ICH6 Family) USB2 EHCI Controller";
|
||||
case 0x2415:
|
||||
return "82801AA AC'97 Audio Controller";
|
||||
case 0x10D3:
|
||||
@ -551,6 +593,40 @@ namespace PCI
|
||||
return "82801IR/IO/IH (ICH9R/DO/DH) 6 port SATA Controller [AHCI mode]";
|
||||
case 0x2930:
|
||||
return "82801I (ICH9 Family) SMBus Controller";
|
||||
case 0x269E:
|
||||
return "631xESB/632xESB IDE Controller";
|
||||
case 0x282A:
|
||||
return "82801 Mobile SATA Controller [RAID mode]";
|
||||
case 0x5914:
|
||||
return "Xeon E3-1200 v6/7th Gen Core Processor Host Bridge/DRAM Registers";
|
||||
case 0x5917:
|
||||
return "UHD Graphics 620";
|
||||
case 0x9D10:
|
||||
return "Sunrise Point-LP PCI Express Root Port #1";
|
||||
case 0x9D11:
|
||||
return "Sunrise Point-LP PCI Express Root Port #2";
|
||||
case 0x9D12:
|
||||
return "Sunrise Point-LP PCI Express Root Port #1";
|
||||
case 0x9D13:
|
||||
return "Sunrise Point-LP PCI Express Root Port #1";
|
||||
case 0x9D14:
|
||||
return "Sunrise Point-LP PCI Express Root Port #5";
|
||||
case 0x9D15:
|
||||
return "Sunrise Point-LP PCI Express Root Port #6";
|
||||
case 0x9D21:
|
||||
return "Sunrise Point-LP PMC";
|
||||
case 0x9D23:
|
||||
return "Sunrise Point-LP SMBus";
|
||||
case 0x9D2F:
|
||||
return "Sunrise Point-LP USB 3.0 xHCI Controller";
|
||||
case 0x9D31:
|
||||
return "Sunrise Point-LP Thermal subsystem";
|
||||
case 0x9D3A:
|
||||
return "Sunrise Point-LP CSME HECI #1";
|
||||
case 0x9D4E:
|
||||
return "Intel(R) 100 Series Chipset Family LPC Controller/eSPI Controller - 9D4E";
|
||||
case 0x9D71:
|
||||
return "Sunrise Point-LP HD Audio";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -567,9 +643,20 @@ namespace PCI
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NVIDIACorporation:
|
||||
{
|
||||
switch (DeviceID)
|
||||
{
|
||||
case 0x174D:
|
||||
return "GM108M [GeForce MX130]";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
fixme("Unknown device %04x:%04x", VendorID, DeviceID);
|
||||
return u32ToHexString(DeviceID);
|
||||
}
|
||||
@ -772,9 +859,12 @@ namespace PCI
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
void e(PCIDeviceHeader *hdr)
|
||||
void e(PCIDevice dev)
|
||||
{
|
||||
debug("%#x:%#x\t\t%s / %s / %s / %s / %s",
|
||||
PCIDeviceHeader *hdr = dev.Header;
|
||||
|
||||
debug("%02x.%02x.%02x - %#x:%#x\t\t%s / %s / %s / %s / %s",
|
||||
dev.Bus, dev.Device, dev.Function,
|
||||
hdr->VendorID, hdr->DeviceID,
|
||||
Descriptors::GetVendorName(hdr->VendorID),
|
||||
Descriptors::GetDeviceName(hdr->VendorID, hdr->DeviceID),
|
||||
@ -784,27 +874,31 @@ namespace PCI
|
||||
}
|
||||
#endif
|
||||
|
||||
void PCI::MapPCIAddresses(PCIDevice Device, Memory::PageTable *Table)
|
||||
void Manager::MapPCIAddresses(PCIDevice Device, Memory::PageTable *Table)
|
||||
{
|
||||
debug("Header Type: %d", Device.Header->HeaderType);
|
||||
switch (Device.Header->HeaderType)
|
||||
{
|
||||
case 128:
|
||||
warn("Unknown header type %d! Guessing PCI Header 0",
|
||||
Device.Header->HeaderType);
|
||||
[[fallthrough]];
|
||||
case 0: /* PCI Header 0 */
|
||||
{
|
||||
uint32_t BAR[6] = {0};
|
||||
size_t BARsSize[6] = {0};
|
||||
PCIHeader0 *hdr0 = (PCIHeader0 *)Device.Header;
|
||||
|
||||
BAR[0] = ((PCIHeader0 *)Device.Header)->BAR0;
|
||||
BAR[1] = ((PCIHeader0 *)Device.Header)->BAR1;
|
||||
BAR[2] = ((PCIHeader0 *)Device.Header)->BAR2;
|
||||
BAR[3] = ((PCIHeader0 *)Device.Header)->BAR3;
|
||||
BAR[4] = ((PCIHeader0 *)Device.Header)->BAR4;
|
||||
BAR[5] = ((PCIHeader0 *)Device.Header)->BAR5;
|
||||
uint32_t BAR[6];
|
||||
size_t BARsSize[6];
|
||||
|
||||
BAR[0] = hdr0->BAR0;
|
||||
BAR[1] = hdr0->BAR1;
|
||||
BAR[2] = hdr0->BAR2;
|
||||
BAR[3] = hdr0->BAR3;
|
||||
BAR[4] = hdr0->BAR4;
|
||||
BAR[5] = hdr0->BAR5;
|
||||
|
||||
debug("Type: %d; IOBase: %#lx; MemoryBase: %#lx",
|
||||
BAR[0] & 1,
|
||||
BAR[1] & (~3),
|
||||
BAR[0] & (~15));
|
||||
BAR[0] & 1, BAR[1] & (~3), BAR[0] & (~15));
|
||||
|
||||
/* BARs Size */
|
||||
for (short i = 0; i < 6; i++)
|
||||
@ -812,25 +906,28 @@ namespace PCI
|
||||
if (BAR[i] == 0)
|
||||
continue;
|
||||
|
||||
size_t size;
|
||||
if ((BAR[i] & 1) == 0) /* Memory Base */
|
||||
{
|
||||
((PCIHeader0 *)Device.Header)->BAR0 = 0xFFFFFFFF;
|
||||
size_t size = ((PCIHeader0 *)Device.Header)->BAR0;
|
||||
((PCIHeader0 *)Device.Header)->BAR0 = BAR[i];
|
||||
hdr0->BAR0 = 0xFFFFFFFF;
|
||||
size = hdr0->BAR0;
|
||||
hdr0->BAR0 = BAR[i];
|
||||
BARsSize[i] = size & (~15);
|
||||
BARsSize[i] = ~BARsSize[i] + 1;
|
||||
BARsSize[i] = BARsSize[i] & 0xFFFFFFFF;
|
||||
debug("BAR%d %#lx size: %d", i, BAR[i], BARsSize[i]);
|
||||
debug("BAR%d %#lx size: %d",
|
||||
i, BAR[i], BARsSize[i]);
|
||||
}
|
||||
else if ((BAR[i] & 1) == 1) /* I/O Base */
|
||||
{
|
||||
((PCIHeader0 *)Device.Header)->BAR1 = 0xFFFFFFFF;
|
||||
size_t size = ((PCIHeader0 *)Device.Header)->BAR1;
|
||||
((PCIHeader0 *)Device.Header)->BAR1 = BAR[i];
|
||||
hdr0->BAR1 = 0xFFFFFFFF;
|
||||
size = hdr0->BAR1;
|
||||
hdr0->BAR1 = BAR[i];
|
||||
BARsSize[i] = size & (~3);
|
||||
BARsSize[i] = ~BARsSize[i] + 1;
|
||||
BARsSize[i] = BARsSize[i] & 0xFFFF;
|
||||
debug("BAR%d %#lx size: %d", i, BAR[i], BARsSize[i]);
|
||||
debug("BAR%d %#lx size: %d",
|
||||
i, BAR[i], BARsSize[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -845,18 +942,24 @@ namespace PCI
|
||||
uintptr_t BARBase = BAR[i] & (~15);
|
||||
size_t BARSize = BARsSize[i];
|
||||
|
||||
debug("Mapping BAR%d %#lx-%#lx", i, BARBase, BARBase + BARSize);
|
||||
Memory::Virtual(Table).Map((void *)BARBase, (void *)BARBase, BARSize,
|
||||
Memory::PTFlag::RW | Memory::PTFlag::PWT);
|
||||
debug("Mapping BAR%d %#lx-%#lx",
|
||||
i, BARBase, BARBase + BARSize);
|
||||
|
||||
if (BARSize > 0)
|
||||
Memory::Virtual(Table).Map((void *)BARBase, (void *)BARBase,
|
||||
BARSize, Memory::RW | Memory::PWT);
|
||||
}
|
||||
else if ((BAR[i] & 1) == 1) /* I/O Base */
|
||||
{
|
||||
uintptr_t BARBase = BAR[i] & (~3);
|
||||
size_t BARSize = BARsSize[i];
|
||||
|
||||
debug("Mapping BAR%d %#x-%#x", i, BARBase, BARBase + BARSize);
|
||||
Memory::Virtual(Table).Map((void *)BARBase, (void *)BARBase, BARSize,
|
||||
Memory::PTFlag::RW | Memory::PTFlag::PWT);
|
||||
debug("Mapping BAR%d %#x-%#x",
|
||||
i, BARBase, BARBase + BARSize);
|
||||
|
||||
if (BARSize > 0)
|
||||
Memory::Virtual(Table).Map((void *)BARBase, (void *)BARBase,
|
||||
BARSize, Memory::RW | Memory::PWT);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -874,12 +977,12 @@ namespace PCI
|
||||
default:
|
||||
{
|
||||
error("Unknown header type %d", Device.Header->HeaderType);
|
||||
return;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PCI::EnumerateFunction(uint64_t DeviceAddress, uint32_t Function, PCIDevice dev)
|
||||
void Manager::EnumerateFunction(uint64_t DeviceAddress, uint32_t Function, PCIDevice dev)
|
||||
{
|
||||
dev.Function = Function;
|
||||
|
||||
@ -896,11 +999,11 @@ namespace PCI
|
||||
|
||||
Devices.push_back(dev);
|
||||
#ifdef DEBUG
|
||||
e(PCIDeviceHdr);
|
||||
e(dev);
|
||||
#endif
|
||||
}
|
||||
|
||||
void PCI::EnumerateDevice(uint64_t BusAddress, uint32_t Device, PCIDevice dev)
|
||||
void Manager::EnumerateDevice(uint64_t BusAddress, uint32_t Device, PCIDevice dev)
|
||||
{
|
||||
dev.Device = Device;
|
||||
|
||||
@ -918,7 +1021,7 @@ namespace PCI
|
||||
EnumerateFunction(DeviceAddress, Function, dev);
|
||||
}
|
||||
|
||||
void PCI::EnumerateBus(uint64_t BaseAddress, uint32_t Bus, PCIDevice dev)
|
||||
void Manager::EnumerateBus(uint64_t BaseAddress, uint32_t Bus, PCIDevice dev)
|
||||
{
|
||||
dev.Bus = Bus;
|
||||
|
||||
@ -945,9 +1048,9 @@ namespace PCI
|
||||
EnumerateDevice(BusAddress, Device, dev);
|
||||
}
|
||||
|
||||
std::vector<PCIDevice> PCI::FindPCIDevice(uint8_t Class, uint8_t Subclass, uint8_t ProgIF)
|
||||
std::list<PCIDevice> Manager::FindPCIDevice(uint8_t Class, uint8_t Subclass, uint8_t ProgIF)
|
||||
{
|
||||
std::vector<PCIDevice> DeviceFound;
|
||||
std::list<PCIDevice> DeviceFound;
|
||||
foreach (auto dev in Devices)
|
||||
{
|
||||
if (dev.Header->Class == Class &&
|
||||
@ -960,9 +1063,9 @@ namespace PCI
|
||||
return DeviceFound;
|
||||
}
|
||||
|
||||
std::vector<PCIDevice> PCI::FindPCIDevice(int VendorID, int DeviceID)
|
||||
std::list<PCIDevice> Manager::FindPCIDevice(uint16_t VendorID, uint16_t DeviceID)
|
||||
{
|
||||
std::vector<PCIDevice> DeviceFound;
|
||||
std::list<PCIDevice> DeviceFound;
|
||||
foreach (auto dev in Devices)
|
||||
{
|
||||
if (dev.Header->VendorID == VendorID &&
|
||||
@ -974,7 +1077,28 @@ namespace PCI
|
||||
return DeviceFound;
|
||||
}
|
||||
|
||||
PCI::PCI()
|
||||
std::list<PCIDevice> Manager::FindPCIDevice(std::list<uint16_t> VendorIDs,
|
||||
std::list<uint16_t> DeviceIDs)
|
||||
{
|
||||
std::list<PCIDevice> DeviceFound;
|
||||
foreach (auto dev in Devices)
|
||||
{
|
||||
foreach (auto VendorID in VendorIDs)
|
||||
{
|
||||
foreach (auto DeviceID in DeviceIDs)
|
||||
{
|
||||
if (dev.Header->VendorID == VendorID &&
|
||||
dev.Header->DeviceID == DeviceID)
|
||||
{
|
||||
DeviceFound.push_back(dev);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return DeviceFound;
|
||||
}
|
||||
|
||||
Manager::Manager()
|
||||
{
|
||||
#if defined(a86)
|
||||
if (!PowerManager->GetACPI())
|
||||
@ -990,7 +1114,7 @@ namespace PCI
|
||||
}
|
||||
|
||||
int Entries = s_cst(int, ((((ACPI::ACPI *)PowerManager->GetACPI())->MCFG->Header.Length) - sizeof(ACPI::ACPI::MCFGHeader)) / sizeof(DeviceConfig));
|
||||
Memory::Virtual vmm = Memory::Virtual(KernelPageTable);
|
||||
Memory::Virtual vmm(KernelPageTable);
|
||||
for (int t = 0; t < Entries; t++)
|
||||
{
|
||||
DeviceConfig *NewDeviceConfig = (DeviceConfig *)((uintptr_t)((ACPI::ACPI *)PowerManager->GetACPI())->MCFG + sizeof(ACPI::ACPI::MCFGHeader) + (sizeof(DeviceConfig) * t));
|
||||
@ -1008,5 +1132,5 @@ namespace PCI
|
||||
#endif
|
||||
}
|
||||
|
||||
PCI::~PCI() {}
|
||||
Manager::~Manager() {}
|
||||
}
|
||||
|
@ -32,15 +32,6 @@ namespace Power
|
||||
if (((ACPI::DSDT *)this->dsdt)->ACPIShutdownSupported)
|
||||
((ACPI::DSDT *)this->dsdt)->Reboot();
|
||||
|
||||
uint8_t val = 0x02;
|
||||
while (val & 0x02)
|
||||
val = inb(0x64);
|
||||
outb(0x64, 0xFE);
|
||||
|
||||
warn("Executing the second attempt to reboot...");
|
||||
|
||||
// https://wiki.osdev.org/Reboot
|
||||
/* Second attempt to reboot */
|
||||
asmv("cli");
|
||||
uint8_t temp;
|
||||
do
|
||||
@ -50,24 +41,24 @@ namespace Power
|
||||
inb(0x60);
|
||||
} while (((temp) & (1 << (1))) != 0);
|
||||
outb(0x64, 0xFE);
|
||||
|
||||
CPU::Stop();
|
||||
}
|
||||
|
||||
void Power::Shutdown()
|
||||
{
|
||||
if (((ACPI::ACPI *)this->acpi)->FADT)
|
||||
{
|
||||
if (((ACPI::DSDT *)this->dsdt)->ACPIShutdownSupported)
|
||||
((ACPI::DSDT *)this->dsdt)->Shutdown();
|
||||
/* TODO: If no ACPI, display "It is now safe to turn off your computer" */
|
||||
|
||||
/* FIXME: Detect emulators and use their shutdown methods */
|
||||
else
|
||||
KPrint("Shutdown not supported");
|
||||
/* TODO: If no ACPI, display "It is now safe to turn off your computer"? */
|
||||
}
|
||||
/* FIXME: Detect emulators and use their shutdown methods */
|
||||
#ifdef DEBUG
|
||||
outl(0xB004, 0x2000); // for qemu
|
||||
outl(0x604, 0x2000); // if qemu not working, bochs and older versions of qemu
|
||||
outl(0x4004, 0x3400); // virtual box
|
||||
#endif
|
||||
CPU::Stop();
|
||||
}
|
||||
|
||||
void Power::InitDSDT()
|
||||
|
208
core/random.cpp
208
core/random.cpp
@ -20,124 +20,124 @@
|
||||
|
||||
namespace Random
|
||||
{
|
||||
static uint64_t Seed = 0xdeadbeef;
|
||||
static uint64_t Seed = 0xdeadbeef;
|
||||
|
||||
uint16_t rand16()
|
||||
{
|
||||
uint16_t rand16()
|
||||
{
|
||||
#if defined(a86)
|
||||
static int RDRANDFlag = 0x1A1A;
|
||||
if (unlikely(RDRANDFlag == 0x1A1A))
|
||||
{
|
||||
if (strcmp(CPU::Hypervisor(), x86_CPUID_VENDOR_TCG) != 0)
|
||||
{
|
||||
if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_AMD) == 0)
|
||||
{
|
||||
CPU::x86::AMD::CPUID0x00000001 cpuid;
|
||||
cpuid.Get();
|
||||
RDRANDFlag = cpuid.ECX.RDRAND;
|
||||
}
|
||||
else if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_INTEL) == 0)
|
||||
{
|
||||
CPU::x86::Intel::CPUID0x00000001 cpuid;
|
||||
cpuid.Get();
|
||||
RDRANDFlag = cpuid.ECX.RDRAND;
|
||||
}
|
||||
}
|
||||
else
|
||||
RDRANDFlag = 0;
|
||||
}
|
||||
static int RDRANDFlag = 0x1A1A;
|
||||
if (unlikely(RDRANDFlag == 0x1A1A))
|
||||
{
|
||||
if (strcmp(CPU::Hypervisor(), x86_CPUID_VENDOR_TCG) != 0)
|
||||
{
|
||||
if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_AMD) == 0)
|
||||
{
|
||||
CPU::x86::AMD::CPUID0x00000001 cpuid;
|
||||
cpuid.Get();
|
||||
RDRANDFlag = cpuid.ECX.RDRAND;
|
||||
}
|
||||
else if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_INTEL) == 0)
|
||||
{
|
||||
CPU::x86::Intel::CPUID0x00000001 cpuid;
|
||||
cpuid.Get();
|
||||
RDRANDFlag = cpuid.ECX.RDRAND;
|
||||
}
|
||||
}
|
||||
else
|
||||
RDRANDFlag = 0;
|
||||
}
|
||||
|
||||
if (RDRANDFlag)
|
||||
{
|
||||
uint16_t RDRANDValue = 0;
|
||||
asmv("1: rdrand %0; jnc 1b"
|
||||
: "=r"(RDRANDValue));
|
||||
return RDRANDValue;
|
||||
}
|
||||
if (RDRANDFlag)
|
||||
{
|
||||
uint16_t RDRANDValue = 0;
|
||||
asmv("1: rdrand %0; jnc 1b"
|
||||
: "=r"(RDRANDValue));
|
||||
return RDRANDValue;
|
||||
}
|
||||
|
||||
Seed = Seed * 1103515245 + 12345;
|
||||
return (uint16_t)(Seed / 65536) % __UINT16_MAX__;
|
||||
Seed = Seed * 1103515245 + 12345;
|
||||
return (uint16_t)(Seed / 65536) % __UINT16_MAX__;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t rand32()
|
||||
{
|
||||
uint32_t rand32()
|
||||
{
|
||||
#if defined(a86)
|
||||
static int RDRANDFlag = 0x1A1A;
|
||||
if (unlikely(RDRANDFlag == 0x1A1A))
|
||||
{
|
||||
if (strcmp(CPU::Hypervisor(), x86_CPUID_VENDOR_TCG) != 0)
|
||||
{
|
||||
if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_AMD) == 0)
|
||||
{
|
||||
CPU::x86::AMD::CPUID0x00000001 cpuid;
|
||||
cpuid.Get();
|
||||
RDRANDFlag = cpuid.ECX.RDRAND;
|
||||
}
|
||||
else if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_INTEL) == 0)
|
||||
{
|
||||
CPU::x86::Intel::CPUID0x00000001 cpuid;
|
||||
cpuid.Get();
|
||||
RDRANDFlag = cpuid.ECX.RDRAND;
|
||||
}
|
||||
}
|
||||
else
|
||||
RDRANDFlag = 0;
|
||||
}
|
||||
static int RDRANDFlag = 0x1A1A;
|
||||
if (unlikely(RDRANDFlag == 0x1A1A))
|
||||
{
|
||||
if (strcmp(CPU::Hypervisor(), x86_CPUID_VENDOR_TCG) != 0)
|
||||
{
|
||||
if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_AMD) == 0)
|
||||
{
|
||||
CPU::x86::AMD::CPUID0x00000001 cpuid;
|
||||
cpuid.Get();
|
||||
RDRANDFlag = cpuid.ECX.RDRAND;
|
||||
}
|
||||
else if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_INTEL) == 0)
|
||||
{
|
||||
CPU::x86::Intel::CPUID0x00000001 cpuid;
|
||||
cpuid.Get();
|
||||
RDRANDFlag = cpuid.ECX.RDRAND;
|
||||
}
|
||||
}
|
||||
else
|
||||
RDRANDFlag = 0;
|
||||
}
|
||||
|
||||
if (RDRANDFlag)
|
||||
{
|
||||
uint32_t RDRANDValue = 0;
|
||||
asmv("1: rdrand %0; jnc 1b"
|
||||
: "=r"(RDRANDValue));
|
||||
return RDRANDValue;
|
||||
}
|
||||
if (RDRANDFlag)
|
||||
{
|
||||
uint32_t RDRANDValue = 0;
|
||||
asmv("1: rdrand %0; jnc 1b"
|
||||
: "=r"(RDRANDValue));
|
||||
return RDRANDValue;
|
||||
}
|
||||
|
||||
Seed = Seed * 1103515245 + 12345;
|
||||
return (uint32_t)(Seed / 65536) % __UINT32_MAX__;
|
||||
Seed = Seed * 1103515245 + 12345;
|
||||
return (uint32_t)(Seed / 65536) % __UINT32_MAX__;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64_t rand64()
|
||||
{
|
||||
uint64_t rand64()
|
||||
{
|
||||
#if defined(a86)
|
||||
static int RDRANDFlag = 0x1A1A;
|
||||
if (unlikely(RDRANDFlag == 0x1A1A))
|
||||
{
|
||||
if (strcmp(CPU::Hypervisor(), x86_CPUID_VENDOR_TCG) != 0)
|
||||
{
|
||||
if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_AMD) == 0)
|
||||
{
|
||||
CPU::x86::AMD::CPUID0x00000001 cpuid;
|
||||
cpuid.Get();
|
||||
RDRANDFlag = cpuid.ECX.RDRAND;
|
||||
}
|
||||
else if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_INTEL) == 0)
|
||||
{
|
||||
CPU::x86::Intel::CPUID0x00000001 cpuid;
|
||||
cpuid.Get();
|
||||
RDRANDFlag = cpuid.ECX.RDRAND;
|
||||
}
|
||||
}
|
||||
else
|
||||
RDRANDFlag = 0;
|
||||
}
|
||||
static int RDRANDFlag = 0x1A1A;
|
||||
if (unlikely(RDRANDFlag == 0x1A1A))
|
||||
{
|
||||
if (strcmp(CPU::Hypervisor(), x86_CPUID_VENDOR_TCG) != 0)
|
||||
{
|
||||
if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_AMD) == 0)
|
||||
{
|
||||
CPU::x86::AMD::CPUID0x00000001 cpuid;
|
||||
cpuid.Get();
|
||||
RDRANDFlag = cpuid.ECX.RDRAND;
|
||||
}
|
||||
else if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_INTEL) == 0)
|
||||
{
|
||||
CPU::x86::Intel::CPUID0x00000001 cpuid;
|
||||
cpuid.Get();
|
||||
RDRANDFlag = cpuid.ECX.RDRAND;
|
||||
}
|
||||
}
|
||||
else
|
||||
RDRANDFlag = 0;
|
||||
}
|
||||
|
||||
if (RDRANDFlag)
|
||||
{
|
||||
uintptr_t RDRANDValue = 0;
|
||||
asmv("1: rdrand %0; jnc 1b"
|
||||
: "=r"(RDRANDValue));
|
||||
return RDRANDValue;
|
||||
}
|
||||
if (RDRANDFlag)
|
||||
{
|
||||
uintptr_t RDRANDValue = 0;
|
||||
asmv("1: rdrand %0; jnc 1b"
|
||||
: "=r"(RDRANDValue));
|
||||
return RDRANDValue;
|
||||
}
|
||||
|
||||
Seed = Seed * 1103515245 + 12345;
|
||||
return (uint64_t)(Seed / 65536) % __UINT64_MAX__;
|
||||
Seed = Seed * 1103515245 + 12345;
|
||||
return (uint64_t)(Seed / 65536) % __UINT64_MAX__;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ChangeSeed(uint64_t CustomSeed) { Seed = CustomSeed; }
|
||||
void ChangeSeed(uint64_t CustomSeed) { Seed = CustomSeed; }
|
||||
}
|
||||
|
620
core/smbios.hpp
620
core/smbios.hpp
@ -22,336 +22,336 @@
|
||||
|
||||
namespace SMBIOS
|
||||
{
|
||||
enum SMBIOSType
|
||||
{
|
||||
SMBIOSTypeBIOSInformation = 0,
|
||||
SMBIOSTypeSystemInformation = 1,
|
||||
SMBIOSTypeBaseBoardInformation = 2,
|
||||
SMBIOSTypeSystemEnclosure = 3,
|
||||
SMBIOSTypeProcessorInformation = 4,
|
||||
SMBIOSTypeMemoryControllerInformation = 5,
|
||||
SMBIOSTypeMemoryModuleInformation = 6,
|
||||
SMBIOSTypeCacheInformation = 7,
|
||||
SMBIOSTypePortConnectorInformation = 8,
|
||||
SMBIOSTypeSystemSlots = 9,
|
||||
SMBIOSTypeOnBoardDevicesInformation = 10,
|
||||
SMBIOSTypeOEMStrings = 11,
|
||||
SMBIOSTypeSystemConfigurationOptions = 12,
|
||||
SMBIOSTypeBIOSLanguageInformation = 13,
|
||||
SMBIOSTypeGroupAssociations = 14,
|
||||
SMBIOSTypeSystemEventLog = 15,
|
||||
SMBIOSTypePhysicalMemoryArray = 16,
|
||||
SMBIOSTypeMemoryDevice = 17,
|
||||
SMBIOSType32BitMemoryErrorInformation = 18,
|
||||
SMBIOSTypeMemoryArrayMappedAddress = 19,
|
||||
SMBIOSTypeMemoryDeviceMappedAddress = 20,
|
||||
SMBIOSTypeBuiltInPointingDevice = 21,
|
||||
SMBIOSTypePortableBattery = 22,
|
||||
SMBIOSTypeSystemReset = 23,
|
||||
SMBIOSTypeHardwareSecurity = 24,
|
||||
SMBIOSTypeSystemPowerControls = 25,
|
||||
SMBIOSTypeVoltageProbe = 26,
|
||||
SMBIOSTypeCoolingDevice = 27,
|
||||
SMBIOSTypeTemperatureProbe = 28,
|
||||
SMBIOSTypeElectricalCurrentProbe = 29,
|
||||
SMBIOSTypeOutofBandRemoteAccess = 30,
|
||||
SMBIOSTypeBootIntegrityServices = 31,
|
||||
SMBIOSTypeSystemBoot = 32,
|
||||
SMBIOSType64BitMemoryErrorInformation = 33,
|
||||
SMBIOSTypeManagementDevice = 34,
|
||||
SMBIOSTypeManagementDeviceComponent = 35,
|
||||
SMBIOSTypeManagementDeviceThresholdData = 36,
|
||||
SMBIOSTypeMemoryChannel = 37,
|
||||
SMBIOSTypeIPMIDevice = 38,
|
||||
SMBIOSTypePowerSupply = 39,
|
||||
SMBIOSTypeAdditionalInformation = 40,
|
||||
SMBIOSTypeOnboardDevicesExtendedInformation = 41,
|
||||
SMBIOSTypeManagementControllerHostInterface = 42,
|
||||
SMBIOSTypeTPMDevice = 43,
|
||||
SMBIOSTypeProcessorAdditionalInformation = 44,
|
||||
SMBIOSTypeInactive = 126,
|
||||
SMBIOSTypeEndOfTable = 127
|
||||
};
|
||||
enum SMBIOSType
|
||||
{
|
||||
SMBIOSTypeBIOSInformation = 0,
|
||||
SMBIOSTypeSystemInformation = 1,
|
||||
SMBIOSTypeBaseBoardInformation = 2,
|
||||
SMBIOSTypeSystemEnclosure = 3,
|
||||
SMBIOSTypeProcessorInformation = 4,
|
||||
SMBIOSTypeMemoryControllerInformation = 5,
|
||||
SMBIOSTypeMemoryModuleInformation = 6,
|
||||
SMBIOSTypeCacheInformation = 7,
|
||||
SMBIOSTypePortConnectorInformation = 8,
|
||||
SMBIOSTypeSystemSlots = 9,
|
||||
SMBIOSTypeOnBoardDevicesInformation = 10,
|
||||
SMBIOSTypeOEMStrings = 11,
|
||||
SMBIOSTypeSystemConfigurationOptions = 12,
|
||||
SMBIOSTypeBIOSLanguageInformation = 13,
|
||||
SMBIOSTypeGroupAssociations = 14,
|
||||
SMBIOSTypeSystemEventLog = 15,
|
||||
SMBIOSTypePhysicalMemoryArray = 16,
|
||||
SMBIOSTypeMemoryDevice = 17,
|
||||
SMBIOSType32BitMemoryErrorInformation = 18,
|
||||
SMBIOSTypeMemoryArrayMappedAddress = 19,
|
||||
SMBIOSTypeMemoryDeviceMappedAddress = 20,
|
||||
SMBIOSTypeBuiltInPointingDevice = 21,
|
||||
SMBIOSTypePortableBattery = 22,
|
||||
SMBIOSTypeSystemReset = 23,
|
||||
SMBIOSTypeHardwareSecurity = 24,
|
||||
SMBIOSTypeSystemPowerControls = 25,
|
||||
SMBIOSTypeVoltageProbe = 26,
|
||||
SMBIOSTypeCoolingDevice = 27,
|
||||
SMBIOSTypeTemperatureProbe = 28,
|
||||
SMBIOSTypeElectricalCurrentProbe = 29,
|
||||
SMBIOSTypeOutofBandRemoteAccess = 30,
|
||||
SMBIOSTypeBootIntegrityServices = 31,
|
||||
SMBIOSTypeSystemBoot = 32,
|
||||
SMBIOSType64BitMemoryErrorInformation = 33,
|
||||
SMBIOSTypeManagementDevice = 34,
|
||||
SMBIOSTypeManagementDeviceComponent = 35,
|
||||
SMBIOSTypeManagementDeviceThresholdData = 36,
|
||||
SMBIOSTypeMemoryChannel = 37,
|
||||
SMBIOSTypeIPMIDevice = 38,
|
||||
SMBIOSTypePowerSupply = 39,
|
||||
SMBIOSTypeAdditionalInformation = 40,
|
||||
SMBIOSTypeOnboardDevicesExtendedInformation = 41,
|
||||
SMBIOSTypeManagementControllerHostInterface = 42,
|
||||
SMBIOSTypeTPMDevice = 43,
|
||||
SMBIOSTypeProcessorAdditionalInformation = 44,
|
||||
SMBIOSTypeInactive = 126,
|
||||
SMBIOSTypeEndOfTable = 127
|
||||
};
|
||||
|
||||
struct SMBIOSHeader
|
||||
{
|
||||
unsigned char Type;
|
||||
unsigned char Length;
|
||||
unsigned short Handle;
|
||||
};
|
||||
struct SMBIOSHeader
|
||||
{
|
||||
unsigned char Type;
|
||||
unsigned char Length;
|
||||
unsigned short Handle;
|
||||
};
|
||||
|
||||
struct SMBIOSEntryPoint
|
||||
{
|
||||
char EntryPointString[4];
|
||||
unsigned char Checksum;
|
||||
unsigned char Length;
|
||||
unsigned char MajorVersion;
|
||||
unsigned char MinorVersion;
|
||||
unsigned short MaxStructureSize;
|
||||
unsigned char EntryPointRevision;
|
||||
char FormattedArea[5];
|
||||
char EntryPointString2[5];
|
||||
unsigned char Checksum2;
|
||||
unsigned short TableLength;
|
||||
unsigned int TableAddress;
|
||||
unsigned short NumberOfStructures;
|
||||
unsigned char BCDRevision;
|
||||
};
|
||||
struct SMBIOSEntryPoint
|
||||
{
|
||||
char EntryPointString[4];
|
||||
unsigned char Checksum;
|
||||
unsigned char Length;
|
||||
unsigned char MajorVersion;
|
||||
unsigned char MinorVersion;
|
||||
unsigned short MaxStructureSize;
|
||||
unsigned char EntryPointRevision;
|
||||
char FormattedArea[5];
|
||||
char EntryPointString2[5];
|
||||
unsigned char Checksum2;
|
||||
unsigned short TableLength;
|
||||
unsigned int TableAddress;
|
||||
unsigned short NumberOfStructures;
|
||||
unsigned char BCDRevision;
|
||||
};
|
||||
|
||||
static inline char *SMBIOSNextString(char *Str)
|
||||
{
|
||||
while (*Str != '\0')
|
||||
Str++;
|
||||
return Str + 1;
|
||||
}
|
||||
static inline char *SMBIOSNextString(char *Str)
|
||||
{
|
||||
while (*Str != '\0')
|
||||
Str++;
|
||||
return Str + 1;
|
||||
}
|
||||
|
||||
struct SMBIOSBIOSInformation
|
||||
{
|
||||
SMBIOSHeader Header;
|
||||
unsigned char Vendor;
|
||||
unsigned char Version;
|
||||
unsigned short StartingAddressSegment;
|
||||
unsigned char ReleaseDate;
|
||||
unsigned char ROMSize;
|
||||
unsigned long Characteristics;
|
||||
unsigned char CharacteristicsExtensionBytes[2];
|
||||
unsigned char SystemBIOSMajorRelease;
|
||||
unsigned char SystemBIOSMinorRelease;
|
||||
unsigned char EmbeddedControllerFirmwareMajorRelease;
|
||||
unsigned char EmbeddedControllerFirmwareMinorRelease;
|
||||
struct SMBIOSBIOSInformation
|
||||
{
|
||||
SMBIOSHeader Header;
|
||||
unsigned char Vendor;
|
||||
unsigned char Version;
|
||||
unsigned short StartingAddressSegment;
|
||||
unsigned char ReleaseDate;
|
||||
unsigned char ROMSize;
|
||||
unsigned long Characteristics;
|
||||
unsigned char CharacteristicsExtensionBytes[2];
|
||||
unsigned char SystemBIOSMajorRelease;
|
||||
unsigned char SystemBIOSMinorRelease;
|
||||
unsigned char EmbeddedControllerFirmwareMajorRelease;
|
||||
unsigned char EmbeddedControllerFirmwareMinorRelease;
|
||||
|
||||
const char *GetString(unsigned char Index)
|
||||
{
|
||||
char *Str = (char *)((unsigned long)this + this->Header.Length);
|
||||
Index--;
|
||||
if (Index == 0 || Index > 10)
|
||||
return Str;
|
||||
for (unsigned char i = 0; i < Index; i++)
|
||||
Str = SMBIOSNextString(Str);
|
||||
return Str;
|
||||
}
|
||||
};
|
||||
const char *GetString(unsigned char Index)
|
||||
{
|
||||
char *Str = (char *)((unsigned long)this + this->Header.Length);
|
||||
Index--;
|
||||
if (Index == 0 || Index > 10)
|
||||
return Str;
|
||||
for (unsigned char i = 0; i < Index; i++)
|
||||
Str = SMBIOSNextString(Str);
|
||||
return Str;
|
||||
}
|
||||
};
|
||||
|
||||
struct SMBIOSSystemInformation
|
||||
{
|
||||
SMBIOSHeader Header;
|
||||
unsigned char Manufacturer;
|
||||
unsigned char ProductName;
|
||||
unsigned char Version;
|
||||
unsigned char SerialNumber;
|
||||
unsigned char UUID[16];
|
||||
unsigned char WakeUpType;
|
||||
unsigned char SKU;
|
||||
unsigned char Family;
|
||||
struct SMBIOSSystemInformation
|
||||
{
|
||||
SMBIOSHeader Header;
|
||||
unsigned char Manufacturer;
|
||||
unsigned char ProductName;
|
||||
unsigned char Version;
|
||||
unsigned char SerialNumber;
|
||||
unsigned char UUID[16];
|
||||
unsigned char WakeUpType;
|
||||
unsigned char SKU;
|
||||
unsigned char Family;
|
||||
|
||||
const char *GetString(unsigned char Index)
|
||||
{
|
||||
char *Str = (char *)((unsigned long)this + this->Header.Length);
|
||||
Index--;
|
||||
if (Index == 0 || Index > 10)
|
||||
return Str;
|
||||
for (unsigned char i = 0; i < Index; i++)
|
||||
Str = SMBIOSNextString(Str);
|
||||
return Str;
|
||||
}
|
||||
};
|
||||
const char *GetString(unsigned char Index)
|
||||
{
|
||||
char *Str = (char *)((unsigned long)this + this->Header.Length);
|
||||
Index--;
|
||||
if (Index == 0 || Index > 10)
|
||||
return Str;
|
||||
for (unsigned char i = 0; i < Index; i++)
|
||||
Str = SMBIOSNextString(Str);
|
||||
return Str;
|
||||
}
|
||||
};
|
||||
|
||||
struct SMBIOSBaseBoardInformation
|
||||
{
|
||||
SMBIOSHeader Header;
|
||||
unsigned char Manufacturer;
|
||||
unsigned char Product;
|
||||
unsigned char Version;
|
||||
unsigned char SerialNumber;
|
||||
unsigned char AssetTag;
|
||||
unsigned char FeatureFlags;
|
||||
unsigned char LocationInChassis;
|
||||
unsigned short ChassisHandle;
|
||||
unsigned char BoardType;
|
||||
unsigned char NumberOfContainedObjectHandles;
|
||||
unsigned short ContainedObjectHandles[0];
|
||||
struct SMBIOSBaseBoardInformation
|
||||
{
|
||||
SMBIOSHeader Header;
|
||||
unsigned char Manufacturer;
|
||||
unsigned char Product;
|
||||
unsigned char Version;
|
||||
unsigned char SerialNumber;
|
||||
unsigned char AssetTag;
|
||||
unsigned char FeatureFlags;
|
||||
unsigned char LocationInChassis;
|
||||
unsigned short ChassisHandle;
|
||||
unsigned char BoardType;
|
||||
unsigned char NumberOfContainedObjectHandles;
|
||||
unsigned short ContainedObjectHandles[0];
|
||||
|
||||
const char *GetString(unsigned char Index)
|
||||
{
|
||||
char *Str = (char *)((unsigned long)this + this->Header.Length);
|
||||
Index--;
|
||||
if (Index == 0 || Index > 10)
|
||||
return Str;
|
||||
for (unsigned char i = 0; i < Index; i++)
|
||||
Str = SMBIOSNextString(Str);
|
||||
return Str;
|
||||
}
|
||||
};
|
||||
const char *GetString(unsigned char Index)
|
||||
{
|
||||
char *Str = (char *)((unsigned long)this + this->Header.Length);
|
||||
Index--;
|
||||
if (Index == 0 || Index > 10)
|
||||
return Str;
|
||||
for (unsigned char i = 0; i < Index; i++)
|
||||
Str = SMBIOSNextString(Str);
|
||||
return Str;
|
||||
}
|
||||
};
|
||||
|
||||
struct SMBIOSProcessorInformation
|
||||
{
|
||||
SMBIOSHeader Header;
|
||||
unsigned char SocketDesignation;
|
||||
unsigned char ProcessorType;
|
||||
unsigned char ProcessorFamily;
|
||||
unsigned char ProcessorManufacturer;
|
||||
unsigned long ProcessorID;
|
||||
unsigned char ProcessorVersion;
|
||||
unsigned char Voltage;
|
||||
unsigned short ExternalClock;
|
||||
unsigned short MaxSpeed;
|
||||
unsigned short CurrentSpeed;
|
||||
unsigned char Status;
|
||||
unsigned char ProcessorUpgrade;
|
||||
unsigned short L1CacheHandle;
|
||||
unsigned short L2CacheHandle;
|
||||
unsigned short L3CacheHandle;
|
||||
unsigned char SerialNumber;
|
||||
unsigned char AssetTag;
|
||||
unsigned char PartNumber;
|
||||
unsigned char CoreCount;
|
||||
unsigned char CoreEnabled;
|
||||
unsigned char ThreadCount;
|
||||
unsigned short ProcessorCharacteristics;
|
||||
unsigned short ProcessorFamily2;
|
||||
unsigned short CoreCount2;
|
||||
unsigned short CoreEnabled2;
|
||||
unsigned short ThreadCount2;
|
||||
struct SMBIOSProcessorInformation
|
||||
{
|
||||
SMBIOSHeader Header;
|
||||
unsigned char SocketDesignation;
|
||||
unsigned char ProcessorType;
|
||||
unsigned char ProcessorFamily;
|
||||
unsigned char ProcessorManufacturer;
|
||||
unsigned long ProcessorID;
|
||||
unsigned char ProcessorVersion;
|
||||
unsigned char Voltage;
|
||||
unsigned short ExternalClock;
|
||||
unsigned short MaxSpeed;
|
||||
unsigned short CurrentSpeed;
|
||||
unsigned char Status;
|
||||
unsigned char ProcessorUpgrade;
|
||||
unsigned short L1CacheHandle;
|
||||
unsigned short L2CacheHandle;
|
||||
unsigned short L3CacheHandle;
|
||||
unsigned char SerialNumber;
|
||||
unsigned char AssetTag;
|
||||
unsigned char PartNumber;
|
||||
unsigned char CoreCount;
|
||||
unsigned char CoreEnabled;
|
||||
unsigned char ThreadCount;
|
||||
unsigned short ProcessorCharacteristics;
|
||||
unsigned short ProcessorFamily2;
|
||||
unsigned short CoreCount2;
|
||||
unsigned short CoreEnabled2;
|
||||
unsigned short ThreadCount2;
|
||||
|
||||
const char *GetString(unsigned char Index)
|
||||
{
|
||||
char *Str = (char *)((unsigned long)this + this->Header.Length);
|
||||
Index--;
|
||||
if (Index == 0 || Index > 10)
|
||||
return Str;
|
||||
for (unsigned char i = 0; i < Index; i++)
|
||||
Str = SMBIOSNextString(Str);
|
||||
return Str;
|
||||
}
|
||||
};
|
||||
const char *GetString(unsigned char Index)
|
||||
{
|
||||
char *Str = (char *)((unsigned long)this + this->Header.Length);
|
||||
Index--;
|
||||
if (Index == 0 || Index > 10)
|
||||
return Str;
|
||||
for (unsigned char i = 0; i < Index; i++)
|
||||
Str = SMBIOSNextString(Str);
|
||||
return Str;
|
||||
}
|
||||
};
|
||||
|
||||
struct SMBIOSMemoryDevice
|
||||
{
|
||||
SMBIOSHeader Header;
|
||||
unsigned char PhysicalMemoryArrayHandle;
|
||||
unsigned char MemoryErrorInformationHandle;
|
||||
unsigned short TotalWidth;
|
||||
unsigned short DataWidth;
|
||||
unsigned short Size;
|
||||
unsigned char FormFactor;
|
||||
unsigned char DeviceSet;
|
||||
unsigned char DeviceLocator;
|
||||
unsigned char BankLocator;
|
||||
unsigned char MemoryType;
|
||||
unsigned short TypeDetail;
|
||||
unsigned short Speed;
|
||||
unsigned char Manufacturer;
|
||||
unsigned char SerialNumber;
|
||||
unsigned char AssetTag;
|
||||
unsigned char PartNumber;
|
||||
unsigned char Attributes;
|
||||
unsigned short ExtendedSize;
|
||||
unsigned short ConfiguredMemoryClockSpeed;
|
||||
unsigned short MinimumVoltage;
|
||||
unsigned short MaximumVoltage;
|
||||
unsigned short ConfiguredVoltage;
|
||||
unsigned char MemoryTechnology;
|
||||
unsigned char OperatingModeCapability;
|
||||
unsigned char FirmwareVersion;
|
||||
unsigned char ModuleManufacturerID;
|
||||
unsigned char ModuleProductID;
|
||||
unsigned char MemorySubsystemControllerManufacturerID;
|
||||
unsigned char MemorySubsystemControllerProductID;
|
||||
unsigned short NonVolatileSize;
|
||||
unsigned short VolatileSize;
|
||||
unsigned short CacheSize;
|
||||
unsigned short LogicalSize;
|
||||
unsigned char ExtendedSpeed;
|
||||
unsigned char ExtendedConfiguredMemorySpeed;
|
||||
struct SMBIOSMemoryDevice
|
||||
{
|
||||
SMBIOSHeader Header;
|
||||
unsigned char PhysicalMemoryArrayHandle;
|
||||
unsigned char MemoryErrorInformationHandle;
|
||||
unsigned short TotalWidth;
|
||||
unsigned short DataWidth;
|
||||
unsigned short Size;
|
||||
unsigned char FormFactor;
|
||||
unsigned char DeviceSet;
|
||||
unsigned char DeviceLocator;
|
||||
unsigned char BankLocator;
|
||||
unsigned char MemoryType;
|
||||
unsigned short TypeDetail;
|
||||
unsigned short Speed;
|
||||
unsigned char Manufacturer;
|
||||
unsigned char SerialNumber;
|
||||
unsigned char AssetTag;
|
||||
unsigned char PartNumber;
|
||||
unsigned char Attributes;
|
||||
unsigned short ExtendedSize;
|
||||
unsigned short ConfiguredMemoryClockSpeed;
|
||||
unsigned short MinimumVoltage;
|
||||
unsigned short MaximumVoltage;
|
||||
unsigned short ConfiguredVoltage;
|
||||
unsigned char MemoryTechnology;
|
||||
unsigned char OperatingModeCapability;
|
||||
unsigned char FirmwareVersion;
|
||||
unsigned char ModuleManufacturerID;
|
||||
unsigned char ModuleProductID;
|
||||
unsigned char MemorySubsystemControllerManufacturerID;
|
||||
unsigned char MemorySubsystemControllerProductID;
|
||||
unsigned short NonVolatileSize;
|
||||
unsigned short VolatileSize;
|
||||
unsigned short CacheSize;
|
||||
unsigned short LogicalSize;
|
||||
unsigned char ExtendedSpeed;
|
||||
unsigned char ExtendedConfiguredMemorySpeed;
|
||||
|
||||
const char *GetString(unsigned char Index)
|
||||
{
|
||||
char *Str = (char *)((unsigned long)this + this->Header.Length);
|
||||
Index--;
|
||||
if (Index == 0 || Index > 10)
|
||||
return Str;
|
||||
for (unsigned char i = 0; i < Index; i++)
|
||||
Str = SMBIOSNextString(Str);
|
||||
return Str;
|
||||
}
|
||||
};
|
||||
const char *GetString(unsigned char Index)
|
||||
{
|
||||
char *Str = (char *)((unsigned long)this + this->Header.Length);
|
||||
Index--;
|
||||
if (Index == 0 || Index > 10)
|
||||
return Str;
|
||||
for (unsigned char i = 0; i < Index; i++)
|
||||
Str = SMBIOSNextString(Str);
|
||||
return Str;
|
||||
}
|
||||
};
|
||||
|
||||
struct SMBIOSMemoryArrayMappedAddress
|
||||
{
|
||||
SMBIOSHeader Header;
|
||||
unsigned int StartingAddress;
|
||||
unsigned int EndingAddress;
|
||||
unsigned short MemoryArrayHandle;
|
||||
unsigned char PartitionWidth;
|
||||
struct SMBIOSMemoryArrayMappedAddress
|
||||
{
|
||||
SMBIOSHeader Header;
|
||||
unsigned int StartingAddress;
|
||||
unsigned int EndingAddress;
|
||||
unsigned short MemoryArrayHandle;
|
||||
unsigned char PartitionWidth;
|
||||
|
||||
const char *GetString(unsigned char Index)
|
||||
{
|
||||
char *Str = (char *)((unsigned long)this + this->Header.Length);
|
||||
Index--;
|
||||
if (Index == 0 || Index > 10)
|
||||
return Str;
|
||||
for (unsigned char i = 0; i < Index; i++)
|
||||
Str = SMBIOSNextString(Str);
|
||||
return Str;
|
||||
}
|
||||
};
|
||||
const char *GetString(unsigned char Index)
|
||||
{
|
||||
char *Str = (char *)((unsigned long)this + this->Header.Length);
|
||||
Index--;
|
||||
if (Index == 0 || Index > 10)
|
||||
return Str;
|
||||
for (unsigned char i = 0; i < Index; i++)
|
||||
Str = SMBIOSNextString(Str);
|
||||
return Str;
|
||||
}
|
||||
};
|
||||
|
||||
struct SMBIOSMemoryDeviceMappedAddress
|
||||
{
|
||||
SMBIOSHeader Header;
|
||||
unsigned int StartingAddress;
|
||||
unsigned int EndingAddress;
|
||||
unsigned short MemoryDeviceHandle;
|
||||
unsigned short MemoryArrayMappedAddressHandle;
|
||||
unsigned char PartitionRowPosition;
|
||||
unsigned char InterleavePosition;
|
||||
unsigned char InterleavedDataDepth;
|
||||
struct SMBIOSMemoryDeviceMappedAddress
|
||||
{
|
||||
SMBIOSHeader Header;
|
||||
unsigned int StartingAddress;
|
||||
unsigned int EndingAddress;
|
||||
unsigned short MemoryDeviceHandle;
|
||||
unsigned short MemoryArrayMappedAddressHandle;
|
||||
unsigned char PartitionRowPosition;
|
||||
unsigned char InterleavePosition;
|
||||
unsigned char InterleavedDataDepth;
|
||||
|
||||
const char *GetString(unsigned char Index)
|
||||
{
|
||||
char *Str = (char *)((unsigned long)this + this->Header.Length);
|
||||
Index--;
|
||||
if (Index == 0 || Index > 10)
|
||||
return Str;
|
||||
for (unsigned char i = 0; i < Index; i++)
|
||||
Str = SMBIOSNextString(Str);
|
||||
return Str;
|
||||
}
|
||||
};
|
||||
const char *GetString(unsigned char Index)
|
||||
{
|
||||
char *Str = (char *)((unsigned long)this + this->Header.Length);
|
||||
Index--;
|
||||
if (Index == 0 || Index > 10)
|
||||
return Str;
|
||||
for (unsigned char i = 0; i < Index; i++)
|
||||
Str = SMBIOSNextString(Str);
|
||||
return Str;
|
||||
}
|
||||
};
|
||||
|
||||
struct SMBIOSMemoryArray
|
||||
{
|
||||
SMBIOSHeader Header;
|
||||
unsigned char Location;
|
||||
unsigned char Use;
|
||||
unsigned char MemoryErrorCorrection;
|
||||
unsigned int MaximumCapacity;
|
||||
unsigned short MemoryErrorInformationHandle;
|
||||
unsigned short NumberOfMemoryDevices;
|
||||
struct SMBIOSMemoryArray
|
||||
{
|
||||
SMBIOSHeader Header;
|
||||
unsigned char Location;
|
||||
unsigned char Use;
|
||||
unsigned char MemoryErrorCorrection;
|
||||
unsigned int MaximumCapacity;
|
||||
unsigned short MemoryErrorInformationHandle;
|
||||
unsigned short NumberOfMemoryDevices;
|
||||
|
||||
const char *GetString(unsigned char Index)
|
||||
{
|
||||
char *Str = (char *)((unsigned long)this + this->Header.Length);
|
||||
Index--;
|
||||
if (Index == 0 || Index > 10)
|
||||
return Str;
|
||||
for (unsigned char i = 0; i < Index; i++)
|
||||
Str = SMBIOSNextString(Str);
|
||||
return Str;
|
||||
}
|
||||
};
|
||||
const char *GetString(unsigned char Index)
|
||||
{
|
||||
char *Str = (char *)((unsigned long)this + this->Header.Length);
|
||||
Index--;
|
||||
if (Index == 0 || Index > 10)
|
||||
return Str;
|
||||
for (unsigned char i = 0; i < Index; i++)
|
||||
Str = SMBIOSNextString(Str);
|
||||
return Str;
|
||||
}
|
||||
};
|
||||
|
||||
bool CheckSMBIOS();
|
||||
SMBIOSEntryPoint *GetSMBIOSEntryPoint();
|
||||
void *GetSMBIOSHeader(SMBIOSType Type);
|
||||
SMBIOSBIOSInformation *GetBIOSInformation();
|
||||
SMBIOSSystemInformation *GetSystemInformation();
|
||||
SMBIOSBaseBoardInformation *GetBaseBoardInformation();
|
||||
SMBIOSProcessorInformation *GetProcessorInformation();
|
||||
SMBIOSMemoryArray *GetMemoryArray();
|
||||
SMBIOSMemoryDevice *GetMemoryDevice();
|
||||
SMBIOSMemoryArrayMappedAddress *GetMemoryArrayMappedAddress();
|
||||
SMBIOSMemoryDeviceMappedAddress *GetMemoryDeviceMappedAddress();
|
||||
bool CheckSMBIOS();
|
||||
SMBIOSEntryPoint *GetSMBIOSEntryPoint();
|
||||
void *GetSMBIOSHeader(SMBIOSType Type);
|
||||
SMBIOSBIOSInformation *GetBIOSInformation();
|
||||
SMBIOSSystemInformation *GetSystemInformation();
|
||||
SMBIOSBaseBoardInformation *GetBaseBoardInformation();
|
||||
SMBIOSProcessorInformation *GetProcessorInformation();
|
||||
SMBIOSMemoryArray *GetMemoryArray();
|
||||
SMBIOSMemoryDevice *GetMemoryDevice();
|
||||
SMBIOSMemoryArrayMappedAddress *GetMemoryArrayMappedAddress();
|
||||
SMBIOSMemoryDeviceMappedAddress *GetMemoryDeviceMappedAddress();
|
||||
}
|
||||
|
||||
#endif // !__FENNIX_KERNEL_SMBIOS_H__
|
||||
|
@ -25,82 +25,82 @@
|
||||
|
||||
EXTERNC __weak __no_stack_protector uintptr_t __stack_chk_guard_init(void)
|
||||
{
|
||||
int MaxRetries = 0;
|
||||
int MaxRetries = 0;
|
||||
#if UINTPTR_MAX == UINT32_MAX
|
||||
uint32_t num;
|
||||
uint32_t num;
|
||||
Retry:
|
||||
num = Random::rand32();
|
||||
if (num < 0x1000 && MaxRetries++ < 10)
|
||||
goto Retry;
|
||||
return num;
|
||||
num = Random::rand32();
|
||||
if (num < 0x1000 && MaxRetries++ < 10)
|
||||
goto Retry;
|
||||
return num;
|
||||
|
||||
#else
|
||||
uint64_t num;
|
||||
uint64_t num;
|
||||
Retry:
|
||||
num = Random::rand64();
|
||||
if (num < 0x100000 && MaxRetries++ < 10)
|
||||
goto Retry;
|
||||
return num;
|
||||
num = Random::rand64();
|
||||
if (num < 0x100000 && MaxRetries++ < 10)
|
||||
goto Retry;
|
||||
return num;
|
||||
#endif
|
||||
}
|
||||
|
||||
EXTERNC __constructor __no_stack_protector void __guard_setup(void)
|
||||
{
|
||||
debug("__guard_setup");
|
||||
if (__stack_chk_guard == 0)
|
||||
__stack_chk_guard = __stack_chk_guard_init();
|
||||
debug("Stack guard value: %ld", __stack_chk_guard);
|
||||
debug("__guard_setup");
|
||||
if (__stack_chk_guard == 0)
|
||||
__stack_chk_guard = __stack_chk_guard_init();
|
||||
debug("Stack guard value: %ld", __stack_chk_guard);
|
||||
}
|
||||
|
||||
EXTERNC __weak __noreturn __no_stack_protector void __stack_chk_fail(void)
|
||||
{
|
||||
TaskingPanic();
|
||||
for (short i = 0; i < 10; i++)
|
||||
error("Stack smashing detected!");
|
||||
debug("Current stack check guard value: %#lx", __stack_chk_guard);
|
||||
KPrint("\eFF0000Stack smashing detected!");
|
||||
TaskingPanic();
|
||||
for (short i = 0; i < 10; i++)
|
||||
error("Stack smashing detected!");
|
||||
debug("Current stack check guard value: %#lx", __stack_chk_guard);
|
||||
KPrint("\eFF0000Stack smashing detected!");
|
||||
|
||||
void *Stack = nullptr;
|
||||
void *Stack = nullptr;
|
||||
#if defined(a86)
|
||||
|
||||
#if defined(a64)
|
||||
asmv("movq %%rsp, %0"
|
||||
: "=r"(Stack));
|
||||
asmv("movq %%rsp, %0"
|
||||
: "=r"(Stack));
|
||||
#elif defined(a32)
|
||||
asmv("movl %%esp, %0"
|
||||
: "=r"(Stack));
|
||||
asmv("movl %%esp, %0"
|
||||
: "=r"(Stack));
|
||||
#endif
|
||||
|
||||
#elif defined(aa64)
|
||||
|
||||
asmv("mov %%sp, %0"
|
||||
: "=r"(Stack));
|
||||
asmv("mov %%sp, %0"
|
||||
: "=r"(Stack));
|
||||
|
||||
#endif
|
||||
error("Stack address: %#lx", Stack);
|
||||
error("Stack address: %#lx", Stack);
|
||||
|
||||
if (DebuggerIsAttached)
|
||||
if (DebuggerIsAttached)
|
||||
#ifdef a86
|
||||
asmv("int $0x3");
|
||||
asmv("int $0x3");
|
||||
#elif defined(aa64)
|
||||
asmv("brk #0");
|
||||
asmv("brk #0");
|
||||
#endif
|
||||
|
||||
CPU::Stop();
|
||||
CPU::Stop();
|
||||
}
|
||||
|
||||
// https://github.com/gcc-mirror/gcc/blob/master/libssp/ssp.c
|
||||
EXTERNC __weak __noreturn __no_stack_protector void __chk_fail(void)
|
||||
{
|
||||
TaskingPanic();
|
||||
for (short i = 0; i < 10; i++)
|
||||
error("Buffer overflow detected!");
|
||||
KPrint("\eFF0000Buffer overflow detected!");
|
||||
TaskingPanic();
|
||||
for (short i = 0; i < 10; i++)
|
||||
error("Buffer overflow detected!");
|
||||
KPrint("\eFF0000Buffer overflow detected!");
|
||||
|
||||
#if defined(a86)
|
||||
while (1)
|
||||
asmv("cli; hlt");
|
||||
while (1)
|
||||
asmv("cli; hlt");
|
||||
#elif defined(aa64)
|
||||
asmv("wfe");
|
||||
asmv("wfe");
|
||||
#endif
|
||||
}
|
||||
|
@ -25,20 +25,69 @@
|
||||
|
||||
namespace SymbolResolver
|
||||
{
|
||||
const NIF char *Symbols::GetSymbolFromAddress(uintptr_t Address)
|
||||
const NIF char *Symbols::GetSymbol(uintptr_t Address)
|
||||
{
|
||||
SymbolTable Result{};
|
||||
foreach (auto tbl in this->SymTable)
|
||||
|
||||
if (this->SymbolTableExists == false)
|
||||
{
|
||||
if (tbl.Address <= Address &&
|
||||
tbl.Address > Result.Address)
|
||||
Result = tbl;
|
||||
debug("Symbol table does not exist");
|
||||
if (this->SymTable.size() > 0)
|
||||
{
|
||||
debug("SymbolTableExists is false but SymTable.size() is %d",
|
||||
this->SymTable.size());
|
||||
}
|
||||
return Result.FunctionName;
|
||||
}
|
||||
// debug("Address: %#lx, Function: %s",
|
||||
// Address, Result.FunctionName);
|
||||
|
||||
std::vector<SymbolTable> rSymTable = this->SymTable;
|
||||
rSymTable.reverse();
|
||||
|
||||
foreach (auto st in rSymTable)
|
||||
{
|
||||
if (unlikely(st.Address <= Address &&
|
||||
st.Address > Result.Address))
|
||||
{
|
||||
Result = st;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// debug("Symbol %#lx: %s", Result.Address, Result.FunctionName);
|
||||
return Result.FunctionName;
|
||||
}
|
||||
|
||||
uintptr_t Symbols::GetSymbol(const char *Name)
|
||||
{
|
||||
SymbolTable Result{};
|
||||
|
||||
if (this->SymbolTableExists == false)
|
||||
{
|
||||
debug("Symbol table does not exist");
|
||||
if (this->SymTable.size() > 0)
|
||||
{
|
||||
debug("SymbolTableExists is false but SymTable.size() is %d",
|
||||
this->SymTable.size());
|
||||
}
|
||||
return Result.Address;
|
||||
}
|
||||
|
||||
std::vector<SymbolTable> rSymTable = this->SymTable;
|
||||
rSymTable.reverse();
|
||||
|
||||
foreach (auto st in rSymTable)
|
||||
{
|
||||
if (unlikely(strcmp(st.FunctionName, Name) == 0))
|
||||
{
|
||||
Result = st;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// debug("Symbol %#lx: %s", Result.Address, Result.FunctionName);
|
||||
return Result.Address;
|
||||
}
|
||||
|
||||
void Symbols::AddSymbol(uintptr_t Address, const char *Name)
|
||||
{
|
||||
SymbolTable tbl{};
|
||||
@ -121,11 +170,11 @@ namespace SymbolResolver
|
||||
TotalEntries, TO_KiB(TotalEntries * sizeof(SymbolTable)));
|
||||
Elf_Sym *sym;
|
||||
const char *name;
|
||||
Memory::Virtual vma = Memory::Virtual();
|
||||
Memory::Virtual vmm;
|
||||
for (size_t i = 0, g = TotalEntries; i < g; i++)
|
||||
{
|
||||
sym = &Symbols[i];
|
||||
if (!vma.Check(sym))
|
||||
if (!vmm.Check(sym))
|
||||
{
|
||||
error("Symbol %d has invalid address %#lx!",
|
||||
i, sym);
|
||||
@ -137,7 +186,7 @@ namespace SymbolResolver
|
||||
}
|
||||
|
||||
name = (const char *)&StringAddress[Symbols[i].st_name];
|
||||
if (!vma.Check((void *)name))
|
||||
if (!vmm.Check((void *)name))
|
||||
{
|
||||
error("String %d has invalid address %#lx!",
|
||||
i, name);
|
||||
@ -168,7 +217,8 @@ namespace SymbolResolver
|
||||
{
|
||||
/* FIXME: Get only the required headers instead of the whole file */
|
||||
|
||||
if (ImageAddress == 0 || Memory::Virtual().Check((void *)ImageAddress) == false)
|
||||
if (ImageAddress == 0 ||
|
||||
Memory::Virtual().Check((void *)ImageAddress) == false)
|
||||
{
|
||||
error("Invalid image address %#lx", ImageAddress);
|
||||
return;
|
||||
@ -261,17 +311,27 @@ namespace SymbolResolver
|
||||
// this->SymTable[i].FunctionName);
|
||||
}
|
||||
}
|
||||
|
||||
if (this->SymbolTableExists)
|
||||
{
|
||||
debug("Symbol table exists, %d entries (%ld KiB)",
|
||||
this->SymTable.size(), TO_KiB(this->SymTable.size() * sizeof(SymbolTable)));
|
||||
}
|
||||
}
|
||||
|
||||
Symbols::Symbols(uintptr_t ImageAddress)
|
||||
{
|
||||
debug("+ %#lx", this);
|
||||
this->Image = (void *)ImageAddress;
|
||||
this->AppendSymbols(ImageAddress);
|
||||
}
|
||||
|
||||
Symbols::~Symbols()
|
||||
{
|
||||
for (auto tbl : this->SymTable)
|
||||
debug("- %#lx", this);
|
||||
debug("Freeing %d symbols",
|
||||
this->SymTable.size());
|
||||
foreach (auto tbl in this->SymTable)
|
||||
delete[] tbl.FunctionName;
|
||||
}
|
||||
}
|
||||
|
@ -29,13 +29,13 @@ namespace Time
|
||||
bool HighPrecisionEventTimer::Sleep(size_t Duration, Units Unit)
|
||||
{
|
||||
#if defined(a64)
|
||||
uint64_t Target = mminq(&((HPET *)hpet)->MainCounterValue) + (Duration * ConvertUnit(Unit)) / clk;
|
||||
while (mminq(&((HPET *)hpet)->MainCounterValue) < Target)
|
||||
uint64_t Target = mminq(&hpet->MainCounterValue) + (Duration * ConvertUnit(Unit)) / clk;
|
||||
while (mminq(&hpet->MainCounterValue) < Target)
|
||||
CPU::Pause();
|
||||
return true;
|
||||
#elif defined(a32)
|
||||
uint64_t Target = mminl(&((HPET *)hpet)->MainCounterValue) + (Duration * ConvertUnit(Unit)) / clk;
|
||||
while (mminl(&((HPET *)hpet)->MainCounterValue) < Target)
|
||||
uint64_t Target = mminl(&hpet->MainCounterValue) + (Duration * ConvertUnit(Unit)) / clk;
|
||||
while (mminl(&hpet->MainCounterValue) < Target)
|
||||
CPU::Pause();
|
||||
return true;
|
||||
#endif
|
||||
@ -45,18 +45,18 @@ namespace Time
|
||||
uint64_t HighPrecisionEventTimer::GetCounter()
|
||||
{
|
||||
#if defined(a64)
|
||||
return mminq(&((HPET *)hpet)->MainCounterValue);
|
||||
return mminq(&hpet->MainCounterValue);
|
||||
#elif defined(a32)
|
||||
return mminl(&((HPET *)hpet)->MainCounterValue);
|
||||
return mminl(&hpet->MainCounterValue);
|
||||
#endif
|
||||
}
|
||||
|
||||
uint64_t HighPrecisionEventTimer::CalculateTarget(uint64_t Target, Units Unit)
|
||||
{
|
||||
#if defined(a64)
|
||||
return mminq(&((HPET *)hpet)->MainCounterValue) + (Target * ConvertUnit(Unit)) / clk;
|
||||
return mminq(&hpet->MainCounterValue) + (Target * ConvertUnit(Unit)) / clk;
|
||||
#elif defined(a32)
|
||||
return mminl(&((HPET *)hpet)->MainCounterValue) + (Target * ConvertUnit(Unit)) / clk;
|
||||
return mminl(&hpet->MainCounterValue) + (Target * ConvertUnit(Unit)) / clk;
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -66,7 +66,9 @@ namespace Time
|
||||
uint64_t Subtraction = this->GetCounter() - this->ClassCreationTime;
|
||||
if (Subtraction <= 0 || this->clk <= 0)
|
||||
return 0;
|
||||
return uint64_t(Subtraction / (this->clk / ConvertUnit(Units::Nanoseconds)));
|
||||
|
||||
Subtraction *= ConvertUnit(Units::Nanoseconds);
|
||||
return uint64_t(Subtraction / this->clk);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -74,13 +76,16 @@ namespace Time
|
||||
{
|
||||
#if defined(a86)
|
||||
ACPI::ACPI::HPETHeader *HPET_HDR = (ACPI::ACPI::HPETHeader *)hpet;
|
||||
Memory::Virtual().Map((void *)HPET_HDR->Address.Address,
|
||||
(void *)HPET_HDR->Address.Address,
|
||||
Memory::PTFlag::RW | Memory::PTFlag::PCD);
|
||||
Memory::Virtual vmm;
|
||||
vmm.Map((void *)HPET_HDR->Address.Address,
|
||||
(void *)HPET_HDR->Address.Address,
|
||||
Memory::PTFlag::RW | Memory::PTFlag::PCD);
|
||||
this->hpet = (HPET *)HPET_HDR->Address.Address;
|
||||
trace("%s timer is at address %016p", HPET_HDR->Header.OEMID, (void *)HPET_HDR->Address.Address);
|
||||
trace("%s timer is at address %016p",
|
||||
HPET_HDR->Header.OEMID,
|
||||
(void *)HPET_HDR->Address.Address);
|
||||
clk = s_cst(uint32_t, (uint64_t)this->hpet->GeneralCapabilities >> 32);
|
||||
debug("HPET clock is %u Hz", clk);
|
||||
KPrint("HPET clock is %u Hz", clk);
|
||||
#ifdef a64
|
||||
mmoutq(&this->hpet->GeneralConfiguration, 0);
|
||||
mmoutq(&this->hpet->MainCounterValue, 0);
|
||||
|
@ -1,18 +1,18 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
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 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.
|
||||
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/>.
|
||||
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 <time.hpp>
|
||||
@ -21,91 +21,91 @@
|
||||
|
||||
namespace Time
|
||||
{
|
||||
Clock ReadClock()
|
||||
{
|
||||
Clock tm;
|
||||
Clock ReadClock()
|
||||
{
|
||||
Clock tm;
|
||||
#if defined(a86)
|
||||
uint32_t t = 0;
|
||||
outb(0x70, 0x00);
|
||||
t = inb(0x71);
|
||||
tm.Second = ((t & 0x0F) + ((t >> 4) * 10));
|
||||
outb(0x70, 0x02);
|
||||
t = inb(0x71);
|
||||
tm.Minute = ((t & 0x0F) + ((t >> 4) * 10));
|
||||
outb(0x70, 0x04);
|
||||
t = inb(0x71);
|
||||
tm.Hour = ((t & 0x0F) + ((t >> 4) * 10));
|
||||
outb(0x70, 0x07);
|
||||
t = inb(0x71);
|
||||
tm.Day = ((t & 0x0F) + ((t >> 4) * 10));
|
||||
outb(0x70, 0x08);
|
||||
t = inb(0x71);
|
||||
tm.Month = ((t & 0x0F) + ((t >> 4) * 10));
|
||||
outb(0x70, 0x09);
|
||||
t = inb(0x71);
|
||||
tm.Year = ((t & 0x0F) + ((t >> 4) * 10));
|
||||
tm.Counter = 0;
|
||||
uint32_t t = 0;
|
||||
outb(0x70, 0x00);
|
||||
t = inb(0x71);
|
||||
tm.Second = ((t & 0x0F) + ((t >> 4) * 10));
|
||||
outb(0x70, 0x02);
|
||||
t = inb(0x71);
|
||||
tm.Minute = ((t & 0x0F) + ((t >> 4) * 10));
|
||||
outb(0x70, 0x04);
|
||||
t = inb(0x71);
|
||||
tm.Hour = ((t & 0x0F) + ((t >> 4) * 10));
|
||||
outb(0x70, 0x07);
|
||||
t = inb(0x71);
|
||||
tm.Day = ((t & 0x0F) + ((t >> 4) * 10));
|
||||
outb(0x70, 0x08);
|
||||
t = inb(0x71);
|
||||
tm.Month = ((t & 0x0F) + ((t >> 4) * 10));
|
||||
outb(0x70, 0x09);
|
||||
t = inb(0x71);
|
||||
tm.Year = ((t & 0x0F) + ((t >> 4) * 10));
|
||||
tm.Counter = 0;
|
||||
#elif defined(aa64)
|
||||
tm.Year = 0;
|
||||
tm.Month = 0;
|
||||
tm.Day = 0;
|
||||
tm.Hour = 0;
|
||||
tm.Minute = 0;
|
||||
tm.Second = 0;
|
||||
tm.Counter = 0;
|
||||
tm.Year = 0;
|
||||
tm.Month = 0;
|
||||
tm.Day = 0;
|
||||
tm.Hour = 0;
|
||||
tm.Minute = 0;
|
||||
tm.Second = 0;
|
||||
tm.Counter = 0;
|
||||
#endif
|
||||
return tm;
|
||||
}
|
||||
return tm;
|
||||
}
|
||||
|
||||
Clock ConvertFromUnix(int Timestamp)
|
||||
{
|
||||
Clock result;
|
||||
Clock ConvertFromUnix(int Timestamp)
|
||||
{
|
||||
Clock result;
|
||||
|
||||
uint64_t Seconds = Timestamp;
|
||||
uint64_t Minutes = Seconds / 60;
|
||||
uint64_t Hours = Minutes / 60;
|
||||
uint64_t Days = Hours / 24;
|
||||
uint64_t Seconds = Timestamp;
|
||||
uint64_t Minutes = Seconds / 60;
|
||||
uint64_t Hours = Minutes / 60;
|
||||
uint64_t Days = Hours / 24;
|
||||
|
||||
result.Year = 1970;
|
||||
while (Days >= 365)
|
||||
{
|
||||
if (result.Year % 4 == 0 &&
|
||||
(result.Year % 100 != 0 ||
|
||||
result.Year % 400 == 0))
|
||||
{
|
||||
if (Days >= 366)
|
||||
{
|
||||
Days -= 366;
|
||||
result.Year++;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
Days -= 365;
|
||||
result.Year++;
|
||||
}
|
||||
}
|
||||
result.Year = 1970;
|
||||
while (Days >= 365)
|
||||
{
|
||||
if (result.Year % 4 == 0 &&
|
||||
(result.Year % 100 != 0 ||
|
||||
result.Year % 400 == 0))
|
||||
{
|
||||
if (Days >= 366)
|
||||
{
|
||||
Days -= 366;
|
||||
result.Year++;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
Days -= 365;
|
||||
result.Year++;
|
||||
}
|
||||
}
|
||||
|
||||
int DaysInMonth[] = {31,
|
||||
result.Year % 4 == 0
|
||||
? 29
|
||||
: 28,
|
||||
31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
|
||||
for (result.Month = 0; result.Month < 12; result.Month++)
|
||||
{
|
||||
if (Days < s_cst(uint64_t, (DaysInMonth[result.Month])))
|
||||
break;
|
||||
Days -= DaysInMonth[result.Month];
|
||||
}
|
||||
result.Month++;
|
||||
int DaysInMonth[] = {31,
|
||||
result.Year % 4 == 0
|
||||
? 29
|
||||
: 28,
|
||||
31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
|
||||
for (result.Month = 0; result.Month < 12; result.Month++)
|
||||
{
|
||||
if (Days < s_cst(uint64_t, (DaysInMonth[result.Month])))
|
||||
break;
|
||||
Days -= DaysInMonth[result.Month];
|
||||
}
|
||||
result.Month++;
|
||||
|
||||
result.Day = s_cst(int, (Days) + 1);
|
||||
result.Hour = s_cst(int, (Hours % 24));
|
||||
result.Minute = s_cst(int, (Minutes % 60));
|
||||
result.Second = s_cst(int, (Seconds % 60));
|
||||
result.Counter = s_cst(uint64_t, (Timestamp));
|
||||
return result;
|
||||
}
|
||||
result.Day = s_cst(int, (Days) + 1);
|
||||
result.Hour = s_cst(int, (Hours % 24));
|
||||
result.Minute = s_cst(int, (Minutes % 60));
|
||||
result.Second = s_cst(int, (Seconds % 60));
|
||||
result.Counter = s_cst(uint64_t, (Timestamp));
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
@ -60,7 +60,7 @@ namespace Time
|
||||
TimeStampCounter::TimeStampCounter()
|
||||
{
|
||||
#if defined(a86)
|
||||
fixme(""); // FIXME: This is not a good way to measure the clock speed
|
||||
stub; // FIXME: This is not a good way to measure the clock speed
|
||||
uint64_t Start = CPU::Counter();
|
||||
TimeManager->Sleep(1, Units::Milliseconds);
|
||||
uint64_t End = CPU::Counter();
|
||||
|
362
core/ubsan.c
362
core/ubsan.c
@ -51,309 +51,309 @@ __ubsan_handle_cfi_check_fail
|
||||
|
||||
void __asan_report_load1(void *unknown)
|
||||
{
|
||||
ubsan("load1");
|
||||
UNUSED(unknown);
|
||||
ubsan("load1");
|
||||
UNUSED(unknown);
|
||||
}
|
||||
|
||||
void __asan_report_load2(void *unknown)
|
||||
{
|
||||
ubsan("load2");
|
||||
UNUSED(unknown);
|
||||
ubsan("load2");
|
||||
UNUSED(unknown);
|
||||
}
|
||||
|
||||
void __asan_report_load4(void *unknown)
|
||||
{
|
||||
ubsan("load4");
|
||||
UNUSED(unknown);
|
||||
ubsan("load4");
|
||||
UNUSED(unknown);
|
||||
}
|
||||
|
||||
void __asan_report_load8(void *unknown)
|
||||
{
|
||||
ubsan("load8");
|
||||
UNUSED(unknown);
|
||||
ubsan("load8");
|
||||
UNUSED(unknown);
|
||||
}
|
||||
|
||||
void __asan_report_load16(void *unknown)
|
||||
{
|
||||
ubsan("load16");
|
||||
UNUSED(unknown);
|
||||
ubsan("load16");
|
||||
UNUSED(unknown);
|
||||
}
|
||||
|
||||
void __asan_report_load_n(void *unknown, uintptr_t size)
|
||||
{
|
||||
ubsan("loadn");
|
||||
UNUSED(unknown);
|
||||
UNUSED(size);
|
||||
ubsan("loadn");
|
||||
UNUSED(unknown);
|
||||
UNUSED(size);
|
||||
}
|
||||
|
||||
void __asan_report_store1(void *unknown)
|
||||
{
|
||||
ubsan("store1");
|
||||
UNUSED(unknown);
|
||||
ubsan("store1");
|
||||
UNUSED(unknown);
|
||||
}
|
||||
|
||||
void __asan_report_store2(void *unknown)
|
||||
{
|
||||
ubsan("store2");
|
||||
UNUSED(unknown);
|
||||
ubsan("store2");
|
||||
UNUSED(unknown);
|
||||
}
|
||||
|
||||
void __asan_report_store4(void *unknown)
|
||||
{
|
||||
ubsan("store4");
|
||||
UNUSED(unknown);
|
||||
ubsan("store4");
|
||||
UNUSED(unknown);
|
||||
}
|
||||
|
||||
void __asan_report_store8(void *unknown)
|
||||
{
|
||||
ubsan("store8");
|
||||
UNUSED(unknown);
|
||||
ubsan("store8");
|
||||
UNUSED(unknown);
|
||||
}
|
||||
|
||||
void __asan_report_store16(void *unknown)
|
||||
{
|
||||
ubsan("store16");
|
||||
UNUSED(unknown);
|
||||
ubsan("store16");
|
||||
UNUSED(unknown);
|
||||
}
|
||||
|
||||
void __asan_report_store_n(void *unknown, uintptr_t size)
|
||||
{
|
||||
ubsan("storen");
|
||||
UNUSED(unknown);
|
||||
UNUSED(size);
|
||||
ubsan("storen");
|
||||
UNUSED(unknown);
|
||||
UNUSED(size);
|
||||
}
|
||||
|
||||
void __asan_report_load1_noabort(void *unknown)
|
||||
{
|
||||
ubsan("load1");
|
||||
UNUSED(unknown);
|
||||
ubsan("load1");
|
||||
UNUSED(unknown);
|
||||
}
|
||||
|
||||
void __asan_report_load2_noabort(void *unknown)
|
||||
{
|
||||
ubsan("load2");
|
||||
UNUSED(unknown);
|
||||
ubsan("load2");
|
||||
UNUSED(unknown);
|
||||
}
|
||||
|
||||
void __asan_report_load4_noabort(void *unknown)
|
||||
{
|
||||
ubsan("load4");
|
||||
UNUSED(unknown);
|
||||
ubsan("load4");
|
||||
UNUSED(unknown);
|
||||
}
|
||||
|
||||
void __asan_report_load8_noabort(void *unknown)
|
||||
{
|
||||
ubsan("load8");
|
||||
UNUSED(unknown);
|
||||
ubsan("load8");
|
||||
UNUSED(unknown);
|
||||
}
|
||||
|
||||
void __asan_report_load16_noabort(void *unknown)
|
||||
{
|
||||
ubsan("load16");
|
||||
UNUSED(unknown);
|
||||
ubsan("load16");
|
||||
UNUSED(unknown);
|
||||
}
|
||||
|
||||
void __asan_report_load_n_noabort(void *unknown, uintptr_t size)
|
||||
{
|
||||
ubsan("loadn");
|
||||
UNUSED(unknown);
|
||||
UNUSED(size);
|
||||
ubsan("loadn");
|
||||
UNUSED(unknown);
|
||||
UNUSED(size);
|
||||
}
|
||||
|
||||
void __asan_report_store1_noabort(void *unknown)
|
||||
{
|
||||
ubsan("store1");
|
||||
UNUSED(unknown);
|
||||
ubsan("store1");
|
||||
UNUSED(unknown);
|
||||
}
|
||||
|
||||
void __asan_report_store2_noabort(void *unknown)
|
||||
{
|
||||
ubsan("store2");
|
||||
UNUSED(unknown);
|
||||
ubsan("store2");
|
||||
UNUSED(unknown);
|
||||
}
|
||||
|
||||
void __asan_report_store4_noabort(void *unknown)
|
||||
{
|
||||
ubsan("store4");
|
||||
UNUSED(unknown);
|
||||
ubsan("store4");
|
||||
UNUSED(unknown);
|
||||
}
|
||||
|
||||
void __asan_report_store8_noabort(void *unknown)
|
||||
{
|
||||
ubsan("store8");
|
||||
UNUSED(unknown);
|
||||
ubsan("store8");
|
||||
UNUSED(unknown);
|
||||
}
|
||||
|
||||
void __asan_report_store16_noabort(void *unknown)
|
||||
{
|
||||
ubsan("store16");
|
||||
UNUSED(unknown);
|
||||
ubsan("store16");
|
||||
UNUSED(unknown);
|
||||
}
|
||||
|
||||
void __asan_report_store_n_noabort(void *unknown, uintptr_t size)
|
||||
{
|
||||
ubsan("storen");
|
||||
UNUSED(unknown);
|
||||
UNUSED(size);
|
||||
ubsan("storen");
|
||||
UNUSED(unknown);
|
||||
UNUSED(size);
|
||||
}
|
||||
|
||||
void __asan_stack_malloc_0(uintptr_t size)
|
||||
{
|
||||
ubsan("stack malloc 0");
|
||||
UNUSED(size);
|
||||
ubsan("stack malloc 0");
|
||||
UNUSED(size);
|
||||
}
|
||||
|
||||
void __asan_stack_malloc_1(uintptr_t size)
|
||||
{
|
||||
ubsan("stack malloc 1");
|
||||
UNUSED(size);
|
||||
ubsan("stack malloc 1");
|
||||
UNUSED(size);
|
||||
}
|
||||
|
||||
void __asan_stack_malloc_2(uintptr_t size)
|
||||
{
|
||||
ubsan("stack malloc 2");
|
||||
UNUSED(size);
|
||||
ubsan("stack malloc 2");
|
||||
UNUSED(size);
|
||||
}
|
||||
|
||||
void __asan_stack_malloc_3(uintptr_t size)
|
||||
{
|
||||
ubsan("stack malloc 3");
|
||||
UNUSED(size);
|
||||
ubsan("stack malloc 3");
|
||||
UNUSED(size);
|
||||
}
|
||||
|
||||
void __asan_stack_malloc_4(uintptr_t size)
|
||||
{
|
||||
ubsan("stack malloc 4");
|
||||
UNUSED(size);
|
||||
ubsan("stack malloc 4");
|
||||
UNUSED(size);
|
||||
}
|
||||
|
||||
void __asan_stack_malloc_5(uintptr_t size)
|
||||
{
|
||||
ubsan("stack malloc 5");
|
||||
UNUSED(size);
|
||||
ubsan("stack malloc 5");
|
||||
UNUSED(size);
|
||||
}
|
||||
|
||||
void __asan_stack_malloc_6(uintptr_t size)
|
||||
{
|
||||
ubsan("stack malloc 6");
|
||||
UNUSED(size);
|
||||
ubsan("stack malloc 6");
|
||||
UNUSED(size);
|
||||
}
|
||||
|
||||
void __asan_stack_malloc_7(uintptr_t size)
|
||||
{
|
||||
ubsan("stack malloc 7");
|
||||
UNUSED(size);
|
||||
ubsan("stack malloc 7");
|
||||
UNUSED(size);
|
||||
}
|
||||
|
||||
void __asan_stack_malloc_8(uintptr_t size)
|
||||
{
|
||||
ubsan("stack malloc 8");
|
||||
UNUSED(size);
|
||||
ubsan("stack malloc 8");
|
||||
UNUSED(size);
|
||||
}
|
||||
|
||||
void __asan_stack_malloc_9(uintptr_t size)
|
||||
{
|
||||
ubsan("stack malloc 9");
|
||||
UNUSED(size);
|
||||
ubsan("stack malloc 9");
|
||||
UNUSED(size);
|
||||
}
|
||||
|
||||
void __asan_stack_free_0(void *ptr, uintptr_t size)
|
||||
{
|
||||
ubsan("stack free 0");
|
||||
UNUSED(ptr);
|
||||
UNUSED(size);
|
||||
ubsan("stack free 0");
|
||||
UNUSED(ptr);
|
||||
UNUSED(size);
|
||||
}
|
||||
|
||||
void __asan_stack_free_1(void *ptr, uintptr_t size)
|
||||
{
|
||||
ubsan("stack free 1");
|
||||
UNUSED(ptr);
|
||||
UNUSED(size);
|
||||
ubsan("stack free 1");
|
||||
UNUSED(ptr);
|
||||
UNUSED(size);
|
||||
}
|
||||
|
||||
void __asan_stack_free_2(void *ptr, uintptr_t size)
|
||||
{
|
||||
ubsan("stack free 2");
|
||||
UNUSED(ptr);
|
||||
UNUSED(size);
|
||||
ubsan("stack free 2");
|
||||
UNUSED(ptr);
|
||||
UNUSED(size);
|
||||
}
|
||||
|
||||
void __asan_stack_free_3(void *ptr, uintptr_t size)
|
||||
{
|
||||
ubsan("stack free 3");
|
||||
UNUSED(ptr);
|
||||
UNUSED(size);
|
||||
ubsan("stack free 3");
|
||||
UNUSED(ptr);
|
||||
UNUSED(size);
|
||||
}
|
||||
|
||||
void __asan_stack_free_4(void *ptr, uintptr_t size)
|
||||
{
|
||||
ubsan("stack free 4");
|
||||
UNUSED(ptr);
|
||||
UNUSED(size);
|
||||
ubsan("stack free 4");
|
||||
UNUSED(ptr);
|
||||
UNUSED(size);
|
||||
}
|
||||
|
||||
void __asan_stack_free_5(void *ptr, uintptr_t size)
|
||||
{
|
||||
ubsan("stack free 5");
|
||||
UNUSED(ptr);
|
||||
UNUSED(size);
|
||||
ubsan("stack free 5");
|
||||
UNUSED(ptr);
|
||||
UNUSED(size);
|
||||
}
|
||||
|
||||
void __asan_stack_free_6(void *ptr, uintptr_t size)
|
||||
{
|
||||
ubsan("stack free 6");
|
||||
UNUSED(ptr);
|
||||
UNUSED(size);
|
||||
ubsan("stack free 6");
|
||||
UNUSED(ptr);
|
||||
UNUSED(size);
|
||||
}
|
||||
|
||||
void __asan_stack_free_7(void *ptr, uintptr_t size)
|
||||
{
|
||||
ubsan("stack free 7");
|
||||
UNUSED(ptr);
|
||||
UNUSED(size);
|
||||
ubsan("stack free 7");
|
||||
UNUSED(ptr);
|
||||
UNUSED(size);
|
||||
}
|
||||
|
||||
void __asan_stack_free_8(void *ptr, uintptr_t size)
|
||||
{
|
||||
ubsan("stack free 8");
|
||||
UNUSED(ptr);
|
||||
UNUSED(size);
|
||||
ubsan("stack free 8");
|
||||
UNUSED(ptr);
|
||||
UNUSED(size);
|
||||
}
|
||||
|
||||
void __asan_stack_free_9(void *ptr, uintptr_t size)
|
||||
{
|
||||
ubsan("stack free 9");
|
||||
UNUSED(ptr);
|
||||
UNUSED(size);
|
||||
ubsan("stack free 9");
|
||||
UNUSED(ptr);
|
||||
UNUSED(size);
|
||||
}
|
||||
|
||||
void __asan_poison_stack_memory(void *addr, uintptr_t size)
|
||||
{
|
||||
ubsan("poison stack memory");
|
||||
UNUSED(addr);
|
||||
UNUSED(size);
|
||||
ubsan("poison stack memory");
|
||||
UNUSED(addr);
|
||||
UNUSED(size);
|
||||
}
|
||||
|
||||
void __asan_unpoison_stack_memory(void *addr, uintptr_t size)
|
||||
{
|
||||
ubsan("unpoison stack memory");
|
||||
UNUSED(addr);
|
||||
UNUSED(size);
|
||||
ubsan("unpoison stack memory");
|
||||
UNUSED(addr);
|
||||
UNUSED(size);
|
||||
}
|
||||
|
||||
void __asan_before_dynamic_init(const char *module_name)
|
||||
{
|
||||
ubsan("before dynamic init");
|
||||
UNUSED(module_name);
|
||||
ubsan("before dynamic init");
|
||||
UNUSED(module_name);
|
||||
}
|
||||
|
||||
void __asan_after_dynamic_init(void) { ubsan("after dynamic init"); }
|
||||
|
||||
void __asan_register_globals(void *unknown, size_t size)
|
||||
{
|
||||
ubsan("register_globals");
|
||||
UNUSED(unknown);
|
||||
UNUSED(size);
|
||||
ubsan("register_globals");
|
||||
UNUSED(unknown);
|
||||
UNUSED(size);
|
||||
}
|
||||
|
||||
void __asan_unregister_globals(void) { ubsan("unregister_globals"); }
|
||||
@ -364,155 +364,155 @@ void __asan_option_detect_stack_use_after_return(void) { ubsan("stack use after
|
||||
|
||||
__noreturn void __asan_handle_no_return(void)
|
||||
{
|
||||
ubsan("no_return");
|
||||
while (1)
|
||||
;
|
||||
ubsan("no_return");
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
|
||||
#define is_aligned(value, alignment) !(value & (alignment - 1))
|
||||
|
||||
const char *Type_Check_Kinds[] = {
|
||||
"Load of",
|
||||
"Store to",
|
||||
"Reference binding to",
|
||||
"Member access within",
|
||||
"Member call on",
|
||||
"Constructor call on",
|
||||
"Downcast of",
|
||||
"Downcast of",
|
||||
"Upcast of",
|
||||
"Cast to virtual base of",
|
||||
"Load of",
|
||||
"Store to",
|
||||
"Reference binding to",
|
||||
"Member access within",
|
||||
"Member call on",
|
||||
"Constructor call on",
|
||||
"Downcast of",
|
||||
"Downcast of",
|
||||
"Upcast of",
|
||||
"Cast to virtual base of",
|
||||
};
|
||||
|
||||
void __ubsan_handle_type_mismatch_v1(struct type_mismatch_v1_data *type_mismatch, uintptr_t pointer)
|
||||
{
|
||||
struct source_location *location = &type_mismatch->location;
|
||||
if (pointer == 0)
|
||||
{
|
||||
ubsan("\t\tIn File: %s:%i:%i", location->file, location->line, location->column);
|
||||
ubsan("Null pointer access.");
|
||||
}
|
||||
else if (type_mismatch->alignment != 0 && is_aligned(pointer, type_mismatch->alignment))
|
||||
{
|
||||
ubsan("\t\tIn File: %s:%i:%i", location->file, location->line, location->column);
|
||||
ubsan("Unaligned memory access %#lx.", pointer);
|
||||
}
|
||||
else
|
||||
{
|
||||
ubsan("\t\tIn File: %s:%i:%i", location->file, location->line, location->column);
|
||||
ubsan("%s address %#lx with insufficient space for object of type %s",
|
||||
Type_Check_Kinds[type_mismatch->type_check_kind],
|
||||
(void *)pointer, type_mismatch->type->name);
|
||||
}
|
||||
struct source_location *location = &type_mismatch->location;
|
||||
if (pointer == 0)
|
||||
{
|
||||
ubsan("\t\tIn File: %s:%i:%i", location->file, location->line, location->column);
|
||||
ubsan("Null pointer access.");
|
||||
}
|
||||
else if (type_mismatch->alignment != 0 && is_aligned(pointer, type_mismatch->alignment))
|
||||
{
|
||||
ubsan("\t\tIn File: %s:%i:%i", location->file, location->line, location->column);
|
||||
ubsan("Unaligned memory access %#lx.", pointer);
|
||||
}
|
||||
else
|
||||
{
|
||||
ubsan("\t\tIn File: %s:%i:%i", location->file, location->line, location->column);
|
||||
ubsan("%s address %#lx with insufficient space for object of type %s",
|
||||
Type_Check_Kinds[type_mismatch->type_check_kind],
|
||||
(void *)pointer, type_mismatch->type->name);
|
||||
}
|
||||
}
|
||||
|
||||
void __ubsan_handle_add_overflow(struct overflow_data *data)
|
||||
{
|
||||
ubsan("\t\tIn File: %s:%i:%i", data->location.file, data->location.line, data->location.column);
|
||||
ubsan("Addition overflow.");
|
||||
ubsan("\t\tIn File: %s:%i:%i", data->location.file, data->location.line, data->location.column);
|
||||
ubsan("Addition overflow.");
|
||||
}
|
||||
|
||||
void __ubsan_handle_sub_overflow(struct overflow_data *data)
|
||||
{
|
||||
ubsan("\t\tIn File: %s:%i:%i", data->location.file, data->location.line, data->location.column);
|
||||
ubsan("Subtraction overflow.");
|
||||
ubsan("\t\tIn File: %s:%i:%i", data->location.file, data->location.line, data->location.column);
|
||||
ubsan("Subtraction overflow.");
|
||||
}
|
||||
|
||||
void __ubsan_handle_mul_overflow(struct overflow_data *data)
|
||||
{
|
||||
ubsan("\t\tIn File: %s:%i:%i", data->location.file, data->location.line, data->location.column);
|
||||
ubsan("Multiplication overflow.");
|
||||
ubsan("\t\tIn File: %s:%i:%i", data->location.file, data->location.line, data->location.column);
|
||||
ubsan("Multiplication overflow.");
|
||||
}
|
||||
|
||||
void __ubsan_handle_divrem_overflow(struct overflow_data *data)
|
||||
{
|
||||
ubsan("\t\tIn File: %s:%i:%i", data->location.file, data->location.line, data->location.column);
|
||||
ubsan("Division overflow.");
|
||||
ubsan("\t\tIn File: %s:%i:%i", data->location.file, data->location.line, data->location.column);
|
||||
ubsan("Division overflow.");
|
||||
}
|
||||
|
||||
void __ubsan_handle_negate_overflow(struct overflow_data *data)
|
||||
{
|
||||
ubsan("\t\tIn File: %s:%i:%i", data->location.file, data->location.line, data->location.column);
|
||||
ubsan("Negation overflow.");
|
||||
ubsan("\t\tIn File: %s:%i:%i", data->location.file, data->location.line, data->location.column);
|
||||
ubsan("Negation overflow.");
|
||||
}
|
||||
|
||||
void __ubsan_handle_pointer_overflow(struct overflow_data *data)
|
||||
{
|
||||
ubsan("\t\tIn File: %s:%i:%i", data->location.file, data->location.line, data->location.column);
|
||||
ubsan("Pointer overflow.");
|
||||
ubsan("\t\tIn File: %s:%i:%i", data->location.file, data->location.line, data->location.column);
|
||||
ubsan("Pointer overflow.");
|
||||
}
|
||||
|
||||
void __ubsan_handle_shift_out_of_bounds(struct shift_out_of_bounds_data *data)
|
||||
{
|
||||
ubsan("\t\tIn File: %s:%i:%i", data->location.file, data->location.line, data->location.column);
|
||||
ubsan("Shift out of bounds.");
|
||||
ubsan("\t\tIn File: %s:%i:%i", data->location.file, data->location.line, data->location.column);
|
||||
ubsan("Shift out of bounds.");
|
||||
}
|
||||
|
||||
void __ubsan_handle_load_invalid_value(struct invalid_value_data *data)
|
||||
{
|
||||
ubsan("\t\tIn File: %s:%i:%i", data->location.file, data->location.line, data->location.column);
|
||||
ubsan("Invalid load value.");
|
||||
ubsan("\t\tIn File: %s:%i:%i", data->location.file, data->location.line, data->location.column);
|
||||
ubsan("Invalid load value.");
|
||||
}
|
||||
|
||||
void __ubsan_handle_out_of_bounds(struct array_out_of_bounds_data *data)
|
||||
{
|
||||
ubsan("\t\tIn File: %s:%i:%i", data->location.file, data->location.line, data->location.column);
|
||||
ubsan("Array out of bounds.");
|
||||
ubsan("\t\tIn File: %s:%i:%i", data->location.file, data->location.line, data->location.column);
|
||||
ubsan("Array out of bounds.");
|
||||
}
|
||||
|
||||
void __ubsan_handle_vla_bound_not_positive(struct negative_vla_data *data)
|
||||
{
|
||||
ubsan("\t\tIn File: %s:%i:%i", data->location.file, data->location.line, data->location.column);
|
||||
ubsan("Variable-length argument is negative.");
|
||||
ubsan("\t\tIn File: %s:%i:%i", data->location.file, data->location.line, data->location.column);
|
||||
ubsan("Variable-length argument is negative.");
|
||||
}
|
||||
|
||||
void __ubsan_handle_nonnull_return(struct nonnull_return_data *data)
|
||||
{
|
||||
ubsan("\t\tIn File: %s:%i:%i", data->location.file, data->location.line, data->location.column);
|
||||
ubsan("Non-null return is null.");
|
||||
ubsan("\t\tIn File: %s:%i:%i", data->location.file, data->location.line, data->location.column);
|
||||
ubsan("Non-null return is null.");
|
||||
}
|
||||
|
||||
void __ubsan_handle_nonnull_return_v1(struct nonnull_return_data *data)
|
||||
{
|
||||
ubsan("\t\tIn File: %s:%i:%i", data->location.file, data->location.line, data->location.column);
|
||||
ubsan("Non-null return is null.");
|
||||
ubsan("\t\tIn File: %s:%i:%i", data->location.file, data->location.line, data->location.column);
|
||||
ubsan("Non-null return is null.");
|
||||
}
|
||||
|
||||
void __ubsan_handle_nonnull_arg(struct nonnull_arg_data *data)
|
||||
{
|
||||
ubsan("\t\tIn File: %s:%i:%i", data->location.file, data->location.line, data->location.column);
|
||||
ubsan("Non-null argument is null.");
|
||||
ubsan("\t\tIn File: %s:%i:%i", data->location.file, data->location.line, data->location.column);
|
||||
ubsan("Non-null argument is null.");
|
||||
}
|
||||
|
||||
void __ubsan_handle_builtin_unreachable(struct unreachable_data *data)
|
||||
{
|
||||
ubsan("\t\tIn File: %s:%i:%i", data->location.file, data->location.line, data->location.column);
|
||||
ubsan("Unreachable code reached.");
|
||||
ubsan("\t\tIn File: %s:%i:%i", data->location.file, data->location.line, data->location.column);
|
||||
ubsan("Unreachable code reached.");
|
||||
}
|
||||
|
||||
void __ubsan_handle_invalid_builtin(struct invalid_builtin_data *data)
|
||||
{
|
||||
ubsan("\t\tIn File: %s:%i:%i", data->location.file, data->location.line, data->location.column);
|
||||
ubsan("Invalid builtin.");
|
||||
ubsan("\t\tIn File: %s:%i:%i", data->location.file, data->location.line, data->location.column);
|
||||
ubsan("Invalid builtin.");
|
||||
}
|
||||
|
||||
void __ubsan_handle_missing_return(struct unreachable_data *data)
|
||||
{
|
||||
ubsan("\t\tIn File: %s:%i:%i", data->location.file, data->location.line, data->location.column);
|
||||
ubsan("Missing return.");
|
||||
ubsan("\t\tIn File: %s:%i:%i", data->location.file, data->location.line, data->location.column);
|
||||
ubsan("Missing return.");
|
||||
}
|
||||
|
||||
void __ubsan_vptr_type_cache(uintptr_t *cache, uintptr_t ptr)
|
||||
{
|
||||
ubsan("Vptr type cache.");
|
||||
*cache = ptr;
|
||||
ubsan("Vptr type cache.");
|
||||
*cache = ptr;
|
||||
}
|
||||
|
||||
void __ubsan_handle_dynamic_type_cache_miss(struct dynamic_type_cache_miss_data *data, uintptr_t ptr)
|
||||
{
|
||||
ubsan("\t\tIn File: %s:%i:%i", data->location.file, data->location.line, data->location.column);
|
||||
ubsan("Dynamic type cache miss.");
|
||||
UNUSED(ptr);
|
||||
ubsan("\t\tIn File: %s:%i:%i", data->location.file, data->location.line, data->location.column);
|
||||
ubsan("Dynamic type cache miss.");
|
||||
UNUSED(ptr);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
64
core/ubsan.h
64
core/ubsan.h
@ -22,90 +22,90 @@
|
||||
|
||||
struct source_location
|
||||
{
|
||||
const char *file;
|
||||
uint32_t line;
|
||||
uint32_t column;
|
||||
const char *file;
|
||||
uint32_t line;
|
||||
uint32_t column;
|
||||
};
|
||||
|
||||
struct type_descriptor
|
||||
{
|
||||
uint16_t kind;
|
||||
uint16_t info;
|
||||
char name[];
|
||||
uint16_t kind;
|
||||
uint16_t info;
|
||||
char name[];
|
||||
};
|
||||
|
||||
struct type_mismatch_v1_data
|
||||
{
|
||||
struct source_location location;
|
||||
struct type_descriptor *type;
|
||||
uint8_t alignment;
|
||||
uint8_t type_check_kind;
|
||||
struct source_location location;
|
||||
struct type_descriptor *type;
|
||||
uint8_t alignment;
|
||||
uint8_t type_check_kind;
|
||||
};
|
||||
|
||||
struct out_of_bounds_info
|
||||
{
|
||||
struct source_location location;
|
||||
struct type_descriptor left_type;
|
||||
struct type_descriptor right_type;
|
||||
struct source_location location;
|
||||
struct type_descriptor left_type;
|
||||
struct type_descriptor right_type;
|
||||
};
|
||||
|
||||
struct overflow_data
|
||||
{
|
||||
struct source_location location;
|
||||
struct type_descriptor *type;
|
||||
struct source_location location;
|
||||
struct type_descriptor *type;
|
||||
};
|
||||
|
||||
struct negative_vla_data
|
||||
{
|
||||
struct source_location location;
|
||||
struct type_descriptor *type;
|
||||
struct source_location location;
|
||||
struct type_descriptor *type;
|
||||
};
|
||||
|
||||
struct invalid_value_data
|
||||
{
|
||||
struct source_location location;
|
||||
struct type_descriptor *type;
|
||||
struct source_location location;
|
||||
struct type_descriptor *type;
|
||||
};
|
||||
|
||||
struct nonnull_return_data
|
||||
{
|
||||
struct source_location location;
|
||||
struct source_location location;
|
||||
};
|
||||
|
||||
struct nonnull_arg_data
|
||||
{
|
||||
struct source_location location;
|
||||
struct source_location location;
|
||||
};
|
||||
|
||||
struct unreachable_data
|
||||
{
|
||||
struct source_location location;
|
||||
struct source_location location;
|
||||
};
|
||||
|
||||
struct invalid_builtin_data
|
||||
{
|
||||
struct source_location location;
|
||||
uint8_t kind;
|
||||
struct source_location location;
|
||||
uint8_t kind;
|
||||
};
|
||||
|
||||
struct array_out_of_bounds_data
|
||||
{
|
||||
struct source_location location;
|
||||
struct type_descriptor *array_type;
|
||||
struct type_descriptor *index_type;
|
||||
struct source_location location;
|
||||
struct type_descriptor *array_type;
|
||||
struct type_descriptor *index_type;
|
||||
};
|
||||
|
||||
struct shift_out_of_bounds_data
|
||||
{
|
||||
struct source_location location;
|
||||
struct type_descriptor *left_type;
|
||||
struct type_descriptor *right_type;
|
||||
struct source_location location;
|
||||
struct type_descriptor *left_type;
|
||||
struct type_descriptor *right_type;
|
||||
};
|
||||
|
||||
struct dynamic_type_cache_miss_data
|
||||
{
|
||||
struct source_location location;
|
||||
struct type_descriptor *type;
|
||||
struct source_location location;
|
||||
struct type_descriptor *type;
|
||||
};
|
||||
|
||||
#endif // !__FENNIX_KERNEL_UBSAN_H__
|
||||
|
@ -21,60 +21,60 @@
|
||||
|
||||
namespace Video
|
||||
{
|
||||
Font::Font(uintptr_t *Start, uintptr_t *End, FontType Type)
|
||||
{
|
||||
trace("Initializing font with start %#lx and end %#lx Type: %d", Start, End, Type);
|
||||
this->Info.StartAddress = Start;
|
||||
this->Info.EndAddress = End;
|
||||
this->Info.Type = Type;
|
||||
size_t FontDataLength = End - Start;
|
||||
Font::Font(uintptr_t *Start, uintptr_t *End, FontType Type)
|
||||
{
|
||||
trace("Initializing font with start %#lx and end %#lx Type: %d", Start, End, Type);
|
||||
this->Info.StartAddress = Start;
|
||||
this->Info.EndAddress = End;
|
||||
this->Info.Type = Type;
|
||||
size_t FontDataLength = End - Start;
|
||||
|
||||
if (Type == FontType::PCScreenFont2)
|
||||
{
|
||||
this->Info.PSF2Font = new PSF2_FONT;
|
||||
if (Type == FontType::PCScreenFont2)
|
||||
{
|
||||
this->Info.PSF2Font = new PSF2_FONT;
|
||||
|
||||
PSF2_HEADER *font2 = (PSF2_HEADER *)KernelAllocator.RequestPages(TO_PAGES(FontDataLength + 1));
|
||||
memcpy((void *)font2, Start, FontDataLength);
|
||||
PSF2_HEADER *font2 = (PSF2_HEADER *)KernelAllocator.RequestPages(TO_PAGES(FontDataLength + 1));
|
||||
memcpy((void *)font2, Start, FontDataLength);
|
||||
|
||||
Memory::Virtual().Map((void *)font2, (void *)font2,
|
||||
FontDataLength, Memory::PTFlag::RW);
|
||||
Memory::Virtual().Map((void *)font2, (void *)font2,
|
||||
FontDataLength, Memory::PTFlag::RW);
|
||||
|
||||
if (font2->magic[0] != PSF2_MAGIC0 || font2->magic[1] != PSF2_MAGIC1 ||
|
||||
font2->magic[2] != PSF2_MAGIC2 || font2->magic[3] != PSF2_MAGIC3)
|
||||
{
|
||||
error("Font2 magic mismatch.");
|
||||
KernelAllocator.FreePages((void *)font2, TO_PAGES(FontDataLength + 1));
|
||||
return;
|
||||
}
|
||||
if (font2->magic[0] != PSF2_MAGIC0 || font2->magic[1] != PSF2_MAGIC1 ||
|
||||
font2->magic[2] != PSF2_MAGIC2 || font2->magic[3] != PSF2_MAGIC3)
|
||||
{
|
||||
error("Font2 magic mismatch.");
|
||||
KernelAllocator.FreePages((void *)font2, TO_PAGES(FontDataLength + 1));
|
||||
return;
|
||||
}
|
||||
|
||||
this->Info.PSF2Font->Header = font2;
|
||||
this->Info.PSF2Font->GlyphBuffer =
|
||||
r_cst(void *, r_cst(uintptr_t, Start) + sizeof(PSF2_HEADER));
|
||||
this->Info.Width = font2->width;
|
||||
this->Info.Height = font2->height;
|
||||
}
|
||||
else if (Type == FontType::PCScreenFont1)
|
||||
{
|
||||
this->Info.PSF1Font = new PSF1_FONT;
|
||||
PSF1_HEADER *font1 = (PSF1_HEADER *)Start;
|
||||
if (font1->magic[0] != PSF1_MAGIC0 || font1->magic[1] != PSF1_MAGIC1)
|
||||
error("Font1 magic mismatch.");
|
||||
uint32_t glyphBufferSize = font1->charsize * 256;
|
||||
if (font1->mode == 1) // 512 glyph mode
|
||||
glyphBufferSize = font1->charsize * 512;
|
||||
void *glyphBuffer =
|
||||
r_cst(void *, r_cst(uintptr_t, Start) + sizeof(PSF1_HEADER));
|
||||
this->Info.PSF1Font->Header = font1;
|
||||
this->Info.PSF1Font->GlyphBuffer = glyphBuffer;
|
||||
UNUSED(glyphBufferSize); // TODO: Use this in the future?
|
||||
this->Info.PSF2Font->Header = font2;
|
||||
this->Info.PSF2Font->GlyphBuffer =
|
||||
r_cst(void *, r_cst(uintptr_t, Start) + sizeof(PSF2_HEADER));
|
||||
this->Info.Width = font2->width;
|
||||
this->Info.Height = font2->height;
|
||||
}
|
||||
else if (Type == FontType::PCScreenFont1)
|
||||
{
|
||||
this->Info.PSF1Font = new PSF1_FONT;
|
||||
PSF1_HEADER *font1 = (PSF1_HEADER *)Start;
|
||||
if (font1->magic[0] != PSF1_MAGIC0 || font1->magic[1] != PSF1_MAGIC1)
|
||||
error("Font1 magic mismatch.");
|
||||
uint32_t glyphBufferSize = font1->charsize * 256;
|
||||
if (font1->mode == 1) // 512 glyph mode
|
||||
glyphBufferSize = font1->charsize * 512;
|
||||
void *glyphBuffer =
|
||||
r_cst(void *, r_cst(uintptr_t, Start) + sizeof(PSF1_HEADER));
|
||||
this->Info.PSF1Font->Header = font1;
|
||||
this->Info.PSF1Font->GlyphBuffer = glyphBuffer;
|
||||
UNUSED(glyphBufferSize); // TODO: Use this in the future?
|
||||
|
||||
// TODO: Get font size.
|
||||
this->Info.Width = 16;
|
||||
this->Info.Height = 8;
|
||||
}
|
||||
}
|
||||
// TODO: Get font size.
|
||||
this->Info.Width = 16;
|
||||
this->Info.Height = 8;
|
||||
}
|
||||
}
|
||||
|
||||
Font::~Font()
|
||||
{
|
||||
}
|
||||
Font::~Font()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
326
driver.h
Normal file
326
driver.h
Normal file
@ -0,0 +1,326 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __FENNIX_API_DRIVER_FUNCTIONS_H__
|
||||
#define __FENNIX_API_DRIVER_FUNCTIONS_H__
|
||||
|
||||
#include <types.h>
|
||||
|
||||
typedef enum
|
||||
{
|
||||
_drf_Entry,
|
||||
_drf_Final,
|
||||
_drf_Panic,
|
||||
_drf_Probe,
|
||||
} __driverRegFunc;
|
||||
|
||||
typedef union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint8_t LeftButton : 1;
|
||||
uint8_t RightButton : 1;
|
||||
uint8_t MiddleButton : 1;
|
||||
uint8_t Button4 : 1;
|
||||
uint8_t Button5 : 1;
|
||||
uint8_t Button6 : 1;
|
||||
uint8_t Button7 : 1;
|
||||
uint8_t Button8 : 1;
|
||||
};
|
||||
uint8_t Value;
|
||||
} __MouseButtons;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* PCIDevice */ void *Device;
|
||||
/* __PCIArray */ void *Next;
|
||||
} __PCIArray;
|
||||
|
||||
/* ========================================== */
|
||||
|
||||
#define PCI_END 0x0000
|
||||
#define KEY_NULL 0x00
|
||||
|
||||
typedef enum
|
||||
{
|
||||
KEY_1,
|
||||
KEY_2,
|
||||
KEY_3,
|
||||
KEY_4,
|
||||
KEY_5,
|
||||
KEY_6,
|
||||
KEY_7,
|
||||
KEY_8,
|
||||
KEY_9,
|
||||
KEY_0,
|
||||
|
||||
KEY_Q,
|
||||
KEY_W,
|
||||
KEY_E,
|
||||
KEY_R,
|
||||
KEY_T,
|
||||
KEY_Y,
|
||||
KEY_U,
|
||||
KEY_I,
|
||||
KEY_O,
|
||||
KEY_P,
|
||||
KEY_A,
|
||||
KEY_S,
|
||||
KEY_D,
|
||||
KEY_F,
|
||||
KEY_G,
|
||||
KEY_H,
|
||||
KEY_J,
|
||||
KEY_K,
|
||||
KEY_L,
|
||||
KEY_Z,
|
||||
KEY_X,
|
||||
KEY_C,
|
||||
KEY_V,
|
||||
KEY_B,
|
||||
KEY_N,
|
||||
KEY_M,
|
||||
|
||||
KEY_F1,
|
||||
KEY_F2,
|
||||
KEY_F3,
|
||||
KEY_F4,
|
||||
KEY_F5,
|
||||
KEY_F6,
|
||||
KEY_F7,
|
||||
KEY_F8,
|
||||
KEY_F9,
|
||||
KEY_F10,
|
||||
KEY_F11,
|
||||
KEY_F12,
|
||||
|
||||
KEYPAD_7,
|
||||
KEYPAD_8,
|
||||
KEYPAD_9,
|
||||
KEYPAD_MINUS,
|
||||
KEYPAD_4,
|
||||
KEYPAD_5,
|
||||
KEYPAD_6,
|
||||
KEYPAD_PLUS,
|
||||
KEYPAD_1,
|
||||
KEYPAD_2,
|
||||
KEYPAD_3,
|
||||
KEYPAD_0,
|
||||
KEYPAD_PERIOD,
|
||||
KEYPAD_RETURN,
|
||||
KEYPAD_ASTERISK,
|
||||
KEYPAD_SLASH,
|
||||
|
||||
KEY_LEFT_CTRL,
|
||||
KEY_RIGHT_CTRL,
|
||||
KEY_LEFT_SHIFT,
|
||||
KEY_RIGHT_SHIFT,
|
||||
KEY_LEFT_ALT,
|
||||
KEY_RIGHT_ALT,
|
||||
KEY_ESCAPE,
|
||||
KEY_MINUS,
|
||||
KEY_EQUAL,
|
||||
KEY_BACKSPACE,
|
||||
KEY_TAB,
|
||||
KEY_LEFT_BRACKET,
|
||||
KEY_RIGHT_BRACKET,
|
||||
KEY_RETURN,
|
||||
KEY_SEMICOLON,
|
||||
KEY_APOSTROPHE,
|
||||
KEY_BACK_TICK,
|
||||
KEY_BACKSLASH,
|
||||
KEY_COMMA,
|
||||
KEY_PERIOD,
|
||||
KEY_SLASH,
|
||||
KEY_SPACE,
|
||||
KEY_CAPS_LOCK,
|
||||
KEY_NUM_LOCK,
|
||||
KEY_SCROLL_LOCK,
|
||||
KEY_PRINT_SCREEN,
|
||||
|
||||
KEY_HOME,
|
||||
KEY_UP_ARROW,
|
||||
KEY_LEFT_ARROW,
|
||||
KEY_RIGHT_ARROW,
|
||||
KEY_DOWN_ARROW,
|
||||
KEY_PAGE_UP,
|
||||
KEY_PAGE_DOWN,
|
||||
KEY_END,
|
||||
KEY_INSERT,
|
||||
KEY_DELETE,
|
||||
KEY_LEFT_GUI,
|
||||
KEY_RIGHT_GUI,
|
||||
KEY_APPS,
|
||||
|
||||
KEY_MULTIMEDIA_PREV_TRACK,
|
||||
KEY_MULTIMEDIA_NEXT_TRACK,
|
||||
KEY_MULTIMEDIA_MUTE,
|
||||
KEY_MULTIMEDIA_CALCULATOR,
|
||||
KEY_MULTIMEDIA_PLAY,
|
||||
KEY_MULTIMEDIA_STOP,
|
||||
KEY_MULTIMEDIA_VOL_DOWN,
|
||||
KEY_MULTIMEDIA_VOL_UP,
|
||||
KEY_MULTIMEDIA_WWW_HOME,
|
||||
KEY_MULTIMEDIA_WWW_SEARCH,
|
||||
KEY_MULTIMEDIA_WWW_FAVORITES,
|
||||
KEY_MULTIMEDIA_WWW_REFRESH,
|
||||
KEY_MULTIMEDIA_WWW_STOP,
|
||||
KEY_MULTIMEDIA_WWW_FORWARD,
|
||||
KEY_MULTIMEDIA_WWW_BACK,
|
||||
KEY_MULTIMEDIA_MY_COMPUTER,
|
||||
KEY_MULTIMEDIA_EMAIL,
|
||||
KEY_MULTIMEDIA_MEDIA_SELECT,
|
||||
|
||||
KEY_ACPI_POWER,
|
||||
KEY_ACPI_SLEEP,
|
||||
KEY_ACPI_WAKE,
|
||||
|
||||
KEY_PRESSED = 0x80,
|
||||
} KeyScanCodes;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
ddt_Keyboard,
|
||||
ddt_Mouse,
|
||||
ddt_Joystick,
|
||||
ddt_Gamepad,
|
||||
ddt_Touchpad,
|
||||
ddt_Touchscreen,
|
||||
|
||||
ddt_SATA,
|
||||
ddt_ATA,
|
||||
ddt_NVMe,
|
||||
|
||||
ddt_Audio,
|
||||
|
||||
ddt_Network,
|
||||
} DeviceDriverType;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
IOCTL_AUDIO_GET_VOLUME,
|
||||
IOCTL_AUDIO_SET_VOLUME,
|
||||
|
||||
IOCTL_AUDIO_GET_MUTE,
|
||||
IOCTL_AUDIO_SET_MUTE,
|
||||
|
||||
IOCTL_AUDIO_GET_SAMPLE_RATE,
|
||||
IOCTL_AUDIO_SET_SAMPLE_RATE,
|
||||
|
||||
IOCTL_AUDIO_GET_CHANNELS,
|
||||
IOCTL_AUDIO_SET_CHANNELS,
|
||||
} AudioIoctl;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
IOCTL_NET_GET_MAC,
|
||||
} NetIoctl;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
MAP_PRESENT = 1 << 0,
|
||||
MAP_WRITE = 1 << 1,
|
||||
MAP_USER = 1 << 2,
|
||||
MAP_WRITE_THROUGH = 1 << 3,
|
||||
MAP_CACHE_DISABLE = 1 << 4,
|
||||
} PageMapFlags;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint8_t Major;
|
||||
uint8_t Minor;
|
||||
uint8_t Patch;
|
||||
} APIVersion;
|
||||
|
||||
dev_t MajorID;
|
||||
uintptr_t Base;
|
||||
|
||||
/* Internal */
|
||||
int (*RegisterFunction)(dev_t MajorID, void *Function, __driverRegFunc Type);
|
||||
int (*GetDriverInfo)(dev_t MajorID, const char *Name, const char *Description, const char *Author, const char *Version, const char *License);
|
||||
|
||||
/* Interrupts */
|
||||
int (*RegisterInterruptHandler)(dev_t MajorID, uint8_t IRQ, void *Handler);
|
||||
int (*OverrideInterruptHandler)(dev_t MajorID, uint8_t IRQ, void *Handler);
|
||||
int (*UnregisterInterruptHandler)(dev_t MajorID, uint8_t IRQ, void *Handler);
|
||||
int (*UnregisterAllInterruptHandlers)(dev_t MajorID, void *Handler);
|
||||
|
||||
/* Input */
|
||||
dev_t (*RegisterInputDevice)(dev_t MajorID, DeviceDriverType Type);
|
||||
int (*UnregisterInputDevice)(dev_t MajorID, dev_t MinorID, DeviceDriverType Type);
|
||||
int (*ReportKeyboardEvent)(dev_t MajorID, dev_t MinorID, uint8_t ScanCode);
|
||||
int (*ReportRelativeMouseEvent)(dev_t MajorID, dev_t MinorID, __MouseButtons Button, int X, int Y, int8_t Z);
|
||||
int (*ReportAbsoluteMouseEvent)(dev_t MajorID, dev_t MinorID, __MouseButtons Button, uintptr_t X, uintptr_t Y, int8_t Z);
|
||||
|
||||
/* Storage */
|
||||
dev_t (*RegisterBlockDevice)(dev_t MajorID, DeviceDriverType Type, void *Open, void *Close, void *Read, void *Write, void *Ioctl);
|
||||
int (*UnregisterBlockDevice)(dev_t MajorID, dev_t MinorID, DeviceDriverType Type);
|
||||
|
||||
/* Audio */
|
||||
dev_t (*RegisterAudioDevice)(dev_t MajorID, DeviceDriverType Type, void *Open, void *Close, void *Read, void *Write, void *Ioctl);
|
||||
int (*UnregisterAudioDevice)(dev_t MajorID, dev_t MinorID, DeviceDriverType Type);
|
||||
|
||||
/* Network */
|
||||
dev_t (*RegisterNetDevice)(dev_t MajorID, DeviceDriverType Type, void *Open, void *Close, void *Read, void *Write, void *Ioctl);
|
||||
int (*UnregisterNetDevice)(dev_t MajorID, dev_t MinorID, DeviceDriverType Type);
|
||||
int (*ReportNetworkPacket)(dev_t MajorID, dev_t MinorID, void *Buffer, size_t Size);
|
||||
|
||||
/* Logging */
|
||||
void (*KPrint)(dev_t MajorID, const char *Format, va_list args);
|
||||
void (*KernelLog)(dev_t MajorID, const char *Format, va_list args);
|
||||
|
||||
/* Memory */
|
||||
void *(*RequestPages)(dev_t MajorID, size_t Pages);
|
||||
void (*FreePages)(dev_t MajorID, void *Pointer, size_t Pages);
|
||||
|
||||
/* Mapping */
|
||||
void (*AppendMapFlag)(dev_t MajorID, void *Address, PageMapFlags Flag);
|
||||
void (*RemoveMapFlag)(dev_t MajorID, void *Address, PageMapFlags Flag);
|
||||
void (*MapPages)(dev_t MajorID, void *PhysicalAddress, void *VirtualAddress, size_t Pages, uint32_t Flags);
|
||||
void (*UnmapPages)(dev_t MajorID, void *VirtualAddress, size_t Pages);
|
||||
|
||||
/* Scheduling */
|
||||
pid_t (*CreateKernelProcess)(dev_t MajorID, const char *Name);
|
||||
pid_t (*CreateKernelThread)(dev_t MajorID, pid_t pId, const char *Name, void *EntryPoint, void *Argument);
|
||||
int (*KillProcess)(dev_t MajorID, pid_t pId, int ExitCode);
|
||||
int (*KillThread)(dev_t MajorID, pid_t tId, int ExitCode);
|
||||
void (*Yield)(dev_t MajorID);
|
||||
void (*Sleep)(dev_t MajorID, uint64_t Milliseconds);
|
||||
|
||||
/* PCI */
|
||||
__PCIArray *(*GetPCIDevices)(dev_t MajorID, uint16_t Vendors[], uint16_t Devices[]);
|
||||
void (*InitializePCI)(dev_t MajorID, void *Header);
|
||||
uint32_t (*GetBAR)(dev_t MajorID, uint8_t Index, void *Header);
|
||||
|
||||
/* Kernel std API */
|
||||
void *(*memcpy)(dev_t MajorID, void *Destination, const void *Source, size_t Length);
|
||||
void *(*memset)(dev_t MajorID, void *Destination, int Value, size_t Length);
|
||||
void *(*memmove)(dev_t MajorID, void *Destination, const void *Source, size_t Length);
|
||||
int (*memcmp)(dev_t MajorID, const void *Left, const void *Right, size_t Length);
|
||||
size_t (*strlen)(dev_t MajorID, const char *String);
|
||||
char *(*strcpy)(dev_t MajorID, char *Destination, const char *Source);
|
||||
char *(*strcat)(dev_t MajorID, char *Destination, const char *Source);
|
||||
int (*strcmp)(dev_t MajorID, const char *Left, const char *Right);
|
||||
int (*strncmp)(dev_t MajorID, const char *Left, const char *Right, size_t Length);
|
||||
char *(*strchr)(dev_t MajorID, const char *String, int Character);
|
||||
char *(*strrchr)(dev_t MajorID, const char *String, int Character);
|
||||
char *(*strstr)(dev_t MajorID, const char *Haystack, const char *Needle);
|
||||
} __driverAPI;
|
||||
|
||||
#endif // !__FENNIX_API_DRIVER_FUNCTIONS_H__
|
@ -19,52 +19,34 @@
|
||||
|
||||
#include <msexec.h>
|
||||
|
||||
#include "../kernel.h"
|
||||
#include "../Fex.hpp"
|
||||
|
||||
namespace Execute
|
||||
{
|
||||
BinaryType GetBinaryType(const char *Path)
|
||||
{
|
||||
debug("Checking binary type of %s(ptr: %#lx)",
|
||||
Path, Path);
|
||||
BinaryType Type;
|
||||
int fd = fopen(Path, "r");
|
||||
|
||||
if (fd < 0)
|
||||
{
|
||||
debug("Failed to open file %s: %s",
|
||||
Path, strerror(fd));
|
||||
return (BinaryType)fd;
|
||||
}
|
||||
|
||||
debug("File opened: %s, descriptor %d", Path, fd);
|
||||
Memory::SmartHeap sh = Memory::SmartHeap(1024);
|
||||
fread(fd, sh, 128);
|
||||
|
||||
Fex *FexHdr = (Fex *)sh.Get();
|
||||
Elf32_Ehdr *ELFHeader = (Elf32_Ehdr *)sh.Get();
|
||||
IMAGE_DOS_HEADER *MZHeader = (IMAGE_DOS_HEADER *)sh.Get();
|
||||
|
||||
/* Check Fex header. */
|
||||
if (FexHdr->Magic[0] == 'F' &&
|
||||
FexHdr->Magic[1] == 'E' &&
|
||||
FexHdr->Magic[2] == 'X' &&
|
||||
FexHdr->Magic[3] == '\0')
|
||||
{
|
||||
/* If the fex type is driver, we shouldn't return as Fex. */
|
||||
if (FexHdr->Type == FexFormatType_Executable)
|
||||
{
|
||||
debug("Image - Fex");
|
||||
Type = BinaryType::BinTypeFex;
|
||||
goto Success;
|
||||
}
|
||||
else if (FexHdr->Type == FexFormatType_Module)
|
||||
{
|
||||
fixme("Fex Module is not supposed to be executed.");
|
||||
/* TODO: Module installation pop-up. */
|
||||
}
|
||||
}
|
||||
|
||||
/* Check ELF header. */
|
||||
else if (ELFHeader->e_ident[EI_MAG0] == ELFMAG0 &&
|
||||
ELFHeader->e_ident[EI_MAG1] == ELFMAG1 &&
|
||||
ELFHeader->e_ident[EI_MAG2] == ELFMAG2 &&
|
||||
ELFHeader->e_ident[EI_MAG3] == ELFMAG3)
|
||||
if (ELFHeader->e_ident[EI_MAG0] == ELFMAG0 &&
|
||||
ELFHeader->e_ident[EI_MAG1] == ELFMAG1 &&
|
||||
ELFHeader->e_ident[EI_MAG2] == ELFMAG2 &&
|
||||
ELFHeader->e_ident[EI_MAG3] == ELFMAG3)
|
||||
{
|
||||
debug("Image - ELF");
|
||||
Type = BinaryType::BinTypeELF;
|
||||
|
@ -26,7 +26,6 @@
|
||||
#include <abi.h>
|
||||
|
||||
#include "../../kernel.h"
|
||||
#include "../../Fex.hpp"
|
||||
|
||||
using namespace Tasking;
|
||||
using namespace vfs;
|
||||
@ -162,8 +161,9 @@ namespace Execute
|
||||
uintptr_t EntryPoint = ELFHeader.e_entry;
|
||||
debug("Entry point is %#lx", EntryPoint);
|
||||
|
||||
Memory::Virtual vmm = Memory::Virtual(TargetProcess->PageTable);
|
||||
Memory::Virtual vmm(TargetProcess->PageTable);
|
||||
Memory::VirtualMemoryArea *vma = TargetProcess->vma;
|
||||
debug("Target process page table is %#lx", TargetProcess->PageTable);
|
||||
|
||||
LoadPhdrs_x86_64(fd, ELFHeader, vma, TargetProcess);
|
||||
|
||||
@ -188,9 +188,10 @@ namespace Execute
|
||||
|
||||
vmm.Map(vAddr, pAddr,
|
||||
ProgramHeader.p_memsz,
|
||||
Memory::P | Memory::RW | Memory::US);
|
||||
Memory::RW | Memory::US);
|
||||
|
||||
debug("Mapped %#lx to %#lx", vAddr, pAddr);
|
||||
debug("Mapped %#lx to %#lx (%ld bytes)",
|
||||
vAddr, pAddr, ProgramHeader.p_memsz);
|
||||
debug("Segment Offset is %#lx", SegDestOffset);
|
||||
|
||||
debug("Copying segment to p: %#lx-%#lx; v: %#lx-%#lx (%ld file bytes, %ld mem bytes)",
|
||||
@ -202,6 +203,8 @@ namespace Execute
|
||||
|
||||
if (ProgramHeader.p_filesz > 0)
|
||||
{
|
||||
debug("%d %#lx %d", ProgramHeader.p_offset,
|
||||
(uint8_t *)pAddr + SegDestOffset, ProgramHeader.p_filesz);
|
||||
lseek(fd, ProgramHeader.p_offset, SEEK_SET);
|
||||
fread(fd, (uint8_t *)pAddr + SegDestOffset, ProgramHeader.p_filesz);
|
||||
}
|
||||
@ -209,11 +212,100 @@ namespace Execute
|
||||
if (ProgramHeader.p_memsz - ProgramHeader.p_filesz > 0)
|
||||
{
|
||||
void *zAddr = (void *)(uintptr_t(pAddr) + SegDestOffset + ProgramHeader.p_filesz);
|
||||
|
||||
debug("Zeroing %d bytes at %#lx",
|
||||
ProgramHeader.p_memsz - ProgramHeader.p_filesz, zAddr);
|
||||
|
||||
memset(zAddr, 0, ProgramHeader.p_memsz - ProgramHeader.p_filesz);
|
||||
}
|
||||
ProgramBreakHeader = ProgramHeader;
|
||||
break;
|
||||
}
|
||||
case PT_NOTE:
|
||||
{
|
||||
Elf64_Nhdr NoteHeader;
|
||||
lseek(fd, ProgramHeader.p_offset, SEEK_SET);
|
||||
fread(fd, (uint8_t *)&NoteHeader, sizeof(Elf64_Nhdr));
|
||||
|
||||
switch (NoteHeader.n_type)
|
||||
{
|
||||
case NT_PRSTATUS:
|
||||
{
|
||||
Elf64_Prstatus prstatus;
|
||||
lseek(fd, ProgramHeader.p_offset + sizeof(Elf64_Nhdr), SEEK_SET);
|
||||
fread(fd, (uint8_t *)&prstatus, sizeof(Elf64_Prstatus));
|
||||
debug("PRSTATUS: %#lx", prstatus.pr_reg[0]);
|
||||
break;
|
||||
}
|
||||
case NT_PRPSINFO:
|
||||
{
|
||||
Elf64_Prpsinfo prpsinfo;
|
||||
lseek(fd, ProgramHeader.p_offset + sizeof(Elf64_Nhdr), SEEK_SET);
|
||||
fread(fd, (uint8_t *)&prpsinfo, sizeof(Elf64_Prpsinfo));
|
||||
debug("PRPSINFO: %s", prpsinfo.pr_fname);
|
||||
break;
|
||||
}
|
||||
case NT_PLATFORM:
|
||||
{
|
||||
char platform[256];
|
||||
lseek(fd, ProgramHeader.p_offset + sizeof(Elf64_Nhdr), SEEK_SET);
|
||||
fread(fd, (uint8_t *)&platform, 256);
|
||||
debug("PLATFORM: %s", platform);
|
||||
break;
|
||||
}
|
||||
case NT_AUXV:
|
||||
{
|
||||
Elf64_auxv_t auxv;
|
||||
lseek(fd, ProgramHeader.p_offset + sizeof(Elf64_Nhdr), SEEK_SET);
|
||||
fread(fd, (uint8_t *)&auxv, sizeof(Elf64_auxv_t));
|
||||
debug("AUXV: %#lx", auxv.a_un.a_val);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
fixme("Unhandled note type: %#lx", NoteHeader.n_type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PT_TLS:
|
||||
{
|
||||
size_t tlsSize = ProgramHeader.p_memsz;
|
||||
debug("TLS Size: %ld (%ld pages)",
|
||||
tlsSize, TO_PAGES(tlsSize));
|
||||
void *tlsMemory = vma->RequestPages(TO_PAGES(tlsSize));
|
||||
lseek(fd, ProgramHeader.p_offset, SEEK_SET);
|
||||
fread(fd, (uint8_t *)tlsMemory, tlsSize);
|
||||
TargetProcess->TLS = {
|
||||
.pBase = uintptr_t(tlsMemory),
|
||||
.vBase = ProgramHeader.p_vaddr,
|
||||
.Align = ProgramHeader.p_align,
|
||||
.Size = ProgramHeader.p_memsz,
|
||||
.fSize = ProgramHeader.p_filesz,
|
||||
};
|
||||
break;
|
||||
}
|
||||
case 0x6474E550: /* PT_GNU_EH_FRAME */
|
||||
{
|
||||
fixme("PT_GNU_EH_FRAME");
|
||||
break;
|
||||
}
|
||||
case 0x6474e551: /* PT_GNU_STACK */
|
||||
{
|
||||
fixme("PT_GNU_STACK");
|
||||
break;
|
||||
}
|
||||
case 0x6474e552: /* PT_GNU_RELRO */
|
||||
{
|
||||
fixme("PT_GNU_RELRO");
|
||||
break;
|
||||
}
|
||||
case 0x6474e553: /* PT_GNU_PROPERTY */
|
||||
{
|
||||
fixme("PT_GNU_PROPERTY");
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
fixme("Unhandled program header type: %#lx",
|
||||
@ -238,6 +330,11 @@ namespace Execute
|
||||
fread(fd, sh, statbuf.st_size);
|
||||
TargetProcess->ELFSymbolTable->AppendSymbols(uintptr_t(sh.Get()));
|
||||
|
||||
#ifdef DEBUG
|
||||
if (!TargetProcess->ELFSymbolTable->SymTableExists)
|
||||
debug("NO SYMBOL TABLE FOUND?");
|
||||
#endif
|
||||
|
||||
debug("Entry Point: %#lx", EntryPoint);
|
||||
|
||||
this->GenerateAuxiliaryVector_x86_64(vma, fd, ELFHeader,
|
||||
@ -299,7 +396,7 @@ namespace Execute
|
||||
uintptr_t EntryPoint = ELFHeader.e_entry;
|
||||
debug("Entry point is %#lx", EntryPoint);
|
||||
|
||||
Memory::Virtual vmm = Memory::Virtual(TargetProcess->PageTable);
|
||||
Memory::Virtual vmm(TargetProcess->PageTable);
|
||||
Memory::VirtualMemoryArea *vma = TargetProcess->vma;
|
||||
uintptr_t BaseAddress = 0;
|
||||
|
||||
@ -396,6 +493,26 @@ namespace Execute
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 0x6474E550: /* PT_GNU_EH_FRAME */
|
||||
{
|
||||
fixme("PT_GNU_EH_FRAME");
|
||||
break;
|
||||
}
|
||||
case 0x6474e551: /* PT_GNU_STACK */
|
||||
{
|
||||
fixme("PT_GNU_STACK");
|
||||
break;
|
||||
}
|
||||
case 0x6474e552: /* PT_GNU_RELRO */
|
||||
{
|
||||
fixme("PT_GNU_RELRO");
|
||||
break;
|
||||
}
|
||||
case 0x6474e553: /* PT_GNU_PROPERTY */
|
||||
{
|
||||
fixme("PT_GNU_PROPERTY");
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
fixme("Unhandled program header type: %#lx",
|
||||
@ -417,240 +534,209 @@ namespace Execute
|
||||
EntryPoint += BaseAddress;
|
||||
debug("The new ep is %#lx", EntryPoint);
|
||||
|
||||
std::vector<Elf64_Dyn> JmpRel = ELFGetDynamicTag_x86_64(fd, DT_JMPREL);
|
||||
std::vector<Elf64_Dyn> SymTab = ELFGetDynamicTag_x86_64(fd, DT_SYMTAB);
|
||||
std::vector<Elf64_Dyn> StrTab = ELFGetDynamicTag_x86_64(fd, DT_STRTAB);
|
||||
std::vector<Elf64_Dyn> RelaDyn = ELFGetDynamicTag_x86_64(fd, DT_RELA);
|
||||
std::vector<Elf64_Dyn> RelaDynSize = ELFGetDynamicTag_x86_64(fd, DT_RELASZ);
|
||||
|
||||
size_t JmpRelSize = JmpRel.size();
|
||||
size_t SymTabSize = SymTab.size();
|
||||
size_t StrTabSize = StrTab.size();
|
||||
size_t RelaDynSize_v = RelaDyn.size();
|
||||
|
||||
if (JmpRelSize < 1)
|
||||
{
|
||||
debug("No DT_JMPREL");
|
||||
}
|
||||
|
||||
if (SymTabSize < 1)
|
||||
{
|
||||
debug("No DT_SYMTAB");
|
||||
}
|
||||
|
||||
if (StrTabSize < 1)
|
||||
{
|
||||
debug("No DT_STRTAB");
|
||||
}
|
||||
|
||||
if (RelaDynSize_v < 1)
|
||||
{
|
||||
debug("No DT_RELA");
|
||||
}
|
||||
|
||||
if (RelaDynSize[0].d_un.d_val < 1)
|
||||
{
|
||||
debug("DT_RELASZ is < 1");
|
||||
}
|
||||
|
||||
if (JmpRelSize > 0 && SymTabSize > 0 && StrTabSize > 0)
|
||||
{
|
||||
debug("JmpRel: %#lx, SymTab: %#lx, StrTab: %#lx",
|
||||
JmpRel[0].d_un.d_ptr, SymTab[0].d_un.d_ptr,
|
||||
StrTab[0].d_un.d_ptr);
|
||||
|
||||
Elf64_Rela *_JmpRel = (Elf64_Rela *)((uintptr_t)BaseAddress + JmpRel[0].d_un.d_ptr);
|
||||
Elf64_Sym *_SymTab = (Elf64_Sym *)((uintptr_t)BaseAddress + SymTab[0].d_un.d_ptr);
|
||||
char *_DynStr = (char *)((uintptr_t)BaseAddress + StrTab[0].d_un.d_ptr);
|
||||
Elf64_Rela *_RelaDyn = (Elf64_Rela *)((uintptr_t)BaseAddress + RelaDyn[0].d_un.d_ptr);
|
||||
|
||||
Elf64_Shdr shdr;
|
||||
for (Elf64_Half i = 0; i < ELFHeader.e_shnum; i++)
|
||||
{
|
||||
lseek(fd, ELFHeader.e_shoff + i * sizeof(Elf64_Shdr), SEEK_SET);
|
||||
fread(fd, (uint8_t *)&shdr, sizeof(Elf64_Shdr));
|
||||
|
||||
char sectionName[32];
|
||||
Elf64_Shdr n_shdr;
|
||||
lseek(fd, ELFHeader.e_shoff + ELFHeader.e_shstrndx * sizeof(Elf64_Shdr), SEEK_SET);
|
||||
fread(fd, (uint8_t *)&n_shdr, sizeof(Elf64_Shdr));
|
||||
lseek(fd, n_shdr.sh_offset + shdr.sh_name, SEEK_SET);
|
||||
fread(fd, (uint8_t *)sectionName, 32);
|
||||
debug("shdr: %s", sectionName);
|
||||
|
||||
if (strcmp(sectionName, ".rela.plt") == 0)
|
||||
{
|
||||
// .rela.plt
|
||||
// R_X86_64_JUMP_SLOT
|
||||
Elf64_Xword numEntries = shdr.sh_size / shdr.sh_entsize;
|
||||
for (Elf64_Xword i = 0; i < numEntries; i++)
|
||||
{
|
||||
Elf64_Addr *GOTEntry = (Elf64_Addr *)(shdr.sh_addr +
|
||||
BaseAddress +
|
||||
i * sizeof(Elf64_Addr));
|
||||
Elf64_Rela *Rel = _JmpRel + i;
|
||||
Elf64_Xword RelType = ELF64_R_TYPE(Rel->r_info);
|
||||
|
||||
switch (RelType)
|
||||
{
|
||||
case R_X86_64_JUMP_SLOT:
|
||||
{
|
||||
Elf64_Xword SymIndex = ELF64_R_SYM(Rel->r_info);
|
||||
Elf64_Sym *Sym = _SymTab + SymIndex;
|
||||
|
||||
if (Sym->st_name)
|
||||
{
|
||||
char *SymName = _DynStr + Sym->st_name;
|
||||
debug("SymName: %s", SymName);
|
||||
|
||||
Elf64_Sym LibSym = ELFLookupSymbol(fd, SymName);
|
||||
if (LibSym.st_value)
|
||||
{
|
||||
*GOTEntry = (Elf64_Addr)(BaseAddress + LibSym.st_value);
|
||||
debug("GOT[%ld](%#lx): %#lx",
|
||||
i, uintptr_t(GOTEntry) - BaseAddress,
|
||||
*GOTEntry);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
default:
|
||||
{
|
||||
fixme("Unhandled relocation type: %#lx", RelType);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (strcmp(sectionName, ".rela.dyn") == 0)
|
||||
{
|
||||
// .rela.dyn
|
||||
// R_X86_64_RELATIVE
|
||||
// R_X86_64_GLOB_DAT
|
||||
if (RelaDynSize_v < 1 || RelaDynSize[0].d_un.d_val < 1)
|
||||
continue;
|
||||
Elf64_Xword numRelaDynEntries = RelaDynSize[0].d_un.d_val / sizeof(Elf64_Rela);
|
||||
for (Elf64_Xword i = 0; i < numRelaDynEntries; i++)
|
||||
{
|
||||
Elf64_Rela *Rel = _RelaDyn + i;
|
||||
Elf64_Addr *GOTEntry = (Elf64_Addr *)(Rel->r_offset + BaseAddress);
|
||||
Elf64_Xword RelType = ELF64_R_TYPE(Rel->r_info);
|
||||
|
||||
switch (RelType)
|
||||
{
|
||||
case R_X86_64_RELATIVE:
|
||||
{
|
||||
*GOTEntry = (Elf64_Addr)(BaseAddress + Rel->r_addend);
|
||||
debug("GOT[%ld](%#lx): %#lx (R_X86_64_RELATIVE)",
|
||||
i, uintptr_t(GOTEntry) - BaseAddress,
|
||||
*GOTEntry);
|
||||
break;
|
||||
}
|
||||
case R_X86_64_GLOB_DAT:
|
||||
{
|
||||
Elf64_Xword SymIndex = ELF64_R_SYM(Rel->r_info);
|
||||
Elf64_Sym *Sym = _SymTab + SymIndex;
|
||||
|
||||
if (Sym->st_name)
|
||||
{
|
||||
char *SymName = _DynStr + Sym->st_name;
|
||||
debug("SymName: %s", SymName);
|
||||
|
||||
Elf64_Sym LibSym = ELFLookupSymbol(fd, SymName);
|
||||
if (LibSym.st_value)
|
||||
{
|
||||
*GOTEntry = (Elf64_Addr)(BaseAddress + LibSym.st_value);
|
||||
debug("GOT[%ld](%#lx): %#lx (R_X86_64_GLOB_DAT)",
|
||||
i, uintptr_t(GOTEntry) - BaseAddress,
|
||||
*GOTEntry);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
fixme("Unhandled relocation type: %#lx", RelType);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (strcmp(sectionName, ".dynsym") == 0)
|
||||
{
|
||||
// .dynsym
|
||||
// STT_OBJECT
|
||||
|
||||
Elf64_Sym *SymArray = (Elf64_Sym *)(shdr.sh_addr + BaseAddress);
|
||||
Elf64_Xword numEntries = shdr.sh_size / shdr.sh_entsize;
|
||||
debug("start %#lx (off %#lx), entries %ld",
|
||||
SymArray, shdr.sh_addr, numEntries);
|
||||
for (Elf64_Xword j = 0; j < numEntries; j++)
|
||||
{
|
||||
Elf64_Sym Sym = SymArray[j];
|
||||
|
||||
if (Sym.st_shndx == SHN_UNDEF)
|
||||
continue;
|
||||
|
||||
if (Sym.st_value == 0)
|
||||
continue;
|
||||
|
||||
unsigned char SymType = ELF64_ST_TYPE(Sym.st_info);
|
||||
|
||||
if (SymType == STT_OBJECT)
|
||||
{
|
||||
Elf64_Addr *GOTEntry = (Elf64_Addr *)(Sym.st_value + BaseAddress);
|
||||
*GOTEntry = (Elf64_Addr)(BaseAddress + Sym.st_value);
|
||||
|
||||
debug("%ld: \"%s\" %#lx -> %#lx", j,
|
||||
_DynStr + Sym.st_name,
|
||||
uintptr_t(GOTEntry) - BaseAddress,
|
||||
*GOTEntry);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (strcmp(sectionName, ".symtab") == 0)
|
||||
{
|
||||
// .symtab
|
||||
// STT_OBJECT
|
||||
|
||||
Elf64_Xword numEntries = shdr.sh_size / shdr.sh_entsize;
|
||||
Elf64_Sym *SymArray = new Elf64_Sym[numEntries];
|
||||
lseek(fd, shdr.sh_offset, SEEK_SET);
|
||||
fread(fd, (uint8_t *)SymArray, shdr.sh_size);
|
||||
|
||||
debug("start %#lx (off %#lx), entries %ld",
|
||||
SymArray, shdr.sh_addr, numEntries);
|
||||
for (Elf64_Xword j = 0; j < numEntries; j++)
|
||||
{
|
||||
Elf64_Sym Sym = SymArray[j];
|
||||
|
||||
if (Sym.st_shndx == SHN_UNDEF)
|
||||
continue;
|
||||
|
||||
if (Sym.st_value == 0)
|
||||
continue;
|
||||
|
||||
unsigned char SymType = ELF64_ST_TYPE(Sym.st_info);
|
||||
|
||||
if (SymType == STT_OBJECT)
|
||||
{
|
||||
Elf64_Addr *GOTEntry = (Elf64_Addr *)(Sym.st_value + BaseAddress);
|
||||
*GOTEntry = (Elf64_Addr)(BaseAddress + Sym.st_value);
|
||||
|
||||
debug("%ld: \"<fixme>\" %#lx -> %#lx", j,
|
||||
/*_DynStr + Sym.st_name,*/
|
||||
uintptr_t(GOTEntry) - BaseAddress,
|
||||
*GOTEntry);
|
||||
}
|
||||
}
|
||||
delete[] SymArray;
|
||||
}
|
||||
|
||||
// if (shdr.sh_type == SHT_PROGBITS &&
|
||||
// (shdr.sh_flags & SHF_WRITE) &&
|
||||
// (shdr.sh_flags & SHF_ALLOC))
|
||||
}
|
||||
}
|
||||
// std::vector<Elf64_Dyn> JmpRel = ELFGetDynamicTag_x86_64(fd, DT_JMPREL);
|
||||
// std::vector<Elf64_Dyn> SymTab = ELFGetDynamicTag_x86_64(fd, DT_SYMTAB);
|
||||
// std::vector<Elf64_Dyn> StrTab = ELFGetDynamicTag_x86_64(fd, DT_STRTAB);
|
||||
// std::vector<Elf64_Dyn> RelaDyn = ELFGetDynamicTag_x86_64(fd, DT_RELA);
|
||||
// std::vector<Elf64_Dyn> RelaDynSize = ELFGetDynamicTag_x86_64(fd, DT_RELASZ);
|
||||
// size_t JmpRelSize = JmpRel.size();
|
||||
// size_t SymTabSize = SymTab.size();
|
||||
// size_t StrTabSize = StrTab.size();
|
||||
// size_t RelaDynSize_v = RelaDyn.size();
|
||||
// if (JmpRelSize < 1)
|
||||
// {
|
||||
// debug("No DT_JMPREL");
|
||||
// }
|
||||
// if (SymTabSize < 1)
|
||||
// {
|
||||
// debug("No DT_SYMTAB");
|
||||
// }
|
||||
// if (StrTabSize < 1)
|
||||
// {
|
||||
// debug("No DT_STRTAB");
|
||||
// }
|
||||
// if (RelaDynSize_v < 1)
|
||||
// {
|
||||
// debug("No DT_RELA");
|
||||
// }
|
||||
// if (RelaDynSize[0].d_un.d_val < 1)
|
||||
// {
|
||||
// debug("DT_RELASZ is < 1");
|
||||
// }
|
||||
// if (JmpRelSize > 0 && SymTabSize > 0 && StrTabSize > 0)
|
||||
// {
|
||||
// debug("JmpRel: %#lx, SymTab: %#lx, StrTab: %#lx",
|
||||
// JmpRel[0].d_un.d_ptr, SymTab[0].d_un.d_ptr,
|
||||
// StrTab[0].d_un.d_ptr);
|
||||
// Elf64_Rela *_JmpRel = (Elf64_Rela *)((uintptr_t)BaseAddress + JmpRel[0].d_un.d_ptr);
|
||||
// Elf64_Sym *_SymTab = (Elf64_Sym *)((uintptr_t)BaseAddress + SymTab[0].d_un.d_ptr);
|
||||
// char *_DynStr = (char *)((uintptr_t)BaseAddress + StrTab[0].d_un.d_ptr);
|
||||
// Elf64_Rela *_RelaDyn = (Elf64_Rela *)((uintptr_t)BaseAddress + RelaDyn[0].d_un.d_ptr);
|
||||
// Elf64_Shdr shdr;
|
||||
// for (Elf64_Half i = 0; i < ELFHeader.e_shnum; i++)
|
||||
// {
|
||||
// lseek(fd, ELFHeader.e_shoff + i * sizeof(Elf64_Shdr), SEEK_SET);
|
||||
// fread(fd, (uint8_t *)&shdr, sizeof(Elf64_Shdr));
|
||||
// char sectionName[32];
|
||||
// Elf64_Shdr n_shdr;
|
||||
// lseek(fd, ELFHeader.e_shoff + ELFHeader.e_shstrndx * sizeof(Elf64_Shdr), SEEK_SET);
|
||||
// fread(fd, (uint8_t *)&n_shdr, sizeof(Elf64_Shdr));
|
||||
// lseek(fd, n_shdr.sh_offset + shdr.sh_name, SEEK_SET);
|
||||
// fread(fd, (uint8_t *)sectionName, 32);
|
||||
// debug("shdr: %s", sectionName);
|
||||
// if (strcmp(sectionName, ".rela.plt") == 0)
|
||||
// {
|
||||
// // .rela.plt
|
||||
// // R_X86_64_JUMP_SLOT
|
||||
// Elf64_Xword numEntries = shdr.sh_size / shdr.sh_entsize;
|
||||
// for (Elf64_Xword i = 0; i < numEntries; i++)
|
||||
// {
|
||||
// Elf64_Addr *GOTEntry = (Elf64_Addr *)(shdr.sh_addr +
|
||||
// BaseAddress +
|
||||
// i * sizeof(Elf64_Addr));
|
||||
// Elf64_Rela *Rel = _JmpRel + i;
|
||||
// Elf64_Xword RelType = ELF64_R_TYPE(Rel->r_info);
|
||||
// switch (RelType)
|
||||
// {
|
||||
// case R_X86_64_JUMP_SLOT:
|
||||
// {
|
||||
// Elf64_Xword SymIndex = ELF64_R_SYM(Rel->r_info);
|
||||
// Elf64_Sym *Sym = _SymTab + SymIndex;
|
||||
// if (Sym->st_name)
|
||||
// {
|
||||
// char *SymName = _DynStr + Sym->st_name;
|
||||
// debug("SymName: %s", SymName);
|
||||
// Elf64_Sym LibSym = ELFLookupSymbol(fd, SymName);
|
||||
// if (LibSym.st_value)
|
||||
// {
|
||||
// *GOTEntry = (Elf64_Addr)(BaseAddress + LibSym.st_value);
|
||||
// debug("GOT[%ld](%#lx): %#lx",
|
||||
// i, uintptr_t(GOTEntry) - BaseAddress,
|
||||
// *GOTEntry);
|
||||
// }
|
||||
// }
|
||||
// continue;
|
||||
// }
|
||||
// default:
|
||||
// {
|
||||
// fixme("Unhandled relocation type: %#lx", RelType);
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// else if (strcmp(sectionName, ".rela.dyn") == 0)
|
||||
// {
|
||||
// // .rela.dyn
|
||||
// // R_X86_64_RELATIVE
|
||||
// // R_X86_64_GLOB_DAT
|
||||
// if (RelaDynSize_v < 1 || RelaDynSize[0].d_un.d_val < 1)
|
||||
// continue;
|
||||
// Elf64_Xword numRelaDynEntries = RelaDynSize[0].d_un.d_val / sizeof(Elf64_Rela);
|
||||
// for (Elf64_Xword i = 0; i < numRelaDynEntries; i++)
|
||||
// {
|
||||
// Elf64_Rela *Rel = _RelaDyn + i;
|
||||
// Elf64_Addr *GOTEntry = (Elf64_Addr *)(Rel->r_offset + BaseAddress);
|
||||
// Elf64_Xword RelType = ELF64_R_TYPE(Rel->r_info);
|
||||
// switch (RelType)
|
||||
// {
|
||||
// case R_X86_64_RELATIVE:
|
||||
// {
|
||||
// *GOTEntry = (Elf64_Addr)(BaseAddress + Rel->r_addend);
|
||||
// debug("GOT[%ld](%#lx): %#lx (R_X86_64_RELATIVE)",
|
||||
// i, uintptr_t(GOTEntry) - BaseAddress,
|
||||
// *GOTEntry);
|
||||
// break;
|
||||
// }
|
||||
// case R_X86_64_GLOB_DAT:
|
||||
// {
|
||||
// Elf64_Xword SymIndex = ELF64_R_SYM(Rel->r_info);
|
||||
// Elf64_Sym *Sym = _SymTab + SymIndex;
|
||||
// if (Sym->st_name)
|
||||
// {
|
||||
// char *SymName = _DynStr + Sym->st_name;
|
||||
// debug("SymName: %s", SymName);
|
||||
// Elf64_Sym LibSym = ELFLookupSymbol(fd, SymName);
|
||||
// if (LibSym.st_value)
|
||||
// {
|
||||
// *GOTEntry = (Elf64_Addr)(BaseAddress + LibSym.st_value);
|
||||
// debug("GOT[%ld](%#lx): %#lx (R_X86_64_GLOB_DAT)",
|
||||
// i, uintptr_t(GOTEntry) - BaseAddress,
|
||||
// *GOTEntry);
|
||||
// }
|
||||
// }
|
||||
// break;
|
||||
// }
|
||||
// default:
|
||||
// {
|
||||
// fixme("Unhandled relocation type: %#lx", RelType);
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// else if (strcmp(sectionName, ".dynsym") == 0)
|
||||
// {
|
||||
// // .dynsym
|
||||
// // STT_OBJECT
|
||||
// Elf64_Sym *SymArray = (Elf64_Sym *)(shdr.sh_addr + BaseAddress);
|
||||
// Elf64_Xword numEntries = shdr.sh_size / shdr.sh_entsize;
|
||||
// debug("start %#lx (off %#lx), entries %ld",
|
||||
// SymArray, shdr.sh_addr, numEntries);
|
||||
// for (Elf64_Xword j = 0; j < numEntries; j++)
|
||||
// {
|
||||
// Elf64_Sym Sym = SymArray[j];
|
||||
// if (Sym.st_shndx == SHN_UNDEF)
|
||||
// continue;
|
||||
// if (Sym.st_value == 0)
|
||||
// continue;
|
||||
// unsigned char SymType = ELF64_ST_TYPE(Sym.st_info);
|
||||
// if (SymType == STT_OBJECT)
|
||||
// {
|
||||
// Elf64_Addr *GOTEntry = (Elf64_Addr *)(Sym.st_value + BaseAddress);
|
||||
// *GOTEntry = (Elf64_Addr)(BaseAddress + Sym.st_value);
|
||||
// debug("%ld: \"%s\" %#lx -> %#lx", j,
|
||||
// _DynStr + Sym.st_name,
|
||||
// uintptr_t(GOTEntry) - BaseAddress,
|
||||
// *GOTEntry);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// else if (strcmp(sectionName, ".symtab") == 0)
|
||||
// {
|
||||
// // .symtab
|
||||
// // STT_OBJECT
|
||||
// Elf64_Xword numEntries = shdr.sh_size / shdr.sh_entsize;
|
||||
// Elf64_Sym *SymArray = new Elf64_Sym[numEntries];
|
||||
// lseek(fd, shdr.sh_offset, SEEK_SET);
|
||||
// fread(fd, (uint8_t *)SymArray, shdr.sh_size);
|
||||
// debug("start %#lx (off %#lx), entries %ld",
|
||||
// SymArray, shdr.sh_addr, numEntries);
|
||||
// for (Elf64_Xword j = 0; j < numEntries; j++)
|
||||
// {
|
||||
// Elf64_Sym Sym = SymArray[j];
|
||||
// if (Sym.st_shndx == SHN_UNDEF)
|
||||
// continue;
|
||||
// if (Sym.st_value == 0)
|
||||
// continue;
|
||||
// unsigned char SymType = ELF64_ST_TYPE(Sym.st_info);
|
||||
// if (SymType == STT_OBJECT)
|
||||
// {
|
||||
// Elf64_Addr *GOTEntry = (Elf64_Addr *)(Sym.st_value + BaseAddress);
|
||||
// *GOTEntry = (Elf64_Addr)(BaseAddress + Sym.st_value);
|
||||
// debug("%ld: \"<fixme>\" %#lx -> %#lx", j,
|
||||
// /*_DynStr + Sym.st_name,*/
|
||||
// uintptr_t(GOTEntry) - BaseAddress,
|
||||
// *GOTEntry);
|
||||
// }
|
||||
// }
|
||||
// delete[] SymArray;
|
||||
// }
|
||||
// // if (shdr.sh_type == SHT_PROGBITS &&
|
||||
// // (shdr.sh_flags & SHF_WRITE) &&
|
||||
// // (shdr.sh_flags & SHF_ALLOC))
|
||||
// }
|
||||
// }
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
@ -661,6 +747,11 @@ namespace Execute
|
||||
fread(fd, sh, statbuf.st_size);
|
||||
TargetProcess->ELFSymbolTable->AppendSymbols(uintptr_t(sh.Get()), BaseAddress);
|
||||
|
||||
if (!TargetProcess->ELFSymbolTable->SymTableExists)
|
||||
{
|
||||
debug("NO SYMBOL TABLE FOUND?");
|
||||
}
|
||||
|
||||
debug("Entry Point: %#lx", EntryPoint);
|
||||
|
||||
this->GenerateAuxiliaryVector_x86_64(vma, fd, ELFHeader,
|
||||
@ -759,6 +850,7 @@ namespace Execute
|
||||
error("Failed to open %s, errno: %d", AbsolutePath, fd);
|
||||
return;
|
||||
}
|
||||
debug("Opened %s", AbsolutePath);
|
||||
|
||||
int argc = 0;
|
||||
int envc = 0;
|
||||
@ -769,23 +861,23 @@ namespace Execute
|
||||
envc++;
|
||||
|
||||
// ELFargv = new const char *[argc + 2];
|
||||
size_t argv_size = TO_PAGES(argc + 2 * sizeof(char *));
|
||||
ELFargv = (const char **)TargetProcess->vma->RequestPages(argv_size);
|
||||
size_t argv_size = argc + 2 * sizeof(char *);
|
||||
ELFargv = (const char **)TargetProcess->vma->RequestPages(TO_PAGES(argv_size));
|
||||
for (int i = 0; i < argc; i++)
|
||||
{
|
||||
size_t arg_size = TO_PAGES(strlen(argv[i]) + 1);
|
||||
ELFargv[i] = (const char *)TargetProcess->vma->RequestPages(arg_size);
|
||||
size_t arg_size = strlen(argv[i]) + 1;
|
||||
ELFargv[i] = (const char *)TargetProcess->vma->RequestPages(TO_PAGES(arg_size));
|
||||
strcpy((char *)ELFargv[i], argv[i]);
|
||||
}
|
||||
ELFargv[argc] = nullptr;
|
||||
|
||||
// ELFenvp = new const char *[envc + 1];
|
||||
size_t envp_size = TO_PAGES(envc + 1 * sizeof(char *));
|
||||
ELFenvp = (const char **)TargetProcess->vma->RequestPages(envp_size);
|
||||
size_t envp_size = envc + 1 * sizeof(char *);
|
||||
ELFenvp = (const char **)TargetProcess->vma->RequestPages(TO_PAGES(envp_size));
|
||||
for (int i = 0; i < envc; i++)
|
||||
{
|
||||
size_t env_size = TO_PAGES(strlen(envp[i]) + 1);
|
||||
ELFenvp[i] = (const char *)TargetProcess->vma->RequestPages(env_size);
|
||||
size_t env_size = strlen(envp[i]) + 1;
|
||||
ELFenvp[i] = (const char *)TargetProcess->vma->RequestPages(TO_PAGES(env_size));
|
||||
strcpy((char *)ELFenvp[i], envp[i]);
|
||||
}
|
||||
ELFenvp[envc] = nullptr;
|
||||
|
@ -20,7 +20,6 @@
|
||||
#include <msexec.h>
|
||||
|
||||
#include "../../kernel.h"
|
||||
#include "../../Fex.hpp"
|
||||
|
||||
namespace Execute
|
||||
{
|
||||
|
@ -20,83 +20,82 @@
|
||||
#include <msexec.h>
|
||||
|
||||
#include "../../kernel.h"
|
||||
#include "../../Fex.hpp"
|
||||
|
||||
namespace Execute
|
||||
{
|
||||
/* Originally from https://wiki.osdev.org/ELF_Tutorial */
|
||||
/* Originally from https://wiki.osdev.org/ELF_Tutorial */
|
||||
|
||||
void ELFLoadRel(void *BaseImage,
|
||||
const char *Name,
|
||||
Tasking::PCB *Process)
|
||||
{
|
||||
void ELFLoadRel(void *BaseImage,
|
||||
const char *Name,
|
||||
Tasking::PCB *Process)
|
||||
{
|
||||
#if defined(a64)
|
||||
UNUSED(Name);
|
||||
debug("Relocatable");
|
||||
/* TODO: I have to fully implement this, but for now I will leave it as it is now. */
|
||||
warn("Relocatable ELF is not fully supported yet");
|
||||
Elf64_Shdr *shdr = GetELFSheader(((Elf64_Ehdr *)BaseImage));
|
||||
for (Elf64_Half i = 0; i < ((Elf64_Ehdr *)BaseImage)->e_shnum; i++)
|
||||
{
|
||||
Elf64_Shdr *Section = &shdr[i];
|
||||
if (Section->sh_type == SHT_NOBITS)
|
||||
{
|
||||
if (!Section->sh_size)
|
||||
continue;
|
||||
if (Section->sh_flags & SHF_ALLOC)
|
||||
{
|
||||
void *Buffer = KernelAllocator.RequestPages(TO_PAGES(Section->sh_size + 1));
|
||||
memset(Buffer, 0, Section->sh_size);
|
||||
UNUSED(Name);
|
||||
debug("Relocatable");
|
||||
/* TODO: I have to fully implement this, but for now I will leave it as it is now. */
|
||||
warn("Relocatable ELF is not fully supported yet");
|
||||
Elf64_Shdr *shdr = GetELFSheader(((Elf64_Ehdr *)BaseImage));
|
||||
for (Elf64_Half i = 0; i < ((Elf64_Ehdr *)BaseImage)->e_shnum; i++)
|
||||
{
|
||||
Elf64_Shdr *Section = &shdr[i];
|
||||
if (Section->sh_type == SHT_NOBITS)
|
||||
{
|
||||
if (!Section->sh_size)
|
||||
continue;
|
||||
if (Section->sh_flags & SHF_ALLOC)
|
||||
{
|
||||
void *Buffer = KernelAllocator.RequestPages(TO_PAGES(Section->sh_size + 1));
|
||||
memset(Buffer, 0, Section->sh_size);
|
||||
|
||||
Memory::Virtual(Process->PageTable).Map((void *)Buffer, (void *)Buffer, Section->sh_size, Memory::PTFlag::RW | Memory::PTFlag::US);
|
||||
Memory::Virtual(Process->PageTable).Map((void *)Buffer, (void *)Buffer, Section->sh_size, Memory::PTFlag::RW | Memory::PTFlag::US);
|
||||
|
||||
Section->sh_offset = (uintptr_t)Buffer - (uintptr_t)BaseImage;
|
||||
debug("Section %ld", Section->sh_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
Section->sh_offset = (uintptr_t)Buffer - (uintptr_t)BaseImage;
|
||||
debug("Section %ld", Section->sh_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (Elf64_Half i = 0; i < ((Elf64_Ehdr *)BaseImage)->e_shnum; i++)
|
||||
{
|
||||
Elf64_Shdr *Section = &shdr[i];
|
||||
if (Section->sh_type == SHT_REL)
|
||||
{
|
||||
for (size_t Index = 0; Index < Section->sh_size / Section->sh_entsize; Index++)
|
||||
{
|
||||
Elf64_Rel *RelTable = &((Elf64_Rel *)((uintptr_t)BaseImage + Section->sh_offset))[Index];
|
||||
Elf64_Shdr *Target = GetELFSection(((Elf64_Ehdr *)BaseImage), Section->sh_info);
|
||||
for (Elf64_Half i = 0; i < ((Elf64_Ehdr *)BaseImage)->e_shnum; i++)
|
||||
{
|
||||
Elf64_Shdr *Section = &shdr[i];
|
||||
if (Section->sh_type == SHT_REL)
|
||||
{
|
||||
for (size_t Index = 0; Index < Section->sh_size / Section->sh_entsize; Index++)
|
||||
{
|
||||
Elf64_Rel *RelTable = &((Elf64_Rel *)((uintptr_t)BaseImage + Section->sh_offset))[Index];
|
||||
Elf64_Shdr *Target = GetELFSection(((Elf64_Ehdr *)BaseImage), Section->sh_info);
|
||||
|
||||
uintptr_t *RelAddress = (uintptr_t *)(((uintptr_t)BaseImage + Target->sh_offset) + RelTable->r_offset);
|
||||
uint64_t SymbolValue = 0;
|
||||
uintptr_t *RelAddress = (uintptr_t *)(((uintptr_t)BaseImage + Target->sh_offset) + RelTable->r_offset);
|
||||
uint64_t SymbolValue = 0;
|
||||
|
||||
if (ELF64_R_SYM(RelTable->r_info) != SHN_UNDEF)
|
||||
{
|
||||
SymbolValue = ELFGetSymbolValue(((Elf64_Ehdr *)BaseImage), Section->sh_link, ELF64_R_SYM(RelTable->r_info));
|
||||
if (SymbolValue == 0xdead)
|
||||
return;
|
||||
}
|
||||
if (ELF64_R_SYM(RelTable->r_info) != SHN_UNDEF)
|
||||
{
|
||||
SymbolValue = ELFGetSymbolValue(((Elf64_Ehdr *)BaseImage), Section->sh_link, ELF64_R_SYM(RelTable->r_info));
|
||||
if (SymbolValue == 0xdead)
|
||||
return;
|
||||
}
|
||||
|
||||
switch (ELF64_R_TYPE(RelTable->r_info))
|
||||
{
|
||||
case R_386_NONE:
|
||||
break;
|
||||
case R_386_32:
|
||||
*RelAddress = DO_64_64(SymbolValue, *RelAddress);
|
||||
break;
|
||||
case R_386_PC32:
|
||||
*RelAddress = DO_64_PC32(SymbolValue, *RelAddress, (uintptr_t)RelAddress);
|
||||
break;
|
||||
default:
|
||||
{
|
||||
error("Unsupported relocation type: %d", ELF64_R_TYPE(RelTable->r_info));
|
||||
return;
|
||||
}
|
||||
}
|
||||
debug("Symbol value: %#lx", SymbolValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
switch (ELF64_R_TYPE(RelTable->r_info))
|
||||
{
|
||||
case R_386_NONE:
|
||||
break;
|
||||
case R_386_32:
|
||||
*RelAddress = DO_64_64(SymbolValue, *RelAddress);
|
||||
break;
|
||||
case R_386_PC32:
|
||||
*RelAddress = DO_64_PC32(SymbolValue, *RelAddress, (uintptr_t)RelAddress);
|
||||
break;
|
||||
default:
|
||||
{
|
||||
error("Unsupported relocation type: %d", ELF64_R_TYPE(RelTable->r_info));
|
||||
return;
|
||||
}
|
||||
}
|
||||
debug("Symbol value: %#lx", SymbolValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
#elif defined(a32)
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
100
exec/spawn.cpp
100
exec/spawn.cpp
@ -25,14 +25,13 @@
|
||||
#include <abi.h>
|
||||
|
||||
#include "../kernel.h"
|
||||
#include "../Fex.hpp"
|
||||
|
||||
using namespace Tasking;
|
||||
|
||||
namespace Execute
|
||||
{
|
||||
int Spawn(char *Path, const char **argv, const char **envp,
|
||||
Tasking::PCB *Parent,
|
||||
Tasking::PCB *Parent, bool Fork,
|
||||
Tasking::TaskCompatibility Compatibility,
|
||||
bool Critical)
|
||||
{
|
||||
@ -50,19 +49,6 @@ namespace Execute
|
||||
|
||||
switch (GetBinaryType(Path))
|
||||
{
|
||||
case BinaryType::BinTypeFex:
|
||||
{
|
||||
Fex FexHdr;
|
||||
fread(fd, (uint8_t *)&FexHdr, sizeof(Fex));
|
||||
if (FexHdr.Type == FexFormatType::FexFormatType_Executable)
|
||||
{
|
||||
stub;
|
||||
assert(false);
|
||||
}
|
||||
|
||||
fclose(fd);
|
||||
return -ENOEXEC;
|
||||
}
|
||||
case BinaryType::BinTypeELF:
|
||||
{
|
||||
TaskArchitecture Arch = TaskArchitecture::UnknownArchitecture;
|
||||
@ -118,20 +104,44 @@ namespace Execute
|
||||
debug("Loaded elf %s at %#lx with the length of %ld",
|
||||
Path, ElfFile, statbuf.st_size);
|
||||
|
||||
if (Parent == nullptr)
|
||||
Parent = thisProcess;
|
||||
PCB *Process;
|
||||
if (Fork)
|
||||
{
|
||||
assert(Parent != nullptr);
|
||||
CriticalSection cs;
|
||||
|
||||
PCB *Process = TaskManager->CreateProcess(Parent,
|
||||
BaseName,
|
||||
TaskExecutionMode::User,
|
||||
ElfFile, false,
|
||||
0, 0);
|
||||
Process = Parent;
|
||||
foreach (auto tcb in Process->Threads)
|
||||
{
|
||||
debug("Deleting thread %d", tcb->ID);
|
||||
// delete tcb;
|
||||
tcb->SetState(Tasking::Terminated);
|
||||
}
|
||||
|
||||
KernelAllocator.FreePages(ElfFile, TO_PAGES(statbuf.st_size + 1));
|
||||
fixme("free allocated memory");
|
||||
fixme("change symbol table");
|
||||
// Process->vma->FreeAllPages();
|
||||
delete Process->ELFSymbolTable;
|
||||
Process->ELFSymbolTable = new SymbolResolver::Symbols((uintptr_t)ElfFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Parent == nullptr)
|
||||
Parent = thisProcess;
|
||||
|
||||
Process = TaskManager->CreateProcess(Parent,
|
||||
BaseName,
|
||||
TaskExecutionMode::User,
|
||||
ElfFile, false,
|
||||
0, 0);
|
||||
Process->Info.Compatibility = Compatibility;
|
||||
Process->Info.Architecture = Arch;
|
||||
}
|
||||
|
||||
Process->SetWorkingDirectory(fs->GetNodeFromPath(Path)->Parent);
|
||||
Process->Info.Compatibility = TaskCompatibility::Native;
|
||||
Process->Info.Architecture = TaskArchitecture::x64;
|
||||
Process->SetExe(Path);
|
||||
|
||||
KernelAllocator.FreePages(ElfFile, TO_PAGES(statbuf.st_size + 1));
|
||||
|
||||
ELFObject *obj = new ELFObject(Path, Process, argv, envp);
|
||||
if (!obj->IsValid)
|
||||
@ -142,14 +152,40 @@ namespace Execute
|
||||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
/* FIXME: implement stdio fildes */
|
||||
vfs::FileDescriptorTable *pfdt = Parent->FileDescriptors;
|
||||
vfs::FileDescriptorTable *fdt = Process->FileDescriptors;
|
||||
// stdin
|
||||
fdt->_open("/dev/tty", O_RDWR, 0666);
|
||||
// stdout
|
||||
fdt->_open("/dev/tty", O_RDWR, 0666);
|
||||
// stderr
|
||||
fdt->_open("/dev/tty", O_RDWR, 0666);
|
||||
|
||||
auto ForkStdio = [pfdt, fdt](Node *SearchNode)
|
||||
{
|
||||
if (unlikely(SearchNode == nullptr))
|
||||
return false;
|
||||
|
||||
std::vector<FileDescriptorTable::Fildes>
|
||||
pfds = pfdt->GetFileDescriptors();
|
||||
|
||||
foreach (auto ffd in pfds)
|
||||
{
|
||||
if (ffd.Flags & O_CLOEXEC)
|
||||
continue;
|
||||
|
||||
if (ffd.Handle->node == SearchNode)
|
||||
{
|
||||
fdt->_open(ffd.Handle->node->FullPath,
|
||||
ffd.Flags, ffd.Mode);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
if (!ForkStdio(Parent->stdin))
|
||||
fdt->_open("/dev/kcon", O_RDWR, 0666);
|
||||
|
||||
if (!ForkStdio(Parent->stdout))
|
||||
fdt->_open("/dev/kcon", O_RDWR, 0666);
|
||||
|
||||
if (!ForkStdio(Parent->stderr))
|
||||
fdt->_open("/dev/kcon", O_RDWR, 0666);
|
||||
|
||||
TCB *Thread = nullptr;
|
||||
{
|
||||
|
568
include/acpi.hpp
568
include/acpi.hpp
@ -20,6 +20,7 @@
|
||||
|
||||
#include <types.h>
|
||||
|
||||
#include <unordered_map>
|
||||
#include <boot/binfo.h>
|
||||
#include <ints.hpp>
|
||||
#include <cpu.hpp>
|
||||
@ -27,272 +28,359 @@
|
||||
|
||||
namespace ACPI
|
||||
{
|
||||
class ACPI
|
||||
{
|
||||
public:
|
||||
struct ACPIHeader
|
||||
{
|
||||
unsigned char Signature[4];
|
||||
uint32_t Length;
|
||||
uint8_t Revision;
|
||||
uint8_t Checksum;
|
||||
uint8_t OEMID[6];
|
||||
uint8_t OEMTableID[8];
|
||||
uint32_t OEMRevision;
|
||||
uint32_t CreatorID;
|
||||
uint32_t CreatorRevision;
|
||||
} __packed;
|
||||
class ACPI
|
||||
{
|
||||
public:
|
||||
struct ACPIHeader
|
||||
{
|
||||
unsigned char Signature[4];
|
||||
uint32_t Length;
|
||||
uint8_t Revision;
|
||||
uint8_t Checksum;
|
||||
uint8_t OEMID[6];
|
||||
uint8_t OEMTableID[8];
|
||||
uint32_t OEMRevision;
|
||||
uint32_t CreatorID;
|
||||
uint32_t CreatorRevision;
|
||||
} __packed;
|
||||
|
||||
struct GenericAddressStructure
|
||||
{
|
||||
uint8_t AddressSpace;
|
||||
uint8_t BitWidth;
|
||||
uint8_t BitOffset;
|
||||
uint8_t AccessSize;
|
||||
uint64_t Address;
|
||||
} __packed;
|
||||
struct GenericAddressStructure
|
||||
{
|
||||
uint8_t AddressSpace;
|
||||
uint8_t BitWidth;
|
||||
uint8_t BitOffset;
|
||||
uint8_t AccessSize;
|
||||
uint64_t Address;
|
||||
} __packed;
|
||||
|
||||
struct MCFGHeader
|
||||
{
|
||||
struct ACPIHeader Header;
|
||||
uint64_t Reserved;
|
||||
} __packed;
|
||||
enum DBG2PortType
|
||||
{
|
||||
TYPE_SERIAL = 0x8000,
|
||||
TYPE_1394 = 0x8001,
|
||||
TYPE_USB = 0x8002,
|
||||
TYPE_NET = 0x8003
|
||||
};
|
||||
|
||||
struct HPETHeader
|
||||
{
|
||||
ACPIHeader Header;
|
||||
uint8_t HardwareRevID;
|
||||
uint8_t ComparatorCount : 5;
|
||||
uint8_t CounterSize : 1;
|
||||
uint8_t Reserved : 1;
|
||||
uint8_t LegacyReplacement : 1;
|
||||
uint16_t PCIVendorID;
|
||||
struct GenericAddressStructure Address;
|
||||
uint8_t HPETNumber;
|
||||
uint16_t MinimumTick;
|
||||
uint8_t PageProtection;
|
||||
} __packed;
|
||||
enum DBG2PortSubtype
|
||||
{
|
||||
SUBTYPE_SERIAL_16550_COMPATIBLE = 0x0000,
|
||||
SUBTYPE_SERIAL_16550_SUBSET = 0x0001,
|
||||
SUBTYPE_SERIAL_MAX311xE_SPI_UART = 0x0002,
|
||||
SUBTYPE_SERIAL_Arm_PL011_UART = 0x0003,
|
||||
SUBTYPE_SERIAL_MSM8x60 = 0x0004,
|
||||
SUBTYPE_SERIAL_Nvidia_16550 = 0x0005,
|
||||
SUBTYPE_SERIAL_TI_OMAP = 0x0006,
|
||||
SUBTYPE_SERIAL_APM88xxxx = 0x0008,
|
||||
SUBTYPE_SERIAL_MSM8974 = 0x0009,
|
||||
SUBTYPE_SERIAL_SAM5250 = 0x000A,
|
||||
SUBTYPE_SERIAL_Intel_USIF = 0x000B,
|
||||
SUBTYPE_SERIAL_iMX6 = 0x000C,
|
||||
SUBTYPE_SERIAL_Arm_SBSA_UART = 0x000D,
|
||||
SUBTYPE_SERIAL_Arm_SBSA_Generic_UART = 0x000E,
|
||||
SUBTYPE_SERIAL_Arm_DCC = 0x000F,
|
||||
SUBTYPE_SERIAL_BCM2835 = 0x0010,
|
||||
SUBTYPE_SERIAL_SDM845_At_1_8432MHz = 0x0011,
|
||||
SUBTYPE_SERIAL_16550_With_Generic_Address_Structure = 0x0012,
|
||||
SUBTYPE_SERIAL_SDM845_At_7_372MHz = 0x0013,
|
||||
SUBTYPE_SERIAL_Intel_LPSS = 0x0014,
|
||||
SUBTYPE_SERIAL_RISC_V_SBI_Console = 0x0015,
|
||||
|
||||
struct FADTHeader
|
||||
{
|
||||
ACPIHeader Header;
|
||||
uint32_t FirmwareCtrl;
|
||||
uint32_t Dsdt;
|
||||
uint8_t Reserved;
|
||||
uint8_t PreferredPowerManagementProfile;
|
||||
uint16_t SCI_Interrupt;
|
||||
uint32_t SMI_CommandPort;
|
||||
uint8_t AcpiEnable;
|
||||
uint8_t AcpiDisable;
|
||||
uint8_t S4BIOS_REQ;
|
||||
uint8_t PSTATE_Control;
|
||||
uint32_t PM1aEventBlock;
|
||||
uint32_t PM1bEventBlock;
|
||||
uint32_t PM1aControlBlock;
|
||||
uint32_t PM1bControlBlock;
|
||||
uint32_t PM2ControlBlock;
|
||||
uint32_t PMTimerBlock;
|
||||
uint32_t GPE0Block;
|
||||
uint32_t GPE1Block;
|
||||
uint8_t PM1EventLength;
|
||||
uint8_t PM1ControlLength;
|
||||
uint8_t PM2ControlLength;
|
||||
uint8_t PMTimerLength;
|
||||
uint8_t GPE0Length;
|
||||
uint8_t GPE1Length;
|
||||
uint8_t GPE1Base;
|
||||
uint8_t CStateControl;
|
||||
uint16_t WorstC2Latency;
|
||||
uint16_t WorstC3Latency;
|
||||
uint16_t FlushSize;
|
||||
uint16_t FlushStride;
|
||||
uint8_t DutyOffset;
|
||||
uint8_t DutyWidth;
|
||||
uint8_t DayAlarm;
|
||||
uint8_t MonthAlarm;
|
||||
uint8_t Century;
|
||||
uint16_t BootArchitectureFlags;
|
||||
uint8_t Reserved2;
|
||||
uint32_t Flags;
|
||||
struct GenericAddressStructure ResetReg;
|
||||
uint8_t ResetValue;
|
||||
uint8_t Reserved3[3];
|
||||
uint64_t X_FirmwareControl;
|
||||
uint64_t X_Dsdt;
|
||||
struct GenericAddressStructure X_PM1aEventBlock;
|
||||
struct GenericAddressStructure X_PM1bEventBlock;
|
||||
struct GenericAddressStructure X_PM1aControlBlock;
|
||||
struct GenericAddressStructure X_PM1bControlBlock;
|
||||
struct GenericAddressStructure X_PM2ControlBlock;
|
||||
struct GenericAddressStructure X_PMTimerBlock;
|
||||
struct GenericAddressStructure X_GPE0Block;
|
||||
struct GenericAddressStructure X_GPE1Block;
|
||||
} __packed;
|
||||
SUBTYPE_1394_IEEE1394_HCI = 0x0000,
|
||||
|
||||
SUBTYPE_USB_XHCI = 0x0000,
|
||||
SUBTYPE_USB_EHCI = 0x0001,
|
||||
|
||||
struct BGRTHeader
|
||||
{
|
||||
ACPIHeader Header;
|
||||
uint16_t Version;
|
||||
uint8_t Status;
|
||||
uint8_t ImageType;
|
||||
uint64_t ImageAddress;
|
||||
uint32_t ImageOffsetX;
|
||||
uint32_t ImageOffsetY;
|
||||
};
|
||||
SUBTYPE_NET_NNNN = 0x0000,
|
||||
};
|
||||
|
||||
struct SRATHeader
|
||||
{
|
||||
ACPIHeader Header;
|
||||
uint32_t TableRevision; // Must be value 1
|
||||
uint64_t Reserved; // Reserved, must be zero
|
||||
};
|
||||
struct DBG2Device
|
||||
{
|
||||
uint8_t Revision;
|
||||
uint16_t Length;
|
||||
uint8_t NumberofGenericAddressRegisters;
|
||||
uint16_t NamespaceStringLength;
|
||||
uint16_t NamespaceStringOffset;
|
||||
uint16_t OemDataLength;
|
||||
uint16_t OemDataOffset;
|
||||
uint16_t PortType;
|
||||
uint16_t PortSubtype;
|
||||
uint16_t Reserved;
|
||||
uint16_t BaseAddressRegisterOffset;
|
||||
uint16_t AddressSizeOffset;
|
||||
/* BaseAddressRegister[NumberofGenericAddressRegisters * 12] at offset BaseAddressRegisterOffset */
|
||||
/* AddressSize[NumberofGenericAddressRegisters * 4] at offset AddressSizeOffset */
|
||||
/* NamespaceString[NamespaceStringLength] at offset NamespaceStringOffset */
|
||||
/* OemData[OemDataLength] at offset OemDataOffset */
|
||||
} __packed;
|
||||
|
||||
struct TPM2Header
|
||||
{
|
||||
ACPIHeader Header;
|
||||
uint32_t Flags;
|
||||
uint64_t ControlAddress;
|
||||
uint32_t StartMethod;
|
||||
};
|
||||
struct MCFGHeader
|
||||
{
|
||||
struct ACPIHeader Header;
|
||||
uint64_t Reserved;
|
||||
} __packed;
|
||||
|
||||
struct TCPAHeader
|
||||
{
|
||||
ACPIHeader Header;
|
||||
uint16_t Reserved;
|
||||
uint32_t MaxLogLength;
|
||||
uint64_t LogAddress;
|
||||
};
|
||||
struct HPETHeader
|
||||
{
|
||||
ACPIHeader Header;
|
||||
uint8_t HardwareRevID;
|
||||
uint8_t ComparatorCount : 5;
|
||||
uint8_t CounterSize : 1;
|
||||
uint8_t Reserved : 1;
|
||||
uint8_t LegacyReplacement : 1;
|
||||
uint16_t PCIVendorID;
|
||||
struct GenericAddressStructure Address;
|
||||
uint8_t HPETNumber;
|
||||
uint16_t MinimumTick;
|
||||
uint8_t PageProtection;
|
||||
} __packed;
|
||||
|
||||
struct WAETHeader
|
||||
{
|
||||
ACPIHeader Header;
|
||||
uint32_t Flags;
|
||||
};
|
||||
struct FADTHeader
|
||||
{
|
||||
ACPIHeader Header;
|
||||
uint32_t FirmwareCtrl;
|
||||
uint32_t Dsdt;
|
||||
uint8_t Reserved;
|
||||
uint8_t PreferredPowerManagementProfile;
|
||||
uint16_t SCI_Interrupt;
|
||||
uint32_t SMI_CommandPort;
|
||||
uint8_t AcpiEnable;
|
||||
uint8_t AcpiDisable;
|
||||
uint8_t S4BIOS_REQ;
|
||||
uint8_t PSTATE_Control;
|
||||
uint32_t PM1aEventBlock;
|
||||
uint32_t PM1bEventBlock;
|
||||
uint32_t PM1aControlBlock;
|
||||
uint32_t PM1bControlBlock;
|
||||
uint32_t PM2ControlBlock;
|
||||
uint32_t PMTimerBlock;
|
||||
uint32_t GPE0Block;
|
||||
uint32_t GPE1Block;
|
||||
uint8_t PM1EventLength;
|
||||
uint8_t PM1ControlLength;
|
||||
uint8_t PM2ControlLength;
|
||||
uint8_t PMTimerLength;
|
||||
uint8_t GPE0Length;
|
||||
uint8_t GPE1Length;
|
||||
uint8_t GPE1Base;
|
||||
uint8_t CStateControl;
|
||||
uint16_t WorstC2Latency;
|
||||
uint16_t WorstC3Latency;
|
||||
uint16_t FlushSize;
|
||||
uint16_t FlushStride;
|
||||
uint8_t DutyOffset;
|
||||
uint8_t DutyWidth;
|
||||
uint8_t DayAlarm;
|
||||
uint8_t MonthAlarm;
|
||||
uint8_t Century;
|
||||
uint16_t BootArchitectureFlags;
|
||||
uint8_t Reserved2;
|
||||
uint32_t Flags;
|
||||
struct GenericAddressStructure ResetReg;
|
||||
uint8_t ResetValue;
|
||||
uint8_t Reserved3[3];
|
||||
uint64_t X_FirmwareControl;
|
||||
uint64_t X_Dsdt;
|
||||
struct GenericAddressStructure X_PM1aEventBlock;
|
||||
struct GenericAddressStructure X_PM1bEventBlock;
|
||||
struct GenericAddressStructure X_PM1aControlBlock;
|
||||
struct GenericAddressStructure X_PM1bControlBlock;
|
||||
struct GenericAddressStructure X_PM2ControlBlock;
|
||||
struct GenericAddressStructure X_PMTimerBlock;
|
||||
struct GenericAddressStructure X_GPE0Block;
|
||||
struct GenericAddressStructure X_GPE1Block;
|
||||
} __packed;
|
||||
|
||||
struct HESTHeader
|
||||
{
|
||||
ACPIHeader Header;
|
||||
uint32_t ErrorSourceCount;
|
||||
};
|
||||
struct BGRTHeader
|
||||
{
|
||||
ACPIHeader Header;
|
||||
uint16_t Version;
|
||||
uint8_t Status;
|
||||
uint8_t ImageType;
|
||||
uint64_t ImageAddress;
|
||||
uint32_t ImageOffsetX;
|
||||
uint32_t ImageOffsetY;
|
||||
} __packed;
|
||||
|
||||
struct MADTHeader
|
||||
{
|
||||
ACPIHeader Header;
|
||||
uint32_t LocalControllerAddress;
|
||||
uint32_t Flags;
|
||||
char Entries[];
|
||||
} __packed;
|
||||
struct SRATHeader
|
||||
{
|
||||
ACPIHeader Header;
|
||||
uint32_t TableRevision; // Must be value 1
|
||||
uint64_t Reserved; // Reserved, must be zero
|
||||
} __packed;
|
||||
|
||||
ACPIHeader *XSDT = nullptr;
|
||||
MCFGHeader *MCFG = nullptr;
|
||||
HPETHeader *HPET = nullptr;
|
||||
FADTHeader *FADT = nullptr;
|
||||
BGRTHeader *BGRT = nullptr;
|
||||
SRATHeader *SRAT = nullptr;
|
||||
TPM2Header *TPM2 = nullptr;
|
||||
TCPAHeader *TCPA = nullptr;
|
||||
WAETHeader *WAET = nullptr;
|
||||
MADTHeader *MADT = nullptr;
|
||||
HESTHeader *HEST = nullptr;
|
||||
bool XSDTSupported = false;
|
||||
struct TPM2Header
|
||||
{
|
||||
ACPIHeader Header;
|
||||
uint32_t Flags;
|
||||
uint64_t ControlAddress;
|
||||
uint32_t StartMethod;
|
||||
} __packed;
|
||||
|
||||
void *FindTable(ACPIHeader *ACPIHeader, char *Signature);
|
||||
void SearchTables(ACPIHeader *Header);
|
||||
ACPI();
|
||||
~ACPI();
|
||||
};
|
||||
struct TCPAHeader
|
||||
{
|
||||
ACPIHeader Header;
|
||||
uint16_t Reserved;
|
||||
uint32_t MaxLogLength;
|
||||
uint64_t LogAddress;
|
||||
} __packed;
|
||||
|
||||
class MADT
|
||||
{
|
||||
public:
|
||||
struct APICHeader
|
||||
{
|
||||
uint8_t Type;
|
||||
uint8_t Length;
|
||||
} __packed;
|
||||
struct WAETHeader
|
||||
{
|
||||
ACPIHeader Header;
|
||||
uint32_t Flags;
|
||||
} __packed;
|
||||
|
||||
struct MADTIOApic
|
||||
{
|
||||
struct APICHeader Header;
|
||||
uint8_t APICID;
|
||||
uint8_t reserved;
|
||||
uint32_t Address;
|
||||
uint32_t GSIBase;
|
||||
} __packed;
|
||||
struct HESTHeader
|
||||
{
|
||||
ACPIHeader Header;
|
||||
uint32_t ErrorSourceCount;
|
||||
} __packed;
|
||||
|
||||
struct MADTIso
|
||||
{
|
||||
struct APICHeader Header;
|
||||
uint8_t BuSSource;
|
||||
uint8_t IRQSource;
|
||||
uint32_t GSI;
|
||||
uint16_t Flags;
|
||||
} __packed;
|
||||
struct MADTHeader
|
||||
{
|
||||
ACPIHeader Header;
|
||||
uint32_t LocalControllerAddress;
|
||||
uint32_t Flags;
|
||||
char Entries[];
|
||||
} __packed;
|
||||
|
||||
struct MADTNmi
|
||||
{
|
||||
struct APICHeader Header;
|
||||
uint8_t processor;
|
||||
uint16_t flags;
|
||||
uint8_t lint;
|
||||
} __packed;
|
||||
struct SSDTHeader
|
||||
{
|
||||
ACPIHeader Header;
|
||||
char DefinitionBlock[];
|
||||
} __packed;
|
||||
|
||||
struct LocalAPIC
|
||||
{
|
||||
struct APICHeader Header;
|
||||
uint8_t ACPIProcessorId;
|
||||
uint8_t APICId;
|
||||
uint32_t Flags;
|
||||
} __packed;
|
||||
struct DBGPHeader
|
||||
{
|
||||
ACPIHeader Header;
|
||||
/**
|
||||
* 0 - 16550 compatible
|
||||
* 1 - Subset of 16550
|
||||
*/
|
||||
uint8_t InterfaceType;
|
||||
uint8_t Reserved[3];
|
||||
GenericAddressStructure BaseAddress;
|
||||
} __packed;
|
||||
|
||||
struct LAPIC
|
||||
{
|
||||
uint8_t id;
|
||||
uintptr_t PhysicalAddress;
|
||||
void *VirtualAddress;
|
||||
};
|
||||
struct DBG2Header
|
||||
{
|
||||
ACPIHeader Header;
|
||||
uint32_t OffsetDbgDeviceInfo;
|
||||
uint32_t NumberDbgDeviceInfo;
|
||||
/* DBG2Device[NumberDbgDeviceInfo] at offset OffsetDbgDeviceInfo */
|
||||
} __packed;
|
||||
|
||||
std::vector<MADTIOApic *> ioapic;
|
||||
std::vector<MADTIso *> iso;
|
||||
std::vector<MADTNmi *> nmi;
|
||||
std::vector<LocalAPIC *> lapic;
|
||||
struct LAPIC *LAPICAddress;
|
||||
uint16_t CPUCores;
|
||||
ACPIHeader *XSDT = nullptr;
|
||||
MCFGHeader *MCFG = nullptr;
|
||||
HPETHeader *HPET = nullptr;
|
||||
FADTHeader *FADT = nullptr;
|
||||
BGRTHeader *BGRT = nullptr;
|
||||
SRATHeader *SRAT = nullptr;
|
||||
TPM2Header *TPM2 = nullptr;
|
||||
TCPAHeader *TCPA = nullptr;
|
||||
WAETHeader *WAET = nullptr;
|
||||
MADTHeader *MADT = nullptr;
|
||||
HESTHeader *HEST = nullptr;
|
||||
SSDTHeader *SSDT = nullptr;
|
||||
DBGPHeader *DBGP = nullptr;
|
||||
DBG2Header *DBG2 = nullptr;
|
||||
bool XSDTSupported = false;
|
||||
|
||||
MADT(ACPI::MADTHeader *madt);
|
||||
~MADT();
|
||||
};
|
||||
std::unordered_map<const char *, ACPIHeader *> Tables;
|
||||
|
||||
class DSDT : public Interrupts::Handler
|
||||
{
|
||||
private:
|
||||
uint32_t SMI_CMD = 0;
|
||||
uint8_t ACPI_ENABLE = 0;
|
||||
uint8_t ACPI_DISABLE = 0;
|
||||
uint32_t PM1a_CNT = 0;
|
||||
uint32_t PM1b_CNT = 0;
|
||||
uint16_t SLP_TYPa = 0;
|
||||
uint16_t SLP_TYPb = 0;
|
||||
uint16_t SLP_EN = 0;
|
||||
uint16_t SCI_EN = 0;
|
||||
uint8_t PM1_CNT_LEN = 0;
|
||||
void *FindTable(ACPIHeader *ACPIHeader, char *Signature);
|
||||
void SearchTables(ACPIHeader *Header);
|
||||
ACPI();
|
||||
~ACPI();
|
||||
};
|
||||
|
||||
ACPI *acpi;
|
||||
#if defined(a64)
|
||||
void OnInterruptReceived(CPU::x64::TrapFrame *Frame);
|
||||
#elif defined(a32)
|
||||
void OnInterruptReceived(CPU::x32::TrapFrame *Frame);
|
||||
#endif
|
||||
class MADT
|
||||
{
|
||||
public:
|
||||
struct APICHeader
|
||||
{
|
||||
uint8_t Type;
|
||||
uint8_t Length;
|
||||
} __packed;
|
||||
|
||||
public:
|
||||
bool ACPIShutdownSupported = false;
|
||||
struct MADTIOApic
|
||||
{
|
||||
struct APICHeader Header;
|
||||
uint8_t APICID;
|
||||
uint8_t reserved;
|
||||
uint32_t Address;
|
||||
uint32_t GSIBase;
|
||||
} __packed;
|
||||
|
||||
void Reboot();
|
||||
void Shutdown();
|
||||
struct MADTIso
|
||||
{
|
||||
struct APICHeader Header;
|
||||
uint8_t BuSSource;
|
||||
uint8_t IRQSource;
|
||||
uint32_t GSI;
|
||||
uint16_t Flags;
|
||||
} __packed;
|
||||
|
||||
DSDT(ACPI *acpi);
|
||||
~DSDT();
|
||||
};
|
||||
struct MADTNmi
|
||||
{
|
||||
struct APICHeader Header;
|
||||
uint8_t processor;
|
||||
uint16_t flags;
|
||||
uint8_t lint;
|
||||
} __packed;
|
||||
|
||||
struct LocalAPIC
|
||||
{
|
||||
struct APICHeader Header;
|
||||
uint8_t ACPIProcessorId;
|
||||
uint8_t APICId;
|
||||
uint32_t Flags;
|
||||
} __packed;
|
||||
|
||||
struct LAPIC
|
||||
{
|
||||
uint8_t id;
|
||||
uintptr_t PhysicalAddress;
|
||||
void *VirtualAddress;
|
||||
};
|
||||
|
||||
std::vector<MADTIOApic *> ioapic;
|
||||
std::vector<MADTIso *> iso;
|
||||
std::vector<MADTNmi *> nmi;
|
||||
std::vector<LocalAPIC *> lapic;
|
||||
struct LAPIC *LAPICAddress;
|
||||
uint16_t CPUCores;
|
||||
|
||||
MADT(ACPI::MADTHeader *madt);
|
||||
~MADT();
|
||||
};
|
||||
|
||||
class DSDT : public Interrupts::Handler
|
||||
{
|
||||
private:
|
||||
uint32_t SMI_CMD = 0;
|
||||
uint8_t ACPI_ENABLE = 0;
|
||||
uint8_t ACPI_DISABLE = 0;
|
||||
uint32_t PM1a_CNT = 0;
|
||||
uint32_t PM1b_CNT = 0;
|
||||
uint16_t SLP_TYPa = 0;
|
||||
uint16_t SLP_TYPb = 0;
|
||||
uint16_t SLP_EN = 0;
|
||||
uint16_t SCI_EN = 0;
|
||||
uint8_t PM1_CNT_LEN = 0;
|
||||
|
||||
ACPI *acpi;
|
||||
void OnInterruptReceived(CPU::TrapFrame *Frame);
|
||||
|
||||
public:
|
||||
bool ACPIShutdownSupported = false;
|
||||
|
||||
void Reboot();
|
||||
void Shutdown();
|
||||
|
||||
DSDT(ACPI *acpi);
|
||||
~DSDT();
|
||||
};
|
||||
}
|
||||
|
||||
#endif // !__FENNIX_KERNEL_ACPI_H__
|
||||
|
@ -38,7 +38,7 @@
|
||||
/* Alignment of the multiboot info structure. */
|
||||
#define MULTIBOOT_INFO_ALIGN 0x00000004
|
||||
|
||||
/* Flags set in the ’flags’ member of the multiboot header. */
|
||||
/* Flags set in the 'flags' member of the multiboot header. */
|
||||
|
||||
/* Align all boot modules on i386 page (4KB) boundaries. */
|
||||
#define MULTIBOOT_PAGE_ALIGN 0x00000001
|
||||
@ -52,7 +52,7 @@
|
||||
/* This flag indicates the use of the address fields in the header. */
|
||||
#define MULTIBOOT_AOUT_KLUDGE 0x00010000
|
||||
|
||||
/* Flags to be set in the ’flags’ member of the multiboot info structure. */
|
||||
/* Flags to be set in the 'flags' member of the multiboot info structure. */
|
||||
|
||||
/* is there basic lower/upper memory information? */
|
||||
#define MULTIBOOT_INFO_MEMORY 0x00000001
|
||||
@ -243,7 +243,7 @@ typedef struct multiboot_mmap_entry multiboot_memory_map_t;
|
||||
|
||||
struct multiboot_mod_list
|
||||
{
|
||||
/* the memory used goes from bytes ’mod_start’ to ’mod_end-1’ inclusive */
|
||||
/* the memory used goes from bytes 'mod_start' to 'mod_end-1' inclusive */
|
||||
multiboot_uint32_t mod_start;
|
||||
multiboot_uint32_t mod_end;
|
||||
|
||||
|
208
include/cargs.h
208
include/cargs.h
@ -63,122 +63,122 @@ extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/**
|
||||
* An option is used to describe a flag/argument option submitted when the
|
||||
* program is run.
|
||||
*/
|
||||
typedef struct cag_option
|
||||
{
|
||||
const char identifier;
|
||||
const char *access_letters;
|
||||
const char *access_name;
|
||||
const char *value_name;
|
||||
const char *description;
|
||||
} cag_option;
|
||||
/**
|
||||
* An option is used to describe a flag/argument option submitted when the
|
||||
* program is run.
|
||||
*/
|
||||
typedef struct cag_option
|
||||
{
|
||||
const char identifier;
|
||||
const char *access_letters;
|
||||
const char *access_name;
|
||||
const char *value_name;
|
||||
const char *description;
|
||||
} cag_option;
|
||||
|
||||
/**
|
||||
* A context is used to iterate over all options provided. It stores the parsing
|
||||
* state.
|
||||
*/
|
||||
typedef struct cag_option_context
|
||||
{
|
||||
const struct cag_option *options;
|
||||
size_t option_count;
|
||||
int argc;
|
||||
char **argv;
|
||||
int index;
|
||||
int inner_index;
|
||||
bool forced_end;
|
||||
char identifier;
|
||||
char *value;
|
||||
} cag_option_context;
|
||||
/**
|
||||
* A context is used to iterate over all options provided. It stores the parsing
|
||||
* state.
|
||||
*/
|
||||
typedef struct cag_option_context
|
||||
{
|
||||
const struct cag_option *options;
|
||||
size_t option_count;
|
||||
int argc;
|
||||
char **argv;
|
||||
int index;
|
||||
int inner_index;
|
||||
bool forced_end;
|
||||
char identifier;
|
||||
char *value;
|
||||
} cag_option_context;
|
||||
|
||||
/**
|
||||
* This is just a small macro which calculates the size of an array.
|
||||
*/
|
||||
#define CAG_ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
|
||||
|
||||
/**
|
||||
* @brief Prints all options to the terminal.
|
||||
*
|
||||
* This function prints all options to the terminal. This can be used to
|
||||
* generate the output for a "--help" option.
|
||||
*
|
||||
* @param options The options which will be printed.
|
||||
* @param option_count The option count which will be printed.
|
||||
* @param destination The destination where the output will be printed.
|
||||
*/
|
||||
CAG_PUBLIC void cag_option_print(const cag_option *options, size_t option_count,
|
||||
FILE *destination);
|
||||
/**
|
||||
* @brief Prints all options to the terminal.
|
||||
*
|
||||
* This function prints all options to the terminal. This can be used to
|
||||
* generate the output for a "--help" option.
|
||||
*
|
||||
* @param options The options which will be printed.
|
||||
* @param option_count The option count which will be printed.
|
||||
* @param destination The destination where the output will be printed.
|
||||
*/
|
||||
CAG_PUBLIC void cag_option_print(const cag_option *options, size_t option_count,
|
||||
FILE *destination);
|
||||
|
||||
/**
|
||||
* @brief Prepare argument options context for parsing.
|
||||
*
|
||||
* This function prepares the context for iteration and initializes the context
|
||||
* with the supplied options and arguments. After the context has been prepared,
|
||||
* it can be used to fetch arguments from it.
|
||||
*
|
||||
* @param context The context which will be initialized.
|
||||
* @param options The registered options which are available for the program.
|
||||
* @param option_count The amount of options which are available for the
|
||||
* program.
|
||||
* @param argc The amount of arguments the user supplied in the main function.
|
||||
* @param argv A pointer to the arguments of the main function.
|
||||
*/
|
||||
CAG_PUBLIC void cag_option_prepare(cag_option_context *context,
|
||||
const cag_option *options, size_t option_count, int argc, char **argv);
|
||||
/**
|
||||
* @brief Prepare argument options context for parsing.
|
||||
*
|
||||
* This function prepares the context for iteration and initializes the context
|
||||
* with the supplied options and arguments. After the context has been prepared,
|
||||
* it can be used to fetch arguments from it.
|
||||
*
|
||||
* @param context The context which will be initialized.
|
||||
* @param options The registered options which are available for the program.
|
||||
* @param option_count The amount of options which are available for the
|
||||
* program.
|
||||
* @param argc The amount of arguments the user supplied in the main function.
|
||||
* @param argv A pointer to the arguments of the main function.
|
||||
*/
|
||||
CAG_PUBLIC void cag_option_prepare(cag_option_context *context,
|
||||
const cag_option *options, size_t option_count, int argc, char **argv);
|
||||
|
||||
/**
|
||||
* @brief Fetches an option from the argument list.
|
||||
*
|
||||
* This function fetches a single option from the argument list. The context
|
||||
* will be moved to that item. Information can be extracted from the context
|
||||
* after the item has been fetched.
|
||||
* The arguments will be re-ordered, which means that non-option arguments will
|
||||
* be moved to the end of the argument list. After all options have been
|
||||
* fetched, all non-option arguments will be positioned after the index of
|
||||
* the context.
|
||||
*
|
||||
* @param context The context from which we will fetch the option.
|
||||
* @return Returns true if there was another option or false if the end is
|
||||
* reached.
|
||||
*/
|
||||
CAG_PUBLIC bool cag_option_fetch(cag_option_context *context);
|
||||
/**
|
||||
* @brief Fetches an option from the argument list.
|
||||
*
|
||||
* This function fetches a single option from the argument list. The context
|
||||
* will be moved to that item. Information can be extracted from the context
|
||||
* after the item has been fetched.
|
||||
* The arguments will be re-ordered, which means that non-option arguments will
|
||||
* be moved to the end of the argument list. After all options have been
|
||||
* fetched, all non-option arguments will be positioned after the index of
|
||||
* the context.
|
||||
*
|
||||
* @param context The context from which we will fetch the option.
|
||||
* @return Returns true if there was another option or false if the end is
|
||||
* reached.
|
||||
*/
|
||||
CAG_PUBLIC bool cag_option_fetch(cag_option_context *context);
|
||||
|
||||
/**
|
||||
* @brief Gets the identifier of the option.
|
||||
*
|
||||
* This function gets the identifier of the option, which should be unique to
|
||||
* this option and can be used to determine what kind of option this is.
|
||||
*
|
||||
* @param context The context from which the option was fetched.
|
||||
* @return Returns the identifier of the option.
|
||||
*/
|
||||
CAG_PUBLIC char cag_option_get(const cag_option_context *context);
|
||||
/**
|
||||
* @brief Gets the identifier of the option.
|
||||
*
|
||||
* This function gets the identifier of the option, which should be unique to
|
||||
* this option and can be used to determine what kind of option this is.
|
||||
*
|
||||
* @param context The context from which the option was fetched.
|
||||
* @return Returns the identifier of the option.
|
||||
*/
|
||||
CAG_PUBLIC char cag_option_get(const cag_option_context *context);
|
||||
|
||||
/**
|
||||
* @brief Gets the value from the option.
|
||||
*
|
||||
* This function gets the value from the option, if any. If the option does not
|
||||
* contain a value, this function will return NULL.
|
||||
*
|
||||
* @param context The context from which the option was fetched.
|
||||
* @return Returns a pointer to the value or NULL if there is no value.
|
||||
*/
|
||||
CAG_PUBLIC const char *cag_option_get_value(const cag_option_context *context);
|
||||
/**
|
||||
* @brief Gets the value from the option.
|
||||
*
|
||||
* This function gets the value from the option, if any. If the option does not
|
||||
* contain a value, this function will return NULL.
|
||||
*
|
||||
* @param context The context from which the option was fetched.
|
||||
* @return Returns a pointer to the value or NULL if there is no value.
|
||||
*/
|
||||
CAG_PUBLIC const char *cag_option_get_value(const cag_option_context *context);
|
||||
|
||||
/**
|
||||
* @brief Gets the current index of the context.
|
||||
*
|
||||
* This function gets the index within the argv arguments of the context. The
|
||||
* context always points to the next item which it will inspect. This is
|
||||
* particularly useful to inspect the original argument array, or to get
|
||||
* non-option arguments after option fetching has finished.
|
||||
*
|
||||
* @param context The context from which the option was fetched.
|
||||
* @return Returns the current index of the context.
|
||||
*/
|
||||
CAG_PUBLIC int cag_option_get_index(const cag_option_context *context);
|
||||
/**
|
||||
* @brief Gets the current index of the context.
|
||||
*
|
||||
* This function gets the index within the argv arguments of the context. The
|
||||
* context always points to the next item which it will inspect. This is
|
||||
* particularly useful to inspect the original argument array, or to get
|
||||
* non-option arguments after option fetching has finished.
|
||||
*
|
||||
* @param context The context from which the option was fetched.
|
||||
* @return Returns the current index of the context.
|
||||
*/
|
||||
CAG_PUBLIC int cag_option_get_index(const cag_option_context *context);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
|
@ -23,90 +23,99 @@ extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
typedef struct mbstate_t
|
||||
{
|
||||
int count;
|
||||
unsigned int value;
|
||||
} mbstate_t;
|
||||
typedef struct mbstate_t
|
||||
{
|
||||
int count;
|
||||
unsigned int value;
|
||||
} mbstate_t;
|
||||
|
||||
#define NAN (__builtin_nanf(""))
|
||||
|
||||
int isdigit(int c);
|
||||
int isspace(int c);
|
||||
int isempty(char *str);
|
||||
int isalpha(int c);
|
||||
int isupper(int c);
|
||||
unsigned int isdelim(char c, const char *delim);
|
||||
long abs(long i);
|
||||
void swap(char *x, char *y);
|
||||
char *reverse(char *Buffer, int i, int j);
|
||||
int isdigit(int c);
|
||||
int isspace(int c);
|
||||
int isempty(char *str);
|
||||
int isalpha(int c);
|
||||
int isupper(int c);
|
||||
unsigned int isdelim(char c, const char *delim);
|
||||
long abs(long i);
|
||||
void swap(char *x, char *y);
|
||||
char *reverse(char *Buffer, int i, int j);
|
||||
|
||||
float sqrtf(float x);
|
||||
double clamp(double x, double low, double high);
|
||||
float sqrtf(float x);
|
||||
double clamp(double x, double low, double high);
|
||||
|
||||
float lerp(float a, float b, float t);
|
||||
float smoothstep(float a, float b, float t);
|
||||
float cubicInterpolate(float a, float b, float t);
|
||||
float lerp(float a, float b, float t);
|
||||
float smoothstep(float a, float b, float t);
|
||||
float cubicInterpolate(float a, float b, float t);
|
||||
|
||||
void backspace(char s[]);
|
||||
void append(char s[], char n);
|
||||
void backspace(char s[]);
|
||||
void append(char s[], char n);
|
||||
|
||||
int atoi(const char *String);
|
||||
double atof(const char *String);
|
||||
char *itoa(int Value, char *Buffer, int Base);
|
||||
char *ltoa(long Value, char *Buffer, int Base);
|
||||
char *ultoa(unsigned long Value, char *Buffer, int Base);
|
||||
unsigned long int strtoul(const char *str, char **endptr, int base);
|
||||
int atoi(const char *String);
|
||||
double atof(const char *String);
|
||||
char *itoa(int Value, char *Buffer, int Base);
|
||||
char *ltoa(long Value, char *Buffer, int Base);
|
||||
char *ultoa(unsigned long Value, char *Buffer, int Base);
|
||||
unsigned long int strtoul(const char *str, char **endptr, int base);
|
||||
|
||||
void *memcpy_unsafe(void *dest, const void *src, size_t n);
|
||||
void *memset_unsafe(void *dest, int c, size_t n);
|
||||
void *memmove_unsafe(void *dest, const void *src, size_t n);
|
||||
int memcmp(const void *vl, const void *vr, size_t n);
|
||||
void *memcpy_unsafe(void *dest, const void *src, size_t n);
|
||||
void *memset_unsafe(void *dest, int c, size_t n);
|
||||
void *memmove_unsafe(void *dest, const void *src, size_t n);
|
||||
int memcmp(const void *vl, const void *vr, size_t n);
|
||||
|
||||
void *memcpy_sse(void *dest, const void *src, size_t n);
|
||||
void *memcpy_sse2(void *dest, const void *src, size_t n);
|
||||
void *memcpy_sse3(void *dest, const void *src, size_t n);
|
||||
void *memcpy_ssse3(void *dest, const void *src, size_t n);
|
||||
void *memcpy_sse4_1(void *dest, const void *src, size_t n);
|
||||
void *memcpy_sse4_2(void *dest, const void *src, size_t n);
|
||||
void *memcpy_sse(void *dest, const void *src, size_t n);
|
||||
void *memcpy_sse2(void *dest, const void *src, size_t n);
|
||||
void *memcpy_sse3(void *dest, const void *src, size_t n);
|
||||
void *memcpy_ssse3(void *dest, const void *src, size_t n);
|
||||
void *memcpy_sse4_1(void *dest, const void *src, size_t n);
|
||||
void *memcpy_sse4_2(void *dest, const void *src, size_t n);
|
||||
|
||||
void *memset_sse(void *dest, int c, size_t n);
|
||||
void *memset_sse2(void *dest, int c, size_t n);
|
||||
void *memset_sse3(void *dest, int c, size_t n);
|
||||
void *memset_ssse3(void *dest, int c, size_t n);
|
||||
void *memset_sse4_1(void *dest, int c, size_t n);
|
||||
void *memset_sse4_2(void *dest, int c, size_t n);
|
||||
void *memset_sse(void *dest, int c, size_t n);
|
||||
void *memset_sse2(void *dest, int c, size_t n);
|
||||
void *memset_sse3(void *dest, int c, size_t n);
|
||||
void *memset_ssse3(void *dest, int c, size_t n);
|
||||
void *memset_sse4_1(void *dest, int c, size_t n);
|
||||
void *memset_sse4_2(void *dest, int c, size_t n);
|
||||
|
||||
void *memmove_sse(void *dest, const void *src, size_t n);
|
||||
void *memmove_sse2(void *dest, const void *src, size_t n);
|
||||
void *memmove_sse3(void *dest, const void *src, size_t n);
|
||||
void *memmove_ssse3(void *dest, const void *src, size_t n);
|
||||
void *memmove_sse4_1(void *dest, const void *src, size_t n);
|
||||
void *memmove_sse4_2(void *dest, const void *src, size_t n);
|
||||
void *memmove_sse(void *dest, const void *src, size_t n);
|
||||
void *memmove_sse2(void *dest, const void *src, size_t n);
|
||||
void *memmove_sse3(void *dest, const void *src, size_t n);
|
||||
void *memmove_ssse3(void *dest, const void *src, size_t n);
|
||||
void *memmove_sse4_1(void *dest, const void *src, size_t n);
|
||||
void *memmove_sse4_2(void *dest, const void *src, size_t n);
|
||||
|
||||
long unsigned strlen(const char s[]);
|
||||
int strncmp(const char *s1, const char *s2, unsigned long n);
|
||||
char *strcat_unsafe(char *destination, const char *source);
|
||||
char *strcpy_unsafe(char *destination, const char *source);
|
||||
char *strncpy(char *destination, const char *source, unsigned long num);
|
||||
int strcmp(const char *l, const char *r);
|
||||
char *strstr(const char *haystack, const char *needle);
|
||||
char *strdup(const char *String);
|
||||
char *strchr(const char *String, int Char);
|
||||
char *strrchr(const char *String, int Char);
|
||||
int strncasecmp(const char *lhs, const char *rhs, long unsigned int Count);
|
||||
int strcasecmp(const char *s1, const char *s2);
|
||||
char *strtok(char *src, const char *delim);
|
||||
long int strtol(const char *str, char **endptr, int base);
|
||||
size_t wcslen(const wchar_t *s);
|
||||
size_t wcsrtombs(char *dst, const wchar_t **src, size_t len, mbstate_t *ps);
|
||||
int log2(unsigned int n);
|
||||
long unsigned __strlen(const char s[]);
|
||||
|
||||
void *__memcpy_chk(void *dest, const void *src, size_t len, size_t slen);
|
||||
void *__memset_chk(void *dest, int val, size_t len, size_t slen);
|
||||
void *__memmove_chk(void *dest, const void *src, size_t len, size_t slen);
|
||||
char *__strcat_chk(char *dest, const char *src, size_t slen);
|
||||
char *__strcpy_chk(char *dest, const char *src, size_t slen);
|
||||
long unsigned strlen_sse(const char s[]);
|
||||
long unsigned strlen_sse2(const char s[]);
|
||||
long unsigned strlen_sse3(const char s[]);
|
||||
long unsigned strlen_ssse3(const char s[]);
|
||||
long unsigned strlen_sse4_1(const char s[]);
|
||||
long unsigned strlen_sse4_2(const char s[]);
|
||||
|
||||
long unsigned strlen(const char s[]);
|
||||
int strncmp(const char *s1, const char *s2, unsigned long n);
|
||||
char *strcat_unsafe(char *destination, const char *source);
|
||||
char *strcpy_unsafe(char *destination, const char *source);
|
||||
char *strncpy(char *destination, const char *source, unsigned long num);
|
||||
int strcmp(const char *l, const char *r);
|
||||
char *strstr(const char *haystack, const char *needle);
|
||||
char *strdup(const char *String);
|
||||
char *strchr(const char *String, int Char);
|
||||
char *strrchr(const char *String, int Char);
|
||||
int strncasecmp(const char *string1, const char *string2, size_t count);
|
||||
int strcasecmp(const char *s1, const char *s2);
|
||||
char *strtok(char *src, const char *delim);
|
||||
long int strtol(const char *str, char **endptr, int base);
|
||||
size_t wcslen(const wchar_t *s);
|
||||
size_t wcsrtombs(char *dst, const wchar_t **src, size_t len, mbstate_t *ps);
|
||||
int log2(unsigned int n);
|
||||
|
||||
void *__memcpy_chk(void *dest, const void *src, size_t len, size_t slen);
|
||||
void *__memset_chk(void *dest, int val, size_t len, size_t slen);
|
||||
void *__memmove_chk(void *dest, const void *src, size_t len, size_t slen);
|
||||
char *__strcat_chk(char *dest, const char *src, size_t slen);
|
||||
char *__strcpy_chk(char *dest, const char *src, size_t slen);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
@ -114,20 +123,20 @@ extern "C"
|
||||
|
||||
#undef memcpy
|
||||
#define memcpy(dest, src, n) \
|
||||
__memcpy_chk(dest, src, n, __builtin_object_size(dest, 0))
|
||||
__memcpy_chk(dest, src, n, __builtin_object_size(dest, 0))
|
||||
|
||||
#undef memset
|
||||
#define memset(dest, c, n) \
|
||||
__memset_chk(dest, c, n, __builtin_object_size(dest, 0))
|
||||
__memset_chk(dest, c, n, __builtin_object_size(dest, 0))
|
||||
|
||||
#undef memmove
|
||||
#define memmove(dest, src, n) \
|
||||
__memmove_chk(dest, src, n, __builtin_object_size(dest, 0))
|
||||
__memmove_chk(dest, src, n, __builtin_object_size(dest, 0))
|
||||
|
||||
#undef strcat
|
||||
#define strcat(dest, src) \
|
||||
__strcat_chk(dest, src, __builtin_object_size(dest, 0))
|
||||
__strcat_chk(dest, src, __builtin_object_size(dest, 0))
|
||||
|
||||
#undef strcpy
|
||||
#define strcpy(dest, src) \
|
||||
__strcpy_chk(dest, src, __builtin_object_size(dest, 0))
|
||||
__strcpy_chk(dest, src, __builtin_object_size(dest, 0))
|
||||
|
@ -161,7 +161,7 @@ namespace CPU
|
||||
"cli\n"
|
||||
"hlt\n"
|
||||
"jmp CPUStopLoop");
|
||||
#elif defined(aa64) // annoying warning: "‘noreturn’ function does return" and "‘naked’ attribute directive ignored"
|
||||
#elif defined(aa64) // annoying warning: "'noreturn' function does return" and "'naked' attribute directive ignored"
|
||||
SafeFunction __used inline void Stop()
|
||||
{
|
||||
asmv("CPUStopLoop:\n"
|
||||
@ -198,10 +198,13 @@ namespace CPU
|
||||
* @brief Get/Set the CPU's page table
|
||||
*
|
||||
* @param PT The new page table, if empty, the current page table will be returned
|
||||
* @return void* The current page table
|
||||
* @return Get: The current page table
|
||||
* @return Set: The old page table
|
||||
*/
|
||||
void *PageTable(void *PT = nullptr);
|
||||
|
||||
#define thisPageTable (Memory::PageTable *)CPU::PageTable()
|
||||
|
||||
/** @brief To be used only once. */
|
||||
void InitializeFeatures(int Core);
|
||||
|
||||
@ -826,7 +829,7 @@ namespace CPU
|
||||
uint8_t st[8][16];
|
||||
/** @brief XMM registers */
|
||||
uint8_t xmm[16][16];
|
||||
} __packed;
|
||||
} __packed __aligned(16);
|
||||
|
||||
SafeFunction static inline void lgdt(void *gdt)
|
||||
{
|
||||
@ -950,6 +953,29 @@ namespace CPU
|
||||
uint64_t InterruptNumber /* iar_el1 */; // Interrupt Acknowledge Register
|
||||
} TrapFrame;
|
||||
}
|
||||
|
||||
#if defined(a64)
|
||||
/**
|
||||
* CPU trap frame for the current architecture
|
||||
*
|
||||
* @note This is for x86_64
|
||||
*/
|
||||
typedef x64::TrapFrame TrapFrame;
|
||||
#elif defined(a32)
|
||||
/**
|
||||
* CPU trap frame for the current architecture
|
||||
*
|
||||
* @note This is for x86_32
|
||||
*/
|
||||
typedef x32::TrapFrame TrapFrame;
|
||||
#elif defined(aa64)
|
||||
/**
|
||||
* CPU trap frame for the current architecture
|
||||
*
|
||||
* @note This is for aarch64
|
||||
*/
|
||||
typedef aarch64::TrapFrame TrapFrame;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif // !__FENNIX_KERNEL_CPU_H__
|
||||
|
@ -1,18 +1,18 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
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 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.
|
||||
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/>.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __FENNIX_KERNEL_CPU_x86_INTERRUPTS_H__
|
||||
@ -82,7 +82,7 @@ namespace CPU
|
||||
|
||||
/* Reserved by OS */
|
||||
|
||||
IRQ16 = 0x30, // Reserved for multitasking
|
||||
IRQ16 = 0x30, /* Reserved for multitasking */
|
||||
IRQ17 = 0x31,
|
||||
IRQ18 = 0x32,
|
||||
IRQ19 = 0x33,
|
||||
@ -95,12 +95,11 @@ namespace CPU
|
||||
IRQ26 = 0x3a,
|
||||
IRQ27 = 0x3b,
|
||||
IRQ28 = 0x3c,
|
||||
IRQ29 = 0x3d, // Reserved for icr stop core
|
||||
IRQ29 = 0x3d,
|
||||
IRQ30 = 0x3e,
|
||||
IRQ31 = 0x3f, /* Halt core interrupt */
|
||||
|
||||
/* Free */
|
||||
|
||||
IRQ30 = 0x3e,
|
||||
IRQ31 = 0x3f,
|
||||
IRQ32 = 0x40,
|
||||
IRQ33 = 0x41,
|
||||
IRQ34 = 0x42,
|
||||
|
@ -117,4 +117,6 @@ void SysDbgLockedWriteLine(enum DebugLevel Level, const char *File, int Line, co
|
||||
|
||||
#endif // __cplusplus
|
||||
|
||||
EXTERNC void uart_wrapper(char c, void *unused);
|
||||
|
||||
#endif // !__FENNIX_KERNEL_DEBUGGER_H__
|
||||
|
208
include/driver.hpp
Normal file
208
include/driver.hpp
Normal file
@ -0,0 +1,208 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __FENNIX_KERNEL_DRIVER_H__
|
||||
#define __FENNIX_KERNEL_DRIVER_H__
|
||||
|
||||
#include <types.h>
|
||||
|
||||
#include <filesystem.hpp>
|
||||
#include <unordered_map>
|
||||
#include <memory.hpp>
|
||||
#include <ints.hpp>
|
||||
#include <lock.hpp>
|
||||
#include <task.hpp>
|
||||
#include <debug.h>
|
||||
#include <cpu.hpp>
|
||||
#include <pci.hpp>
|
||||
#include <vector>
|
||||
#include <io.h>
|
||||
#include <list>
|
||||
|
||||
namespace Driver
|
||||
{
|
||||
char GetScanCode(uint8_t ScanCode, bool Upper);
|
||||
bool IsValidChar(uint8_t ScanCode);
|
||||
|
||||
class SlaveDeviceFile : public vfs::Node
|
||||
{
|
||||
private:
|
||||
int /* DeviceDriverType */ DeviceType;
|
||||
|
||||
std::list<uint8_t> KeyQueue;
|
||||
|
||||
public:
|
||||
typedef int (*drvOpen_t)(dev_t, dev_t, int, mode_t);
|
||||
typedef int (*drvClose_t)(dev_t, dev_t);
|
||||
typedef size_t (*drvRead_t)(dev_t, dev_t, uint8_t *, size_t, off_t);
|
||||
typedef size_t (*drvWrite_t)(dev_t, dev_t, uint8_t *, size_t, off_t);
|
||||
typedef int (*drvIoctl_t)(dev_t, dev_t, unsigned long, void *);
|
||||
|
||||
drvOpen_t Open;
|
||||
drvClose_t Close;
|
||||
drvRead_t Read;
|
||||
drvWrite_t Write;
|
||||
drvIoctl_t Ioctl;
|
||||
|
||||
int open(int Flags, mode_t Mode) final;
|
||||
int close() final;
|
||||
size_t read(uint8_t *Buffer,
|
||||
size_t Size,
|
||||
off_t Offset) final;
|
||||
size_t write(uint8_t *Buffer,
|
||||
size_t Size,
|
||||
off_t Offset) final;
|
||||
int ioctl(unsigned long Request,
|
||||
void *Argp) final;
|
||||
|
||||
void ClearBuffers();
|
||||
|
||||
int ReportKeyEvent(uint8_t ScanCode);
|
||||
|
||||
SlaveDeviceFile(const char *Name, vfs::Node *Parent, int Type, vfs::NodeType NType);
|
||||
~SlaveDeviceFile();
|
||||
};
|
||||
|
||||
class MasterDeviceFile : private vfs::Node
|
||||
{
|
||||
private:
|
||||
typedef dev_t maj_t;
|
||||
typedef dev_t min_t;
|
||||
char SlaveName[16];
|
||||
vfs::Node *SlaveParent;
|
||||
int /* DeviceDriverType */ DeviceType;
|
||||
min_t SlaveIDCounter = 0;
|
||||
|
||||
typedef std::unordered_map<min_t, SlaveDeviceFile *> *Slaves;
|
||||
std::unordered_map<maj_t, Slaves> SlavesMap;
|
||||
|
||||
std::list<uint8_t> RawKeyQueue;
|
||||
std::list<uint8_t> KeyQueue;
|
||||
bool UpperCase = false;
|
||||
bool CapsLock = false;
|
||||
|
||||
public:
|
||||
typedef int (*drvOpen_t)(dev_t, dev_t, int, mode_t);
|
||||
typedef int (*drvClose_t)(dev_t, dev_t);
|
||||
typedef size_t (*drvRead_t)(dev_t, dev_t, uint8_t *, size_t, off_t);
|
||||
typedef size_t (*drvWrite_t)(dev_t, dev_t, uint8_t *, size_t, off_t);
|
||||
typedef int (*drvIoctl_t)(dev_t, dev_t, unsigned long, void *);
|
||||
|
||||
int open(int Flags, mode_t Mode) final;
|
||||
int close() final;
|
||||
size_t read(uint8_t *Buffer,
|
||||
size_t Size,
|
||||
off_t Offset) final;
|
||||
size_t write(uint8_t *Buffer,
|
||||
size_t Size,
|
||||
off_t Offset) final;
|
||||
int ioctl(unsigned long Request,
|
||||
void *Argp) final;
|
||||
|
||||
void ClearBuffers();
|
||||
|
||||
int ReportKeyEvent(maj_t ID, min_t MinorID, uint8_t ScanCode);
|
||||
int ReportMouseEvent(maj_t ID, min_t MinorID,
|
||||
bool LeftButton, bool RightButton, bool MiddleButton,
|
||||
bool Button4, bool Button5, bool Button6,
|
||||
bool Button7, bool Button8,
|
||||
uintptr_t X, uintptr_t Y, int8_t Z, bool Relative);
|
||||
|
||||
int ReportNetworkPacket(maj_t ID, min_t MinorID, void *Buffer, size_t Size);
|
||||
|
||||
int NewBlock(maj_t ID, min_t MinorID, drvOpen_t Open, drvClose_t Close,
|
||||
drvRead_t Read, drvWrite_t Write, drvIoctl_t Ioctl);
|
||||
|
||||
int NewAudio(maj_t ID, min_t MinorID, drvOpen_t Open, drvClose_t Close,
|
||||
drvRead_t Read, drvWrite_t Write, drvIoctl_t Ioctl);
|
||||
|
||||
int NewNet(maj_t ID, min_t MinorID, drvOpen_t Open, drvClose_t Close,
|
||||
drvRead_t Read, drvWrite_t Write, drvIoctl_t Ioctl);
|
||||
|
||||
dev_t Register(maj_t ID);
|
||||
int Unregister(maj_t ID, min_t MinorID);
|
||||
|
||||
MasterDeviceFile(const char *MasterName,
|
||||
const char *SlaveName,
|
||||
vfs::Node *Parent,
|
||||
int Type);
|
||||
~MasterDeviceFile();
|
||||
};
|
||||
|
||||
struct DriverObject
|
||||
{
|
||||
uintptr_t BaseAddress = 0;
|
||||
uintptr_t EntryPoint = 0;
|
||||
Memory::VirtualMemoryArea *vma = nullptr;
|
||||
|
||||
/* Path has the same pointer as in the Node */
|
||||
const char *Path = nullptr;
|
||||
std::unordered_map<uint8_t, void *> *InterruptHandlers;
|
||||
|
||||
char Name[32] = {'\0'};
|
||||
char Description[64] = {'\0'};
|
||||
char Author[32] = {'\0'};
|
||||
char Version[16] = {'\0'};
|
||||
char License[32] = {'\0'};
|
||||
bool Initialized = false;
|
||||
int ErrorCode = 0;
|
||||
|
||||
int (*Entry)() = nullptr;
|
||||
int (*Final)() = nullptr;
|
||||
int (*Panic)() = nullptr;
|
||||
int (*Probe)() = nullptr;
|
||||
};
|
||||
|
||||
class Manager
|
||||
{
|
||||
private:
|
||||
NewLock(ModuleInitLock);
|
||||
std::unordered_map<dev_t, DriverObject> Drivers;
|
||||
dev_t MajorIDCounter = 0;
|
||||
|
||||
int LoadDriverFile(uintptr_t &EntryPoint,
|
||||
uintptr_t &BaseAddress,
|
||||
Memory::VirtualMemoryArea *dVma,
|
||||
vfs::RefNode *rDrv);
|
||||
|
||||
public:
|
||||
MasterDeviceFile *InputMouseDev = nullptr;
|
||||
MasterDeviceFile *InputKeyboardDev = nullptr;
|
||||
|
||||
MasterDeviceFile *BlockSATADev = nullptr;
|
||||
MasterDeviceFile *BlockHDDev = nullptr;
|
||||
MasterDeviceFile *BlockNVMeDev = nullptr;
|
||||
|
||||
MasterDeviceFile *AudioDev = nullptr;
|
||||
|
||||
MasterDeviceFile *NetDev = nullptr;
|
||||
|
||||
std::unordered_map<dev_t, DriverObject> &
|
||||
GetDrivers() { return Drivers; }
|
||||
|
||||
void LoadAllDrivers();
|
||||
void UnloadAllDrivers();
|
||||
void Panic();
|
||||
|
||||
Manager();
|
||||
~Manager();
|
||||
};
|
||||
|
||||
void PopulateDriverAPI(void *API);
|
||||
}
|
||||
|
||||
#endif // !__FENNIX_KERNEL_DRIVER_H__
|
209
include/elf.h
209
include/elf.h
@ -26,6 +26,7 @@ typedef uint16_t Elf32_Half;
|
||||
typedef uint32_t Elf32_Off;
|
||||
typedef int32_t Elf32_Sword;
|
||||
typedef uint32_t Elf32_Word;
|
||||
typedef Elf32_Sword Elf32_pid_t;
|
||||
|
||||
/* 64-bit ELF base types. */
|
||||
typedef uint64_t Elf64_Addr;
|
||||
@ -36,6 +37,11 @@ typedef int32_t Elf64_Sword;
|
||||
typedef uint32_t Elf64_Word;
|
||||
typedef uint64_t Elf64_Xword;
|
||||
typedef int64_t Elf64_Sxword;
|
||||
typedef Elf64_Sword Elf64_pid_t;
|
||||
|
||||
#define ELF_NGREG 23
|
||||
typedef Elf32_Word Elf32_greg_t[ELF_NGREG];
|
||||
typedef Elf64_Xword Elf64_greg_t[ELF_NGREG];
|
||||
|
||||
enum IdentificationIndex
|
||||
{
|
||||
@ -227,8 +233,6 @@ enum SegmentTypes
|
||||
PT_TLS = 7,
|
||||
PT_LOPROC = 0x70000000,
|
||||
PT_HIPROC = 0x7fffffff,
|
||||
PT_GNU_EH_FRAME = 0x6474e550,
|
||||
PT_GNU_STACK = 0x6474e551,
|
||||
};
|
||||
|
||||
enum DynamicArrayTags
|
||||
@ -305,15 +309,15 @@ enum DynamicArrayTags
|
||||
|
||||
/* Used for Elf64_Sym st_info */
|
||||
#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 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))
|
||||
#define ELF64_ST_TYPE(info) ((info) & 0xf)
|
||||
#define ELF64_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
|
||||
|
||||
/* Used for Elf64_Sym st_other */
|
||||
#define ELF32_ST_VISIBILITY(o) ((o)&0x3)
|
||||
#define ELF64_ST_VISIBILITY(o) ((o)&0x3)
|
||||
#define ELF32_ST_VISIBILITY(o) ((o) & 0x3)
|
||||
#define ELF64_ST_VISIBILITY(o) ((o) & 0x3)
|
||||
|
||||
#define DO_386_32(S, A) ((S) + (A))
|
||||
#define DO_386_PC32(S, A, P) ((S) + (A) - (P))
|
||||
@ -326,8 +330,8 @@ enum DynamicArrayTags
|
||||
#define ELF32_R_INFO(s, t) (((s) << 8) + (unsigned char)(t))
|
||||
|
||||
#define ELF64_R_SYM(i) ((i) >> 32)
|
||||
#define ELF64_R_TYPE(i) ((i)&0xffffffffL)
|
||||
#define ELF64_R_INFO(s, t) (((s) << 32) + ((t)&0xffffffffL))
|
||||
#define ELF64_R_TYPE(i) ((i) & 0xffffffffL)
|
||||
#define ELF64_R_INFO(s, t) (((s) << 32) + ((t) & 0xffffffffL))
|
||||
|
||||
#define SHN_UNDEF 0
|
||||
#define SHN_ABS 0xfff1
|
||||
@ -576,6 +580,80 @@ enum SpecialSections
|
||||
SHT_HIUSER = 0x8fffffff
|
||||
};
|
||||
|
||||
#define NT_PRSTATUS 1
|
||||
#define NT_PRFPREG 2
|
||||
#define NT_FPREGSET 2
|
||||
#define NT_PRPSINFO 3
|
||||
#define NT_PRXREG 4
|
||||
#define NT_TASKSTRUCT 4
|
||||
#define NT_PLATFORM 5
|
||||
#define NT_AUXV 6
|
||||
#define NT_GWINDOWS 7
|
||||
#define NT_ASRS 8
|
||||
#define NT_PSTATUS 10
|
||||
#define NT_PSINFO 13
|
||||
#define NT_PRCRED 14
|
||||
#define NT_UTSNAME 15
|
||||
#define NT_LWPSTATUS 16
|
||||
#define NT_LWPSINFO 17
|
||||
#define NT_PRFPXREG 20
|
||||
#define NT_SIGINFO 0x53494749
|
||||
#define NT_FILE 0x46494c45
|
||||
#define NT_PRXFPREG 0x46e62b7f
|
||||
#define NT_PPC_VMX 0x100
|
||||
#define NT_PPC_SPE 0x101
|
||||
#define NT_PPC_VSX 0x102
|
||||
#define NT_PPC_TAR 0x103
|
||||
#define NT_PPC_PPR 0x104
|
||||
#define NT_PPC_DSCR 0x105
|
||||
#define NT_PPC_EBB 0x106
|
||||
#define NT_PPC_PMU 0x107
|
||||
#define NT_PPC_TM_CGPR 0x108
|
||||
#define NT_PPC_TM_CFPR 0x109
|
||||
#define NT_PPC_TM_CVMX 0x10a
|
||||
#define NT_PPC_TM_CVSX 0x10b
|
||||
#define NT_PPC_TM_SPR 0x10c
|
||||
#define NT_PPC_TM_CTAR 0x10d
|
||||
#define NT_PPC_TM_CPPR 0x10e
|
||||
#define NT_PPC_TM_CDSCR 0x10f
|
||||
#define NT_386_TLS 0x200
|
||||
#define NT_386_IOPERM 0x201
|
||||
#define NT_X86_XSTATE 0x202
|
||||
#define NT_S390_HIGH_GPRS 0x300
|
||||
#define NT_S390_TIMER 0x301
|
||||
#define NT_S390_TODCMP 0x302
|
||||
#define NT_S390_TODPREG 0x303
|
||||
#define NT_S390_CTRS 0x304
|
||||
#define NT_S390_PREFIX 0x305
|
||||
#define NT_S390_LAST_BREAK 0x306
|
||||
#define NT_S390_SYSTEM_CALL 0x307
|
||||
#define NT_S390_TDB 0x308
|
||||
#define NT_S390_VXRS_LOW 0x309
|
||||
#define NT_S390_VXRS_HIGH 0x30a
|
||||
#define NT_S390_GS_CB 0x30b
|
||||
#define NT_S390_GS_BC 0x30c
|
||||
#define NT_S390_RI_CB 0x30d
|
||||
#define NT_ARM_VFP 0x400
|
||||
#define NT_ARM_TLS 0x401
|
||||
#define NT_ARM_HW_BREAK 0x402
|
||||
#define NT_ARM_HW_WATCH 0x403
|
||||
#define NT_ARM_SYSTEM_CALL 0x404
|
||||
#define NT_ARM_SVE 0x405
|
||||
#define NT_ARM_PAC_MASK 0x406
|
||||
#define NT_ARM_PACA_KEYS 0x407
|
||||
#define NT_ARM_PACG_KEYS 0x408
|
||||
#define NT_ARM_TAGGED_ADDR_CTRL 0x409
|
||||
#define NT_ARM_PAC_ENABLED_KEYS 0x40a
|
||||
#define NT_METAG_CBUF 0x500
|
||||
#define NT_METAG_RPIPE 0x501
|
||||
#define NT_METAG_TLS 0x502
|
||||
#define NT_ARC_V2 0x600
|
||||
#define NT_VMCOREDD 0x700
|
||||
#define NT_MIPS_DSP 0x800
|
||||
#define NT_MIPS_FP_MODE 0x801
|
||||
#define NT_MIPS_MSA 0x802
|
||||
#define NT_VERSION 1
|
||||
|
||||
typedef struct elf32_hdr
|
||||
{
|
||||
unsigned char e_ident[EI_NIDENT];
|
||||
@ -730,6 +808,117 @@ typedef struct
|
||||
Elf64_Sxword r_addend;
|
||||
} Elf64_Rela;
|
||||
|
||||
struct Elf32_Nhdr
|
||||
{
|
||||
Elf32_Word n_namesz;
|
||||
Elf32_Word n_descsz;
|
||||
Elf32_Word n_type;
|
||||
};
|
||||
|
||||
struct Elf64_Nhdr
|
||||
{
|
||||
Elf64_Word n_namesz;
|
||||
Elf64_Word n_descsz;
|
||||
Elf64_Word n_type;
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Elf32_Sword si_signo;
|
||||
Elf32_Sword si_code;
|
||||
Elf32_Sword si_errno;
|
||||
} Elf32_Siginfo;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Elf64_Sword si_signo;
|
||||
Elf64_Sword si_code;
|
||||
Elf64_Sword si_errno;
|
||||
} Elf64_Siginfo;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Elf32_Sword tv_sec;
|
||||
Elf32_Sword tv_usec;
|
||||
} Elf32_Prtimeval;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Elf64_Sxword tv_sec;
|
||||
Elf64_Sxword tv_usec;
|
||||
} Elf64_Prtimeval;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Elf32_Siginfo pr_info;
|
||||
Elf32_Half pr_cursig;
|
||||
Elf32_Word pr_sigpend;
|
||||
Elf32_Word pr_sighold;
|
||||
Elf32_pid_t pr_pid;
|
||||
Elf32_pid_t pr_ppid;
|
||||
Elf32_pid_t pr_pgrp;
|
||||
Elf32_pid_t pr_sid;
|
||||
Elf32_Prtimeval pr_utime;
|
||||
Elf32_Prtimeval pr_stime;
|
||||
Elf32_Prtimeval pr_cutime;
|
||||
Elf32_Prtimeval pr_cstime;
|
||||
Elf32_greg_t pr_reg;
|
||||
Elf32_Word pr_fpvalid;
|
||||
} Elf32_Prstatus;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Elf64_Siginfo pr_info;
|
||||
Elf64_Half pr_cursig;
|
||||
Elf64_Word pr_sigpend;
|
||||
Elf64_Word pr_sighold;
|
||||
Elf64_pid_t pr_pid;
|
||||
Elf64_pid_t pr_ppid;
|
||||
Elf64_pid_t pr_pgrp;
|
||||
Elf64_pid_t pr_sid;
|
||||
Elf64_Prtimeval pr_utime;
|
||||
Elf64_Prtimeval pr_stime;
|
||||
Elf64_Prtimeval pr_cutime;
|
||||
Elf64_Prtimeval pr_cstime;
|
||||
Elf64_greg_t pr_reg;
|
||||
Elf64_Word pr_fpvalid;
|
||||
} Elf64_Prstatus;
|
||||
|
||||
#define ELF_PRARGSZ 80
|
||||
typedef struct
|
||||
{
|
||||
char pr_state;
|
||||
char pr_sname;
|
||||
char pr_zomb;
|
||||
char pr_nice;
|
||||
Elf32_Word pr_flag;
|
||||
Elf32_Half pr_uid;
|
||||
Elf32_Half pr_gid;
|
||||
Elf32_pid_t pr_pid;
|
||||
Elf32_pid_t pr_ppid;
|
||||
Elf32_pid_t pr_pgrp;
|
||||
Elf32_pid_t pr_sid;
|
||||
char pr_fname[16];
|
||||
char pr_psargs[ELF_PRARGSZ];
|
||||
} Elf32_Prpsinfo;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char pr_state;
|
||||
char pr_sname;
|
||||
char pr_zomb;
|
||||
char pr_nice;
|
||||
Elf64_Xword pr_flag;
|
||||
Elf64_Half pr_uid;
|
||||
Elf64_Half pr_gid;
|
||||
Elf64_pid_t pr_pid;
|
||||
Elf64_pid_t pr_ppid;
|
||||
Elf64_pid_t pr_pgrp;
|
||||
Elf64_pid_t pr_sid;
|
||||
char pr_fname[16];
|
||||
char pr_psargs[ELF_PRARGSZ];
|
||||
} Elf64_Prpsinfo;
|
||||
|
||||
#if defined(a64) || defined(aa64)
|
||||
typedef Elf64_Addr Elf_Addr;
|
||||
typedef Elf64_Half Elf_Half;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user