Update kernel

This commit is contained in:
EnderIce2 2024-01-19 06:47:42 +02:00
parent fd15592608
commit 96daa43d38
Signed by untrusted user who does not match committer: enderice2
GPG Key ID: EACC3AD603BAB4DD
282 changed files with 25486 additions and 15700 deletions

91
.gdbinit Normal file
View 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
View File

@ -2,5 +2,5 @@
*.su
*.gcno
*.map
*.fsys
fennix.elf
*.log

View File

@ -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."
}
}

View File

@ -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
View File

@ -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
View 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
View 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"]
}
}
}
]
}

View File

@ -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!

View File

@ -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
View File

@ -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__

View File

@ -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.

View File

@ -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
View File

@ -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.

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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; }

View File

@ -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,

View File

@ -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);

View File

@ -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",

View File

@ -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);
}
}

View File

@ -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:

View File

@ -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

View File

@ -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)
{

View File

@ -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; }

View File

@ -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);

View File

@ -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);
}
}

View File

@ -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__

View File

@ -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*)
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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();
}
}

View File

@ -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)

View File

@ -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);

View File

@ -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);
}

View File

@ -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);

View File

@ -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);

View File

@ -34,9 +34,9 @@
namespace CrashHandler
{
SafeFunction void DisplayConsoleScreen(CRData data)
{
EHPrint("TODO");
UNUSED(data);
}
SafeFunction void DisplayConsoleScreen(CRData data)
{
EHPrint("TODO");
UNUSED(data);
}
}

View File

@ -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;
}
}
}
}

View File

@ -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
}
}
}

View File

@ -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");
}
}
}
}

View File

@ -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");
}
}

View File

@ -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");
}
}

View File

@ -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:

View File

@ -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__

View File

@ -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++))

View File

@ -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
View 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;
}
}

View 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();
}
}

View 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
View 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
View 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;
}
}

View File

@ -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;
}

View File

@ -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
}
}

View File

@ -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;

View File

@ -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. */
}

View File

@ -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;

View File

@ -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
}

View File

@ -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;
}

File diff suppressed because it is too large Load Diff

View 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

View 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;
}

View File

@ -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);

View File

@ -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 *);
/* ... */
}

View File

@ -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;

View File

@ -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()

View File

@ -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)),

View File

@ -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);
}
}

View File

@ -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))(&regs);
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
}
}

View File

@ -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,
},
};

View File

@ -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;
}
}
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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() {}
}

View File

@ -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()

View File

@ -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; }
}

View File

@ -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__

View File

@ -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
}

View File

@ -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;
}
}

View File

@ -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);

View File

@ -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;
}
}

View File

@ -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();

View File

@ -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

View File

@ -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__

View File

@ -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
View 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__

View File

@ -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;

View File

@ -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;

View File

@ -20,7 +20,6 @@
#include <msexec.h>
#include "../../kernel.h"
#include "../../Fex.hpp"
namespace Execute
{

View File

@ -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
}
}
}

View File

@ -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;
{

View File

@ -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__

View File

@ -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;

View File

@ -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"

View File

@ -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))

View File

@ -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__

View File

@ -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,

View File

@ -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
View 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__

View File

@ -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