mirror of
https://github.com/Fennix-Project/Lynx.git
synced 2025-05-25 14:04:44 +00:00
Revert changes
This commit is contained in:
parent
4e8599969b
commit
64553b5f84
139
.vscode/c_cpp_properties.json
vendored
139
.vscode/c_cpp_properties.json
vendored
@ -199,145 +199,6 @@
|
||||
"-fstack-check",
|
||||
"-fsanitize=undefined",
|
||||
|
||||
// VSCode flags
|
||||
"-ffreestanding",
|
||||
"-nostdinc",
|
||||
"-nostdinc++"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "FennixLoader x64 (Linux, GCC, debug)",
|
||||
"includePath": [
|
||||
"${workspaceFolder}/FennixLoader/include"
|
||||
],
|
||||
"defines": [
|
||||
"__debug_vscode__",
|
||||
"KERNEL_NAME=\"Fennix\"",
|
||||
"KERNEL_VERSION=\"1.0\"",
|
||||
"GIT_COMMIT=\"0000000000000000000000000000000000000000\"",
|
||||
"GIT_COMMIT_SHORT=\"0000000\"",
|
||||
"DEBUG=\"1\""
|
||||
],
|
||||
"compilerPath": "${workspaceFolder}/../tools/cross/bin/amd64-elf-gcc",
|
||||
"cStandard": "c17",
|
||||
"cppStandard": "c++20",
|
||||
"intelliSenseMode": "gcc-x64",
|
||||
"configurationProvider": "ms-vscode.makefile-tools",
|
||||
"compilerArgs": [
|
||||
// Compiler flags
|
||||
"-fno-pic",
|
||||
"-fno-pie",
|
||||
"-mno-red-zone",
|
||||
"-march=core2",
|
||||
"-pipe",
|
||||
"-mcmodel=kernel",
|
||||
"-fno-builtin",
|
||||
|
||||
// Warnings
|
||||
"-Wall",
|
||||
"-Wextra",
|
||||
"-Wfloat-equal",
|
||||
"-Wpointer-arith",
|
||||
"-Wcast-align",
|
||||
"-Wredundant-decls",
|
||||
"-Winit-self",
|
||||
"-Wswitch-default",
|
||||
"-Wstrict-overflow=5",
|
||||
"-Wconversion",
|
||||
|
||||
// C++ flags
|
||||
"-fno-rtti",
|
||||
"-fexceptions",
|
||||
|
||||
// Linker flags
|
||||
"-T${workspaceFolder}/Architecture/amd64/linker.ld",
|
||||
"-Wl,-static,--no-dynamic-linker,-ztext",
|
||||
"-nostdlib",
|
||||
"-nodefaultlibs",
|
||||
"-nolibc",
|
||||
"-zmax-page-size=0x1000",
|
||||
"-shared",
|
||||
|
||||
// Debug flags
|
||||
"-ggdb3",
|
||||
"-O0",
|
||||
"-fdiagnostics-color=always",
|
||||
"-fverbose-asm",
|
||||
"-fstack-usage",
|
||||
"-fstack-check",
|
||||
"-fsanitize=undefined",
|
||||
|
||||
// VSCode flags
|
||||
"-ffreestanding",
|
||||
"-nostdinc",
|
||||
"-nostdinc++"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "FennixLoader x32 (Linux, GCC, debug)",
|
||||
"includePath": [
|
||||
"${workspaceFolder}/FennixLoader/include"
|
||||
],
|
||||
"defines": [
|
||||
"__debug_vscode__",
|
||||
"KERNEL_NAME=\"Fennix\"",
|
||||
"KERNEL_VERSION=\"1.0\"",
|
||||
"GIT_COMMIT=\"0000000000000000000000000000000000000000\"",
|
||||
"GIT_COMMIT_SHORT=\"0000000\"",
|
||||
"DEBUG=\"1\""
|
||||
],
|
||||
"compilerPath": "${workspaceFolder}/../tools/cross/bin/i386-elf-gcc",
|
||||
"cStandard": "c17",
|
||||
"cppStandard": "c++20",
|
||||
"intelliSenseMode": "gcc-x86",
|
||||
"configurationProvider": "ms-vscode.makefile-tools",
|
||||
"compilerArgs": [
|
||||
// Compiler flags
|
||||
"-fno-pic",
|
||||
"-fno-pie",
|
||||
"-mno-80387",
|
||||
"-mno-mmx",
|
||||
"-mno-3dnow",
|
||||
"-mno-red-zone",
|
||||
"-march=pentium",
|
||||
"-pipe",
|
||||
"-msoft-float",
|
||||
"-fno-builtin",
|
||||
|
||||
// Warnings
|
||||
"-Wall",
|
||||
"-Wextra",
|
||||
"-Wfloat-equal",
|
||||
"-Wpointer-arith",
|
||||
"-Wcast-align",
|
||||
"-Wredundant-decls",
|
||||
"-Winit-self",
|
||||
"-Wswitch-default",
|
||||
"-Wstrict-overflow=5",
|
||||
"-Wconversion",
|
||||
|
||||
// C++ flags
|
||||
"-fno-rtti",
|
||||
"-fexceptions",
|
||||
|
||||
// Linker flags
|
||||
"-T${workspaceFolder}/Architecture/i386/linker.ld",
|
||||
"-Wl,-static,--no-dynamic-linker,-ztext",
|
||||
"-nostdlib",
|
||||
"-nodefaultlibs",
|
||||
"-nolibc",
|
||||
"-zmax-page-size=0x1000",
|
||||
"-shared",
|
||||
|
||||
// Debug flags
|
||||
"-ggdb3",
|
||||
"-O0",
|
||||
"-fdiagnostics-color=always",
|
||||
"-fverbose-asm",
|
||||
"-fstack-usage",
|
||||
"-fstack-check",
|
||||
"-fsanitize=undefined",
|
||||
|
||||
// VSCode flags
|
||||
"-ffreestanding",
|
||||
"-nostdinc",
|
||||
|
40
.vscode/launch.json
vendored
40
.vscode/launch.json
vendored
@ -1,40 +0,0 @@
|
||||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "FLDR.elf",
|
||||
"type": "cppdbg",
|
||||
"request": "launch",
|
||||
"program": "${workspaceRoot}/FLDR.elf",
|
||||
"cwd": "${workspaceRoot}",
|
||||
"args": [],
|
||||
"targetArchitecture": "x86",
|
||||
"MIMode": "gdb",
|
||||
"miDebuggerPath": "/usr/bin/gdb",
|
||||
"miDebuggerArgs": "",
|
||||
"externalConsole": false,
|
||||
"additionalSOLibSearchPath": "${workspaceRoot}",
|
||||
"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 ${workspaceRoot}/FLDR.elf",
|
||||
"description": "Load binary."
|
||||
},
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
@ -1,327 +0,0 @@
|
||||
/* Source: https://github.com/glitchub/arith64 */
|
||||
#define arith64_u64 unsigned long long int
|
||||
#define arith64_s64 signed long long int
|
||||
#define arith64_u32 unsigned int
|
||||
#define arith64_s32 int
|
||||
|
||||
typedef union
|
||||
{
|
||||
arith64_u64 u64;
|
||||
arith64_s64 s64;
|
||||
struct
|
||||
{
|
||||
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||
arith64_u32 hi;
|
||||
arith64_u32 lo;
|
||||
#else
|
||||
arith64_u32 lo;
|
||||
arith64_u32 hi;
|
||||
#endif
|
||||
} u32;
|
||||
struct
|
||||
{
|
||||
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||
arith64_s32 hi;
|
||||
arith64_s32 lo;
|
||||
#else
|
||||
arith64_s32 lo;
|
||||
arith64_s32 hi;
|
||||
#endif
|
||||
} s32;
|
||||
} arith64_word;
|
||||
|
||||
#define arith64_hi(n) (arith64_word){.u64 = n}.u32.hi
|
||||
#define arith64_lo(n) (arith64_word){.u64 = n}.u32.lo
|
||||
#define arith64_neg(a, b) (((a) ^ ((((arith64_s64)(b)) >= 0) - 1)) + (((arith64_s64)(b)) < 0))
|
||||
#define arith64_abs(a) arith64_neg(a, a)
|
||||
|
||||
arith64_s64 __absvdi2(arith64_s64 a)
|
||||
{
|
||||
return arith64_abs(a);
|
||||
}
|
||||
|
||||
arith64_s64 __ashldi3(arith64_s64 a, int b)
|
||||
{
|
||||
arith64_word w = {.s64 = a};
|
||||
|
||||
b &= 63;
|
||||
|
||||
if (b >= 32)
|
||||
{
|
||||
w.u32.hi = w.u32.lo << (b - 32);
|
||||
w.u32.lo = 0;
|
||||
}
|
||||
else if (b)
|
||||
{
|
||||
w.u32.hi = (w.u32.lo >> (32 - b)) | (w.u32.hi << b);
|
||||
w.u32.lo <<= b;
|
||||
}
|
||||
return w.s64;
|
||||
}
|
||||
|
||||
arith64_s64 __ashrdi3(arith64_s64 a, int b)
|
||||
{
|
||||
arith64_word w = {.s64 = a};
|
||||
|
||||
b &= 63;
|
||||
|
||||
if (b >= 32)
|
||||
{
|
||||
w.s32.lo = w.s32.hi >> (b - 32);
|
||||
w.s32.hi >>= 31; // 0xFFFFFFFF or 0
|
||||
}
|
||||
else if (b)
|
||||
{
|
||||
w.u32.lo = (w.u32.hi << (32 - b)) | (w.u32.lo >> b);
|
||||
w.s32.hi >>= b;
|
||||
}
|
||||
return w.s64;
|
||||
}
|
||||
|
||||
int __clzsi2(arith64_u32 a)
|
||||
{
|
||||
int b, n = 0;
|
||||
b = !(a & 0xffff0000) << 4;
|
||||
n += b;
|
||||
a <<= b;
|
||||
b = !(a & 0xff000000) << 3;
|
||||
n += b;
|
||||
a <<= b;
|
||||
b = !(a & 0xf0000000) << 2;
|
||||
n += b;
|
||||
a <<= b;
|
||||
b = !(a & 0xc0000000) << 1;
|
||||
n += b;
|
||||
a <<= b;
|
||||
return n + !(a & 0x80000000);
|
||||
}
|
||||
|
||||
int __clzdi2(arith64_u64 a)
|
||||
{
|
||||
int b, n = 0;
|
||||
b = !(a & 0xffffffff00000000ULL) << 5;
|
||||
n += b;
|
||||
a <<= b;
|
||||
b = !(a & 0xffff000000000000ULL) << 4;
|
||||
n += b;
|
||||
a <<= b;
|
||||
b = !(a & 0xff00000000000000ULL) << 3;
|
||||
n += b;
|
||||
a <<= b;
|
||||
b = !(a & 0xf000000000000000ULL) << 2;
|
||||
n += b;
|
||||
a <<= b;
|
||||
b = !(a & 0xc000000000000000ULL) << 1;
|
||||
n += b;
|
||||
a <<= b;
|
||||
return n + !(a & 0x8000000000000000ULL);
|
||||
}
|
||||
|
||||
int __ctzsi2(arith64_u32 a)
|
||||
{
|
||||
int b, n = 0;
|
||||
b = !(a & 0x0000ffff) << 4;
|
||||
n += b;
|
||||
a >>= b;
|
||||
b = !(a & 0x000000ff) << 3;
|
||||
n += b;
|
||||
a >>= b;
|
||||
b = !(a & 0x0000000f) << 2;
|
||||
n += b;
|
||||
a >>= b;
|
||||
b = !(a & 0x00000003) << 1;
|
||||
n += b;
|
||||
a >>= b;
|
||||
return n + !(a & 0x00000001);
|
||||
}
|
||||
|
||||
int __ctzdi2(arith64_u64 a)
|
||||
{
|
||||
int b, n = 0;
|
||||
b = !(a & 0x00000000ffffffffULL) << 5;
|
||||
n += b;
|
||||
a >>= b;
|
||||
b = !(a & 0x000000000000ffffULL) << 4;
|
||||
n += b;
|
||||
a >>= b;
|
||||
b = !(a & 0x00000000000000ffULL) << 3;
|
||||
n += b;
|
||||
a >>= b;
|
||||
b = !(a & 0x000000000000000fULL) << 2;
|
||||
n += b;
|
||||
a >>= b;
|
||||
b = !(a & 0x0000000000000003ULL) << 1;
|
||||
n += b;
|
||||
a >>= b;
|
||||
return n + !(a & 0x0000000000000001ULL);
|
||||
}
|
||||
|
||||
arith64_u64 __divmoddi4(arith64_u64 a, arith64_u64 b, arith64_u64 *c)
|
||||
{
|
||||
if (b > a)
|
||||
{
|
||||
if (c)
|
||||
*c = a;
|
||||
return 0;
|
||||
}
|
||||
if (!arith64_hi(b))
|
||||
{
|
||||
if (b == 0)
|
||||
{
|
||||
volatile char x = 0;
|
||||
x = 1 / x;
|
||||
}
|
||||
if (b == 1)
|
||||
{
|
||||
if (c)
|
||||
*c = 0;
|
||||
return a;
|
||||
}
|
||||
if (!arith64_hi(a))
|
||||
{
|
||||
if (c)
|
||||
*c = arith64_lo(a) % arith64_lo(b);
|
||||
return arith64_lo(a) / arith64_lo(b);
|
||||
}
|
||||
}
|
||||
|
||||
char bits = __clzdi2(b) - __clzdi2(a) + 1;
|
||||
arith64_u64 rem = a >> bits;
|
||||
a <<= 64 - bits;
|
||||
arith64_u64 wrap = 0;
|
||||
while (bits-- > 0)
|
||||
{
|
||||
rem = (rem << 1) | (a >> 63);
|
||||
a = (a << 1) | (wrap & 1);
|
||||
wrap = ((arith64_s64)(b - rem - 1) >> 63);
|
||||
rem -= b & wrap;
|
||||
}
|
||||
if (c)
|
||||
*c = rem;
|
||||
return (a << 1) | (wrap & 1);
|
||||
}
|
||||
|
||||
arith64_s64 __divdi3(arith64_s64 a, arith64_s64 b)
|
||||
{
|
||||
arith64_u64 q = __divmoddi4(arith64_abs(a), arith64_abs(b), (void *)0);
|
||||
return arith64_neg(q, a ^ b);
|
||||
}
|
||||
|
||||
int __ffsdi2(arith64_u64 a) { return a ? __ctzdi2(a) + 1 : 0; }
|
||||
|
||||
arith64_u64 __lshrdi3(arith64_u64 a, int b)
|
||||
{
|
||||
arith64_word w = {.u64 = a};
|
||||
|
||||
b &= 63;
|
||||
|
||||
if (b >= 32)
|
||||
{
|
||||
w.u32.lo = w.u32.hi >> (b - 32);
|
||||
w.u32.hi = 0;
|
||||
}
|
||||
else if (b)
|
||||
{
|
||||
w.u32.lo = (w.u32.hi << (32 - b)) | (w.u32.lo >> b);
|
||||
w.u32.hi >>= b;
|
||||
}
|
||||
return w.u64;
|
||||
}
|
||||
|
||||
arith64_s64 __moddi3(arith64_s64 a, arith64_s64 b)
|
||||
{
|
||||
arith64_u64 r;
|
||||
__divmoddi4(arith64_abs(a), arith64_abs(b), &r);
|
||||
return arith64_neg(r, a);
|
||||
}
|
||||
|
||||
int __popcountsi2(arith64_u32 a)
|
||||
{
|
||||
|
||||
a = a - ((a >> 1) & 0x55555555);
|
||||
a = ((a >> 2) & 0x33333333) + (a & 0x33333333);
|
||||
a = (a + (a >> 4)) & 0x0F0F0F0F;
|
||||
a = (a + (a >> 16));
|
||||
|
||||
return (a + (a >> 8)) & 63;
|
||||
}
|
||||
|
||||
int __popcountdi2(arith64_u64 a)
|
||||
{
|
||||
|
||||
a = a - ((a >> 1) & 0x5555555555555555ULL);
|
||||
a = ((a >> 2) & 0x3333333333333333ULL) + (a & 0x3333333333333333ULL);
|
||||
a = (a + (a >> 4)) & 0x0F0F0F0F0F0F0F0FULL;
|
||||
a = (a + (a >> 32));
|
||||
a = (a + (a >> 16));
|
||||
|
||||
return (a + (a >> 8)) & 127;
|
||||
}
|
||||
|
||||
arith64_u64 __udivdi3(arith64_u64 a, arith64_u64 b) { return __divmoddi4(a, b, (void *)0); }
|
||||
|
||||
arith64_u64 __umoddi3(arith64_u64 a, arith64_u64 b)
|
||||
{
|
||||
arith64_u64 r;
|
||||
__divmoddi4(a, b, &r);
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Good documentation: https://splichal.eu/scripts/sphinx/gccint/_build/html/the-gcc-low-level-runtime-library/routines-for-floating-point-emulation.html */
|
||||
|
||||
double __adddf3(double a, double b) { return a + b; }
|
||||
double __muldf3(double a, double b) { return a * b; }
|
||||
double __floatsidf(int i) { return (double)i; }
|
||||
int __ltdf2(double a, double b) { return a < b; }
|
||||
int __gtdf2(double a, double b) { return a > b; }
|
||||
int __nedf2(double a, double b) { return a != b; }
|
||||
int __eqdf2(double a, double b) { return a == b; }
|
||||
double __floatdidf(long i) { return (double)i; }
|
||||
double __divdf3(double a, double b) { return a / b; }
|
||||
double __subdf3(double a, double b) { return a - b; }
|
||||
int __gedf2(double a, double b) { return a >= b; }
|
||||
int __fixdfsi(double a) { return (int)a; }
|
||||
long __fixdfdi(double a) { return (long)a; }
|
||||
int __ledf2(double a, double b) { return a <= b; }
|
||||
|
||||
/* FIXME: Check if these functions are implemented correctly */
|
||||
|
||||
typedef long long int64_t;
|
||||
typedef unsigned long long uint64_t;
|
||||
typedef unsigned int uint32_t;
|
||||
typedef struct
|
||||
{
|
||||
uint64_t value;
|
||||
} atomic_uint64_t;
|
||||
|
||||
uint64_t __atomic_load_8(const atomic_uint64_t *p)
|
||||
{
|
||||
uint64_t value;
|
||||
__asm__ volatile("lock cmpxchg8b %1"
|
||||
: "=A"(value)
|
||||
: "m"(*p)
|
||||
: "memory");
|
||||
return value;
|
||||
}
|
||||
|
||||
void __atomic_store_8(atomic_uint64_t *p, uint64_t value)
|
||||
{
|
||||
__asm__ volatile("lock cmpxchg8b %0"
|
||||
: "=m"(p->value)
|
||||
: "a"((uint32_t)value), "d"((uint32_t)(value >> 32)), "m"(*p)
|
||||
: "memory");
|
||||
}
|
||||
|
||||
/* FIXME: __fixsfsi is not implemented correctly(?) */
|
||||
int __fixsfsi(float a) { return (int)a; }
|
||||
|
||||
int __ltsf2(float a, float b) { return a < b; }
|
||||
int __eqsf2(float a, float b) { return a == b; }
|
||||
float __divsf3(float a, float b) { return a / b; }
|
||||
double __extendsfdf2(float a) { return (double)a; }
|
||||
float __truncdfsf2(double a) { return (float)a; }
|
||||
float __subsf3(float a, float b) { return a - b; }
|
||||
float __floatsisf(int a) { return (float)a; }
|
||||
int __fixunssfsi(float a) { return (int)a; }
|
||||
float __mulsf3(float a, float b) { return a * b; }
|
||||
float __addsf3(float a, float b) { return a + b; }
|
@ -1,34 +0,0 @@
|
||||
[bits 32]
|
||||
|
||||
extern loader_main
|
||||
|
||||
section .text
|
||||
|
||||
MB_HeaderMagic:
|
||||
dq 0
|
||||
|
||||
MB_HeaderInfo:
|
||||
dq 0
|
||||
|
||||
global _start
|
||||
_start:
|
||||
cli
|
||||
mov [MB_HeaderMagic], eax
|
||||
mov [MB_HeaderInfo], ebx
|
||||
mov esp, KernelStack
|
||||
mov eax, [MB_HeaderMagic]
|
||||
mov ebx, [MB_HeaderInfo]
|
||||
push ebx
|
||||
push eax
|
||||
call loader_main
|
||||
.hang:
|
||||
cli
|
||||
hlt
|
||||
jmp .hang
|
||||
|
||||
STACK_SIZE equ 0x4000 ; 16KB
|
||||
|
||||
section .bss
|
||||
align 16
|
||||
KernelStack:
|
||||
resb STACK_SIZE
|
@ -1,115 +0,0 @@
|
||||
#include <debug.h>
|
||||
#include <printf.h>
|
||||
|
||||
enum vga_color
|
||||
{
|
||||
VGA_COLOR_BLACK = 0,
|
||||
VGA_COLOR_BLUE = 1,
|
||||
VGA_COLOR_GREEN = 2,
|
||||
VGA_COLOR_CYAN = 3,
|
||||
VGA_COLOR_RED = 4,
|
||||
VGA_COLOR_MAGENTA = 5,
|
||||
VGA_COLOR_BROWN = 6,
|
||||
VGA_COLOR_LIGHT_GREY = 7,
|
||||
VGA_COLOR_DARK_GREY = 8,
|
||||
VGA_COLOR_LIGHT_BLUE = 9,
|
||||
VGA_COLOR_LIGHT_GREEN = 10,
|
||||
VGA_COLOR_LIGHT_CYAN = 11,
|
||||
VGA_COLOR_LIGHT_RED = 12,
|
||||
VGA_COLOR_LIGHT_MAGENTA = 13,
|
||||
VGA_COLOR_LIGHT_BROWN = 14,
|
||||
VGA_COLOR_WHITE = 15,
|
||||
};
|
||||
|
||||
extern "C" void terminal_setcolor(uint8_t color);
|
||||
extern "C" void putchar(char c);
|
||||
extern bool DoNotWriteOnScreen;
|
||||
|
||||
static inline void WritePrefix(DebugLevel Level, const char *File, int Line, const char *Function)
|
||||
{
|
||||
const char *DbgLvlString;
|
||||
switch (Level)
|
||||
{
|
||||
case DebugLevelError:
|
||||
DbgLvlString = "ERROR";
|
||||
terminal_setcolor(VGA_COLOR_RED);
|
||||
break;
|
||||
case DebugLevelWarning:
|
||||
DbgLvlString = "WARN ";
|
||||
terminal_setcolor(VGA_COLOR_BROWN);
|
||||
break;
|
||||
case DebugLevelInfo:
|
||||
DbgLvlString = "INFO ";
|
||||
terminal_setcolor(VGA_COLOR_LIGHT_GREY);
|
||||
break;
|
||||
case DebugLevelDebug:
|
||||
DbgLvlString = "DEBUG";
|
||||
terminal_setcolor(VGA_COLOR_GREEN);
|
||||
break;
|
||||
case DebugLevelTrace:
|
||||
DbgLvlString = "TRACE";
|
||||
terminal_setcolor(VGA_COLOR_DARK_GREY);
|
||||
break;
|
||||
case DebugLevelFixme:
|
||||
DbgLvlString = "FIXME";
|
||||
terminal_setcolor(VGA_COLOR_LIGHT_RED);
|
||||
break;
|
||||
case DebugLevelUbsan:
|
||||
{
|
||||
DbgLvlString = "UBSAN";
|
||||
printf("%s|%s: ", DbgLvlString, Function);
|
||||
terminal_setcolor(VGA_COLOR_LIGHT_RED);
|
||||
return;
|
||||
}
|
||||
default:
|
||||
DbgLvlString = "UNKNW";
|
||||
terminal_setcolor(VGA_COLOR_WHITE);
|
||||
break;
|
||||
}
|
||||
DoNotWriteOnScreen = true;
|
||||
printf("%s|%s->%s:%d: ", DbgLvlString, File, Function, Line);
|
||||
DoNotWriteOnScreen = false;
|
||||
}
|
||||
|
||||
namespace SysDbg
|
||||
{
|
||||
void Write(DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...)
|
||||
{
|
||||
WritePrefix(Level, File, Line, Function);
|
||||
va_list args;
|
||||
va_start(args, Format);
|
||||
vprintf(Format, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void WriteLine(DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...)
|
||||
{
|
||||
WritePrefix(Level, File, Line, Function);
|
||||
va_list args;
|
||||
va_start(args, Format);
|
||||
vprintf(Format, args);
|
||||
va_end(args);
|
||||
putchar('\n');
|
||||
}
|
||||
}
|
||||
|
||||
// C compatibility
|
||||
extern "C" void SysDbgWrite(enum DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...)
|
||||
{
|
||||
WritePrefix(Level, File, Line, Function);
|
||||
va_list args;
|
||||
va_start(args, Format);
|
||||
vprintf(Format, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
// C compatibility
|
||||
extern "C" void SysDbgWriteLine(enum DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...)
|
||||
{
|
||||
WritePrefix(Level, File, Line, Function);
|
||||
va_list args;
|
||||
va_start(args, Format);
|
||||
vprintf(Format, args);
|
||||
va_end(args);
|
||||
putchar('\n');
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
[bits 32]
|
||||
global Detect64Bit
|
||||
Detect64Bit:
|
||||
mov eax, 0x80000000
|
||||
cpuid
|
||||
cmp eax, 0x80000001
|
||||
jb .NoLongMode
|
||||
mov eax, 0x80000001
|
||||
cpuid
|
||||
test edx, 1 << 29
|
||||
jz .NoLongMode
|
||||
mov eax, 1
|
||||
ret
|
||||
.NoLongMode:
|
||||
xor eax, eax
|
||||
ret
|
@ -1,20 +0,0 @@
|
||||
[bits 32]
|
||||
global DetectCPUID
|
||||
DetectCPUID:
|
||||
pushfd
|
||||
pop eax
|
||||
mov ecx, eax
|
||||
xor eax, 1 << 21
|
||||
push eax
|
||||
popfd
|
||||
pushfd
|
||||
pop eax
|
||||
push ecx
|
||||
popfd
|
||||
xor eax, ecx
|
||||
jz .NoCPUID
|
||||
mov eax, 1
|
||||
ret
|
||||
.NoCPUID:
|
||||
xor eax, eax
|
||||
ret
|
@ -1,142 +0,0 @@
|
||||
#include "loadelf.hpp"
|
||||
|
||||
#include <memory.hpp>
|
||||
#include <debug.h>
|
||||
#include <elf.h>
|
||||
|
||||
static uint64_t KernelJumpAddress = 0x0;
|
||||
|
||||
bool LoadElfInMemory(void *Address, size_t Length, bool Allow64)
|
||||
{
|
||||
Elf32_Ehdr *Header32 = (Elf32_Ehdr *)Address;
|
||||
Elf64_Ehdr *Header64 = (Elf64_Ehdr *)Address;
|
||||
|
||||
bool Is64Bit = false;
|
||||
|
||||
if (Header32->e_ident[EI_MAG0] == ELFMAG0 &&
|
||||
Header32->e_ident[EI_MAG1] == ELFMAG1 &&
|
||||
Header32->e_ident[EI_MAG2] == ELFMAG2 &&
|
||||
Header32->e_ident[EI_MAG3] == ELFMAG3)
|
||||
{
|
||||
debug("Elf magic is correct");
|
||||
if (Header32->e_machine == EM_X86_64)
|
||||
{
|
||||
if (!Allow64)
|
||||
{
|
||||
error("64 bit elf not allowed");
|
||||
return false;
|
||||
}
|
||||
Is64Bit = true;
|
||||
debug("Elf is 64 bit");
|
||||
}
|
||||
else if (Header32->e_machine == EM_386)
|
||||
{
|
||||
if (Allow64)
|
||||
{
|
||||
error("32 bit elf not allowed");
|
||||
return false;
|
||||
}
|
||||
debug("Elf is 32 bit");
|
||||
}
|
||||
else
|
||||
{
|
||||
error("Elf is neither 32 nor 64 bit");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Is64Bit)
|
||||
{
|
||||
fixme("64 bit elf not implemented");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Header32->e_phentsize != sizeof(Elf32_Phdr))
|
||||
{
|
||||
error("Elf program header size is not correct");
|
||||
return false;
|
||||
}
|
||||
|
||||
Elf32_Phdr *ProgramHeader = (Elf32_Phdr *)((uintptr_t)Address + Header32->e_phoff);
|
||||
for (size_t i = 0; i < Header32->e_phnum; i++)
|
||||
{
|
||||
if (ProgramHeader[i].p_type != PT_LOAD)
|
||||
continue;
|
||||
|
||||
if (ProgramHeader[i].p_filesz > ProgramHeader[i].p_memsz)
|
||||
{
|
||||
error("File size is greater than memory size");
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t SegmentSize = ProgramHeader[i].p_memsz;
|
||||
void *VirtualAddress = (void *)ProgramHeader[i].p_vaddr;
|
||||
void *PhysicalAddress = KernelAllocator32.RequestPages(TO_PAGES(SegmentSize));
|
||||
debug("- Segment: %p (physical allocated at: %p) (%#x bytes)", VirtualAddress, PhysicalAddress, SegmentSize);
|
||||
|
||||
debug(" Mapping %d pages at %p (%p-%p)", TO_PAGES(SegmentSize), VirtualAddress, PhysicalAddress, (void *)((uintptr_t)PhysicalAddress + TO_PAGES(SegmentSize) * PAGE_SIZE));
|
||||
Memory32::Virtual().Map(VirtualAddress, PhysicalAddress, SegmentSize, P | RW);
|
||||
|
||||
void *memcpy_Dest = (void *)((uintptr_t)PhysicalAddress + (ProgramHeader[i].p_vaddr - 0xC0000000));
|
||||
void *memcpy_Src = (void *)((uintptr_t)Address + ProgramHeader[i].p_offset);
|
||||
debug(" memcpy(%p, %p, %#x)", memcpy_Dest, memcpy_Src, ProgramHeader[i].p_filesz);
|
||||
memcpy(memcpy_Dest, memcpy_Src, ProgramHeader[i].p_filesz);
|
||||
|
||||
if (ProgramHeader[i].p_filesz < ProgramHeader[i].p_memsz)
|
||||
{
|
||||
debug(" Zeroing %#x bytes at %p", ProgramHeader[i].p_memsz - ProgramHeader[i].p_filesz, (void *)((uintptr_t)PhysicalAddress + ProgramHeader[i].p_filesz));
|
||||
memset((void *)((uintptr_t)PhysicalAddress + ProgramHeader[i].p_filesz), 0, ProgramHeader[i].p_memsz - ProgramHeader[i].p_filesz);
|
||||
}
|
||||
}
|
||||
|
||||
void *Stack = KernelAllocator32.RequestPage();
|
||||
memset(Stack, 0, PAGE_SIZE - 1);
|
||||
debug("Stack allocated at: %p", Stack);
|
||||
|
||||
void *StackTop = (void *)((uintptr_t)Stack + PAGE_SIZE - 0x10);
|
||||
debug("Stack top at: %p", StackTop);
|
||||
|
||||
debug("Memory Info: %lldMB / %lldMB (%lldMB reserved)",
|
||||
TO_MB(KernelAllocator32.UsedMemory),
|
||||
TO_MB(KernelAllocator32.TotalMemory),
|
||||
TO_MB(KernelAllocator32.ReservedMemory));
|
||||
|
||||
debug("Kernel Entry Point: %p", (void *)Header32->e_entry);
|
||||
KernelJumpAddress = (uint64_t)Header32->e_entry;
|
||||
|
||||
asmv("cli");
|
||||
asmv("mov %0, %%esp"
|
||||
:
|
||||
: "r"(StackTop));
|
||||
asmv("pushf\n"
|
||||
"orl $0x46, (%esp)\n"
|
||||
"popf");
|
||||
asmv("mov $0x80000011, %eax");
|
||||
asmv("mov %eax, %cr0");
|
||||
asmv("mov $0, %eax");
|
||||
asmv("mov %eax, %cr4");
|
||||
asmv("mov $0, %eax\n"
|
||||
"mov $0, %ebx\n"
|
||||
"mov $0, %ecx\n"
|
||||
"mov $0, %edx\n"
|
||||
"mov $0, %esi\n"
|
||||
"mov $0, %edi\n"
|
||||
"mov $0, %ebp\n");
|
||||
asmv("call %0"
|
||||
:
|
||||
: "r"(KernelJumpAddress));
|
||||
// asmv("jmp %0"
|
||||
// :
|
||||
// : "r"(KernelJumpAddress));
|
||||
|
||||
|
||||
// asmv("call *%0"
|
||||
// :
|
||||
// : "r"(KernelJumpAddress));
|
||||
|
||||
// void (*EntryPoint)() = (void (*)())KernelJumpAddress;
|
||||
// EntryPoint();
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
@ -1,371 +0,0 @@
|
||||
#include <multiboot2.h>
|
||||
#include <memory.hpp>
|
||||
#include <binfo.h>
|
||||
#include <debug.h>
|
||||
#include <uart.hpp>
|
||||
|
||||
#include "loadelf.hpp"
|
||||
|
||||
using namespace UniversalAsynchronousReceiverTransmitter;
|
||||
|
||||
BootInfo mb2binfo;
|
||||
|
||||
bool DoNotWriteOnScreen = false;
|
||||
extern "C" void terminal_initialize(void);
|
||||
extern "C" void terminal_putchar(char c);
|
||||
|
||||
extern "C" int DetectCPUID();
|
||||
extern "C" int Detect64Bit();
|
||||
extern "C" void EnablePaging();
|
||||
|
||||
char *strncpy(char *destination, const char *source, unsigned long num)
|
||||
{
|
||||
if (destination == NULL)
|
||||
return NULL;
|
||||
char *ptr = destination;
|
||||
while (*source && num--)
|
||||
{
|
||||
*destination = *source;
|
||||
destination++;
|
||||
source++;
|
||||
}
|
||||
*destination = '\0';
|
||||
return ptr;
|
||||
}
|
||||
|
||||
long unsigned strlen(const char s[])
|
||||
{
|
||||
long unsigned i = 0;
|
||||
if (s)
|
||||
while (s[i] != '\0')
|
||||
++i;
|
||||
return i;
|
||||
}
|
||||
|
||||
int strcmp(const char *l, const char *r)
|
||||
{
|
||||
for (; *l == *r && *l; l++, r++)
|
||||
;
|
||||
return *(unsigned char *)l - *(unsigned char *)r;
|
||||
}
|
||||
|
||||
extern "C" void putchar(char c)
|
||||
{
|
||||
if (mb2binfo.Framebuffer[0].Type == FramebufferType::EGA && !DoNotWriteOnScreen)
|
||||
terminal_putchar(c);
|
||||
UART(COM1).Write(c);
|
||||
}
|
||||
|
||||
void ProcessMB2(uint32_t Info)
|
||||
{
|
||||
auto InfoAddress = Info;
|
||||
for (auto Tag = (struct multiboot_tag *)((uint8_t *)(uint64_t)InfoAddress + 8);
|
||||
;
|
||||
Tag = (struct multiboot_tag *)((multiboot_uint8_t *)Tag + ((Tag->size + 7) & ~7)))
|
||||
{
|
||||
if (Tag->type == MULTIBOOT_TAG_TYPE_END)
|
||||
{
|
||||
debug("End of multiboot2 tags");
|
||||
break;
|
||||
}
|
||||
|
||||
switch (Tag->type)
|
||||
{
|
||||
case MULTIBOOT_TAG_TYPE_CMDLINE:
|
||||
{
|
||||
strncpy(mb2binfo.Kernel.CommandLine,
|
||||
((multiboot_tag_string *)Tag)->string,
|
||||
strlen(((multiboot_tag_string *)Tag)->string));
|
||||
debug("Kernel command line: %s", mb2binfo.Kernel.CommandLine);
|
||||
break;
|
||||
}
|
||||
case MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME:
|
||||
{
|
||||
strncpy(mb2binfo.Bootloader.Name,
|
||||
((multiboot_tag_string *)Tag)->string,
|
||||
strlen(((multiboot_tag_string *)Tag)->string));
|
||||
debug("Bootloader name: %s", mb2binfo.Bootloader.Name);
|
||||
break;
|
||||
}
|
||||
case MULTIBOOT_TAG_TYPE_MODULE:
|
||||
{
|
||||
multiboot_tag_module *module = (multiboot_tag_module *)Tag;
|
||||
static int module_count = 0;
|
||||
mb2binfo.Modules[module_count].Address = (void *)(uint64_t)module->mod_start;
|
||||
mb2binfo.Modules[module_count].Size = (uint64_t)module->size;
|
||||
strncpy(mb2binfo.Modules[module_count].Path, "(null)", 6);
|
||||
strncpy(mb2binfo.Modules[module_count].CommandLine, module->cmdline,
|
||||
strlen(module->cmdline));
|
||||
debug("Module: %s %s %p %lld", mb2binfo.Modules[module_count].Path,
|
||||
mb2binfo.Modules[module_count].CommandLine,
|
||||
mb2binfo.Modules[module_count].Address,
|
||||
mb2binfo.Modules[module_count].Size);
|
||||
module_count++;
|
||||
break;
|
||||
}
|
||||
case MULTIBOOT_TAG_TYPE_BASIC_MEMINFO:
|
||||
{
|
||||
multiboot_tag_basic_meminfo *meminfo = (multiboot_tag_basic_meminfo *)Tag;
|
||||
fixme("basic_meminfo->[mem_lower: %#x, mem_upper: %#x]",
|
||||
meminfo->mem_lower, meminfo->mem_upper);
|
||||
break;
|
||||
}
|
||||
case MULTIBOOT_TAG_TYPE_BOOTDEV:
|
||||
{
|
||||
multiboot_tag_bootdev *bootdev = (multiboot_tag_bootdev *)Tag;
|
||||
fixme("bootdev->[biosdev: %#x, slice: %#x, part: %#x]",
|
||||
bootdev->biosdev, bootdev->slice, bootdev->part);
|
||||
break;
|
||||
}
|
||||
case MULTIBOOT_TAG_TYPE_MMAP:
|
||||
{
|
||||
multiboot_tag_mmap *mmap = (multiboot_tag_mmap *)Tag;
|
||||
uint32_t EntryCount = mmap->size / sizeof(multiboot_mmap_entry);
|
||||
mb2binfo.Memory.Entries = EntryCount;
|
||||
for (uint32_t i = 0; i < EntryCount; i++)
|
||||
{
|
||||
if (EntryCount > MAX_MEMORY_ENTRIES)
|
||||
{
|
||||
warn("Too many memory entries, skipping the rest...");
|
||||
break;
|
||||
}
|
||||
multiboot_mmap_entry entry = mmap->entries[i];
|
||||
mb2binfo.Memory.Size += entry.len;
|
||||
switch (entry.type)
|
||||
{
|
||||
case MULTIBOOT_MEMORY_AVAILABLE:
|
||||
mb2binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr;
|
||||
mb2binfo.Memory.Entry[i].Length = entry.len;
|
||||
mb2binfo.Memory.Entry[i].Type = Usable;
|
||||
debug("Available memory: %#llx - %#llx", entry.addr, entry.addr + entry.len);
|
||||
break;
|
||||
case MULTIBOOT_MEMORY_RESERVED:
|
||||
mb2binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr;
|
||||
mb2binfo.Memory.Entry[i].Length = entry.len;
|
||||
mb2binfo.Memory.Entry[i].Type = Reserved;
|
||||
debug("Reserved memory: %#llx - %#llx", entry.addr, entry.addr + entry.len);
|
||||
break;
|
||||
case MULTIBOOT_MEMORY_ACPI_RECLAIMABLE:
|
||||
mb2binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr;
|
||||
mb2binfo.Memory.Entry[i].Length = entry.len;
|
||||
mb2binfo.Memory.Entry[i].Type = ACPIReclaimable;
|
||||
debug("ACPI reclaimable memory: %#llx - %#llx", entry.addr, entry.addr + entry.len);
|
||||
break;
|
||||
case MULTIBOOT_MEMORY_NVS:
|
||||
mb2binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr;
|
||||
mb2binfo.Memory.Entry[i].Length = entry.len;
|
||||
mb2binfo.Memory.Entry[i].Type = ACPINVS;
|
||||
debug("ACPI NVS memory: %#llx - %#llx", entry.addr, entry.addr + entry.len);
|
||||
break;
|
||||
case MULTIBOOT_MEMORY_BADRAM:
|
||||
mb2binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr;
|
||||
mb2binfo.Memory.Entry[i].Length = entry.len;
|
||||
mb2binfo.Memory.Entry[i].Type = BadMemory;
|
||||
debug("Bad memory: %#llx - %#llx", entry.addr, entry.addr + entry.len);
|
||||
break;
|
||||
default:
|
||||
mb2binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr;
|
||||
mb2binfo.Memory.Entry[i].Length = entry.len;
|
||||
mb2binfo.Memory.Entry[i].Type = Unknown;
|
||||
debug("Unknown memory: %#llx - %#llx", entry.addr, entry.addr + entry.len);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MULTIBOOT_TAG_TYPE_VBE:
|
||||
{
|
||||
multiboot_tag_vbe *vbe = (multiboot_tag_vbe *)Tag;
|
||||
fixme("vbe->[vbe_mode: %#x, vbe_interface_seg: %#x, vbe_interface_off: %#x, vbe_interface_len: %#x]",
|
||||
vbe->vbe_mode, vbe->vbe_interface_seg, vbe->vbe_interface_off, vbe->vbe_interface_len);
|
||||
break;
|
||||
}
|
||||
case MULTIBOOT_TAG_TYPE_FRAMEBUFFER:
|
||||
{
|
||||
multiboot_tag_framebuffer *fb = (multiboot_tag_framebuffer *)Tag;
|
||||
static int fb_count = 0;
|
||||
mb2binfo.Framebuffer[fb_count].BaseAddress = (void *)fb->common.framebuffer_addr;
|
||||
mb2binfo.Framebuffer[fb_count].Width = fb->common.framebuffer_width;
|
||||
mb2binfo.Framebuffer[fb_count].Height = fb->common.framebuffer_height;
|
||||
mb2binfo.Framebuffer[fb_count].Pitch = fb->common.framebuffer_pitch;
|
||||
mb2binfo.Framebuffer[fb_count].BitsPerPixel = fb->common.framebuffer_bpp;
|
||||
switch (fb->common.framebuffer_type)
|
||||
{
|
||||
case MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED:
|
||||
{
|
||||
mb2binfo.Framebuffer[fb_count].Type = FramebufferType::Indexed;
|
||||
break;
|
||||
}
|
||||
case MULTIBOOT_FRAMEBUFFER_TYPE_RGB:
|
||||
{
|
||||
mb2binfo.Framebuffer[fb_count].Type = FramebufferType::RGB;
|
||||
mb2binfo.Framebuffer[fb_count].RedMaskSize = fb->framebuffer_red_mask_size;
|
||||
mb2binfo.Framebuffer[fb_count].RedMaskShift = fb->framebuffer_red_field_position;
|
||||
mb2binfo.Framebuffer[fb_count].GreenMaskSize = fb->framebuffer_green_mask_size;
|
||||
mb2binfo.Framebuffer[fb_count].GreenMaskShift = fb->framebuffer_green_field_position;
|
||||
mb2binfo.Framebuffer[fb_count].BlueMaskSize = fb->framebuffer_blue_mask_size;
|
||||
mb2binfo.Framebuffer[fb_count].BlueMaskShift = fb->framebuffer_blue_field_position;
|
||||
break;
|
||||
}
|
||||
case MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT:
|
||||
{
|
||||
mb2binfo.Framebuffer[fb_count].Type = FramebufferType::EGA;
|
||||
break;
|
||||
}
|
||||
}
|
||||
debug("Framebuffer %d: %dx%d %d bpp", Tag, fb->common.framebuffer_width, fb->common.framebuffer_height, fb->common.framebuffer_bpp);
|
||||
debug("More info:\nAddress: %p\nPitch: %lld\nMemoryModel: %d\nRedMaskSize: %d\nRedMaskShift: %d\nGreenMaskSize: %d\nGreenMaskShift: %d\nBlueMaskSize: %d\nBlueMaskShift: %d",
|
||||
fb->common.framebuffer_addr, fb->common.framebuffer_pitch, fb->common.framebuffer_type,
|
||||
fb->framebuffer_red_mask_size, fb->framebuffer_red_field_position, fb->framebuffer_green_mask_size,
|
||||
fb->framebuffer_green_field_position, fb->framebuffer_blue_mask_size, fb->framebuffer_blue_field_position);
|
||||
fb_count++;
|
||||
break;
|
||||
}
|
||||
case MULTIBOOT_TAG_TYPE_ELF_SECTIONS:
|
||||
{
|
||||
multiboot_tag_elf_sections *elf = (multiboot_tag_elf_sections *)Tag;
|
||||
fixme("elf_sections->[num=%d, size=%d, entsize=%d, shndx=%d]",
|
||||
elf->num, elf->size, elf->entsize, elf->shndx);
|
||||
break;
|
||||
}
|
||||
case MULTIBOOT_TAG_TYPE_APM:
|
||||
{
|
||||
multiboot_tag_apm *apm = (multiboot_tag_apm *)Tag;
|
||||
fixme("apm->[version: %d, cseg: %d, offset: %d, cseg_16: %d, dseg: %d, flags: %d, cseg_len: %d, cseg_16_len: %d, dseg_len: %d]",
|
||||
apm->version, apm->cseg, apm->offset, apm->cseg_16, apm->dseg, apm->flags, apm->cseg_len, apm->cseg_16_len, apm->dseg_len);
|
||||
break;
|
||||
}
|
||||
case MULTIBOOT_TAG_TYPE_EFI32:
|
||||
{
|
||||
multiboot_tag_efi32 *efi32 = (multiboot_tag_efi32 *)Tag;
|
||||
fixme("efi32->[pointer: %p, size: %d]", efi32->pointer, efi32->size);
|
||||
break;
|
||||
}
|
||||
case MULTIBOOT_TAG_TYPE_EFI64:
|
||||
{
|
||||
multiboot_tag_efi64 *efi64 = (multiboot_tag_efi64 *)Tag;
|
||||
fixme("efi64->[pointer: %p, size: %d]", efi64->pointer, efi64->size);
|
||||
break;
|
||||
}
|
||||
case MULTIBOOT_TAG_TYPE_SMBIOS:
|
||||
{
|
||||
multiboot_tag_smbios *smbios = (multiboot_tag_smbios *)Tag;
|
||||
fixme("smbios->[major: %d, minor: %d]", smbios->major, smbios->minor);
|
||||
break;
|
||||
}
|
||||
case MULTIBOOT_TAG_TYPE_ACPI_OLD:
|
||||
{
|
||||
mb2binfo.RSDP = (BootInfo::RSDPInfo *)((multiboot_tag_old_acpi *)Tag)->rsdp;
|
||||
debug("OLD ACPI RSDP: %p", mb2binfo.RSDP);
|
||||
break;
|
||||
}
|
||||
case MULTIBOOT_TAG_TYPE_ACPI_NEW:
|
||||
{
|
||||
mb2binfo.RSDP = (BootInfo::RSDPInfo *)((multiboot_tag_new_acpi *)Tag)->rsdp;
|
||||
debug("NEW ACPI RSDP: %p", mb2binfo.RSDP);
|
||||
break;
|
||||
}
|
||||
case MULTIBOOT_TAG_TYPE_NETWORK:
|
||||
{
|
||||
multiboot_tag_network *net = (multiboot_tag_network *)Tag;
|
||||
fixme("network->[dhcpack: %p]", net->dhcpack);
|
||||
break;
|
||||
}
|
||||
case MULTIBOOT_TAG_TYPE_EFI_MMAP:
|
||||
{
|
||||
multiboot_tag_efi_mmap *efi_mmap = (multiboot_tag_efi_mmap *)Tag;
|
||||
fixme("efi_mmap->[descr_size: %d, descr_vers: %d, efi_mmap: %p]",
|
||||
efi_mmap->descr_size, efi_mmap->descr_vers, efi_mmap->efi_mmap);
|
||||
break;
|
||||
}
|
||||
case MULTIBOOT_TAG_TYPE_EFI_BS:
|
||||
{
|
||||
fixme("efi_bs->[%p] (unknown structure)", Tag);
|
||||
break;
|
||||
}
|
||||
case MULTIBOOT_TAG_TYPE_EFI32_IH:
|
||||
{
|
||||
multiboot_tag_efi32_ih *efi32_ih = (multiboot_tag_efi32_ih *)Tag;
|
||||
fixme("efi32_ih->[pointer: %p]", efi32_ih->pointer);
|
||||
break;
|
||||
}
|
||||
case MULTIBOOT_TAG_TYPE_EFI64_IH:
|
||||
{
|
||||
multiboot_tag_efi64_ih *efi64_ih = (multiboot_tag_efi64_ih *)Tag;
|
||||
fixme("efi64_ih->[pointer: %p]", efi64_ih->pointer);
|
||||
break;
|
||||
}
|
||||
case MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR:
|
||||
{
|
||||
multiboot_tag_load_base_addr *load_base_addr = (multiboot_tag_load_base_addr *)Tag;
|
||||
mb2binfo.Kernel.PhysicalBase = (void *)load_base_addr->load_base_addr;
|
||||
mb2binfo.Kernel.VirtualBase = (void *)(load_base_addr->load_base_addr + 0xC0000000);
|
||||
debug("Kernel base: %p (physical) %p (virtual)", mb2binfo.Kernel.PhysicalBase, mb2binfo.Kernel.VirtualBase);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
error("Unknown multiboot2 tag type: %d", Tag->type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
typedef void (*CallPtr)(void);
|
||||
extern CallPtr __init_array_start[0], __init_array_end[0];
|
||||
extern CallPtr __fini_array_start[0], __fini_array_end[0];
|
||||
|
||||
extern "C" int loader_main(uint32_t magic, uint32_t addr)
|
||||
{
|
||||
if (magic != MULTIBOOT2_BOOTLOADER_MAGIC)
|
||||
{
|
||||
error("Multiboot magic is invalid (%#x != %#x)", magic, MULTIBOOT2_BOOTLOADER_MAGIC);
|
||||
while (1)
|
||||
asmv("cli; hlt");
|
||||
}
|
||||
|
||||
for (CallPtr *func = __init_array_start; func != __init_array_end; func++)
|
||||
(*func)();
|
||||
|
||||
ProcessMB2(addr);
|
||||
if (mb2binfo.Framebuffer[0].Type == FramebufferType::EGA)
|
||||
terminal_initialize();
|
||||
debug("Multiboot2 tags processed");
|
||||
InitializeMemoryManagement(&mb2binfo, true);
|
||||
EnablePaging();
|
||||
|
||||
bool Load64Bit = false;
|
||||
|
||||
if (DetectCPUID())
|
||||
{
|
||||
debug("CPUID supported");
|
||||
if (Detect64Bit())
|
||||
{
|
||||
info("64-bit CPU detected");
|
||||
if (strcmp(mb2binfo.Kernel.CommandLine, "no64bit") == 0)
|
||||
info("64-bit kernel disabled");
|
||||
else
|
||||
Load64Bit = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
info("32-bit CPU detected");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
error("CPUID not supported");
|
||||
while (1)
|
||||
asmv("cli; hlt");
|
||||
}
|
||||
if (!LoadElfInMemory(mb2binfo.Modules[0].Address, mb2binfo.Modules[0].Size, Load64Bit))
|
||||
{
|
||||
error("Kernel not loaded");
|
||||
while (1)
|
||||
asmv("cli; hlt");
|
||||
}
|
||||
error("Unwanted reach");
|
||||
while (1)
|
||||
asmv("cli; hlt");
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
section .multiboot2
|
||||
align 4096
|
||||
HEADER_START:
|
||||
dd 0xE85250D6
|
||||
dd 0
|
||||
dd (HEADER_END - HEADER_START)
|
||||
dd 0x100000000 - (HEADER_END - HEADER_START) - 0 - 0xE85250D6
|
||||
align 8
|
||||
MB2_INFO_REQUEST_TAG_START:
|
||||
dw 1
|
||||
dw 0
|
||||
dd MB2_INFO_REQUEST_TAG_END - MB2_INFO_REQUEST_TAG_START
|
||||
dd 1 ; Command Line
|
||||
dd 2 ; Boot Loader Name
|
||||
dd 3 ; Module
|
||||
dd 4 ; Basic Memory Information
|
||||
dd 5 ; BIOS Boot Device
|
||||
dd 6 ; Memory Map
|
||||
dd 7 ; VBE
|
||||
dd 8 ; Framebuffer
|
||||
dd 9 ; ELF Sections
|
||||
dd 10 ; APM Table
|
||||
dd 11 ; EFI 32-bit System Table Pointer
|
||||
dd 12 ; EFI 64-bit System Table Pointer
|
||||
; dd 13 ; SMBIOS
|
||||
dd 14 ; ACPI Old
|
||||
dd 15 ; ACPI New
|
||||
dd 16 ; Network
|
||||
dd 17 ; EFI Memory Map
|
||||
dd 18 ; EFI Boot Services Notifier
|
||||
dd 19 ; EFI 32-bit Image Handle Pointer
|
||||
dd 20 ; EFI 64-bit Image Handle Pointer
|
||||
dd 21 ; Load Base Address
|
||||
MB2_INFO_REQUEST_TAG_END:
|
||||
align 8
|
||||
MB2_TAG_START:
|
||||
dw 0
|
||||
dw 0
|
||||
dd MB2_TAG_END - MB2_TAG_START
|
||||
MB2_TAG_END:
|
||||
HEADER_END:
|
@ -1,5 +0,0 @@
|
||||
section .multiboot
|
||||
align 4
|
||||
dd 0x1BADB002
|
||||
dd 1 << 0 | 1 << 1
|
||||
dd -(0x1BADB002 + (1 << 0 | 1 << 1))
|
@ -1,50 +0,0 @@
|
||||
# Config file
|
||||
include ../../Makefile.conf
|
||||
|
||||
NASM_ARCH =
|
||||
|
||||
CC = ../../$(COMPILER_PATH)/i386-elf-gcc
|
||||
CPP = ../../$(COMPILER_PATH)/i386-elf-g++
|
||||
NASM = /usr/bin/nasm
|
||||
|
||||
ASM_SOURCES = $(shell find ./ -type f -name '*.asm')
|
||||
C_SOURCES = $(shell find ./ -type f -name '*.c')
|
||||
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp')
|
||||
|
||||
OBJ = $(C_SOURCES:.c=.o) $(CPP_SOURCES:.cpp=.o) $(ASM_SOURCES:.asm=.o)
|
||||
|
||||
LDFLAGS = -shared -nostdlib -nodefaultlibs -nolibc -Tlinker.ld
|
||||
|
||||
CFLAGS = -fno-pic -fno-pie \
|
||||
-mno-red-zone -pipe \
|
||||
-fno-builtin -Wno-main \
|
||||
-march=pentium -I./include -Wall -Wextra
|
||||
|
||||
ifeq ($(DEBUG), 1)
|
||||
CFLAGS += -DDEBUG -ggdb3 -O0 -fdiagnostics-color=always -fsanitize=undefined
|
||||
NASM_ARCH += -F dwarf -g
|
||||
endif
|
||||
|
||||
build: $(OBJ)
|
||||
$(info Linking $@)
|
||||
$(CC) $(LDFLAGS) $(OBJ) -o FLDR.elf
|
||||
mv FLDR.elf ../FLDR.elf
|
||||
|
||||
%.o: %.c
|
||||
$(info Compiling $<)
|
||||
$(CC) $(CFLAGS) -std=c17 -c $< -o $@
|
||||
|
||||
%.o: %.cpp
|
||||
$(info Compiling $<)
|
||||
$(CPP) $(CFLAGS) -std=c++20 -fexceptions -c $< -o $@ -fno-rtti
|
||||
|
||||
%.o: %.asm
|
||||
$(info Compiling $<)
|
||||
$(NASM) $< $(NASM_ARCH) -f elf32 -o $@
|
||||
|
||||
clean_only_obj:
|
||||
$(info Removing objects $(OBJ))
|
||||
rm -f $(OBJ)
|
||||
|
||||
clean:
|
||||
rm -f $(OBJ)
|
@ -1,28 +0,0 @@
|
||||
#include <bitmap.hpp>
|
||||
|
||||
bool Bitmap::operator[](uint64_t index) { return Get(index); }
|
||||
|
||||
bool Bitmap::Get(uint64_t index)
|
||||
{
|
||||
if (index > Size * 8)
|
||||
return false;
|
||||
uint64_t byteIndex = index / 8;
|
||||
uint8_t bitIndex = index % 8;
|
||||
uint8_t bitIndexer = 0b10000000 >> bitIndex;
|
||||
if ((Buffer[byteIndex] & bitIndexer) > 0)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Bitmap::Set(uint64_t index, bool value)
|
||||
{
|
||||
if (index > Size * 8)
|
||||
return false;
|
||||
uint64_t byteIndex = index / 8;
|
||||
uint8_t bitIndex = index % 8;
|
||||
uint8_t bitIndexer = 0b10000000 >> bitIndex;
|
||||
Buffer[byteIndex] &= ~bitIndexer;
|
||||
if (value)
|
||||
Buffer[byteIndex] |= bitIndexer;
|
||||
return true;
|
||||
}
|
@ -1,50 +0,0 @@
|
||||
#include <memory.hpp>
|
||||
|
||||
Memory32::Physical KernelAllocator32{};
|
||||
Memory32::PageTable *KernelPageTable32 = nullptr;
|
||||
|
||||
Memory64::Physical KernelAllocator64{};
|
||||
Memory64::PageTable *KernelPageTable64 = nullptr;
|
||||
|
||||
void InitializeMemoryManagement(BootInfo *Info, bool is32)
|
||||
{
|
||||
if (is32)
|
||||
{
|
||||
trace("Initializing Physical Memory Manager");
|
||||
// KernelAllocator32 = Physical(); <- Already called in the constructor
|
||||
KernelAllocator32.Init(Info);
|
||||
info("Memory Info: %lldMB / %lldMB (%lldMB reserved)",
|
||||
TO_MB(KernelAllocator32.UsedMemory),
|
||||
TO_MB(KernelAllocator32.TotalMemory),
|
||||
TO_MB(KernelAllocator32.ReservedMemory));
|
||||
|
||||
trace("Initializing Virtual Memory Manager");
|
||||
|
||||
KernelPageTable32 = (Memory32::PageTable *)KernelAllocator32.RequestPages(TO_PAGES(PAGE_SIZE + 1));
|
||||
memset(KernelPageTable32, 0, PAGE_SIZE);
|
||||
|
||||
{
|
||||
Memory32::Virtual va = Memory32::Virtual(KernelPageTable32);
|
||||
debug("Mapping from 0x0 to %#llx", Info->Memory.Size);
|
||||
size_t MemSize = Info->Memory.Size;
|
||||
va.Map((void *)0, (void *)0, MemSize, PTFlag::RW);
|
||||
|
||||
debug("Mapping Framebuffer");
|
||||
int itrfb = 0;
|
||||
while (true)
|
||||
{
|
||||
if (!Info->Framebuffer[itrfb].BaseAddress)
|
||||
break;
|
||||
|
||||
va.Map((void *)Info->Framebuffer[itrfb].BaseAddress,
|
||||
(void *)Info->Framebuffer[itrfb].BaseAddress,
|
||||
Info->Framebuffer[itrfb].Pitch * Info->Framebuffer[itrfb].Height,
|
||||
PTFlag::RW | PTFlag::US | PTFlag::G);
|
||||
itrfb++;
|
||||
}
|
||||
}
|
||||
|
||||
trace("Applying new page table from address %#lx", KernelPageTable32);
|
||||
asmv("mov %0, %%cr3" ::"r"(KernelPageTable32));
|
||||
}
|
||||
}
|
@ -1,583 +0,0 @@
|
||||
#include <memory.hpp>
|
||||
namespace Memory32
|
||||
{
|
||||
void *Physical::RequestPage()
|
||||
{
|
||||
for (; PageBitmapIndex < PageBitmap.Size * 8; PageBitmapIndex++)
|
||||
{
|
||||
if (PageBitmap[PageBitmapIndex] == true)
|
||||
continue;
|
||||
|
||||
this->LockPage((void *)(PageBitmapIndex * PAGE_SIZE));
|
||||
return (void *)(PageBitmapIndex * PAGE_SIZE);
|
||||
}
|
||||
|
||||
error("Out of memory! (Free: %ldMB; Used: %ldMB; Reserved: %ldMB)", TO_MB(FreeMemory), TO_MB(UsedMemory), TO_MB(ReservedMemory));
|
||||
while (1)
|
||||
asmv("cli; hlt");
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
void *Physical::RequestPages(size_t Count)
|
||||
{
|
||||
for (; PageBitmapIndex < PageBitmap.Size * 8; PageBitmapIndex++)
|
||||
{
|
||||
if (PageBitmap[PageBitmapIndex] == true)
|
||||
continue;
|
||||
|
||||
for (uint64_t Index = PageBitmapIndex; Index < PageBitmap.Size * 8; Index++)
|
||||
{
|
||||
if (PageBitmap[Index] == true)
|
||||
continue;
|
||||
|
||||
for (size_t i = 0; i < Count; i++)
|
||||
{
|
||||
if (PageBitmap[Index + i] == true)
|
||||
goto NextPage;
|
||||
}
|
||||
|
||||
this->LockPages((void *)(Index * PAGE_SIZE), Count);
|
||||
return (void *)(Index * PAGE_SIZE);
|
||||
|
||||
NextPage:
|
||||
Index += Count;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
error("Out of memory! (Free: %ldMB; Used: %ldMB; Reserved: %ldMB)", TO_MB(FreeMemory), TO_MB(UsedMemory), TO_MB(ReservedMemory));
|
||||
while (1)
|
||||
asmv("cli; hlt");
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
void Physical::FreePage(void *Address)
|
||||
{
|
||||
if (unlikely(Address == nullptr))
|
||||
{
|
||||
warn("Null pointer passed to FreePage.");
|
||||
return;
|
||||
}
|
||||
|
||||
size_t Index = (size_t)Address / PAGE_SIZE;
|
||||
|
||||
if (unlikely(PageBitmap[Index] == false))
|
||||
{
|
||||
warn("Tried to free an already free page. (%p)", Address);
|
||||
return;
|
||||
}
|
||||
|
||||
if (PageBitmap.Set(Index, false))
|
||||
{
|
||||
FreeMemory += PAGE_SIZE;
|
||||
UsedMemory -= PAGE_SIZE;
|
||||
if (PageBitmapIndex > Index)
|
||||
PageBitmapIndex = Index;
|
||||
}
|
||||
}
|
||||
|
||||
void Physical::FreePages(void *Address, size_t Count)
|
||||
{
|
||||
if (unlikely(Address == nullptr || Count == 0))
|
||||
{
|
||||
warn("%s%s%s passed to FreePages.", Address == nullptr ? "Null pointer " : "", Address == nullptr && Count == 0 ? "and " : "", Count == 0 ? "Zero count" : "");
|
||||
return;
|
||||
}
|
||||
for (size_t t = 0; t < Count; t++)
|
||||
this->FreePage((void *)((uintptr_t)Address + (t * PAGE_SIZE)));
|
||||
}
|
||||
|
||||
void Physical::LockPage(void *Address)
|
||||
{
|
||||
if (unlikely(Address == nullptr))
|
||||
warn("Trying to lock null address.");
|
||||
|
||||
uintptr_t Index = (uintptr_t)Address / PAGE_SIZE;
|
||||
|
||||
if (unlikely(PageBitmap[Index] == true))
|
||||
return;
|
||||
|
||||
if (PageBitmap.Set(Index, true))
|
||||
{
|
||||
FreeMemory -= PAGE_SIZE;
|
||||
UsedMemory += PAGE_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
void Physical::LockPages(void *Address, size_t PageCount)
|
||||
{
|
||||
if (unlikely(Address == nullptr || PageCount == 0))
|
||||
warn("Trying to lock %s%s.", Address ? "null address" : "", PageCount ? "0 pages" : "");
|
||||
|
||||
for (size_t i = 0; i < PageCount; i++)
|
||||
this->LockPage((void *)((uintptr_t)Address + (i * PAGE_SIZE)));
|
||||
}
|
||||
|
||||
void Physical::ReservePage(void *Address)
|
||||
{
|
||||
if (unlikely(Address == nullptr))
|
||||
warn("Trying to reserve null address.");
|
||||
|
||||
uintptr_t Index = (Address == NULL) ? 0 : (uintptr_t)Address / PAGE_SIZE;
|
||||
|
||||
if (unlikely(PageBitmap[Index] == true))
|
||||
return;
|
||||
|
||||
if (PageBitmap.Set(Index, true))
|
||||
{
|
||||
FreeMemory -= PAGE_SIZE;
|
||||
ReservedMemory += PAGE_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
void Physical::ReservePages(void *Address, size_t PageCount)
|
||||
{
|
||||
if (unlikely(Address == nullptr || PageCount == 0))
|
||||
warn("Trying to reserve %s%s.", Address ? "null address" : "", PageCount ? "0 pages" : "");
|
||||
|
||||
for (size_t t = 0; t < PageCount; t++)
|
||||
{
|
||||
uintptr_t Index = ((uintptr_t)Address + (t * PAGE_SIZE)) / PAGE_SIZE;
|
||||
|
||||
if (unlikely(PageBitmap[Index] == true))
|
||||
return;
|
||||
|
||||
if (PageBitmap.Set(Index, true))
|
||||
{
|
||||
FreeMemory -= PAGE_SIZE;
|
||||
ReservedMemory += PAGE_SIZE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Physical::UnreservePage(void *Address)
|
||||
{
|
||||
if (unlikely(Address == nullptr))
|
||||
warn("Trying to unreserve null address.");
|
||||
|
||||
uintptr_t Index = (Address == NULL) ? 0 : (uintptr_t)Address / PAGE_SIZE;
|
||||
|
||||
if (unlikely(PageBitmap[Index] == false))
|
||||
return;
|
||||
|
||||
if (PageBitmap.Set(Index, false))
|
||||
{
|
||||
FreeMemory += PAGE_SIZE;
|
||||
ReservedMemory -= PAGE_SIZE;
|
||||
if (PageBitmapIndex > Index)
|
||||
PageBitmapIndex = Index;
|
||||
}
|
||||
}
|
||||
|
||||
void Physical::UnreservePages(void *Address, size_t PageCount)
|
||||
{
|
||||
if (unlikely(Address == nullptr || PageCount == 0))
|
||||
warn("Trying to unreserve %s%s.", Address ? "null address" : "", PageCount ? "0 pages" : "");
|
||||
|
||||
for (size_t t = 0; t < PageCount; t++)
|
||||
{
|
||||
uintptr_t Index = ((uintptr_t)Address + (t * PAGE_SIZE)) / PAGE_SIZE;
|
||||
|
||||
if (unlikely(PageBitmap[Index] == false))
|
||||
return;
|
||||
|
||||
if (PageBitmap.Set(Index, false))
|
||||
{
|
||||
FreeMemory += PAGE_SIZE;
|
||||
ReservedMemory -= PAGE_SIZE;
|
||||
if (PageBitmapIndex > Index)
|
||||
PageBitmapIndex = Index;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Physical::Init(BootInfo *Info)
|
||||
{
|
||||
uint64_t MemorySize = Info->Memory.Size;
|
||||
debug("Memory size: %lld bytes (%ld pages)", MemorySize, TO_PAGES(MemorySize));
|
||||
UsedMemory = 0;
|
||||
ReservedMemory = 0;
|
||||
TotalMemory = MemorySize;
|
||||
FreeMemory = MemorySize;
|
||||
|
||||
void *LargestFreeMemorySegment = nullptr;
|
||||
uint64_t LargestFreeMemorySegmentSize = 0;
|
||||
|
||||
for (uint64_t i = 0; i < Info->Memory.Entries; i++)
|
||||
{
|
||||
if (Info->Memory.Entry[i].Type == Usable)
|
||||
{
|
||||
if (Info->Memory.Entry[i].Length > LargestFreeMemorySegmentSize)
|
||||
{
|
||||
/* We don't want to use 0 as a memory address. */
|
||||
if (Info->Memory.Entry[i].BaseAddress == 0x0)
|
||||
continue;
|
||||
|
||||
LargestFreeMemorySegment = (void *)Info->Memory.Entry[i].BaseAddress;
|
||||
LargestFreeMemorySegmentSize = Info->Memory.Entry[i].Length;
|
||||
|
||||
debug("Largest free memory segment: %llp (%lldMB)",
|
||||
(void *)Info->Memory.Entry[i].BaseAddress,
|
||||
TO_MB(Info->Memory.Entry[i].Length));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (LargestFreeMemorySegment == nullptr)
|
||||
{
|
||||
error("No free memory found!");
|
||||
while (1)
|
||||
asmv("cli; hlt");
|
||||
}
|
||||
|
||||
size_t BitmapSize = (MemorySize / PAGE_SIZE) / 8 + 1;
|
||||
void *LargestFreeMemorySegmentNoKernel = nullptr;
|
||||
|
||||
if ((uintptr_t)LargestFreeMemorySegment >= (uintptr_t)&_kernel_start &&
|
||||
(uintptr_t)LargestFreeMemorySegment <= (uintptr_t)&_kernel_end)
|
||||
{
|
||||
LargestFreeMemorySegmentNoKernel = (void *)((uintptr_t)LargestFreeMemorySegment + (uintptr_t)&_kernel_end);
|
||||
if ((uintptr_t)LargestFreeMemorySegmentNoKernel > ((uintptr_t)LargestFreeMemorySegment + LargestFreeMemorySegmentSize))
|
||||
{
|
||||
error("No free memory found!");
|
||||
while (1)
|
||||
asmv("cli; hlt");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LargestFreeMemorySegmentNoKernel = LargestFreeMemorySegment;
|
||||
}
|
||||
|
||||
debug("Initializing Bitmap at %llp-%llp (%lld Bytes)",
|
||||
LargestFreeMemorySegmentNoKernel,
|
||||
(void *)((uintptr_t)LargestFreeMemorySegmentNoKernel + BitmapSize),
|
||||
BitmapSize);
|
||||
|
||||
PageBitmap.Size = BitmapSize;
|
||||
PageBitmap.Buffer = (uint8_t *)LargestFreeMemorySegmentNoKernel;
|
||||
for (size_t i = 0; i < BitmapSize; i++)
|
||||
*(uint8_t *)(PageBitmap.Buffer + i) = 0;
|
||||
|
||||
debug("Reserving pages...");
|
||||
this->ReservePages(0, TO_PAGES(Info->Memory.Size));
|
||||
debug("Unreserving usable pages...");
|
||||
|
||||
for (uint64_t i = 0; i < Info->Memory.Entries; i++)
|
||||
{
|
||||
if (Info->Memory.Entry[i].Type == Usable)
|
||||
this->UnreservePages(Info->Memory.Entry[i].BaseAddress, TO_PAGES(Info->Memory.Entry[i].Length));
|
||||
}
|
||||
|
||||
debug("Reserving bitmap pages...");
|
||||
this->ReservePages(PageBitmap.Buffer, TO_PAGES(PageBitmap.Size));
|
||||
debug("Reserving kernel...");
|
||||
this->ReservePages(&_kernel_start, TO_PAGES((uintptr_t)&_kernel_end - (uintptr_t)&_kernel_start));
|
||||
debug("Reserving kernel and its modules...");
|
||||
|
||||
BootInfo::ModuleInfo *Module = &Info->Modules[0];
|
||||
int ModuleIndex = 0;
|
||||
do
|
||||
{
|
||||
debug("Reserving %s (%p-%p)", Module->CommandLine, Module->Address, (void *)((uintptr_t)Module->Address + Module->Size));
|
||||
this->ReservePages(Module->Address, TO_PAGES(Module->Size));
|
||||
Module = &Info->Modules[++ModuleIndex];
|
||||
} while (Module->Address);
|
||||
|
||||
this->ReservePages(0, 16);
|
||||
}
|
||||
|
||||
Physical::Physical() {}
|
||||
Physical::~Physical() {}
|
||||
}
|
||||
|
||||
namespace Memory64
|
||||
{
|
||||
void *Physical::RequestPage()
|
||||
{
|
||||
for (; PageBitmapIndex < PageBitmap.Size * 8; PageBitmapIndex++)
|
||||
{
|
||||
if (PageBitmap[PageBitmapIndex] == true)
|
||||
continue;
|
||||
|
||||
this->LockPage((void *)(PageBitmapIndex * PAGE_SIZE));
|
||||
return (void *)(PageBitmapIndex * PAGE_SIZE);
|
||||
}
|
||||
|
||||
error("Out of memory! (Free: %ldMB; Used: %ldMB; Reserved: %ldMB)", TO_MB(FreeMemory), TO_MB(UsedMemory), TO_MB(ReservedMemory));
|
||||
while (1)
|
||||
asmv("cli; hlt");
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
void *Physical::RequestPages(size_t Count)
|
||||
{
|
||||
for (; PageBitmapIndex < PageBitmap.Size * 8; PageBitmapIndex++)
|
||||
{
|
||||
if (PageBitmap[PageBitmapIndex] == true)
|
||||
continue;
|
||||
|
||||
for (uint64_t Index = PageBitmapIndex; Index < PageBitmap.Size * 8; Index++)
|
||||
{
|
||||
if (PageBitmap[Index] == true)
|
||||
continue;
|
||||
|
||||
for (size_t i = 0; i < Count; i++)
|
||||
{
|
||||
if (PageBitmap[Index + i] == true)
|
||||
goto NextPage;
|
||||
}
|
||||
|
||||
this->LockPages((void *)(Index * PAGE_SIZE), Count);
|
||||
return (void *)(Index * PAGE_SIZE);
|
||||
|
||||
NextPage:
|
||||
Index += Count;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
error("Out of memory! (Free: %ldMB; Used: %ldMB; Reserved: %ldMB)", TO_MB(FreeMemory), TO_MB(UsedMemory), TO_MB(ReservedMemory));
|
||||
while (1)
|
||||
asmv("cli; hlt");
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
void Physical::FreePage(void *Address)
|
||||
{
|
||||
if (unlikely(Address == nullptr))
|
||||
{
|
||||
warn("Null pointer passed to FreePage.");
|
||||
return;
|
||||
}
|
||||
|
||||
size_t Index = (size_t)Address / PAGE_SIZE;
|
||||
|
||||
if (unlikely(PageBitmap[Index] == false))
|
||||
{
|
||||
warn("Tried to free an already free page. (%p)", Address);
|
||||
return;
|
||||
}
|
||||
|
||||
if (PageBitmap.Set(Index, false))
|
||||
{
|
||||
FreeMemory += PAGE_SIZE;
|
||||
UsedMemory -= PAGE_SIZE;
|
||||
if (PageBitmapIndex > Index)
|
||||
PageBitmapIndex = Index;
|
||||
}
|
||||
}
|
||||
|
||||
void Physical::FreePages(void *Address, size_t Count)
|
||||
{
|
||||
if (unlikely(Address == nullptr || Count == 0))
|
||||
{
|
||||
warn("%s%s%s passed to FreePages.", Address == nullptr ? "Null pointer " : "", Address == nullptr && Count == 0 ? "and " : "", Count == 0 ? "Zero count" : "");
|
||||
return;
|
||||
}
|
||||
for (size_t t = 0; t < Count; t++)
|
||||
this->FreePage((void *)((uintptr_t)Address + (t * PAGE_SIZE)));
|
||||
}
|
||||
|
||||
void Physical::LockPage(void *Address)
|
||||
{
|
||||
if (unlikely(Address == nullptr))
|
||||
warn("Trying to lock null address.");
|
||||
|
||||
uintptr_t Index = (uintptr_t)Address / PAGE_SIZE;
|
||||
|
||||
if (unlikely(PageBitmap[Index] == true))
|
||||
return;
|
||||
|
||||
if (PageBitmap.Set(Index, true))
|
||||
{
|
||||
FreeMemory -= PAGE_SIZE;
|
||||
UsedMemory += PAGE_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
void Physical::LockPages(void *Address, size_t PageCount)
|
||||
{
|
||||
if (unlikely(Address == nullptr || PageCount == 0))
|
||||
warn("Trying to lock %s%s.", Address ? "null address" : "", PageCount ? "0 pages" : "");
|
||||
|
||||
for (size_t i = 0; i < PageCount; i++)
|
||||
this->LockPage((void *)((uintptr_t)Address + (i * PAGE_SIZE)));
|
||||
}
|
||||
|
||||
void Physical::ReservePage(void *Address)
|
||||
{
|
||||
if (unlikely(Address == nullptr))
|
||||
warn("Trying to reserve null address.");
|
||||
|
||||
uintptr_t Index = (Address == NULL) ? 0 : (uintptr_t)Address / PAGE_SIZE;
|
||||
|
||||
if (unlikely(PageBitmap[Index] == true))
|
||||
return;
|
||||
|
||||
if (PageBitmap.Set(Index, true))
|
||||
{
|
||||
FreeMemory -= PAGE_SIZE;
|
||||
ReservedMemory += PAGE_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
void Physical::ReservePages(void *Address, size_t PageCount)
|
||||
{
|
||||
if (unlikely(Address == nullptr || PageCount == 0))
|
||||
warn("Trying to reserve %s%s.", Address ? "null address" : "", PageCount ? "0 pages" : "");
|
||||
|
||||
for (size_t t = 0; t < PageCount; t++)
|
||||
{
|
||||
uintptr_t Index = ((uintptr_t)Address + (t * PAGE_SIZE)) / PAGE_SIZE;
|
||||
|
||||
if (unlikely(PageBitmap[Index] == true))
|
||||
return;
|
||||
|
||||
if (PageBitmap.Set(Index, true))
|
||||
{
|
||||
FreeMemory -= PAGE_SIZE;
|
||||
ReservedMemory += PAGE_SIZE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Physical::UnreservePage(void *Address)
|
||||
{
|
||||
if (unlikely(Address == nullptr))
|
||||
warn("Trying to unreserve null address.");
|
||||
|
||||
uintptr_t Index = (Address == NULL) ? 0 : (uintptr_t)Address / PAGE_SIZE;
|
||||
|
||||
if (unlikely(PageBitmap[Index] == false))
|
||||
return;
|
||||
|
||||
if (PageBitmap.Set(Index, false))
|
||||
{
|
||||
FreeMemory += PAGE_SIZE;
|
||||
ReservedMemory -= PAGE_SIZE;
|
||||
if (PageBitmapIndex > Index)
|
||||
PageBitmapIndex = Index;
|
||||
}
|
||||
}
|
||||
|
||||
void Physical::UnreservePages(void *Address, size_t PageCount)
|
||||
{
|
||||
if (unlikely(Address == nullptr || PageCount == 0))
|
||||
warn("Trying to unreserve %s%s.", Address ? "null address" : "", PageCount ? "0 pages" : "");
|
||||
|
||||
for (size_t t = 0; t < PageCount; t++)
|
||||
{
|
||||
uintptr_t Index = ((uintptr_t)Address + (t * PAGE_SIZE)) / PAGE_SIZE;
|
||||
|
||||
if (unlikely(PageBitmap[Index] == false))
|
||||
return;
|
||||
|
||||
if (PageBitmap.Set(Index, false))
|
||||
{
|
||||
FreeMemory += PAGE_SIZE;
|
||||
ReservedMemory -= PAGE_SIZE;
|
||||
if (PageBitmapIndex > Index)
|
||||
PageBitmapIndex = Index;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Physical::Init(BootInfo *Info)
|
||||
{
|
||||
uint64_t MemorySize = Info->Memory.Size;
|
||||
debug("Memory size: %lld bytes (%ld pages)", MemorySize, TO_PAGES(MemorySize));
|
||||
UsedMemory = 0;
|
||||
ReservedMemory = 0;
|
||||
TotalMemory = MemorySize;
|
||||
FreeMemory = MemorySize;
|
||||
|
||||
void *LargestFreeMemorySegment = nullptr;
|
||||
uint64_t LargestFreeMemorySegmentSize = 0;
|
||||
|
||||
for (uint64_t i = 0; i < Info->Memory.Entries; i++)
|
||||
{
|
||||
if (Info->Memory.Entry[i].Type == Usable)
|
||||
{
|
||||
if (Info->Memory.Entry[i].Length > LargestFreeMemorySegmentSize)
|
||||
{
|
||||
/* We don't want to use 0 as a memory address. */
|
||||
if (Info->Memory.Entry[i].BaseAddress == 0x0)
|
||||
continue;
|
||||
|
||||
LargestFreeMemorySegment = (void *)Info->Memory.Entry[i].BaseAddress;
|
||||
LargestFreeMemorySegmentSize = Info->Memory.Entry[i].Length;
|
||||
|
||||
debug("Largest free memory segment: %llp (%lldMB)",
|
||||
(void *)Info->Memory.Entry[i].BaseAddress,
|
||||
TO_MB(Info->Memory.Entry[i].Length));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (LargestFreeMemorySegment == nullptr)
|
||||
{
|
||||
error("No free memory found!");
|
||||
while (1)
|
||||
asmv("cli; hlt");
|
||||
}
|
||||
|
||||
size_t BitmapSize = (MemorySize / PAGE_SIZE) / 8 + 1;
|
||||
void *LargestFreeMemorySegmentNoKernel = nullptr;
|
||||
|
||||
if ((uintptr_t)LargestFreeMemorySegment >= (uintptr_t)&_kernel_start &&
|
||||
(uintptr_t)LargestFreeMemorySegment <= (uintptr_t)&_kernel_end)
|
||||
{
|
||||
LargestFreeMemorySegmentNoKernel = (void *)((uintptr_t)LargestFreeMemorySegment + (uintptr_t)&_kernel_end);
|
||||
if ((uintptr_t)LargestFreeMemorySegmentNoKernel > ((uintptr_t)LargestFreeMemorySegment + LargestFreeMemorySegmentSize))
|
||||
{
|
||||
error("No free memory found!");
|
||||
while (1)
|
||||
asmv("cli; hlt");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LargestFreeMemorySegmentNoKernel = LargestFreeMemorySegment;
|
||||
}
|
||||
|
||||
debug("Initializing Bitmap at %llp-%llp (%lld Bytes)",
|
||||
LargestFreeMemorySegmentNoKernel,
|
||||
(void *)((uintptr_t)LargestFreeMemorySegmentNoKernel + BitmapSize),
|
||||
BitmapSize);
|
||||
|
||||
PageBitmap.Size = BitmapSize;
|
||||
PageBitmap.Buffer = (uint8_t *)LargestFreeMemorySegmentNoKernel;
|
||||
for (size_t i = 0; i < BitmapSize; i++)
|
||||
*(uint8_t *)(PageBitmap.Buffer + i) = 0;
|
||||
|
||||
debug("Reserving pages...");
|
||||
this->ReservePages(0, TO_PAGES(Info->Memory.Size));
|
||||
debug("Unreserving usable pages...");
|
||||
|
||||
for (uint64_t i = 0; i < Info->Memory.Entries; i++)
|
||||
{
|
||||
if (Info->Memory.Entry[i].Type == Usable)
|
||||
this->UnreservePages(Info->Memory.Entry[i].BaseAddress, TO_PAGES(Info->Memory.Entry[i].Length));
|
||||
}
|
||||
|
||||
debug("Reserving bitmap pages...");
|
||||
this->ReservePages(PageBitmap.Buffer, TO_PAGES(PageBitmap.Size));
|
||||
debug("Reserving fennix loader...");
|
||||
this->ReservePages(&_kernel_start, TO_PAGES((uintptr_t)&_kernel_end - (uintptr_t)&_kernel_start));
|
||||
debug("Reserving kernel and its modules...");
|
||||
|
||||
BootInfo::ModuleInfo *Module = &Info->Modules[0];
|
||||
int ModuleIndex = 0;
|
||||
do
|
||||
{
|
||||
debug("Reserving %s (%p-%p)", Module->CommandLine, Module->Address, (void *)((uintptr_t)Module->Address + Module->Size));
|
||||
this->ReservePages(Module->Address, TO_PAGES(Module->Size));
|
||||
Module = &Info->Modules[++ModuleIndex];
|
||||
} while (Module->Address);
|
||||
this->ReservePages(0, 16);
|
||||
}
|
||||
|
||||
Physical::Physical() {}
|
||||
Physical::~Physical() {}
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
[bits 32]
|
||||
section .text
|
||||
global EnablePaging
|
||||
EnablePaging:
|
||||
mov ecx, cr0
|
||||
or ecx, 0x80000000 ; Set PG in CR0
|
||||
mov cr0, ecx
|
||||
ret
|
@ -1,316 +0,0 @@
|
||||
#include <memory.hpp>
|
||||
#include <debug.h>
|
||||
|
||||
namespace Memory32
|
||||
{
|
||||
void Virtual::Map(void *VirtualAddress, void *PhysicalAddress, uint64_t Flags)
|
||||
{
|
||||
if (unlikely(!this->Table))
|
||||
{
|
||||
error("No page table");
|
||||
return;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
PageDirectoryEntry *PDE = &this->Table->Entries[Index.PDEIndex];
|
||||
PageTableEntryPtr *PTEPtr = nullptr;
|
||||
if (!PDE->Present)
|
||||
{
|
||||
PTEPtr = (PageTableEntryPtr *)KernelAllocator32.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 |= DirectoryFlags;
|
||||
|
||||
PageTableEntry *PTE = &PTEPtr->Entries[Index.PTEIndex];
|
||||
PTE->Present = true;
|
||||
PTE->raw |= Flags;
|
||||
PTE->SetAddress((uintptr_t)PhysicalAddress >> 12);
|
||||
|
||||
asmv("invlpg (%0)" ::"r"(VirtualAddress)
|
||||
: "memory");
|
||||
}
|
||||
|
||||
Virtual::Virtual(PageTable *Table)
|
||||
{
|
||||
if (Table)
|
||||
this->Table = Table;
|
||||
else
|
||||
{
|
||||
asmv("movl %%cr3, %0"
|
||||
: "=r"(this->Table));
|
||||
}
|
||||
}
|
||||
|
||||
Virtual::~Virtual() {}
|
||||
}
|
||||
|
||||
namespace Memory64
|
||||
{
|
||||
bool Virtual::Check(void *VirtualAddress, PTFlag Flag, MapType Type)
|
||||
{
|
||||
// 0x1000 aligned
|
||||
uintptr_t Address = (uintptr_t)VirtualAddress;
|
||||
Address &= 0xFFFFFFFFFFFFF000;
|
||||
|
||||
PageMapIndexer Index = PageMapIndexer(Address);
|
||||
PageMapLevel4 PML4 = this->Table->Entries[Index.PMLIndex];
|
||||
|
||||
PageDirectoryPointerTableEntryPtr *PDPTE = nullptr;
|
||||
PageDirectoryEntryPtr *PDE = nullptr;
|
||||
PageTableEntryPtr *PTE = nullptr;
|
||||
|
||||
if ((PML4.raw & Flag) > 0)
|
||||
{
|
||||
PDPTE = (PageDirectoryPointerTableEntryPtr *)((uintptr_t)PML4.GetAddress() << 12);
|
||||
if (PDPTE)
|
||||
{
|
||||
if ((PDPTE->Entries[Index.PDPTEIndex].Present))
|
||||
{
|
||||
if (Type == MapType::OneGB && PDPTE->Entries[Index.PDPTEIndex].PageSize)
|
||||
return true;
|
||||
|
||||
PDE = (PageDirectoryEntryPtr *)((uintptr_t)PDPTE->Entries[Index.PDPTEIndex].GetAddress() << 12);
|
||||
if (PDE)
|
||||
{
|
||||
if (Type == MapType::TwoMB && PDE->Entries[Index.PDEIndex].PageSize)
|
||||
return true;
|
||||
|
||||
if ((PDE->Entries[Index.PDEIndex].Present))
|
||||
{
|
||||
PTE = (PageTableEntryPtr *)((uintptr_t)PDE->Entries[Index.PDEIndex].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 &= 0xFFFFFFFFFFFFF000;
|
||||
|
||||
PageMapIndexer Index = PageMapIndexer(Address);
|
||||
PageMapLevel4 PML4 = this->Table->Entries[Index.PMLIndex];
|
||||
|
||||
PageDirectoryPointerTableEntryPtr *PDPTE = nullptr;
|
||||
PageDirectoryEntryPtr *PDE = nullptr;
|
||||
PageTableEntryPtr *PTE = nullptr;
|
||||
|
||||
if (PML4.Present)
|
||||
{
|
||||
PDPTE = (PageDirectoryPointerTableEntryPtr *)((uintptr_t)PML4.GetAddress() << 12);
|
||||
if (PDPTE)
|
||||
{
|
||||
if (PDPTE->Entries[Index.PDPTEIndex].Present)
|
||||
{
|
||||
if (PDPTE->Entries[Index.PDPTEIndex].PageSize)
|
||||
return (void *)((uintptr_t)PDPTE->Entries[Index.PDPTEIndex].GetAddress() << 12);
|
||||
|
||||
PDE = (PageDirectoryEntryPtr *)((uintptr_t)PDPTE->Entries[Index.PDPTEIndex].GetAddress() << 12);
|
||||
if (PDE)
|
||||
{
|
||||
if (PDE->Entries[Index.PDEIndex].Present)
|
||||
{
|
||||
if (PDE->Entries[Index.PDEIndex].PageSize)
|
||||
return (void *)((uintptr_t)PDE->Entries[Index.PDEIndex].GetAddress() << 12);
|
||||
|
||||
PTE = (PageTableEntryPtr *)((uintptr_t)PDE->Entries[Index.PDEIndex].GetAddress() << 12);
|
||||
if (PTE)
|
||||
{
|
||||
if (PTE->Entries[Index.PTEIndex].Present)
|
||||
return (void *)((uintptr_t)PTE->Entries[Index.PTEIndex].GetAddress() << 12);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void Virtual::Map(void *VirtualAddress, void *PhysicalAddress, uint64_t Flags, MapType Type)
|
||||
{
|
||||
if (unlikely(!this->Table))
|
||||
{
|
||||
error("No page table");
|
||||
return;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
PageMapLevel4 *PML4 = &this->Table->Entries[Index.PMLIndex];
|
||||
PageDirectoryPointerTableEntryPtr *PDPTEPtr = nullptr;
|
||||
if (!PML4->Present)
|
||||
{
|
||||
PDPTEPtr = (PageDirectoryPointerTableEntryPtr *)KernelAllocator64.RequestPages(TO_PAGES(sizeof(PageDirectoryPointerTableEntryPtr) + 1));
|
||||
memset(PDPTEPtr, 0, sizeof(PageDirectoryPointerTableEntryPtr));
|
||||
PML4->Present = true;
|
||||
PML4->SetAddress((uintptr_t)PDPTEPtr >> 12);
|
||||
}
|
||||
else
|
||||
PDPTEPtr = (PageDirectoryPointerTableEntryPtr *)(PML4->GetAddress() << 12);
|
||||
PML4->raw |= DirectoryFlags;
|
||||
|
||||
PageDirectoryPointerTableEntry *PDPTE = &PDPTEPtr->Entries[Index.PDPTEIndex];
|
||||
if (Type == MapType::OneGB)
|
||||
{
|
||||
PDPTE->raw |= Flags;
|
||||
PDPTE->PageSize = true;
|
||||
PDPTE->SetAddress((uintptr_t)PhysicalAddress >> 12);
|
||||
debug("Mapped 1GB page at %p to %p", VirtualAddress, PhysicalAddress);
|
||||
return;
|
||||
}
|
||||
|
||||
PageDirectoryEntryPtr *PDEPtr = nullptr;
|
||||
if (!PDPTE->Present)
|
||||
{
|
||||
PDEPtr = (PageDirectoryEntryPtr *)KernelAllocator64.RequestPages(TO_PAGES(sizeof(PageDirectoryEntryPtr) + 1));
|
||||
memset(PDEPtr, 0, sizeof(PageDirectoryEntryPtr));
|
||||
PDPTE->Present = true;
|
||||
PDPTE->SetAddress((uintptr_t)PDEPtr >> 12);
|
||||
}
|
||||
else
|
||||
PDEPtr = (PageDirectoryEntryPtr *)(PDPTE->GetAddress() << 12);
|
||||
PDPTE->raw |= DirectoryFlags;
|
||||
|
||||
PageDirectoryEntry *PDE = &PDEPtr->Entries[Index.PDEIndex];
|
||||
if (Type == MapType::TwoMB)
|
||||
{
|
||||
PDE->raw |= Flags;
|
||||
PDE->PageSize = true;
|
||||
PDE->SetAddress((uintptr_t)PhysicalAddress >> 12);
|
||||
debug("Mapped 2MB page at %p to %p", VirtualAddress, PhysicalAddress);
|
||||
return;
|
||||
}
|
||||
|
||||
PageTableEntryPtr *PTEPtr = nullptr;
|
||||
if (!PDE->Present)
|
||||
{
|
||||
PTEPtr = (PageTableEntryPtr *)KernelAllocator64.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 |= DirectoryFlags;
|
||||
|
||||
PageTableEntry *PTE = &PTEPtr->Entries[Index.PTEIndex];
|
||||
PTE->Present = true;
|
||||
PTE->raw |= Flags;
|
||||
PTE->SetAddress((uintptr_t)PhysicalAddress >> 12);
|
||||
|
||||
asmv("invlpg (%0)" ::"r"(VirtualAddress)
|
||||
: "memory");
|
||||
|
||||
#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')
|
||||
|
||||
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)
|
||||
{
|
||||
if (!this->Table)
|
||||
{
|
||||
error("No page table");
|
||||
return;
|
||||
}
|
||||
|
||||
PageMapIndexer Index = PageMapIndexer((uintptr_t)VirtualAddress);
|
||||
PageMapLevel4 *PML4 = &this->Table->Entries[Index.PMLIndex];
|
||||
if (!PML4->Present)
|
||||
{
|
||||
error("Page %#lx not present", PML4->GetAddress());
|
||||
return;
|
||||
}
|
||||
|
||||
PageDirectoryPointerTableEntryPtr *PDPTEPtr = (PageDirectoryPointerTableEntryPtr *)((uintptr_t)PML4->Address << 12);
|
||||
PageDirectoryPointerTableEntry *PDPTE = &PDPTEPtr->Entries[Index.PDPTEIndex];
|
||||
if (!PDPTE->Present)
|
||||
{
|
||||
error("Page %#lx not present", PDPTE->GetAddress());
|
||||
return;
|
||||
}
|
||||
|
||||
if (Type == MapType::OneGB && PDPTE->PageSize)
|
||||
{
|
||||
PDPTE->Present = false;
|
||||
return;
|
||||
}
|
||||
|
||||
PageDirectoryEntryPtr *PDEPtr = (PageDirectoryEntryPtr *)((uintptr_t)PDPTE->Address << 12);
|
||||
PageDirectoryEntry *PDE = &PDEPtr->Entries[Index.PDEIndex];
|
||||
if (!PDE->Present)
|
||||
{
|
||||
error("Page %#lx not present", PDE->GetAddress());
|
||||
return;
|
||||
}
|
||||
|
||||
if (Type == MapType::TwoMB && PDE->PageSize)
|
||||
{
|
||||
PDE->Present = false;
|
||||
return;
|
||||
}
|
||||
|
||||
PageTableEntryPtr *PTEPtr = (PageTableEntryPtr *)((uintptr_t)PDE->Address << 12);
|
||||
PageTableEntry PTE = PTEPtr->Entries[Index.PTEIndex];
|
||||
if (!PTE.Present)
|
||||
{
|
||||
error("Page %#lx not present", PTE.GetAddress());
|
||||
return;
|
||||
}
|
||||
|
||||
PTE.Present = false;
|
||||
PTEPtr->Entries[Index.PTEIndex] = PTE;
|
||||
|
||||
asmv("invlpg (%0)" ::"r"(VirtualAddress)
|
||||
: "memory");
|
||||
}
|
||||
|
||||
Virtual::Virtual(PageTable *Table)
|
||||
{
|
||||
if (Table)
|
||||
this->Table = Table;
|
||||
else
|
||||
{
|
||||
asmv("movl %%cr3, %0" // FIXME: movq
|
||||
: "=r"(this->Table));
|
||||
}
|
||||
}
|
||||
|
||||
Virtual::~Virtual() {}
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
#include <memory.hpp>
|
||||
|
||||
void *memcpy(void *dest, const void *src, size_t n)
|
||||
{
|
||||
unsigned char *d = (unsigned char *)dest;
|
||||
const unsigned char *s = (const unsigned char *)src;
|
||||
while (n--)
|
||||
*d++ = *s++;
|
||||
return dest;
|
||||
}
|
||||
|
||||
void *memset(void *s, int c, size_t n)
|
||||
{
|
||||
unsigned char *p = (unsigned char *)s;
|
||||
while (n--)
|
||||
*p++ = (unsigned char)c;
|
||||
return s;
|
||||
}
|
@ -1,513 +0,0 @@
|
||||
#include "ubsan.h"
|
||||
#include <debug.h>
|
||||
|
||||
extern void __asan_report_load1(void *unknown)
|
||||
{
|
||||
ubsan("load1");
|
||||
UNUSED(unknown);
|
||||
}
|
||||
|
||||
extern void __asan_report_load2(void *unknown)
|
||||
{
|
||||
ubsan("load2");
|
||||
UNUSED(unknown);
|
||||
}
|
||||
|
||||
extern void __asan_report_load4(void *unknown)
|
||||
{
|
||||
ubsan("load4");
|
||||
UNUSED(unknown);
|
||||
}
|
||||
|
||||
extern void __asan_report_load8(void *unknown)
|
||||
{
|
||||
ubsan("load8");
|
||||
UNUSED(unknown);
|
||||
}
|
||||
|
||||
extern void __asan_report_load16(void *unknown)
|
||||
{
|
||||
ubsan("load16");
|
||||
UNUSED(unknown);
|
||||
}
|
||||
|
||||
extern void __asan_report_load_n(void *unknown, uintptr_t size)
|
||||
{
|
||||
ubsan("loadn");
|
||||
UNUSED(unknown);
|
||||
UNUSED(size);
|
||||
}
|
||||
|
||||
extern void __asan_report_store1(void *unknown)
|
||||
{
|
||||
ubsan("store1");
|
||||
UNUSED(unknown);
|
||||
}
|
||||
|
||||
extern void __asan_report_store2(void *unknown)
|
||||
{
|
||||
ubsan("store2");
|
||||
UNUSED(unknown);
|
||||
}
|
||||
|
||||
extern void __asan_report_store4(void *unknown)
|
||||
{
|
||||
ubsan("store4");
|
||||
UNUSED(unknown);
|
||||
}
|
||||
|
||||
extern void __asan_report_store8(void *unknown)
|
||||
{
|
||||
ubsan("store8");
|
||||
UNUSED(unknown);
|
||||
}
|
||||
|
||||
extern void __asan_report_store16(void *unknown)
|
||||
{
|
||||
ubsan("store16");
|
||||
UNUSED(unknown);
|
||||
}
|
||||
|
||||
extern void __asan_report_store_n(void *unknown, uintptr_t size)
|
||||
{
|
||||
ubsan("storen");
|
||||
UNUSED(unknown);
|
||||
UNUSED(size);
|
||||
}
|
||||
|
||||
extern void __asan_report_load1_noabort(void *unknown)
|
||||
{
|
||||
ubsan("load1");
|
||||
UNUSED(unknown);
|
||||
}
|
||||
|
||||
extern void __asan_report_load2_noabort(void *unknown)
|
||||
{
|
||||
ubsan("load2");
|
||||
UNUSED(unknown);
|
||||
}
|
||||
|
||||
extern void __asan_report_load4_noabort(void *unknown)
|
||||
{
|
||||
ubsan("load4");
|
||||
UNUSED(unknown);
|
||||
}
|
||||
|
||||
extern void __asan_report_load8_noabort(void *unknown)
|
||||
{
|
||||
ubsan("load8");
|
||||
UNUSED(unknown);
|
||||
}
|
||||
|
||||
extern void __asan_report_load16_noabort(void *unknown)
|
||||
{
|
||||
ubsan("load16");
|
||||
UNUSED(unknown);
|
||||
}
|
||||
|
||||
extern void __asan_report_load_n_noabort(void *unknown, uintptr_t size)
|
||||
{
|
||||
ubsan("loadn");
|
||||
UNUSED(unknown);
|
||||
UNUSED(size);
|
||||
}
|
||||
|
||||
extern void __asan_report_store1_noabort(void *unknown)
|
||||
{
|
||||
ubsan("store1");
|
||||
UNUSED(unknown);
|
||||
}
|
||||
|
||||
extern void __asan_report_store2_noabort(void *unknown)
|
||||
{
|
||||
ubsan("store2");
|
||||
UNUSED(unknown);
|
||||
}
|
||||
|
||||
extern void __asan_report_store4_noabort(void *unknown)
|
||||
{
|
||||
ubsan("store4");
|
||||
UNUSED(unknown);
|
||||
}
|
||||
|
||||
extern void __asan_report_store8_noabort(void *unknown)
|
||||
{
|
||||
ubsan("store8");
|
||||
UNUSED(unknown);
|
||||
}
|
||||
|
||||
extern void __asan_report_store16_noabort(void *unknown)
|
||||
{
|
||||
ubsan("store16");
|
||||
UNUSED(unknown);
|
||||
}
|
||||
|
||||
extern void __asan_report_store_n_noabort(void *unknown, uintptr_t size)
|
||||
{
|
||||
ubsan("storen");
|
||||
UNUSED(unknown);
|
||||
UNUSED(size);
|
||||
}
|
||||
|
||||
extern void __asan_stack_malloc_0(uintptr_t size)
|
||||
{
|
||||
ubsan("stack malloc 0");
|
||||
UNUSED(size);
|
||||
}
|
||||
|
||||
extern void __asan_stack_malloc_1(uintptr_t size)
|
||||
{
|
||||
ubsan("stack malloc 1");
|
||||
UNUSED(size);
|
||||
}
|
||||
|
||||
extern void __asan_stack_malloc_2(uintptr_t size)
|
||||
{
|
||||
ubsan("stack malloc 2");
|
||||
UNUSED(size);
|
||||
}
|
||||
|
||||
extern void __asan_stack_malloc_3(uintptr_t size)
|
||||
{
|
||||
ubsan("stack malloc 3");
|
||||
UNUSED(size);
|
||||
}
|
||||
|
||||
extern void __asan_stack_malloc_4(uintptr_t size)
|
||||
{
|
||||
ubsan("stack malloc 4");
|
||||
UNUSED(size);
|
||||
}
|
||||
|
||||
extern void __asan_stack_malloc_5(uintptr_t size)
|
||||
{
|
||||
ubsan("stack malloc 5");
|
||||
UNUSED(size);
|
||||
}
|
||||
|
||||
extern void __asan_stack_malloc_6(uintptr_t size)
|
||||
{
|
||||
ubsan("stack malloc 6");
|
||||
UNUSED(size);
|
||||
}
|
||||
|
||||
extern void __asan_stack_malloc_7(uintptr_t size)
|
||||
{
|
||||
ubsan("stack malloc 7");
|
||||
UNUSED(size);
|
||||
}
|
||||
|
||||
extern void __asan_stack_malloc_8(uintptr_t size)
|
||||
{
|
||||
ubsan("stack malloc 8");
|
||||
UNUSED(size);
|
||||
}
|
||||
|
||||
extern void __asan_stack_malloc_9(uintptr_t size)
|
||||
{
|
||||
ubsan("stack malloc 9");
|
||||
UNUSED(size);
|
||||
}
|
||||
|
||||
extern void __asan_stack_free_0(void *ptr, uintptr_t size)
|
||||
{
|
||||
ubsan("stack free 0");
|
||||
UNUSED(ptr);
|
||||
UNUSED(size);
|
||||
}
|
||||
|
||||
extern void __asan_stack_free_1(void *ptr, uintptr_t size)
|
||||
{
|
||||
ubsan("stack free 1");
|
||||
UNUSED(ptr);
|
||||
UNUSED(size);
|
||||
}
|
||||
|
||||
extern void __asan_stack_free_2(void *ptr, uintptr_t size)
|
||||
{
|
||||
ubsan("stack free 2");
|
||||
UNUSED(ptr);
|
||||
UNUSED(size);
|
||||
}
|
||||
|
||||
extern void __asan_stack_free_3(void *ptr, uintptr_t size)
|
||||
{
|
||||
ubsan("stack free 3");
|
||||
UNUSED(ptr);
|
||||
UNUSED(size);
|
||||
}
|
||||
|
||||
extern void __asan_stack_free_4(void *ptr, uintptr_t size)
|
||||
{
|
||||
ubsan("stack free 4");
|
||||
UNUSED(ptr);
|
||||
UNUSED(size);
|
||||
}
|
||||
|
||||
extern void __asan_stack_free_5(void *ptr, uintptr_t size)
|
||||
{
|
||||
ubsan("stack free 5");
|
||||
UNUSED(ptr);
|
||||
UNUSED(size);
|
||||
}
|
||||
|
||||
extern void __asan_stack_free_6(void *ptr, uintptr_t size)
|
||||
{
|
||||
ubsan("stack free 6");
|
||||
UNUSED(ptr);
|
||||
UNUSED(size);
|
||||
}
|
||||
|
||||
extern void __asan_stack_free_7(void *ptr, uintptr_t size)
|
||||
{
|
||||
ubsan("stack free 7");
|
||||
UNUSED(ptr);
|
||||
UNUSED(size);
|
||||
}
|
||||
|
||||
extern void __asan_stack_free_8(void *ptr, uintptr_t size)
|
||||
{
|
||||
ubsan("stack free 8");
|
||||
UNUSED(ptr);
|
||||
UNUSED(size);
|
||||
}
|
||||
|
||||
extern void __asan_stack_free_9(void *ptr, uintptr_t size)
|
||||
{
|
||||
ubsan("stack free 9");
|
||||
UNUSED(ptr);
|
||||
UNUSED(size);
|
||||
}
|
||||
|
||||
extern void __asan_poison_stack_memory(void *addr, uintptr_t size)
|
||||
{
|
||||
ubsan("poison stack memory");
|
||||
UNUSED(addr);
|
||||
UNUSED(size);
|
||||
}
|
||||
|
||||
extern void __asan_unpoison_stack_memory(void *addr, uintptr_t size)
|
||||
{
|
||||
ubsan("unpoison stack memory");
|
||||
UNUSED(addr);
|
||||
UNUSED(size);
|
||||
}
|
||||
|
||||
extern void __asan_before_dynamic_init(const char *module_name)
|
||||
{
|
||||
ubsan("before dynamic init");
|
||||
UNUSED(module_name);
|
||||
}
|
||||
|
||||
extern void __asan_after_dynamic_init(void) { ubsan("after dynamic init"); }
|
||||
|
||||
extern void __asan_register_globals(void *unknown, size_t size)
|
||||
{
|
||||
ubsan("register_globals");
|
||||
UNUSED(unknown);
|
||||
UNUSED(size);
|
||||
}
|
||||
|
||||
extern void __asan_unregister_globals(void) { ubsan("unregister_globals"); }
|
||||
|
||||
extern void __asan_init(void) { ubsan("init"); }
|
||||
extern void __asan_version_mismatch_check_v8(void) { ubsan("version_mismatch_check_v8"); }
|
||||
extern void __asan_option_detect_stack_use_after_return(void) { ubsan("stack use after return"); }
|
||||
|
||||
extern __noreturn void __asan_handle_no_return(void)
|
||||
{
|
||||
ubsan("no_return");
|
||||
while (1)
|
||||
asmv("cli; hlt");
|
||||
}
|
||||
|
||||
#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",
|
||||
};
|
||||
|
||||
bool UBSANMsg(const char *file, uint32_t line, uint32_t column)
|
||||
{
|
||||
ubsan("\t\tIn File: %s:%i:%i", file, line, column);
|
||||
return true;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
if (UBSANMsg(location->file, location->line, location->column))
|
||||
{
|
||||
ubsan("Null pointer access.");
|
||||
}
|
||||
}
|
||||
else if (type_mismatch->alignment != 0 && is_aligned(pointer, type_mismatch->alignment))
|
||||
{
|
||||
if (UBSANMsg(location->file, location->line, location->column))
|
||||
{
|
||||
ubsan("Unaligned memory access %#llx.", pointer);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (UBSANMsg(location->file, location->line, location->column))
|
||||
{
|
||||
ubsan("%s address %#llx 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)
|
||||
{
|
||||
if (UBSANMsg(data->location.file, data->location.line, data->location.column))
|
||||
{
|
||||
ubsan("Addition overflow.");
|
||||
}
|
||||
}
|
||||
|
||||
void __ubsan_handle_sub_overflow(struct overflow_data *data)
|
||||
{
|
||||
if (UBSANMsg(data->location.file, data->location.line, data->location.column))
|
||||
{
|
||||
ubsan("Subtraction overflow.");
|
||||
}
|
||||
}
|
||||
|
||||
void __ubsan_handle_mul_overflow(struct overflow_data *data)
|
||||
{
|
||||
if (UBSANMsg(data->location.file, data->location.line, data->location.column))
|
||||
{
|
||||
ubsan("Multiplication overflow.");
|
||||
}
|
||||
}
|
||||
|
||||
void __ubsan_handle_divrem_overflow(struct overflow_data *data)
|
||||
{
|
||||
if (UBSANMsg(data->location.file, data->location.line, data->location.column))
|
||||
{
|
||||
ubsan("Division overflow.");
|
||||
}
|
||||
}
|
||||
|
||||
void __ubsan_handle_negate_overflow(struct overflow_data *data)
|
||||
{
|
||||
if (UBSANMsg(data->location.file, data->location.line, data->location.column))
|
||||
{
|
||||
ubsan("Negation overflow.");
|
||||
}
|
||||
}
|
||||
|
||||
void __ubsan_handle_pointer_overflow(struct overflow_data *data)
|
||||
{
|
||||
if (UBSANMsg(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)
|
||||
{
|
||||
if (UBSANMsg(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)
|
||||
{
|
||||
if (UBSANMsg(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)
|
||||
{
|
||||
if (UBSANMsg(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)
|
||||
{
|
||||
if (UBSANMsg(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)
|
||||
{
|
||||
if (UBSANMsg(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)
|
||||
{
|
||||
if (UBSANMsg(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)
|
||||
{
|
||||
if (UBSANMsg(data->location.file, data->location.line, data->location.column))
|
||||
{
|
||||
ubsan("Non-null argument is null.");
|
||||
}
|
||||
}
|
||||
|
||||
void __ubsan_handle_builtin_unreachable(struct unreachable_data *data)
|
||||
{
|
||||
if (UBSANMsg(data->location.file, data->location.line, data->location.column))
|
||||
{
|
||||
ubsan("Unreachable code reached.");
|
||||
}
|
||||
}
|
||||
|
||||
void __ubsan_handle_invalid_builtin(struct invalid_builtin_data *data)
|
||||
{
|
||||
if (UBSANMsg(data->location.file, data->location.line, data->location.column))
|
||||
{
|
||||
ubsan("Invalid builtin.");
|
||||
}
|
||||
}
|
||||
|
||||
void __ubsan_handle_missing_return(struct unreachable_data *data)
|
||||
{
|
||||
if (UBSANMsg(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;
|
||||
}
|
||||
|
||||
void __ubsan_handle_dynamic_type_cache_miss(struct dynamic_type_cache_miss_data *data, uintptr_t ptr)
|
||||
{
|
||||
if (UBSANMsg(data->location.file, data->location.line, data->location.column))
|
||||
{
|
||||
ubsan("Dynamic type cache miss.");
|
||||
}
|
||||
UNUSED(ptr);
|
||||
}
|
@ -1,116 +0,0 @@
|
||||
#include <uart.hpp>
|
||||
#include <debug.h>
|
||||
|
||||
volatile bool serialports[8] = {false, false, false, false, false, false, false, false};
|
||||
|
||||
|
||||
__always_inline inline uint8_t inportb(uint16_t Port)
|
||||
{
|
||||
uint8_t Result;
|
||||
asm("in %%dx, %%al"
|
||||
: "=a"(Result)
|
||||
: "d"(Port));
|
||||
return Result;
|
||||
}
|
||||
|
||||
__always_inline inline void outportb(uint16_t Port, uint8_t Data)
|
||||
{
|
||||
asmv("out %%al, %%dx"
|
||||
:
|
||||
: "a"(Data), "d"(Port));
|
||||
}
|
||||
|
||||
namespace UniversalAsynchronousReceiverTransmitter
|
||||
{
|
||||
#define SERIAL_ENABLE_DLAB 0x80
|
||||
#define SERIAL_RATE_115200_LO 0x01
|
||||
#define SERIAL_RATE_115200_HI 0x00
|
||||
#define SERIAL_RATE_57600_LO 0x02
|
||||
#define SERIAL_RATE_57600_HI 0x00
|
||||
#define SERIAL_RATE_38400_LO 0x03
|
||||
#define SERIAL_RATE_38400_HI 0x00
|
||||
#define SERIAL_BUFFER_EMPTY 0x20
|
||||
|
||||
/* TODO: Serial Port implementation needs reword. https://wiki.osdev.org/Serial_Ports */
|
||||
|
||||
SafeFunction UART::UART(SerialPorts Port)
|
||||
{
|
||||
if (Port == COMNULL)
|
||||
return;
|
||||
|
||||
this->Port = Port;
|
||||
int PortNumber = 0;
|
||||
|
||||
switch (Port)
|
||||
{
|
||||
case COM1:
|
||||
PortNumber = 0;
|
||||
break;
|
||||
case COM2:
|
||||
PortNumber = 1;
|
||||
break;
|
||||
case COM3:
|
||||
PortNumber = 2;
|
||||
break;
|
||||
case COM4:
|
||||
PortNumber = 3;
|
||||
break;
|
||||
case COM5:
|
||||
PortNumber = 4;
|
||||
break;
|
||||
case COM6:
|
||||
PortNumber = 5;
|
||||
break;
|
||||
case COM7:
|
||||
PortNumber = 6;
|
||||
break;
|
||||
case COM8:
|
||||
PortNumber = 7;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
if (serialports[PortNumber])
|
||||
return;
|
||||
|
||||
// Initialize the serial port
|
||||
outportb(s_cst(uint16_t, Port + 1), 0x00); // Disable all interrupts
|
||||
outportb(s_cst(uint16_t, Port + 3), SERIAL_ENABLE_DLAB); // Enable DLAB (set baud rate divisor)
|
||||
outportb(s_cst(uint16_t, Port + 0), SERIAL_RATE_115200_LO); // Set divisor to 1 (lo byte) 115200 baud
|
||||
outportb(s_cst(uint16_t, Port + 1), SERIAL_RATE_115200_HI); // (hi byte)
|
||||
outportb(s_cst(uint16_t, Port + 3), 0x03); // 8 bits, no parity, one stop bit
|
||||
outportb(s_cst(uint16_t, Port + 2), 0xC7); // Enable FIFO, clear them, with 14-byte threshold
|
||||
outportb(s_cst(uint16_t, Port + 4), 0x0B); // IRQs enabled, RTS/DSR set
|
||||
|
||||
// Check if the serial port is faulty.
|
||||
if (inportb(s_cst(uint16_t, Port + 0)) != 0xAE)
|
||||
{
|
||||
static int once = 0;
|
||||
if (!once++)
|
||||
warn("Serial port %#llx is faulty.", Port);
|
||||
// serialports[Port] = false; // ignore for now
|
||||
// return;
|
||||
}
|
||||
|
||||
// Set to normal operation mode.
|
||||
outportb(s_cst(uint16_t, Port + 4), 0x0F);
|
||||
serialports[PortNumber] = true;
|
||||
}
|
||||
|
||||
SafeFunction UART::~UART() {}
|
||||
|
||||
SafeFunction void UART::Write(uint8_t Char)
|
||||
{
|
||||
while ((inportb(s_cst(uint16_t, Port + 5)) & SERIAL_BUFFER_EMPTY) == 0)
|
||||
;
|
||||
outportb(Port, Char);
|
||||
}
|
||||
|
||||
SafeFunction uint8_t UART::Read()
|
||||
{
|
||||
while ((inportb(s_cst(uint16_t, Port + 5)) & 1) == 0)
|
||||
;
|
||||
return inportb(Port);
|
||||
}
|
||||
}
|
@ -1,277 +0,0 @@
|
||||
#include <types.h>
|
||||
|
||||
#include <memory.hpp>
|
||||
#include <debug.h>
|
||||
|
||||
// TODO: complete implementation for everything
|
||||
// TODO: https://wiki.osdev.org/C%2B%2B
|
||||
|
||||
#define ATEXIT_MAX_FUNCS 128
|
||||
|
||||
typedef unsigned uarch_t;
|
||||
|
||||
struct atexit_func_entry_t
|
||||
{
|
||||
/*
|
||||
* Each member is at least 4 bytes large. Such that each entry is 12bytes.
|
||||
* 128 * 12 = 1.5KB exact.
|
||||
**/
|
||||
void (*destructor_func)(void *);
|
||||
void *obj_ptr;
|
||||
void *dso_handle;
|
||||
};
|
||||
|
||||
typedef enum
|
||||
{
|
||||
_URC_NO_REASON = 0,
|
||||
_URC_FOREIGN_EXCEPTION_CAUGHT = 1,
|
||||
_URC_FATAL_PHASE2_ERROR = 2,
|
||||
_URC_FATAL_PHASE1_ERROR = 3,
|
||||
_URC_NORMAL_STOP = 4,
|
||||
_URC_END_OF_STACK = 5,
|
||||
_URC_HANDLER_FOUND = 6,
|
||||
_URC_INSTALL_CONTEXT = 7,
|
||||
_URC_CONTINUE_UNWIND = 8
|
||||
} _Unwind_Reason_Code;
|
||||
|
||||
struct _Unwind_Context;
|
||||
typedef unsigned _Unwind_Ptr __attribute__((__mode__(__pointer__)));
|
||||
typedef unsigned _Unwind_Exception_Class __attribute__((__mode__(__DI__)));
|
||||
typedef unsigned _Unwind_Word __attribute__((__mode__(__unwind_word__)));
|
||||
typedef void (*_Unwind_Exception_Cleanup_Fn)(_Unwind_Reason_Code, struct _Unwind_Exception *);
|
||||
typedef int _Unwind_Action;
|
||||
|
||||
struct type_info
|
||||
{
|
||||
const char *name;
|
||||
};
|
||||
|
||||
struct unexpected_handler
|
||||
{
|
||||
void (*unexpected)();
|
||||
};
|
||||
|
||||
struct terminate_handler
|
||||
{
|
||||
void (*handler)();
|
||||
};
|
||||
|
||||
struct _Unwind_Exception
|
||||
{
|
||||
_Unwind_Exception_Class exception_class;
|
||||
_Unwind_Exception_Cleanup_Fn exception_cleanup;
|
||||
#if !defined(__USING_SJLJ_EXCEPTIONS__) && defined(__SEH__)
|
||||
_Unwind_Word private_[6];
|
||||
#else
|
||||
_Unwind_Word private_1;
|
||||
_Unwind_Word private_2;
|
||||
#endif
|
||||
} __attribute__((__aligned__));
|
||||
|
||||
struct __cxa_exception
|
||||
{
|
||||
#if __LP64__
|
||||
size_t referenceCount;
|
||||
#endif
|
||||
type_info *exceptionType;
|
||||
void (*exceptionDestructor)(void *);
|
||||
unexpected_handler unexpectedHandler;
|
||||
terminate_handler terminateHandler;
|
||||
__cxa_exception *nextException;
|
||||
int handlerCount;
|
||||
|
||||
#ifdef __ARM_EABI_UNWINDER__
|
||||
__cxa_exception *nextPropagatingException;
|
||||
int propagationCount;
|
||||
#else
|
||||
int handlerSwitchValue;
|
||||
const unsigned char *actionRecord;
|
||||
const unsigned char *languageSpecificData;
|
||||
_Unwind_Ptr catchTemp;
|
||||
void *adjustedPtr;
|
||||
#endif
|
||||
#if !__LP64__
|
||||
size_t referenceCount;
|
||||
#endif
|
||||
_Unwind_Exception unwindHeader;
|
||||
};
|
||||
|
||||
/* extern */ void *__dso_handle = 0;
|
||||
atexit_func_entry_t __atexit_funcs[ATEXIT_MAX_FUNCS];
|
||||
uarch_t __atexit_func_count = 0;
|
||||
|
||||
extern "C" int __cxa_atexit(void (*f)(void *), void *objptr, void *dso)
|
||||
{
|
||||
fixme("__cxa_atexit( %p %p %p ) triggered.", f, objptr, dso);
|
||||
if (__atexit_func_count >= ATEXIT_MAX_FUNCS)
|
||||
return -1;
|
||||
__atexit_funcs[__atexit_func_count].destructor_func = f;
|
||||
__atexit_funcs[__atexit_func_count].obj_ptr = objptr;
|
||||
__atexit_funcs[__atexit_func_count].dso_handle = dso;
|
||||
__atexit_func_count++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern "C" void __cxa_finalize(void *f)
|
||||
{
|
||||
fixme("__cxa_finalize( %p ) triggered.", f);
|
||||
uarch_t i = __atexit_func_count;
|
||||
if (!f)
|
||||
{
|
||||
while (i--)
|
||||
if (__atexit_funcs[i].destructor_func)
|
||||
(*__atexit_funcs[i].destructor_func)(__atexit_funcs[i].obj_ptr);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
while (i--)
|
||||
if (__atexit_funcs[i].destructor_func == f)
|
||||
{
|
||||
(*__atexit_funcs[i].destructor_func)(__atexit_funcs[i].obj_ptr);
|
||||
__atexit_funcs[i].destructor_func = 0;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" _Unwind_Reason_Code __gxx_personality_v0(int version, _Unwind_Action actions, _Unwind_Exception_Class exception_class, _Unwind_Exception *ue_header, _Unwind_Context *context)
|
||||
{
|
||||
fixme("__gxx_personality_v0( %d %p %p %p %p ) triggered.", version, actions, exception_class, ue_header, context);
|
||||
return _URC_NO_REASON;
|
||||
}
|
||||
|
||||
extern "C" void _Unwind_Resume(struct _Unwind_Exception *exc) { fixme("_Unwind_Resume( %p ) triggered.", exc); }
|
||||
|
||||
static inline size_t align_exception_allocation_size(size_t s, size_t a) { return (s + a - 1) & ~(a - 1); }
|
||||
|
||||
void unexpected_header_stub() { fixme("unexpected() called."); }
|
||||
void terminate_header_stub() { fixme("terminate() called."); }
|
||||
|
||||
extern "C" void *__cxa_allocate_exception(size_t thrown_size) throw()
|
||||
{
|
||||
fixme("__cxa_allocate_exception( %d ) triggered.", thrown_size);
|
||||
|
||||
size_t real_size = align_exception_allocation_size(thrown_size + sizeof(__cxa_exception), alignof(__cxa_exception));
|
||||
|
||||
__cxa_exception *header = (__cxa_exception *)KernelAllocator32.RequestPages(TO_PAGES(real_size));
|
||||
if (!header)
|
||||
{
|
||||
error("Failed to allocate exception.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
header->referenceCount = 1;
|
||||
header->exceptionType = nullptr;
|
||||
header->exceptionDestructor = nullptr;
|
||||
header->unexpectedHandler = {.unexpected = unexpected_header_stub};
|
||||
header->terminateHandler = {.handler = terminate_header_stub};
|
||||
header->nextException = nullptr;
|
||||
header->handlerCount = -1;
|
||||
header->handlerSwitchValue = 0;
|
||||
header->actionRecord = nullptr;
|
||||
header->languageSpecificData = nullptr;
|
||||
header->catchTemp = 0;
|
||||
header->adjustedPtr = nullptr;
|
||||
|
||||
return header + 1;
|
||||
}
|
||||
|
||||
extern "C" void _Unwind_RaiseException(_Unwind_Exception *exc)
|
||||
{
|
||||
fixme("_Unwind_RaiseException( %p ) triggered.", exc);
|
||||
|
||||
__cxa_exception *header = ((__cxa_exception *)exc) - 1;
|
||||
if (header->terminateHandler.handler)
|
||||
{
|
||||
debug("Calling terminate handler.");
|
||||
header->terminateHandler.handler();
|
||||
}
|
||||
else
|
||||
{
|
||||
error("Unhandled exception.");
|
||||
}
|
||||
|
||||
while (1)
|
||||
asmv("cli; hlt");
|
||||
}
|
||||
|
||||
extern "C" void __cxa_throw(void *thrown_object, void *tinfo, void (*dest)(void *))
|
||||
{
|
||||
fixme("__cxa_throw( %p %p %p ) triggered.", thrown_object, tinfo, dest);
|
||||
|
||||
__cxa_exception *header = ((__cxa_exception *)thrown_object) - 1;
|
||||
header->exceptionType = (type_info *)tinfo;
|
||||
header->exceptionDestructor = dest;
|
||||
|
||||
_Unwind_RaiseException(&header->unwindHeader);
|
||||
}
|
||||
|
||||
extern "C" void __cxa_rethrow() { fixme("__cxa_rethrow() triggered."); }
|
||||
|
||||
extern "C" void __cxa_pure_virtual() { fixme("__cxa_pure_virtual() triggered."); }
|
||||
|
||||
extern "C" void __cxa_throw_bad_array_new_length() { fixme("__cxa_throw_bad_array_new_length() triggered."); }
|
||||
|
||||
extern "C" void __cxa_free_exception(void *thrown_exception) { fixme("__cxa_free_exception( %p ) triggered.", thrown_exception); }
|
||||
|
||||
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)
|
||||
extern "C" void *__cxa_begin_catch(void *e) throw()
|
||||
#else
|
||||
extern "C" void *__cxa_begin_catch(void *e)
|
||||
#endif
|
||||
{
|
||||
fixme("__cxa_begin_catch( %p ) triggered.", e);
|
||||
return (void *)0;
|
||||
}
|
||||
|
||||
extern "C" void __cxa_end_catch() { fixme("__cxa_end_catch() triggered."); }
|
||||
|
||||
__extension__ typedef int __guard __attribute__((mode(__DI__)));
|
||||
|
||||
extern "C" int __cxa_guard_acquire(__guard *g)
|
||||
{
|
||||
fixme("__cxa_guard_acquire( %p ) triggered.", g);
|
||||
return !*(char *)(g);
|
||||
}
|
||||
|
||||
extern "C" void __cxa_guard_release(__guard *g)
|
||||
{
|
||||
fixme("__cxa_guard_release( %p ) triggered.", g);
|
||||
*(char *)g = 1;
|
||||
}
|
||||
|
||||
extern "C" void __cxa_guard_abort(__guard *g) { fixme("__cxa_guard_abort( %p ) triggered.", g); }
|
||||
|
||||
// vtable for __cxxabiv1::__class_type_info
|
||||
extern "C" void *_ZTVN10__cxxabiv117__class_type_infoE(void)
|
||||
{
|
||||
fixme("_ZTVN10__cxxabiv117__class_type_infoE() triggered.");
|
||||
return (void *)0;
|
||||
}
|
||||
|
||||
// vtable for __cxxabiv1::__si_class_type_info
|
||||
extern "C" void *_ZTVN10__cxxabiv120__si_class_type_infoE(void)
|
||||
{
|
||||
fixme("_ZTVN10__cxxabiv120__si_class_type_infoE() triggered.");
|
||||
return (void *)0;
|
||||
}
|
||||
|
||||
// typeinfo for int
|
||||
extern "C" void *_ZTIi(void)
|
||||
{
|
||||
fixme("_ZTIi() triggered.");
|
||||
return (void *)0;
|
||||
}
|
||||
|
||||
// typeinfo for unsigned char*
|
||||
extern "C" void *_ZTIPh(void)
|
||||
{
|
||||
fixme("_ZTIPh() triggered.");
|
||||
return (void *)0;
|
||||
}
|
||||
|
||||
// typeinfo for char const*
|
||||
extern "C" void *_ZTIPKc(void)
|
||||
{
|
||||
fixme("_ZTIPKc() triggered.");
|
||||
return (void *)0;
|
||||
}
|
@ -1,166 +0,0 @@
|
||||
/* https://wiki.osdev.org/Bare_Bones */
|
||||
#include <types.h>
|
||||
|
||||
enum vga_color
|
||||
{
|
||||
VGA_COLOR_BLACK = 0,
|
||||
VGA_COLOR_BLUE = 1,
|
||||
VGA_COLOR_GREEN = 2,
|
||||
VGA_COLOR_CYAN = 3,
|
||||
VGA_COLOR_RED = 4,
|
||||
VGA_COLOR_MAGENTA = 5,
|
||||
VGA_COLOR_BROWN = 6,
|
||||
VGA_COLOR_LIGHT_GREY = 7,
|
||||
VGA_COLOR_DARK_GREY = 8,
|
||||
VGA_COLOR_LIGHT_BLUE = 9,
|
||||
VGA_COLOR_LIGHT_GREEN = 10,
|
||||
VGA_COLOR_LIGHT_CYAN = 11,
|
||||
VGA_COLOR_LIGHT_RED = 12,
|
||||
VGA_COLOR_LIGHT_MAGENTA = 13,
|
||||
VGA_COLOR_LIGHT_BROWN = 14,
|
||||
VGA_COLOR_WHITE = 15,
|
||||
};
|
||||
|
||||
void outb(uint16_t port, uint8_t val)
|
||||
{
|
||||
asm volatile("outb %0, %1"
|
||||
:
|
||||
: "a"(val), "Nd"(port));
|
||||
}
|
||||
|
||||
static inline uint8_t vga_entry_color(enum vga_color fg, enum vga_color bg)
|
||||
{
|
||||
return fg | bg << 4;
|
||||
}
|
||||
|
||||
static inline uint16_t vga_entry(unsigned char uc, uint8_t color)
|
||||
{
|
||||
return (uint16_t)uc | (uint16_t)color << 8;
|
||||
}
|
||||
|
||||
size_t ega_strlen(const char *str)
|
||||
{
|
||||
size_t len = 0;
|
||||
while (str[len])
|
||||
len++;
|
||||
return len;
|
||||
}
|
||||
|
||||
static const size_t VGA_WIDTH = 80;
|
||||
static const size_t VGA_HEIGHT = 25;
|
||||
|
||||
int terminal_initialized;
|
||||
size_t terminal_row;
|
||||
size_t terminal_column;
|
||||
uint8_t terminal_color;
|
||||
uint16_t *terminal_buffer;
|
||||
|
||||
void terminal_initialize(void)
|
||||
{
|
||||
terminal_initialized = 1;
|
||||
terminal_row = 0;
|
||||
terminal_column = 0;
|
||||
terminal_color = vga_entry_color(VGA_COLOR_LIGHT_GREY, VGA_COLOR_BLACK);
|
||||
terminal_buffer = (uint16_t *)0xB8000;
|
||||
for (size_t y = 0; y < VGA_HEIGHT; y++)
|
||||
{
|
||||
for (size_t x = 0; x < VGA_WIDTH; x++)
|
||||
{
|
||||
const size_t index = y * VGA_WIDTH + x;
|
||||
terminal_buffer[index] = vga_entry(' ', terminal_color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void terminal_setcolor(uint8_t color)
|
||||
{
|
||||
terminal_color = color;
|
||||
}
|
||||
|
||||
void terminal_putentryat(char c, uint8_t color, size_t x, size_t y)
|
||||
{
|
||||
if (!terminal_initialized)
|
||||
return;
|
||||
const size_t index = y * VGA_WIDTH + x;
|
||||
terminal_buffer[index] = vga_entry(c, color);
|
||||
}
|
||||
|
||||
void terminal_putchar(char c)
|
||||
{
|
||||
if (!terminal_initialized)
|
||||
return;
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case '\n':
|
||||
case '\r':
|
||||
terminal_column = 0;
|
||||
if (++terminal_row >= VGA_HEIGHT)
|
||||
{
|
||||
// terminal_row = 0;
|
||||
// scroll the screen
|
||||
for (size_t y = 0; y < VGA_HEIGHT - 1; y++)
|
||||
{
|
||||
for (size_t x = 0; x < VGA_WIDTH; x++)
|
||||
{
|
||||
const size_t index = y * VGA_WIDTH + x;
|
||||
terminal_buffer[index] = terminal_buffer[index + VGA_WIDTH];
|
||||
}
|
||||
}
|
||||
for (size_t x = 0; x < VGA_WIDTH; x++)
|
||||
{
|
||||
const size_t index = (VGA_HEIGHT - 1) * VGA_WIDTH + x;
|
||||
terminal_buffer[index] = vga_entry(' ', terminal_color);
|
||||
}
|
||||
terminal_row = VGA_HEIGHT - 1;
|
||||
}
|
||||
// Update the cursor
|
||||
uint16_t cursorLocation = terminal_row * 80 + terminal_column;
|
||||
outb(0x3D4, 14); // Tell the VGA board we are setting the high cursor byte.
|
||||
outb(0x3D5, cursorLocation >> 8); // Send the high cursor byte.
|
||||
outb(0x3D4, 15); // Tell the VGA board we are setting the low cursor byte.
|
||||
outb(0x3D5, cursorLocation); // Send the low cursor byte.
|
||||
return;
|
||||
case '\t':
|
||||
terminal_column += 4;
|
||||
if (terminal_column >= VGA_WIDTH)
|
||||
{
|
||||
terminal_column = 0;
|
||||
if (++terminal_row == VGA_HEIGHT)
|
||||
terminal_row = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
terminal_putentryat(c, terminal_color, terminal_column, terminal_row);
|
||||
if (++terminal_column >= VGA_WIDTH)
|
||||
{
|
||||
terminal_column = 0;
|
||||
if (++terminal_row >= VGA_HEIGHT)
|
||||
{
|
||||
// terminal_row = 0;
|
||||
// scroll the screen
|
||||
for (size_t y = 0; y < VGA_HEIGHT - 1; y++)
|
||||
{
|
||||
for (size_t x = 0; x < VGA_WIDTH; x++)
|
||||
{
|
||||
const size_t index = y * VGA_WIDTH + x;
|
||||
terminal_buffer[index] = terminal_buffer[index + VGA_WIDTH];
|
||||
}
|
||||
}
|
||||
for (size_t x = 0; x < VGA_WIDTH; x++)
|
||||
{
|
||||
const size_t index = (VGA_HEIGHT - 1) * VGA_WIDTH + x;
|
||||
terminal_buffer[index] = vga_entry(' ', terminal_color);
|
||||
}
|
||||
terminal_row = VGA_HEIGHT - 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Update the cursor
|
||||
uint16_t cursorLocation = terminal_row * 80 + terminal_column;
|
||||
outb(0x3D4, 14); // Tell the VGA board we are setting the high cursor byte.
|
||||
outb(0x3D5, cursorLocation >> 8); // Send the high cursor byte.
|
||||
outb(0x3D4, 15); // Tell the VGA board we are setting the low cursor byte.
|
||||
outb(0x3D5, cursorLocation); // Send the low cursor byte.
|
||||
}
|
@ -1,130 +0,0 @@
|
||||
#ifndef __FENNIX_KERNEL_BOOT_INFO_H__
|
||||
#define __FENNIX_KERNEL_BOOT_INFO_H__
|
||||
|
||||
enum MemoryType
|
||||
{
|
||||
Unknown_Memory_Type,
|
||||
Usable,
|
||||
Reserved,
|
||||
ACPIReclaimable,
|
||||
ACPINVS,
|
||||
BadMemory,
|
||||
BootloaderReclaimable,
|
||||
KernelAndModules,
|
||||
Framebuffer,
|
||||
Unknown
|
||||
};
|
||||
|
||||
enum FramebufferType
|
||||
{
|
||||
Unknown_Framebuffer_Type,
|
||||
Indexed,
|
||||
RGB,
|
||||
EGA
|
||||
};
|
||||
|
||||
#define MAX_FRAMEBUFFERS 16
|
||||
#define MAX_MEMORY_ENTRIES 256
|
||||
#define MAX_MODULES 16
|
||||
|
||||
struct BootInfo
|
||||
{
|
||||
struct FramebufferInfo
|
||||
{
|
||||
enum FramebufferType Type;
|
||||
void *BaseAddress;
|
||||
__UINT32_TYPE__ Width;
|
||||
__UINT32_TYPE__ Height;
|
||||
__UINT64_TYPE__ Pitch;
|
||||
__UINT16_TYPE__ BitsPerPixel;
|
||||
__UINT8_TYPE__ RedMaskSize;
|
||||
__UINT8_TYPE__ RedMaskShift;
|
||||
__UINT8_TYPE__ GreenMaskSize;
|
||||
__UINT8_TYPE__ GreenMaskShift;
|
||||
__UINT8_TYPE__ BlueMaskSize;
|
||||
__UINT8_TYPE__ BlueMaskShift;
|
||||
void *ExtendedDisplayIdentificationData;
|
||||
__UINT64_TYPE__ EDIDSize;
|
||||
} Framebuffer[MAX_FRAMEBUFFERS];
|
||||
|
||||
struct MemoryInfo
|
||||
{
|
||||
struct MemoryEntryInfo
|
||||
{
|
||||
void *BaseAddress;
|
||||
__UINT64_TYPE__ Length;
|
||||
enum MemoryType Type;
|
||||
} Entry[MAX_MEMORY_ENTRIES];
|
||||
__UINT64_TYPE__ Entries;
|
||||
__UINT64_TYPE__ Size;
|
||||
} Memory;
|
||||
|
||||
struct ModuleInfo
|
||||
{
|
||||
void *Address;
|
||||
char Path[256];
|
||||
char CommandLine[256];
|
||||
__UINT64_TYPE__ Size;
|
||||
} Modules[MAX_MODULES];
|
||||
|
||||
struct RSDPInfo
|
||||
{
|
||||
/**
|
||||
* @brief Signature
|
||||
*/
|
||||
__UINT8_TYPE__ Signature[8];
|
||||
/**
|
||||
* @brief Checksum
|
||||
*/
|
||||
__UINT8_TYPE__ Checksum;
|
||||
/**
|
||||
* @brief OEM ID
|
||||
*/
|
||||
__UINT8_TYPE__ OEMID[6];
|
||||
/**
|
||||
* @brief Revision
|
||||
*/
|
||||
__UINT8_TYPE__ Revision;
|
||||
/**
|
||||
* @brief Address of the Root System Description Table
|
||||
*/
|
||||
__UINT32_TYPE__ RSDTAddress;
|
||||
/* END OF RSDP 1.0 */
|
||||
|
||||
/**
|
||||
* @brief Length
|
||||
*/
|
||||
__UINT32_TYPE__ Length;
|
||||
/**
|
||||
* @brief Extended System Descriptor Table
|
||||
*/
|
||||
__UINT64_TYPE__ XSDTAddress;
|
||||
/**
|
||||
* @brief Extended checksum
|
||||
*/
|
||||
__UINT8_TYPE__ ExtendedChecksum;
|
||||
/**
|
||||
* @brief Reserved
|
||||
*/
|
||||
__UINT8_TYPE__ Reserved[3];
|
||||
} __attribute__((packed)) * RSDP;
|
||||
|
||||
struct KernelInfo
|
||||
{
|
||||
void *PhysicalBase;
|
||||
void *VirtualBase;
|
||||
void *FileBase;
|
||||
char CommandLine[256];
|
||||
__UINT64_TYPE__ Size;
|
||||
} Kernel;
|
||||
|
||||
struct BootloaderInfo
|
||||
{
|
||||
char Name[256];
|
||||
char Version[64];
|
||||
} Bootloader;
|
||||
|
||||
void *SMBIOSPtr;
|
||||
};
|
||||
|
||||
#endif // !__FENNIX_KERNEL_BOOT_INFO_H__
|
@ -1,12 +0,0 @@
|
||||
#pragma once
|
||||
#include <types.h>
|
||||
|
||||
class Bitmap
|
||||
{
|
||||
public:
|
||||
size_t Size;
|
||||
uint8_t *Buffer;
|
||||
bool operator[](uint64_t index);
|
||||
bool Set(uint64_t index, bool value);
|
||||
bool Get(uint64_t index);
|
||||
};
|
@ -1,89 +0,0 @@
|
||||
#ifndef __FENNIX_KERNEL_DEBUGGER_H__
|
||||
#define __FENNIX_KERNEL_DEBUGGER_H__
|
||||
|
||||
#include <types.h>
|
||||
|
||||
enum DebugLevel
|
||||
{
|
||||
DebugLevelNone = 0,
|
||||
DebugLevelError = 1,
|
||||
DebugLevelWarning = 2,
|
||||
DebugLevelInfo = 3,
|
||||
DebugLevelDebug = 4,
|
||||
DebugLevelTrace = 5,
|
||||
DebugLevelFixme = 6,
|
||||
DebugLevelUbsan = 7
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
namespace SysDbg
|
||||
{
|
||||
void Write(DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...);
|
||||
void WriteLine(DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...);
|
||||
void LockedWrite(DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...);
|
||||
void LockedWriteLine(DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...);
|
||||
}
|
||||
|
||||
#define error(Format, ...) SysDbg::WriteLine(DebugLevelError, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
|
||||
#define warn(Format, ...) SysDbg::WriteLine(DebugLevelWarning, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
|
||||
#define info(Format, ...) SysDbg::WriteLine(DebugLevelInfo, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
|
||||
#ifdef DEBUG
|
||||
#define debug(Format, ...) SysDbg::WriteLine(DebugLevelDebug, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
|
||||
#define ubsan(Format, ...) SysDbg::WriteLine(DebugLevelUbsan, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
|
||||
#else
|
||||
#define debug(Format, ...)
|
||||
#define ubsan(Format, ...)
|
||||
#endif
|
||||
#define trace(Format, ...) SysDbg::WriteLine(DebugLevelTrace, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
|
||||
#define fixme(Format, ...) SysDbg::WriteLine(DebugLevelFixme, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
|
||||
|
||||
#define locked_error(Format, ...) SysDbg::LockedWriteLine(DebugLevelError, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
|
||||
#define locked_warn(Format, ...) SysDbg::LockedWriteLine(DebugLevelWarning, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
|
||||
#define locked_info(Format, ...) SysDbg::LockedWriteLine(DebugLevelInfo, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
|
||||
#ifdef DEBUG
|
||||
#define locked_debug(Format, ...) SysDbg::LockedWriteLine(DebugLevelDebug, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
|
||||
#define locked_ubsan(Format, ...) SysDbg::LockedWriteLine(DebugLevelUbsan, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
|
||||
#else
|
||||
#define locked_debug(Format, ...)
|
||||
#define locked_ubsan(Format, ...)
|
||||
#endif
|
||||
#define locked_trace(Format, ...) SysDbg::LockedWriteLine(DebugLevelTrace, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
|
||||
#define locked_fixme(Format, ...) SysDbg::LockedWriteLine(DebugLevelFixme, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
|
||||
|
||||
#else
|
||||
|
||||
void SysDbgWrite(enum DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...);
|
||||
void SysDbgWriteLine(enum DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...);
|
||||
void SysDbgLockedWrite(enum DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...);
|
||||
void SysDbgLockedWriteLine(enum DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...);
|
||||
|
||||
#define error(Format, ...) SysDbgWriteLine(DebugLevelError, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
|
||||
#define warn(Format, ...) SysDbgWriteLine(DebugLevelWarning, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
|
||||
#define info(Format, ...) SysDbgWriteLine(DebugLevelInfo, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
|
||||
#ifdef DEBUG
|
||||
#define debug(Format, ...) SysDbgWriteLine(DebugLevelDebug, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
|
||||
#define ubsan(Format, ...) SysDbgWriteLine(DebugLevelUbsan, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
|
||||
#else
|
||||
#define debug(Format, ...)
|
||||
#define ubsan(Format, ...)
|
||||
#endif
|
||||
#define trace(Format, ...) SysDbgWriteLine(DebugLevelTrace, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
|
||||
#define fixme(Format, ...) SysDbgWriteLine(DebugLevelFixme, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
|
||||
|
||||
#define locked_error(Format, ...) SysDbgLockedWriteLine(DebugLevelError, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
|
||||
#define locked_warn(Format, ...) SysDbgLockedWriteLine(DebugLevelWarning, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
|
||||
#define locked_info(Format, ...) SysDbgLockedWriteLine(DebugLevelInfo, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
|
||||
#ifdef DEBUG
|
||||
#define locked_debug(Format, ...) SysDbgLockedWriteLine(DebugLevelDebug, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
|
||||
#define locked_ubsan(Format, ...) SysDbgLockedWriteLine(DebugLevelUbsan, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
|
||||
#else
|
||||
#define locked_debug(Format, ...)
|
||||
#define locked_ubsan(Format, ...)
|
||||
#endif
|
||||
#define locked_trace(Format, ...) SysDbgLockedWriteLine(DebugLevelTrace, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
|
||||
#define locked_fixme(Format, ...) SysDbgLockedWriteLine(DebugLevelFixme, __FILE__, __LINE__, __FUNCTION__, Format, ##__VA_ARGS__)
|
||||
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif // !__FENNIX_KERNEL_DEBUGGER_H__
|
@ -1,476 +0,0 @@
|
||||
#ifndef __FENNIX_KERNEL_ELF_H__
|
||||
#define __FENNIX_KERNEL_ELF_H__
|
||||
|
||||
#include <types.h>
|
||||
|
||||
// https://wiki.osdev.org/ELF_Tutorial
|
||||
// https://github.com/torvalds/linux/blob/master/include/uapi/linux/elf.h
|
||||
|
||||
/* 32-bit ELF base types. */
|
||||
typedef uint32_t Elf32_Addr;
|
||||
typedef uint16_t Elf32_Half;
|
||||
typedef uint32_t Elf32_Off;
|
||||
typedef int32_t Elf32_Sword;
|
||||
typedef uint32_t Elf32_Word;
|
||||
|
||||
/* 64-bit ELF base types. */
|
||||
typedef uint64_t Elf64_Addr;
|
||||
typedef uint16_t Elf64_Half;
|
||||
typedef int16_t Elf64_SHalf;
|
||||
typedef uint64_t Elf64_Off;
|
||||
typedef int32_t Elf64_Sword;
|
||||
typedef uint32_t Elf64_Word;
|
||||
typedef uint64_t Elf64_Xword;
|
||||
typedef int64_t Elf64_Sxword;
|
||||
|
||||
#define EI_NIDENT 16
|
||||
|
||||
typedef struct elf32_hdr
|
||||
{
|
||||
unsigned char e_ident[EI_NIDENT];
|
||||
Elf32_Half e_type;
|
||||
Elf32_Half e_machine;
|
||||
Elf32_Word e_version;
|
||||
Elf32_Addr e_entry;
|
||||
Elf32_Off e_phoff;
|
||||
Elf32_Off e_shoff;
|
||||
Elf32_Word e_flags;
|
||||
Elf32_Half e_ehsize;
|
||||
Elf32_Half e_phentsize;
|
||||
Elf32_Half e_phnum;
|
||||
Elf32_Half e_shentsize;
|
||||
Elf32_Half e_shnum;
|
||||
Elf32_Half e_shstrndx;
|
||||
} Elf32_Ehdr;
|
||||
|
||||
typedef struct elf64_hdr
|
||||
{
|
||||
unsigned char e_ident[EI_NIDENT]; /* ELF "magic number" */
|
||||
Elf64_Half e_type;
|
||||
Elf64_Half e_machine;
|
||||
Elf64_Word e_version;
|
||||
Elf64_Addr e_entry; /* Entry point virtual address */
|
||||
Elf64_Off e_phoff; /* Program header table file offset */
|
||||
Elf64_Off e_shoff; /* Section header table file offset */
|
||||
Elf64_Word e_flags;
|
||||
Elf64_Half e_ehsize;
|
||||
Elf64_Half e_phentsize;
|
||||
Elf64_Half e_phnum;
|
||||
Elf64_Half e_shentsize;
|
||||
Elf64_Half e_shnum;
|
||||
Elf64_Half e_shstrndx;
|
||||
} Elf64_Ehdr;
|
||||
|
||||
typedef struct elf32_shdr
|
||||
{
|
||||
Elf32_Word sh_name;
|
||||
Elf32_Word sh_type;
|
||||
Elf32_Word sh_flags;
|
||||
Elf32_Addr sh_addr;
|
||||
Elf32_Off sh_offset;
|
||||
Elf32_Word sh_size;
|
||||
Elf32_Word sh_link;
|
||||
Elf32_Word sh_info;
|
||||
Elf32_Word sh_addralign;
|
||||
Elf32_Word sh_entsize;
|
||||
} Elf32_Shdr;
|
||||
|
||||
typedef struct elf64_shdr
|
||||
{
|
||||
Elf64_Word sh_name; /* Section name, index in string tbl */
|
||||
Elf64_Word sh_type; /* Type of section */
|
||||
Elf64_Xword sh_flags; /* Miscellaneous section attributes */
|
||||
Elf64_Addr sh_addr; /* Section virtual addr at execution */
|
||||
Elf64_Off sh_offset; /* Section file offset */
|
||||
Elf64_Xword sh_size; /* Size of section in bytes */
|
||||
Elf64_Word sh_link; /* Index of another section */
|
||||
Elf64_Word sh_info; /* Additional section information */
|
||||
Elf64_Xword sh_addralign; /* Section alignment */
|
||||
Elf64_Xword sh_entsize; /* Entry size if section holds table */
|
||||
} Elf64_Shdr;
|
||||
|
||||
typedef struct {
|
||||
Elf32_Word p_type;
|
||||
Elf32_Off p_offset;
|
||||
Elf32_Addr p_vaddr;
|
||||
Elf32_Addr p_paddr;
|
||||
Elf32_Word p_filesz;
|
||||
Elf32_Word p_memsz;
|
||||
Elf32_Word p_flags;
|
||||
Elf32_Word p_align;
|
||||
} Elf32_Phdr;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Elf64_Word p_type;
|
||||
Elf64_Word p_flags;
|
||||
Elf64_Off p_offset;
|
||||
Elf64_Addr p_vaddr;
|
||||
Elf64_Addr p_paddr;
|
||||
Elf64_Xword p_filesz;
|
||||
Elf64_Xword p_memsz;
|
||||
Elf64_Xword p_align;
|
||||
} Elf64_Phdr;
|
||||
|
||||
typedef struct elf32_rel
|
||||
{
|
||||
Elf32_Addr r_offset;
|
||||
Elf32_Word r_info;
|
||||
} Elf32_Rel;
|
||||
|
||||
typedef struct elf64_rel
|
||||
{
|
||||
Elf64_Addr r_offset; /* Location at which to apply the action */
|
||||
Elf64_Xword r_info; /* index and type of relocation */
|
||||
} Elf64_Rel;
|
||||
|
||||
typedef struct elf32_sym
|
||||
{
|
||||
Elf32_Word st_name;
|
||||
Elf32_Addr st_value;
|
||||
Elf32_Word st_size;
|
||||
unsigned char st_info;
|
||||
unsigned char st_other;
|
||||
Elf32_Half st_shndx;
|
||||
} Elf32_Sym;
|
||||
|
||||
typedef struct elf64_sym
|
||||
{
|
||||
Elf64_Word st_name; /* Symbol name, index in string tbl */
|
||||
unsigned char st_info; /* Type and binding attributes */
|
||||
unsigned char st_other; /* No defined meaning, 0 */
|
||||
Elf64_Half st_shndx; /* Associated section index */
|
||||
Elf64_Addr st_value; /* Value of the symbol */
|
||||
Elf64_Xword st_size; /* Associated symbol size */
|
||||
} Elf64_Sym;
|
||||
|
||||
struct Elf32_Dyn
|
||||
{
|
||||
Elf32_Sword d_tag; /* Type of dynamic table entry. */
|
||||
union
|
||||
{
|
||||
Elf32_Word d_val; /* Integer value of entry. */
|
||||
Elf32_Addr d_ptr; /* Pointer value of entry. */
|
||||
} d_un;
|
||||
};
|
||||
|
||||
struct Elf64_Dyn
|
||||
{
|
||||
Elf64_Sxword d_tag; /* Type of dynamic table entry. */
|
||||
union
|
||||
{
|
||||
Elf64_Xword d_val; /* Integer value of entry. */
|
||||
Elf64_Addr d_ptr; /* Pointer value of entry. */
|
||||
} d_un;
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Elf64_Addr r_offset;
|
||||
Elf64_Xword r_info;
|
||||
Elf64_Sxword r_addend;
|
||||
} Elf64_Rela;
|
||||
|
||||
enum Elf_Ident
|
||||
{
|
||||
EI_MAG0 = 0, // 0x7F
|
||||
EI_MAG1 = 1, // 'E'
|
||||
EI_MAG2 = 2, // 'L'
|
||||
EI_MAG3 = 3, // 'F'
|
||||
EI_CLASS = 4, // Architecture (32/64)
|
||||
EI_DATA = 5, // Byte Order
|
||||
EI_VERSION = 6, // ELF Version
|
||||
EI_OSABI = 7, // OS Specific
|
||||
EI_ABIVERSION = 8, // OS Specific
|
||||
EI_PAD = 9 // Padding
|
||||
};
|
||||
|
||||
enum Elf_OSABI
|
||||
{
|
||||
ELFOSABI_NONE = 0,
|
||||
ELFOSABI_HPUX = 1,
|
||||
ELFOSABI_NETBSD = 2,
|
||||
ELFOSABI_LINUX = 3,
|
||||
ELFOSABI_HURD = 4,
|
||||
ELFOSABI_SOLARIS = 6,
|
||||
ELFOSABI_AIX = 7,
|
||||
ELFOSABI_IRIX = 8,
|
||||
ELFOSABI_FREEBSD = 9,
|
||||
ELFOSABI_TRU64 = 10,
|
||||
ELFOSABI_MODESTO = 11,
|
||||
ELFOSABI_OPENBSD = 12,
|
||||
ELFOSABI_OPENVMS = 13,
|
||||
ELFOSABI_NSK = 14,
|
||||
ELFOSABI_AROS = 15,
|
||||
ELFOSABI_FENIXOS = 16,
|
||||
ELFOSABI_CLOUDABI = 17,
|
||||
ELFOSABI_OPENVOS = 18,
|
||||
ELFOSABI_C6000_ELFABI = 64,
|
||||
ELFOSABI_C6000_LINUX = 65,
|
||||
ELFOSABI_ARM = 97,
|
||||
ELFOSABI_STANDALONE = 255
|
||||
};
|
||||
|
||||
enum Elf_Type
|
||||
{
|
||||
ET_NONE = 0, // Unknown Type
|
||||
ET_REL = 1, // Relocatable File
|
||||
ET_EXEC = 2, // Executable File
|
||||
ET_DYN = 3, // Shared Object File
|
||||
ET_CORE = 4, // Core File
|
||||
ET_LOPROC = 0xff00, // Processor Specific
|
||||
ET_HIPROC = 0xffff // Processor Specific
|
||||
};
|
||||
|
||||
enum RtT_Types
|
||||
{
|
||||
R_386_NONE = 0, // No relocation
|
||||
R_386_32 = 1, // Symbol + Offset
|
||||
R_386_PC32 = 2, // Symbol + Offset - Section Offset
|
||||
|
||||
R_X86_64_NONE = 0,
|
||||
R_X86_64_64 = 1,
|
||||
R_X86_64_PC32 = 2,
|
||||
R_X86_64_GOT32 = 3,
|
||||
R_X86_64_PLT32 = 4,
|
||||
R_X86_64_COPY = 5,
|
||||
R_X86_64_GLOB_DAT = 6,
|
||||
R_X86_64_JUMP_SLOT = 7,
|
||||
R_X86_64_RELATIVE = 8,
|
||||
R_X86_64_GOTPCREL = 9,
|
||||
R_X86_64_32 = 10,
|
||||
R_X86_64_32S = 11,
|
||||
R_X86_64_16 = 12,
|
||||
};
|
||||
|
||||
enum ProgFlags_Types
|
||||
{
|
||||
PF_X = 1,
|
||||
PF_W = 2,
|
||||
PF_R = 4
|
||||
};
|
||||
|
||||
enum StT_Bindings
|
||||
{
|
||||
/**
|
||||
* @brief Local symbol. Symbol is not visible outside the object file.
|
||||
*/
|
||||
STB_LOCAL = 0,
|
||||
/**
|
||||
* @brief Global symbol. These symbols are visible to all object files being combined.
|
||||
*/
|
||||
STB_GLOBAL = 1,
|
||||
/**
|
||||
* @brief Weak symbols. These symbols are like global symbols, but their definitions are not required. Weak symbols are not visible outside the object file containing their definition.
|
||||
*/
|
||||
STB_WEAK = 2,
|
||||
/**
|
||||
* @brief Values in this inclusive range are reserved for operating system-specific semantics.
|
||||
*/
|
||||
STB_LOOS = 10,
|
||||
/**
|
||||
* @brief Values in this inclusive range are reserved for operating system-specific semantics.
|
||||
*/
|
||||
STB_HIOS = 12,
|
||||
/**
|
||||
* @brief Values in this inclusive range are reserved for processor-specific semantics.
|
||||
*/
|
||||
STB_LOPROC = 13,
|
||||
/**
|
||||
* @brief Values in this inclusive range are reserved for processor-specific semantics.
|
||||
*/
|
||||
STB_HIPROC = 15
|
||||
};
|
||||
|
||||
enum StT_Types
|
||||
{
|
||||
STT_NOTYPE = 0, // No type
|
||||
STT_OBJECT = 1, // Variables, arrays, etc.
|
||||
STT_FUNC = 2 // Methods or functions
|
||||
};
|
||||
|
||||
enum SegmentTypes
|
||||
{
|
||||
PT_NULL = 0,
|
||||
PT_LOAD = 1,
|
||||
PT_DYNAMIC = 2,
|
||||
PT_INTERP = 3,
|
||||
PT_NOTE = 4,
|
||||
PT_SHLIB = 5,
|
||||
PT_PHDR = 6,
|
||||
PT_TLS = 7,
|
||||
PT_LOSUNW = 0x6ffffffa,
|
||||
PT_SUNWBSS = 0x6ffffffb,
|
||||
PT_SUNWSTACK = 0x6ffffffa,
|
||||
PT_HISUNW = 0x6fffffff,
|
||||
PT_LOPROC = 0x70000000,
|
||||
PT_HIPROC = 0x7fffffff
|
||||
};
|
||||
|
||||
/* https://docs.oracle.com/cd/E19683-01/817-3677/chapter6-42444/index.html */
|
||||
enum DynamicArrayTags
|
||||
{
|
||||
DT_NULL = 0,
|
||||
DT_NEEDED = 1,
|
||||
DT_PLTRELSZ = 2,
|
||||
DT_PLTGOT = 3,
|
||||
DT_HASH = 4,
|
||||
DT_STRTAB = 5,
|
||||
DT_SYMTAB = 6,
|
||||
DT_RELA = 7,
|
||||
DT_RELASZ = 8,
|
||||
DT_RELAENT = 9,
|
||||
DT_STRSZ = 10,
|
||||
DT_SYMENT = 11,
|
||||
DT_INIT = 12,
|
||||
DT_FINI = 13,
|
||||
DT_SONAME = 14,
|
||||
DT_RPATH = 15,
|
||||
DT_SYMBOLIC = 16,
|
||||
DT_REL = 17,
|
||||
DT_RELSZ = 18,
|
||||
DT_RELENT = 19,
|
||||
DT_PLTREL = 20,
|
||||
DT_DEBUG = 21,
|
||||
DT_TEXTREL = 22,
|
||||
DT_JMPREL = 23,
|
||||
DT_BIND_NOW = 24,
|
||||
DT_INIT_ARRAY = 25,
|
||||
DT_FINI_ARRAY = 26,
|
||||
DT_INIT_ARRAYSZ = 27,
|
||||
DT_FINI_ARRAYSZ = 28,
|
||||
DT_RUNPATH = 29,
|
||||
DT_FLAGS = 30,
|
||||
DT_ENCODING = 32,
|
||||
DT_PREINIT_ARRAY = 32,
|
||||
DT_PREINIT_ARRAYSZ = 33,
|
||||
DT_LOOS = 0x6000000d,
|
||||
DT_SUNW_RTLDINF = 0x6000000e,
|
||||
DT_HIOS = 0x6ffff000,
|
||||
DT_VALRNGLO = 0x6ffffd00,
|
||||
DT_CHECKSUM = 0x6ffffdf8,
|
||||
DT_PLTPADSZ = 0x6ffffdf9,
|
||||
DT_MOVEENT = 0x6ffffdfa,
|
||||
DT_MOVESZ = 0x6ffffdfb,
|
||||
DT_FEATURE_1 = 0x6ffffdfc,
|
||||
DT_POSFLAG_1 = 0x6ffffdfd,
|
||||
DT_SYMINSZ = 0x6ffffdfe,
|
||||
DT_SYMINENT = 0x6ffffdff,
|
||||
DT_VALRNGHI = 0x6ffffdff,
|
||||
DT_ADDRRNGLO = 0x6ffffe00,
|
||||
DT_CONFIG = 0x6ffffefa,
|
||||
DT_DEPAUDIT = 0x6ffffefb,
|
||||
DT_AUDIT = 0x6ffffefc,
|
||||
DT_PLTPAD = 0x6ffffefd,
|
||||
DT_MOVETAB = 0x6ffffefe,
|
||||
DT_SYMINFO = 0x6ffffeff,
|
||||
DT_ADDRRNGHI = 0x6ffffeff,
|
||||
DT_RELACOUNT = 0x6ffffff9,
|
||||
DT_RELCOUNT = 0x6ffffffa,
|
||||
DT_FLAGS_1 = 0x6ffffffb,
|
||||
DT_VERDEF = 0x6ffffffc,
|
||||
DT_VERDEFNUM = 0x6ffffffd,
|
||||
DT_VERNEED = 0x6ffffffe,
|
||||
DT_VERNEEDNUM = 0x6fffffff,
|
||||
DT_LOPROC = 0x70000000,
|
||||
DT_SPARC_REGISTER = 0x70000001,
|
||||
DT_AUXILIARY = 0x7ffffffd,
|
||||
DT_USED = 0x7ffffffe,
|
||||
DT_FILTER = 0x7fffffff,
|
||||
DT_HIPROC = 0x7fffffff
|
||||
};
|
||||
|
||||
// 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 ELF64_ST_BIND(info) ((info) >> 4)
|
||||
#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 DO_386_32(S, A) ((S) + (A))
|
||||
#define DO_386_PC32(S, A, P) ((S) + (A) - (P))
|
||||
|
||||
#define DO_64_64(S, A) ((S) + (A))
|
||||
#define DO_64_PC32(S, A, P) ((S) + (A) - (P))
|
||||
|
||||
#define ELF32_R_SYM(i) ((i) >> 8)
|
||||
#define ELF32_R_TYPE(i) ((unsigned char)(i))
|
||||
#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 SHN_UNDEF 0
|
||||
#define SHN_ABS 0xfff1
|
||||
|
||||
#define SHT_NOBITS 8
|
||||
#define SHT_REL 9
|
||||
|
||||
#define SHF_WRITE 0x1
|
||||
#define SHF_ALLOC 0x2
|
||||
|
||||
#define EM_386 0x3 // x86 Machine Type
|
||||
#define EM_X86_64 0x3E // 64bit
|
||||
#define EM_ARM 0x28 // ARM
|
||||
#define EM_AARCH64 0xb7 // ARM64
|
||||
|
||||
#define EV_CURRENT 0x1 // ELF Current Version
|
||||
|
||||
#define ELFMAG0 0x7F // e_ident[EI_MAG0]
|
||||
#define ELFMAG1 'E' // e_ident[EI_MAG1]
|
||||
#define ELFMAG2 'L' // e_ident[EI_MAG2]
|
||||
#define ELFMAG3 'F' // e_ident[EI_MAG3]
|
||||
|
||||
#define ELFDATANONE 0 /* e_ident[EI_DATA] */
|
||||
#define ELFDATA2LSB 1
|
||||
#define ELFDATA2MSB 2
|
||||
|
||||
#define ELFCLASSNONE 0 /* EI_CLASS */
|
||||
#define ELFCLASS32 1
|
||||
#define ELFCLASS64 2
|
||||
#define ELFCLASSNUM 3
|
||||
|
||||
#define SHT_NULL 0 /* Section header table entry unused */
|
||||
#define SHT_PROGBITS 1 /* Program data */
|
||||
#define SHT_SYMTAB 2 /* Symbol table */
|
||||
#define SHT_STRTAB 3 /* String table */
|
||||
#define SHT_RELA 4 /* Relocation entries with addends */
|
||||
#define SHT_HASH 5 /* Symbol hash table */
|
||||
#define SHT_DYNAMIC 6 /* Dynamic linking information */
|
||||
#define SHT_NOTE 7 /* Notes */
|
||||
#define SHT_NOBITS 8 /* Program space with no data (bss) */
|
||||
#define SHT_REL 9 /* Relocation entries, no addends */
|
||||
#define SHT_SHLIB 10 /* Reserved */
|
||||
#define SHT_DYNSYM 11 /* Dynamic linker symbol table */
|
||||
#define SHT_INIT_ARRAY 14 /* Array of constructors */
|
||||
#define SHT_FINI_ARRAY 15 /* Array of destructors */
|
||||
#define SHT_PREINIT_ARRAY 16 /* Array of pre-constructors */
|
||||
#define SHT_GROUP 17 /* Section group */
|
||||
#define SHT_SYMTAB_SHNDX 18 /* Extended section indeces */
|
||||
#define SHT_NUM 19 /* Number of defined types. */
|
||||
#define SHT_LOOS 0x60000000 /* Start OS-specific. */
|
||||
#define SHT_GNU_ATTRIBUTES 0x6ffffff5 /* Object attributes. */
|
||||
#define SHT_GNU_HASH 0x6ffffff6 /* GNU-style hash table. */
|
||||
#define SHT_GNU_LIBLIST 0x6ffffff7 /* Prelink library list */
|
||||
#define SHT_CHECKSUM 0x6ffffff8 /* Checksum for DSO content. */
|
||||
#define SHT_LOSUNW 0x6ffffffa /* Sun-specific low bound. */
|
||||
#define SHT_SUNW_move 0x6ffffffa
|
||||
#define SHT_SUNW_COMDAT 0x6ffffffb
|
||||
#define SHT_SUNW_syminfo 0x6ffffffc
|
||||
#define SHT_GNU_verdef 0x6ffffffd /* Version definition section. */
|
||||
#define SHT_GNU_verneed 0x6ffffffe /* Version needs section. */
|
||||
#define SHT_GNU_versym 0x6fffffff /* Version symbol table. */
|
||||
#define SHT_HISUNW 0x6fffffff /* Sun-specific high bound. */
|
||||
#define SHT_HIOS 0x6fffffff /* End OS-specific type */
|
||||
#define SHT_LOPROC 0x70000000 /* Start of processor-specific */
|
||||
#define SHT_HIPROC 0x7fffffff /* End of processor-specific */
|
||||
#define SHT_LOUSER 0x80000000 /* Start of application-specific */
|
||||
#define SHT_HIUSER 0x8fffffff /* End of application-specific */
|
||||
|
||||
#endif // !__FENNIX_KERNEL_ELF_H__
|
@ -1,618 +0,0 @@
|
||||
#pragma once
|
||||
#include <bitmap.hpp>
|
||||
#include <binfo.h>
|
||||
#include <debug.h>
|
||||
#include <types.h>
|
||||
|
||||
extern uintptr_t _kernel_start, _kernel_end;
|
||||
|
||||
// kilobyte
|
||||
#define TO_KB(d) ((d) / 1024)
|
||||
// megabyte
|
||||
#define TO_MB(d) ((d) / 1024 / 1024)
|
||||
// gigabyte
|
||||
#define TO_GB(d) ((d) / 1024 / 1024 / 1024)
|
||||
|
||||
#define PAGE_SIZE 0x1000 // 4KB
|
||||
#define PAGE_SIZE_4K PAGE_SIZE // 4KB
|
||||
#define PAGE_SIZE_2M 0x200000 // 2MB
|
||||
#define PAGE_SIZE_4M 0x400000 // 4MB
|
||||
#define PAGE_SIZE_1G 0x40000000 // 1GB
|
||||
|
||||
// To pages
|
||||
#define TO_PAGES(d) (((d) + PAGE_SIZE - 1) / PAGE_SIZE)
|
||||
// From pages
|
||||
#define FROM_PAGES(d) ((d)*PAGE_SIZE)
|
||||
|
||||
enum PTFlag
|
||||
{
|
||||
/** @brief Present */
|
||||
P = 1 << 0,
|
||||
|
||||
/** @brief Read/Write */
|
||||
RW = 1 << 1,
|
||||
|
||||
/** @brief User/Supervisor */
|
||||
US = 1 << 2,
|
||||
|
||||
/** @brief Write-Through */
|
||||
PWT = 1 << 3,
|
||||
|
||||
/** @brief Cache Disable */
|
||||
PCD = 1 << 4,
|
||||
|
||||
/** @brief Accessed */
|
||||
A = 1 << 5,
|
||||
|
||||
/** @brief Dirty */
|
||||
D = 1 << 6,
|
||||
|
||||
/** @brief Page Size */
|
||||
PS = 1 << 7,
|
||||
|
||||
/** @brief Global */
|
||||
G = 1 << 8,
|
||||
|
||||
/** @brief Available 0 */
|
||||
AVL0 = 1 << 9,
|
||||
|
||||
/** @brief Available 1 */
|
||||
AVL1 = 1 << 10,
|
||||
|
||||
/** @brief Available 2 */
|
||||
AVL2 = 1 << 11,
|
||||
|
||||
/** @brief Page Attribute Table */
|
||||
PAT = 1 << 12,
|
||||
|
||||
/** @brief Available 3 */
|
||||
AVL3 = (uint64_t)1 << 52,
|
||||
|
||||
/** @brief Available 4 */
|
||||
AVL4 = (uint64_t)1 << 53,
|
||||
|
||||
/** @brief Available 5 */
|
||||
AVL5 = (uint64_t)1 << 54,
|
||||
|
||||
/** @brief Available 6 */
|
||||
AVL6 = (uint64_t)1 << 55,
|
||||
|
||||
/** @brief Available 7 */
|
||||
AVL7 = (uint64_t)1 << 56,
|
||||
|
||||
/** @brief Available 8 */
|
||||
AVL8 = (uint64_t)1 << 57,
|
||||
|
||||
/** @brief Available 9 */
|
||||
AVL9 = (uint64_t)1 << 58,
|
||||
|
||||
/** @brief Protection Key 0 */
|
||||
PK0 = (uint64_t)1 << 59,
|
||||
|
||||
/** @brief Protection Key 1 */
|
||||
PK1 = (uint64_t)1 << 60,
|
||||
|
||||
/** @brief Protection Key 2 */
|
||||
PK2 = (uint64_t)1 << 61,
|
||||
|
||||
/** @brief Protection Key 3 */
|
||||
PK3 = (uint64_t)1 << 62,
|
||||
|
||||
/** @brief Execute Disable */
|
||||
XD = (uint64_t)1 << 63
|
||||
};
|
||||
|
||||
namespace Memory32
|
||||
{
|
||||
union __packed PageTableEntry
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint32_t Present : 1; // 0
|
||||
uint32_t ReadWrite : 1; // 1
|
||||
uint32_t UserSupervisor : 1; // 2
|
||||
uint32_t WriteThrough : 1; // 3
|
||||
uint32_t CacheDisable : 1; // 4
|
||||
uint32_t Accessed : 1; // 5
|
||||
uint32_t Dirty : 1; // 6
|
||||
uint32_t PageAttributeTable : 1; // 7
|
||||
uint32_t Global : 1; // 8
|
||||
uint32_t Available0 : 3; // 9-11
|
||||
uint32_t Address : 20; // 12-31
|
||||
};
|
||||
uint32_t raw;
|
||||
|
||||
void SetAddress(uintptr_t _Address)
|
||||
{
|
||||
_Address &= 0x000FFFFF;
|
||||
this->raw &= 0xFFC00003;
|
||||
this->raw |= (_Address << 12);
|
||||
}
|
||||
|
||||
uintptr_t GetAddress()
|
||||
{
|
||||
return (this->raw & 0x003FFFFF000) >> 12;
|
||||
}
|
||||
};
|
||||
|
||||
struct __packed PageTableEntryPtr
|
||||
{
|
||||
PageTableEntry Entries[1024];
|
||||
};
|
||||
|
||||
union __packed PageDirectoryEntry
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint32_t Present : 1; // 0
|
||||
uint32_t ReadWrite : 1; // 1
|
||||
uint32_t UserSupervisor : 1; // 2
|
||||
uint32_t WriteThrough : 1; // 3
|
||||
uint32_t CacheDisable : 1; // 4
|
||||
uint32_t Accessed : 1; // 5
|
||||
uint32_t Available0 : 1; // 6
|
||||
uint32_t PageSize : 1; // 7
|
||||
uint32_t Available1 : 4; // 8-11
|
||||
uint32_t Address : 20; // 12-31
|
||||
};
|
||||
uint32_t raw;
|
||||
|
||||
void SetAddress(uintptr_t _Address)
|
||||
{
|
||||
_Address &= 0x000FFFFF;
|
||||
this->raw &= 0xFFC00003;
|
||||
this->raw |= (_Address << 12);
|
||||
}
|
||||
|
||||
uintptr_t GetAddress()
|
||||
{
|
||||
return (this->raw & 0x003FFFFF000) >> 12;
|
||||
}
|
||||
};
|
||||
|
||||
struct PageTable
|
||||
{
|
||||
PageDirectoryEntry Entries[1024];
|
||||
} __aligned(0x1000);
|
||||
|
||||
class Physical
|
||||
{
|
||||
private:
|
||||
uint64_t PageBitmapIndex = 0;
|
||||
Bitmap PageBitmap;
|
||||
|
||||
public:
|
||||
uint64_t TotalMemory = 0;
|
||||
uint64_t FreeMemory = 0;
|
||||
uint64_t ReservedMemory = 0;
|
||||
uint64_t UsedMemory = 0;
|
||||
void LockPage(void *Address);
|
||||
void LockPages(void *Address, size_t PageCount);
|
||||
void ReservePage(void *Address);
|
||||
void ReservePages(void *Address, size_t PageCount);
|
||||
void UnreservePage(void *Address);
|
||||
void UnreservePages(void *Address, size_t PageCount);
|
||||
void *RequestPage();
|
||||
void *RequestPages(size_t Count);
|
||||
void FreePage(void *Address);
|
||||
void FreePages(void *Address, size_t Count);
|
||||
void Init(BootInfo *Info);
|
||||
Physical();
|
||||
~Physical();
|
||||
};
|
||||
|
||||
class Virtual
|
||||
{
|
||||
private:
|
||||
PageTable *Table = nullptr;
|
||||
|
||||
public:
|
||||
class PageMapIndexer
|
||||
{
|
||||
public:
|
||||
uintptr_t PDEIndex = 0;
|
||||
uintptr_t PTEIndex = 0;
|
||||
PageMapIndexer(uintptr_t VirtualAddress)
|
||||
{
|
||||
uintptr_t Address = VirtualAddress;
|
||||
Address >>= 12;
|
||||
this->PTEIndex = Address & 0x3FF;
|
||||
Address >>= 10;
|
||||
this->PDEIndex = Address & 0x3FF;
|
||||
}
|
||||
};
|
||||
|
||||
void Map(void *VirtualAddress, void *PhysicalAddress, uint64_t Flag = PTFlag::P);
|
||||
|
||||
__always_inline inline void Map(void *VirtualAddress, void *PhysicalAddress, size_t Length, uint64_t Flags)
|
||||
{
|
||||
for (uintptr_t i = 0; i < Length; i += PAGE_SIZE_4K)
|
||||
this->Map((void *)((uintptr_t)VirtualAddress + i), (void *)((uintptr_t)PhysicalAddress + i), Flags);
|
||||
}
|
||||
|
||||
Virtual(PageTable *Table = nullptr);
|
||||
~Virtual();
|
||||
};
|
||||
}
|
||||
|
||||
namespace Memory64
|
||||
{
|
||||
union __packed PageTableEntry
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint64_t Present : 1; // 0
|
||||
uint64_t ReadWrite : 1; // 1
|
||||
uint64_t UserSupervisor : 1; // 2
|
||||
uint64_t WriteThrough : 1; // 3
|
||||
uint64_t CacheDisable : 1; // 4
|
||||
uint64_t Accessed : 1; // 5
|
||||
uint64_t Dirty : 1; // 6
|
||||
uint64_t PageAttributeTable : 1; // 7
|
||||
uint64_t Global : 1; // 8
|
||||
uint64_t Available0 : 3; // 9-11
|
||||
uint64_t Address : 40; // 12-51
|
||||
uint64_t Available1 : 7; // 52-58
|
||||
uint64_t ProtectionKey : 4; // 59-62
|
||||
uint64_t ExecuteDisable : 1; // 63
|
||||
};
|
||||
uint64_t raw;
|
||||
|
||||
/** @brief Set Address */
|
||||
void SetAddress(uintptr_t _Address)
|
||||
{
|
||||
_Address &= 0x000000FFFFFFFFFF;
|
||||
this->raw &= 0xFFF0000000000FFF;
|
||||
this->raw |= (_Address << 12);
|
||||
}
|
||||
|
||||
/** @brief Get Address */
|
||||
uintptr_t GetAddress()
|
||||
{
|
||||
return (this->raw & 0x000FFFFFFFFFF000) >> 12;
|
||||
}
|
||||
};
|
||||
|
||||
struct __packed PageTableEntryPtr
|
||||
{
|
||||
PageTableEntry Entries[511];
|
||||
};
|
||||
|
||||
union __packed PageDirectoryEntry
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint64_t Present : 1; // 0
|
||||
uint64_t ReadWrite : 1; // 1
|
||||
uint64_t UserSupervisor : 1; // 2
|
||||
uint64_t WriteThrough : 1; // 3
|
||||
uint64_t CacheDisable : 1; // 4
|
||||
uint64_t Accessed : 1; // 5
|
||||
uint64_t Available0 : 1; // 6
|
||||
uint64_t PageSize : 1; // 7
|
||||
uint64_t Available1 : 4; // 8-11
|
||||
uint64_t Address : 40; // 12-51
|
||||
uint64_t Available2 : 11; // 52-62
|
||||
uint64_t ExecuteDisable : 1; // 63
|
||||
};
|
||||
|
||||
struct
|
||||
{
|
||||
uint64_t Present : 1; // 0
|
||||
uint64_t ReadWrite : 1; // 1
|
||||
uint64_t UserSupervisor : 1; // 2
|
||||
uint64_t WriteThrough : 1; // 3
|
||||
uint64_t CacheDisable : 1; // 4
|
||||
uint64_t Accessed : 1; // 5
|
||||
uint64_t Dirty : 1; // 6
|
||||
uint64_t PageSize : 1; // 7
|
||||
uint64_t Global : 1; // 8
|
||||
uint64_t Available0 : 3; // 9-11
|
||||
uint64_t PageAttributeTable : 1; // 12
|
||||
uint64_t Reserved0 : 8; // 13-20
|
||||
uint64_t Address : 31; // 21-51
|
||||
uint64_t Available1 : 7; // 52-58
|
||||
uint64_t ProtectionKey : 4; // 59-62
|
||||
uint64_t ExecuteDisable : 1; // 63
|
||||
} TwoMB;
|
||||
|
||||
uint64_t raw;
|
||||
|
||||
/** @brief Set PageTableEntryPtr address */
|
||||
void SetAddress(uintptr_t _Address)
|
||||
{
|
||||
_Address &= 0x000000FFFFFFFFFF;
|
||||
this->raw &= 0xFFF0000000000FFF;
|
||||
this->raw |= (_Address << 12);
|
||||
}
|
||||
|
||||
/** @brief Get PageTableEntryPtr address */
|
||||
uintptr_t GetAddress()
|
||||
{
|
||||
return (this->raw & 0x000FFFFFFFFFF000) >> 12;
|
||||
}
|
||||
};
|
||||
|
||||
struct __packed PageDirectoryEntryPtr
|
||||
{
|
||||
PageDirectoryEntry Entries[511];
|
||||
};
|
||||
|
||||
union __packed PageDirectoryPointerTableEntry
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint64_t Present : 1; // 0
|
||||
uint64_t ReadWrite : 1; // 1
|
||||
uint64_t UserSupervisor : 1; // 2
|
||||
uint64_t WriteThrough : 1; // 3
|
||||
uint64_t CacheDisable : 1; // 4
|
||||
uint64_t Accessed : 1; // 5
|
||||
uint64_t Available0 : 1; // 6
|
||||
uint64_t PageSize : 1; // 7
|
||||
uint64_t Available1 : 4; // 8-11
|
||||
uint64_t Address : 40; // 12-51
|
||||
uint64_t Available2 : 11; // 52-62
|
||||
uint64_t ExecuteDisable : 1; // 63
|
||||
};
|
||||
|
||||
struct
|
||||
{
|
||||
uint64_t Present : 1; // 0
|
||||
uint64_t ReadWrite : 1; // 1
|
||||
uint64_t UserSupervisor : 1; // 2
|
||||
uint64_t WriteThrough : 1; // 3
|
||||
uint64_t CacheDisable : 1; // 4
|
||||
uint64_t Accessed : 1; // 5
|
||||
uint64_t Dirty : 1; // 6
|
||||
uint64_t PageSize : 1; // 7
|
||||
uint64_t Global : 1; // 8
|
||||
uint64_t Available0 : 3; // 9-11
|
||||
uint64_t PageAttributeTable : 1; // 12
|
||||
uint64_t Reserved0 : 17; // 13-29
|
||||
uint64_t Address : 22; // 30-51
|
||||
uint64_t Available1 : 7; // 52-58
|
||||
uint64_t ProtectionKey : 4; // 59-62
|
||||
uint64_t ExecuteDisable : 1; // 63
|
||||
} OneGB;
|
||||
|
||||
uint64_t raw;
|
||||
|
||||
/** @brief Set PageDirectoryEntryPtr address */
|
||||
void SetAddress(uintptr_t _Address)
|
||||
{
|
||||
_Address &= 0x000000FFFFFFFFFF;
|
||||
this->raw &= 0xFFF0000000000FFF;
|
||||
this->raw |= (_Address << 12);
|
||||
}
|
||||
|
||||
/** @brief Get PageDirectoryEntryPtr address */
|
||||
uintptr_t GetAddress()
|
||||
{
|
||||
return (this->raw & 0x000FFFFFFFFFF000) >> 12;
|
||||
}
|
||||
};
|
||||
|
||||
struct __packed PageDirectoryPointerTableEntryPtr
|
||||
{
|
||||
PageDirectoryPointerTableEntry Entries[511];
|
||||
};
|
||||
|
||||
union __packed PageMapLevel4
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint64_t Present : 1; // 0
|
||||
uint64_t ReadWrite : 1; // 1
|
||||
uint64_t UserSupervisor : 1; // 2
|
||||
uint64_t WriteThrough : 1; // 3
|
||||
uint64_t CacheDisable : 1; // 4
|
||||
uint64_t Accessed : 1; // 5
|
||||
uint64_t Available0 : 1; // 6
|
||||
uint64_t Reserved0 : 1; // 7
|
||||
uint64_t Available1 : 4; // 8-11
|
||||
uint64_t Address : 40; // 12-51
|
||||
uint64_t Available2 : 11; // 52-62
|
||||
uint64_t ExecuteDisable : 1; // 63
|
||||
};
|
||||
uint64_t raw;
|
||||
|
||||
/** @brief Set PageDirectoryPointerTableEntryPtr address */
|
||||
void SetAddress(uintptr_t _Address)
|
||||
{
|
||||
_Address &= 0x000000FFFFFFFFFF;
|
||||
this->raw &= 0xFFF0000000000FFF;
|
||||
this->raw |= (_Address << 12);
|
||||
}
|
||||
|
||||
/** @brief Get PageDirectoryPointerTableEntryPtr address */
|
||||
uintptr_t GetAddress()
|
||||
{
|
||||
return (this->raw & 0x000FFFFFFFFFF000) >> 12;
|
||||
}
|
||||
};
|
||||
|
||||
struct PageTable
|
||||
{
|
||||
PageMapLevel4 Entries[511];
|
||||
|
||||
/**
|
||||
* @brief Update CR3 with this PageTable
|
||||
*/
|
||||
void Update()
|
||||
{
|
||||
asmv("mov %0, %%cr3" ::"r"(this));
|
||||
}
|
||||
} __aligned(0x1000);
|
||||
|
||||
class Physical
|
||||
{
|
||||
private:
|
||||
uint64_t PageBitmapIndex = 0;
|
||||
Bitmap PageBitmap;
|
||||
|
||||
public:
|
||||
uint64_t TotalMemory = 0;
|
||||
uint64_t FreeMemory = 0;
|
||||
uint64_t ReservedMemory = 0;
|
||||
uint64_t UsedMemory = 0;
|
||||
void LockPage(void *Address);
|
||||
void LockPages(void *Address, size_t PageCount);
|
||||
void ReservePage(void *Address);
|
||||
void ReservePages(void *Address, size_t PageCount);
|
||||
void UnreservePage(void *Address);
|
||||
void UnreservePages(void *Address, size_t PageCount);
|
||||
void *RequestPage();
|
||||
void *RequestPages(size_t Count);
|
||||
void FreePage(void *Address);
|
||||
void FreePages(void *Address, size_t Count);
|
||||
void Init(BootInfo *Info);
|
||||
Physical();
|
||||
~Physical();
|
||||
};
|
||||
|
||||
class Virtual
|
||||
{
|
||||
private:
|
||||
PageTable *Table = nullptr;
|
||||
|
||||
public:
|
||||
enum MapType
|
||||
{
|
||||
NoMapType,
|
||||
FourKB,
|
||||
TwoMB,
|
||||
OneGB
|
||||
};
|
||||
|
||||
class PageMapIndexer
|
||||
{
|
||||
public:
|
||||
uintptr_t PMLIndex = 0;
|
||||
uintptr_t PDPTEIndex = 0;
|
||||
uintptr_t PDEIndex = 0;
|
||||
uintptr_t PTEIndex = 0;
|
||||
PageMapIndexer(uintptr_t VirtualAddress)
|
||||
{
|
||||
uintptr_t Address = VirtualAddress;
|
||||
Address >>= 12;
|
||||
this->PTEIndex = Address & 0x1FF;
|
||||
Address >>= 9;
|
||||
this->PDEIndex = Address & 0x1FF;
|
||||
Address >>= 9;
|
||||
this->PDPTEIndex = Address & 0x1FF;
|
||||
Address >>= 9;
|
||||
this->PMLIndex = Address & 0x1FF;
|
||||
}
|
||||
};
|
||||
|
||||
bool Check(void *VirtualAddress, PTFlag Flag = PTFlag::P, MapType Type = MapType::FourKB);
|
||||
void *GetPhysical(void *VirtualAddress);
|
||||
void Map(void *VirtualAddress, void *PhysicalAddress, uint64_t Flag = PTFlag::P, MapType Type = MapType::FourKB);
|
||||
|
||||
__always_inline inline void Map(void *VirtualAddress, void *PhysicalAddress, size_t Length, uint64_t Flags, MapType Type = MapType::FourKB)
|
||||
{
|
||||
int PageSize = PAGE_SIZE_4K;
|
||||
|
||||
if (Type == MapType::TwoMB)
|
||||
PageSize = PAGE_SIZE_2M;
|
||||
else if (Type == MapType::OneGB)
|
||||
PageSize = PAGE_SIZE_1G;
|
||||
|
||||
for (uintptr_t i = 0; i < Length; i += PageSize)
|
||||
this->Map((void *)((uintptr_t)VirtualAddress + i), (void *)((uintptr_t)PhysicalAddress + i), Flags, Type);
|
||||
}
|
||||
|
||||
__always_inline inline MapType OptimizedMap(void *VirtualAddress, void *PhysicalAddress, size_t Length, uint64_t Flags, bool Fit = false, bool FailOnModulo = false)
|
||||
{
|
||||
if (unlikely(Fit))
|
||||
{
|
||||
while (Length >= PAGE_SIZE_1G)
|
||||
{
|
||||
this->Map(VirtualAddress, PhysicalAddress, Length, Flags, Virtual::MapType::OneGB);
|
||||
VirtualAddress = (void *)((uintptr_t)VirtualAddress + PAGE_SIZE_1G);
|
||||
PhysicalAddress = (void *)((uintptr_t)PhysicalAddress + PAGE_SIZE_1G);
|
||||
Length -= PAGE_SIZE_1G;
|
||||
}
|
||||
|
||||
while (Length >= PAGE_SIZE_2M)
|
||||
{
|
||||
this->Map(VirtualAddress, PhysicalAddress, Length, Flags, Virtual::MapType::TwoMB);
|
||||
VirtualAddress = (void *)((uintptr_t)VirtualAddress + PAGE_SIZE_2M);
|
||||
PhysicalAddress = (void *)((uintptr_t)PhysicalAddress + PAGE_SIZE_2M);
|
||||
Length -= PAGE_SIZE_2M;
|
||||
}
|
||||
|
||||
while (Length >= PAGE_SIZE_4K)
|
||||
{
|
||||
this->Map(VirtualAddress, PhysicalAddress, Length, Flags, Virtual::MapType::FourKB);
|
||||
VirtualAddress = (void *)((uintptr_t)VirtualAddress + PAGE_SIZE_4K);
|
||||
PhysicalAddress = (void *)((uintptr_t)PhysicalAddress + PAGE_SIZE_4K);
|
||||
Length -= PAGE_SIZE_4K;
|
||||
}
|
||||
|
||||
return Virtual::MapType::FourKB;
|
||||
}
|
||||
|
||||
Virtual::MapType Type = Virtual::MapType::FourKB;
|
||||
|
||||
if (Length >= PAGE_SIZE_1G)
|
||||
{
|
||||
Type = Virtual::MapType::OneGB;
|
||||
if (Length % PAGE_SIZE_1G != 0)
|
||||
{
|
||||
warn("Length is not a multiple of 1GB.");
|
||||
if (FailOnModulo)
|
||||
return Virtual::MapType::NoMapType;
|
||||
}
|
||||
}
|
||||
else if (Length >= PAGE_SIZE_2M)
|
||||
{
|
||||
Type = Virtual::MapType::TwoMB;
|
||||
if (Length % PAGE_SIZE_2M != 0)
|
||||
{
|
||||
warn("Length is not a multiple of 2MB.");
|
||||
if (FailOnModulo)
|
||||
return Virtual::MapType::NoMapType;
|
||||
}
|
||||
}
|
||||
|
||||
this->Map(VirtualAddress, PhysicalAddress, Length, Flags, Type);
|
||||
return Type;
|
||||
}
|
||||
|
||||
void Unmap(void *VirtualAddress, MapType Type = MapType::FourKB);
|
||||
|
||||
__always_inline inline void Unmap(void *VirtualAddress, size_t Length, MapType Type = MapType::FourKB)
|
||||
{
|
||||
int PageSize = PAGE_SIZE_4K;
|
||||
|
||||
if (Type == MapType::TwoMB)
|
||||
PageSize = PAGE_SIZE_2M;
|
||||
else if (Type == MapType::OneGB)
|
||||
PageSize = PAGE_SIZE_1G;
|
||||
|
||||
for (uintptr_t i = 0; i < Length; i += PageSize)
|
||||
this->Unmap((void *)((uintptr_t)VirtualAddress + i), Type);
|
||||
}
|
||||
|
||||
__always_inline inline void Remap(void *VirtualAddress, void *PhysicalAddress, uint64_t Flags, MapType Type = MapType::FourKB)
|
||||
{
|
||||
this->Unmap(VirtualAddress, Type);
|
||||
this->Map(VirtualAddress, PhysicalAddress, Flags, Type);
|
||||
}
|
||||
|
||||
Virtual(PageTable *Table = nullptr);
|
||||
~Virtual();
|
||||
};
|
||||
}
|
||||
|
||||
extern Memory32::Physical KernelAllocator32;
|
||||
extern Memory32::PageTable *KernelPageTable32;
|
||||
|
||||
extern Memory64::Physical KernelAllocator64;
|
||||
extern Memory64::PageTable *KernelPageTable64;
|
||||
|
||||
void *memcpy(void *dest, const void *src, size_t n);
|
||||
void *memset(void *s, int c, size_t n);
|
||||
void InitializeMemoryManagement(BootInfo *Info, bool is32);
|
@ -1,274 +0,0 @@
|
||||
/* multiboot.h - Multiboot header file. */
|
||||
/* Copyright (C) 1999,2003,2007,2008,2009,2010 Free Software Foundation, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ANY
|
||||
* DEVELOPER OR DISTRIBUTOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
|
||||
* IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef MULTIBOOT_HEADER
|
||||
#define MULTIBOOT_HEADER 1
|
||||
|
||||
/* How many bytes from the start of the file we search for the header. */
|
||||
#define MULTIBOOT_SEARCH 8192
|
||||
#define MULTIBOOT_HEADER_ALIGN 4
|
||||
|
||||
/* The magic field should contain this. */
|
||||
#define MULTIBOOT_HEADER_MAGIC 0x1BADB002
|
||||
|
||||
/* This should be in %eax. */
|
||||
#define MULTIBOOT_BOOTLOADER_MAGIC 0x2BADB002
|
||||
|
||||
/* Alignment of multiboot modules. */
|
||||
#define MULTIBOOT_MOD_ALIGN 0x00001000
|
||||
|
||||
/* Alignment of the multiboot info structure. */
|
||||
#define MULTIBOOT_INFO_ALIGN 0x00000004
|
||||
|
||||
/* Flags set in the ’flags’ member of the multiboot header. */
|
||||
|
||||
/* Align all boot modules on i386 page (4KB) boundaries. */
|
||||
#define MULTIBOOT_PAGE_ALIGN 0x00000001
|
||||
|
||||
/* Must pass memory information to OS. */
|
||||
#define MULTIBOOT_MEMORY_INFO 0x00000002
|
||||
|
||||
/* Must pass video information to OS. */
|
||||
#define MULTIBOOT_VIDEO_MODE 0x00000004
|
||||
|
||||
/* 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. */
|
||||
|
||||
/* is there basic lower/upper memory information? */
|
||||
#define MULTIBOOT_INFO_MEMORY 0x00000001
|
||||
/* is there a boot device set? */
|
||||
#define MULTIBOOT_INFO_BOOTDEV 0x00000002
|
||||
/* is the command-line defined? */
|
||||
#define MULTIBOOT_INFO_CMDLINE 0x00000004
|
||||
/* are there modules to do something with? */
|
||||
#define MULTIBOOT_INFO_MODS 0x00000008
|
||||
|
||||
/* These next two are mutually exclusive */
|
||||
|
||||
/* is there a symbol table loaded? */
|
||||
#define MULTIBOOT_INFO_AOUT_SYMS 0x00000010
|
||||
/* is there an ELF section header table? */
|
||||
#define MULTIBOOT_INFO_ELF_SHDR 0X00000020
|
||||
|
||||
/* is there a full memory map? */
|
||||
#define MULTIBOOT_INFO_MEM_MAP 0x00000040
|
||||
|
||||
/* Is there drive info? */
|
||||
#define MULTIBOOT_INFO_DRIVE_INFO 0x00000080
|
||||
|
||||
/* Is there a config table? */
|
||||
#define MULTIBOOT_INFO_CONFIG_TABLE 0x00000100
|
||||
|
||||
/* Is there a boot loader name? */
|
||||
#define MULTIBOOT_INFO_BOOT_LOADER_NAME 0x00000200
|
||||
|
||||
/* Is there a APM table? */
|
||||
#define MULTIBOOT_INFO_APM_TABLE 0x00000400
|
||||
|
||||
/* Is there video information? */
|
||||
#define MULTIBOOT_INFO_VBE_INFO 0x00000800
|
||||
#define MULTIBOOT_INFO_FRAMEBUFFER_INFO 0x00001000
|
||||
|
||||
#ifndef ASM_FILE
|
||||
|
||||
typedef unsigned char multiboot_uint8_t;
|
||||
typedef unsigned short multiboot_uint16_t;
|
||||
typedef unsigned int multiboot_uint32_t;
|
||||
typedef unsigned long long multiboot_uint64_t;
|
||||
|
||||
struct multiboot_header
|
||||
{
|
||||
/* Must be MULTIBOOT_MAGIC - see above. */
|
||||
multiboot_uint32_t magic;
|
||||
|
||||
/* Feature flags. */
|
||||
multiboot_uint32_t flags;
|
||||
|
||||
/* The above fields plus this one must equal 0 mod 2^32. */
|
||||
multiboot_uint32_t checksum;
|
||||
|
||||
/* These are only valid if MULTIBOOT_AOUT_KLUDGE is set. */
|
||||
multiboot_uint32_t header_addr;
|
||||
multiboot_uint32_t load_addr;
|
||||
multiboot_uint32_t load_end_addr;
|
||||
multiboot_uint32_t bss_end_addr;
|
||||
multiboot_uint32_t entry_addr;
|
||||
|
||||
/* These are only valid if MULTIBOOT_VIDEO_MODE is set. */
|
||||
multiboot_uint32_t mode_type;
|
||||
multiboot_uint32_t width;
|
||||
multiboot_uint32_t height;
|
||||
multiboot_uint32_t depth;
|
||||
};
|
||||
|
||||
/* The symbol table for a.out. */
|
||||
struct multiboot_aout_symbol_table
|
||||
{
|
||||
multiboot_uint32_t tabsize;
|
||||
multiboot_uint32_t strsize;
|
||||
multiboot_uint32_t addr;
|
||||
multiboot_uint32_t reserved;
|
||||
};
|
||||
typedef struct multiboot_aout_symbol_table multiboot_aout_symbol_table_t;
|
||||
|
||||
/* The section header table for ELF. */
|
||||
struct multiboot_elf_section_header_table
|
||||
{
|
||||
multiboot_uint32_t num;
|
||||
multiboot_uint32_t size;
|
||||
multiboot_uint32_t addr;
|
||||
multiboot_uint32_t shndx;
|
||||
};
|
||||
typedef struct multiboot_elf_section_header_table multiboot_elf_section_header_table_t;
|
||||
|
||||
struct multiboot_info
|
||||
{
|
||||
/* Multiboot info version number */
|
||||
multiboot_uint32_t flags;
|
||||
|
||||
/* Available memory from BIOS */
|
||||
multiboot_uint32_t mem_lower;
|
||||
multiboot_uint32_t mem_upper;
|
||||
|
||||
/* "root" partition */
|
||||
multiboot_uint32_t boot_device;
|
||||
|
||||
/* Kernel command line */
|
||||
multiboot_uint32_t cmdline;
|
||||
|
||||
/* Boot-Module list */
|
||||
multiboot_uint32_t mods_count;
|
||||
multiboot_uint32_t mods_addr;
|
||||
|
||||
union
|
||||
{
|
||||
multiboot_aout_symbol_table_t aout_sym;
|
||||
multiboot_elf_section_header_table_t elf_sec;
|
||||
} u;
|
||||
|
||||
/* Memory Mapping buffer */
|
||||
multiboot_uint32_t mmap_length;
|
||||
multiboot_uint32_t mmap_addr;
|
||||
|
||||
/* Drive Info buffer */
|
||||
multiboot_uint32_t drives_length;
|
||||
multiboot_uint32_t drives_addr;
|
||||
|
||||
/* ROM configuration table */
|
||||
multiboot_uint32_t config_table;
|
||||
|
||||
/* Boot Loader Name */
|
||||
multiboot_uint32_t boot_loader_name;
|
||||
|
||||
/* APM table */
|
||||
multiboot_uint32_t apm_table;
|
||||
|
||||
/* Video */
|
||||
multiboot_uint32_t vbe_control_info;
|
||||
multiboot_uint32_t vbe_mode_info;
|
||||
multiboot_uint16_t vbe_mode;
|
||||
multiboot_uint16_t vbe_interface_seg;
|
||||
multiboot_uint16_t vbe_interface_off;
|
||||
multiboot_uint16_t vbe_interface_len;
|
||||
|
||||
multiboot_uint64_t framebuffer_addr;
|
||||
multiboot_uint32_t framebuffer_pitch;
|
||||
multiboot_uint32_t framebuffer_width;
|
||||
multiboot_uint32_t framebuffer_height;
|
||||
multiboot_uint8_t framebuffer_bpp;
|
||||
#define MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED 0
|
||||
#define MULTIBOOT_FRAMEBUFFER_TYPE_RGB 1
|
||||
#define MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT 2
|
||||
multiboot_uint8_t framebuffer_type;
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
multiboot_uint32_t framebuffer_palette_addr;
|
||||
multiboot_uint16_t framebuffer_palette_num_colors;
|
||||
};
|
||||
struct
|
||||
{
|
||||
multiboot_uint8_t framebuffer_red_field_position;
|
||||
multiboot_uint8_t framebuffer_red_mask_size;
|
||||
multiboot_uint8_t framebuffer_green_field_position;
|
||||
multiboot_uint8_t framebuffer_green_mask_size;
|
||||
multiboot_uint8_t framebuffer_blue_field_position;
|
||||
multiboot_uint8_t framebuffer_blue_mask_size;
|
||||
};
|
||||
};
|
||||
};
|
||||
typedef struct multiboot_info multiboot_info_t;
|
||||
|
||||
struct multiboot_color
|
||||
{
|
||||
multiboot_uint8_t red;
|
||||
multiboot_uint8_t green;
|
||||
multiboot_uint8_t blue;
|
||||
};
|
||||
|
||||
struct multiboot_mmap_entry
|
||||
{
|
||||
multiboot_uint32_t size;
|
||||
multiboot_uint64_t addr;
|
||||
multiboot_uint64_t len;
|
||||
#define MULTIBOOT_MEMORY_AVAILABLE 1
|
||||
#define MULTIBOOT_MEMORY_RESERVED 2
|
||||
#define MULTIBOOT_MEMORY_ACPI_RECLAIMABLE 3
|
||||
#define MULTIBOOT_MEMORY_NVS 4
|
||||
#define MULTIBOOT_MEMORY_BADRAM 5
|
||||
multiboot_uint32_t type;
|
||||
} __attribute__((packed));
|
||||
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 */
|
||||
multiboot_uint32_t mod_start;
|
||||
multiboot_uint32_t mod_end;
|
||||
|
||||
/* Module command line */
|
||||
multiboot_uint32_t cmdline;
|
||||
|
||||
/* padding to take it to 16 bytes (must be zero) */
|
||||
multiboot_uint32_t pad;
|
||||
};
|
||||
typedef struct multiboot_mod_list multiboot_module_t;
|
||||
|
||||
/* APM BIOS info. */
|
||||
struct multiboot_apm_info
|
||||
{
|
||||
multiboot_uint16_t version;
|
||||
multiboot_uint16_t cseg;
|
||||
multiboot_uint32_t offset;
|
||||
multiboot_uint16_t cseg_16;
|
||||
multiboot_uint16_t dseg;
|
||||
multiboot_uint16_t flags;
|
||||
multiboot_uint16_t cseg_len;
|
||||
multiboot_uint16_t cseg_16_len;
|
||||
multiboot_uint16_t dseg_len;
|
||||
};
|
||||
|
||||
#endif /* ! ASM_FILE */
|
||||
|
||||
#endif /* ! MULTIBOOT_HEADER */
|
@ -1,417 +0,0 @@
|
||||
/* multiboot2.h - Multiboot 2 header file. */
|
||||
/* Copyright (C) 1999,2003,2007,2008,2009,2010 Free Software Foundation, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ANY
|
||||
* DEVELOPER OR DISTRIBUTOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
|
||||
* IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef MULTIBOOT_HEADER
|
||||
#define MULTIBOOT_HEADER 1
|
||||
|
||||
/* How many bytes from the start of the file we search for the header. */
|
||||
#define MULTIBOOT_SEARCH 32768
|
||||
#define MULTIBOOT_HEADER_ALIGN 8
|
||||
|
||||
/* The magic field should contain this. */
|
||||
#define MULTIBOOT2_HEADER_MAGIC 0xe85250d6
|
||||
|
||||
/* This should be in %eax. */
|
||||
#define MULTIBOOT2_BOOTLOADER_MAGIC 0x36d76289
|
||||
|
||||
/* Alignment of multiboot modules. */
|
||||
#define MULTIBOOT_MOD_ALIGN 0x00001000
|
||||
|
||||
/* Alignment of the multiboot info structure. */
|
||||
#define MULTIBOOT_INFO_ALIGN 0x00000008
|
||||
|
||||
/* Flags set in the 'flags' member of the multiboot header. */
|
||||
|
||||
#define MULTIBOOT_TAG_ALIGN 8
|
||||
#define MULTIBOOT_TAG_TYPE_END 0
|
||||
#define MULTIBOOT_TAG_TYPE_CMDLINE 1
|
||||
#define MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME 2
|
||||
#define MULTIBOOT_TAG_TYPE_MODULE 3
|
||||
#define MULTIBOOT_TAG_TYPE_BASIC_MEMINFO 4
|
||||
#define MULTIBOOT_TAG_TYPE_BOOTDEV 5
|
||||
#define MULTIBOOT_TAG_TYPE_MMAP 6
|
||||
#define MULTIBOOT_TAG_TYPE_VBE 7
|
||||
#define MULTIBOOT_TAG_TYPE_FRAMEBUFFER 8
|
||||
#define MULTIBOOT_TAG_TYPE_ELF_SECTIONS 9
|
||||
#define MULTIBOOT_TAG_TYPE_APM 10
|
||||
#define MULTIBOOT_TAG_TYPE_EFI32 11
|
||||
#define MULTIBOOT_TAG_TYPE_EFI64 12
|
||||
#define MULTIBOOT_TAG_TYPE_SMBIOS 13
|
||||
#define MULTIBOOT_TAG_TYPE_ACPI_OLD 14
|
||||
#define MULTIBOOT_TAG_TYPE_ACPI_NEW 15
|
||||
#define MULTIBOOT_TAG_TYPE_NETWORK 16
|
||||
#define MULTIBOOT_TAG_TYPE_EFI_MMAP 17
|
||||
#define MULTIBOOT_TAG_TYPE_EFI_BS 18
|
||||
#define MULTIBOOT_TAG_TYPE_EFI32_IH 19
|
||||
#define MULTIBOOT_TAG_TYPE_EFI64_IH 20
|
||||
#define MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR 21
|
||||
|
||||
#define MULTIBOOT_HEADER_TAG_END 0
|
||||
#define MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST 1
|
||||
#define MULTIBOOT_HEADER_TAG_ADDRESS 2
|
||||
#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS 3
|
||||
#define MULTIBOOT_HEADER_TAG_CONSOLE_FLAGS 4
|
||||
#define MULTIBOOT_HEADER_TAG_FRAMEBUFFER 5
|
||||
#define MULTIBOOT_HEADER_TAG_MODULE_ALIGN 6
|
||||
#define MULTIBOOT_HEADER_TAG_EFI_BS 7
|
||||
#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI32 8
|
||||
#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI64 9
|
||||
#define MULTIBOOT_HEADER_TAG_RELOCATABLE 10
|
||||
|
||||
#define MULTIBOOT_ARCHITECTURE_I386 0
|
||||
#define MULTIBOOT_ARCHITECTURE_MIPS32 4
|
||||
#define MULTIBOOT_HEADER_TAG_OPTIONAL 1
|
||||
|
||||
#define MULTIBOOT_LOAD_PREFERENCE_NONE 0
|
||||
#define MULTIBOOT_LOAD_PREFERENCE_LOW 1
|
||||
#define MULTIBOOT_LOAD_PREFERENCE_HIGH 2
|
||||
|
||||
#define MULTIBOOT_CONSOLE_FLAGS_CONSOLE_REQUIRED 1
|
||||
#define MULTIBOOT_CONSOLE_FLAGS_EGA_TEXT_SUPPORTED 2
|
||||
|
||||
#ifndef ASM_FILE
|
||||
|
||||
typedef unsigned char multiboot_uint8_t;
|
||||
typedef unsigned short multiboot_uint16_t;
|
||||
typedef unsigned int multiboot_uint32_t;
|
||||
typedef unsigned long long multiboot_uint64_t;
|
||||
|
||||
struct multiboot_header
|
||||
{
|
||||
/* Must be MULTIBOOT_MAGIC - see above. */
|
||||
multiboot_uint32_t magic;
|
||||
|
||||
/* ISA */
|
||||
multiboot_uint32_t architecture;
|
||||
|
||||
/* Total header length. */
|
||||
multiboot_uint32_t header_length;
|
||||
|
||||
/* The above fields plus this one must equal 0 mod 2^32. */
|
||||
multiboot_uint32_t checksum;
|
||||
};
|
||||
|
||||
struct multiboot_header_tag
|
||||
{
|
||||
multiboot_uint16_t type;
|
||||
multiboot_uint16_t flags;
|
||||
multiboot_uint32_t size;
|
||||
};
|
||||
|
||||
struct multiboot_header_tag_information_request
|
||||
{
|
||||
multiboot_uint16_t type;
|
||||
multiboot_uint16_t flags;
|
||||
multiboot_uint32_t size;
|
||||
multiboot_uint32_t requests[0];
|
||||
};
|
||||
|
||||
struct multiboot_header_tag_address
|
||||
{
|
||||
multiboot_uint16_t type;
|
||||
multiboot_uint16_t flags;
|
||||
multiboot_uint32_t size;
|
||||
multiboot_uint32_t header_addr;
|
||||
multiboot_uint32_t load_addr;
|
||||
multiboot_uint32_t load_end_addr;
|
||||
multiboot_uint32_t bss_end_addr;
|
||||
};
|
||||
|
||||
struct multiboot_header_tag_entry_address
|
||||
{
|
||||
multiboot_uint16_t type;
|
||||
multiboot_uint16_t flags;
|
||||
multiboot_uint32_t size;
|
||||
multiboot_uint32_t entry_addr;
|
||||
};
|
||||
|
||||
struct multiboot_header_tag_console_flags
|
||||
{
|
||||
multiboot_uint16_t type;
|
||||
multiboot_uint16_t flags;
|
||||
multiboot_uint32_t size;
|
||||
multiboot_uint32_t console_flags;
|
||||
};
|
||||
|
||||
struct multiboot_header_tag_framebuffer
|
||||
{
|
||||
multiboot_uint16_t type;
|
||||
multiboot_uint16_t flags;
|
||||
multiboot_uint32_t size;
|
||||
multiboot_uint32_t width;
|
||||
multiboot_uint32_t height;
|
||||
multiboot_uint32_t depth;
|
||||
};
|
||||
|
||||
struct multiboot_header_tag_module_align
|
||||
{
|
||||
multiboot_uint16_t type;
|
||||
multiboot_uint16_t flags;
|
||||
multiboot_uint32_t size;
|
||||
};
|
||||
|
||||
struct multiboot_header_tag_relocatable
|
||||
{
|
||||
multiboot_uint16_t type;
|
||||
multiboot_uint16_t flags;
|
||||
multiboot_uint32_t size;
|
||||
multiboot_uint32_t min_addr;
|
||||
multiboot_uint32_t max_addr;
|
||||
multiboot_uint32_t align;
|
||||
multiboot_uint32_t preference;
|
||||
};
|
||||
|
||||
struct multiboot_color
|
||||
{
|
||||
multiboot_uint8_t red;
|
||||
multiboot_uint8_t green;
|
||||
multiboot_uint8_t blue;
|
||||
};
|
||||
|
||||
struct multiboot_mmap_entry
|
||||
{
|
||||
multiboot_uint64_t addr;
|
||||
multiboot_uint64_t len;
|
||||
#define MULTIBOOT_MEMORY_AVAILABLE 1
|
||||
#define MULTIBOOT_MEMORY_RESERVED 2
|
||||
#define MULTIBOOT_MEMORY_ACPI_RECLAIMABLE 3
|
||||
#define MULTIBOOT_MEMORY_NVS 4
|
||||
#define MULTIBOOT_MEMORY_BADRAM 5
|
||||
multiboot_uint32_t type;
|
||||
multiboot_uint32_t zero;
|
||||
};
|
||||
typedef struct multiboot_mmap_entry multiboot_memory_map_t;
|
||||
|
||||
struct multiboot_tag
|
||||
{
|
||||
multiboot_uint32_t type;
|
||||
multiboot_uint32_t size;
|
||||
};
|
||||
|
||||
struct multiboot_tag_string
|
||||
{
|
||||
multiboot_uint32_t type;
|
||||
multiboot_uint32_t size;
|
||||
char string[0];
|
||||
};
|
||||
|
||||
struct multiboot_tag_module
|
||||
{
|
||||
multiboot_uint32_t type;
|
||||
multiboot_uint32_t size;
|
||||
multiboot_uint32_t mod_start;
|
||||
multiboot_uint32_t mod_end;
|
||||
char cmdline[0];
|
||||
};
|
||||
|
||||
struct multiboot_tag_basic_meminfo
|
||||
{
|
||||
multiboot_uint32_t type;
|
||||
multiboot_uint32_t size;
|
||||
multiboot_uint32_t mem_lower;
|
||||
multiboot_uint32_t mem_upper;
|
||||
};
|
||||
|
||||
struct multiboot_tag_bootdev
|
||||
{
|
||||
multiboot_uint32_t type;
|
||||
multiboot_uint32_t size;
|
||||
multiboot_uint32_t biosdev;
|
||||
multiboot_uint32_t slice;
|
||||
multiboot_uint32_t part;
|
||||
};
|
||||
|
||||
struct multiboot_tag_mmap
|
||||
{
|
||||
multiboot_uint32_t type;
|
||||
multiboot_uint32_t size;
|
||||
multiboot_uint32_t entry_size;
|
||||
multiboot_uint32_t entry_version;
|
||||
struct multiboot_mmap_entry entries[0];
|
||||
};
|
||||
|
||||
struct multiboot_vbe_info_block
|
||||
{
|
||||
multiboot_uint8_t external_specification[512];
|
||||
};
|
||||
|
||||
struct multiboot_vbe_mode_info_block
|
||||
{
|
||||
multiboot_uint8_t external_specification[256];
|
||||
};
|
||||
|
||||
struct multiboot_tag_vbe
|
||||
{
|
||||
multiboot_uint32_t type;
|
||||
multiboot_uint32_t size;
|
||||
|
||||
multiboot_uint16_t vbe_mode;
|
||||
multiboot_uint16_t vbe_interface_seg;
|
||||
multiboot_uint16_t vbe_interface_off;
|
||||
multiboot_uint16_t vbe_interface_len;
|
||||
|
||||
struct multiboot_vbe_info_block vbe_control_info;
|
||||
struct multiboot_vbe_mode_info_block vbe_mode_info;
|
||||
};
|
||||
|
||||
struct multiboot_tag_framebuffer_common
|
||||
{
|
||||
multiboot_uint32_t type;
|
||||
multiboot_uint32_t size;
|
||||
|
||||
multiboot_uint64_t framebuffer_addr;
|
||||
multiboot_uint32_t framebuffer_pitch;
|
||||
multiboot_uint32_t framebuffer_width;
|
||||
multiboot_uint32_t framebuffer_height;
|
||||
multiboot_uint8_t framebuffer_bpp;
|
||||
#define MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED 0
|
||||
#define MULTIBOOT_FRAMEBUFFER_TYPE_RGB 1
|
||||
#define MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT 2
|
||||
multiboot_uint8_t framebuffer_type;
|
||||
multiboot_uint16_t reserved;
|
||||
};
|
||||
|
||||
struct multiboot_tag_framebuffer
|
||||
{
|
||||
struct multiboot_tag_framebuffer_common common;
|
||||
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
multiboot_uint16_t framebuffer_palette_num_colors;
|
||||
struct multiboot_color framebuffer_palette[0];
|
||||
};
|
||||
struct
|
||||
{
|
||||
multiboot_uint8_t framebuffer_red_field_position;
|
||||
multiboot_uint8_t framebuffer_red_mask_size;
|
||||
multiboot_uint8_t framebuffer_green_field_position;
|
||||
multiboot_uint8_t framebuffer_green_mask_size;
|
||||
multiboot_uint8_t framebuffer_blue_field_position;
|
||||
multiboot_uint8_t framebuffer_blue_mask_size;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
struct multiboot_tag_elf_sections
|
||||
{
|
||||
multiboot_uint32_t type;
|
||||
multiboot_uint32_t size;
|
||||
multiboot_uint32_t num;
|
||||
multiboot_uint32_t entsize;
|
||||
multiboot_uint32_t shndx;
|
||||
char sections[0];
|
||||
};
|
||||
|
||||
struct multiboot_tag_apm
|
||||
{
|
||||
multiboot_uint32_t type;
|
||||
multiboot_uint32_t size;
|
||||
multiboot_uint16_t version;
|
||||
multiboot_uint16_t cseg;
|
||||
multiboot_uint32_t offset;
|
||||
multiboot_uint16_t cseg_16;
|
||||
multiboot_uint16_t dseg;
|
||||
multiboot_uint16_t flags;
|
||||
multiboot_uint16_t cseg_len;
|
||||
multiboot_uint16_t cseg_16_len;
|
||||
multiboot_uint16_t dseg_len;
|
||||
};
|
||||
|
||||
struct multiboot_tag_efi32
|
||||
{
|
||||
multiboot_uint32_t type;
|
||||
multiboot_uint32_t size;
|
||||
multiboot_uint32_t pointer;
|
||||
};
|
||||
|
||||
struct multiboot_tag_efi64
|
||||
{
|
||||
multiboot_uint32_t type;
|
||||
multiboot_uint32_t size;
|
||||
multiboot_uint64_t pointer;
|
||||
};
|
||||
|
||||
struct multiboot_tag_smbios
|
||||
{
|
||||
multiboot_uint32_t type;
|
||||
multiboot_uint32_t size;
|
||||
multiboot_uint8_t major;
|
||||
multiboot_uint8_t minor;
|
||||
multiboot_uint8_t reserved[6];
|
||||
multiboot_uint8_t tables[0];
|
||||
};
|
||||
|
||||
struct multiboot_tag_old_acpi
|
||||
{
|
||||
multiboot_uint32_t type;
|
||||
multiboot_uint32_t size;
|
||||
multiboot_uint8_t rsdp[0];
|
||||
};
|
||||
|
||||
struct multiboot_tag_new_acpi
|
||||
{
|
||||
multiboot_uint32_t type;
|
||||
multiboot_uint32_t size;
|
||||
multiboot_uint8_t rsdp[0];
|
||||
};
|
||||
|
||||
struct multiboot_tag_network
|
||||
{
|
||||
multiboot_uint32_t type;
|
||||
multiboot_uint32_t size;
|
||||
multiboot_uint8_t dhcpack[0];
|
||||
};
|
||||
|
||||
struct multiboot_tag_efi_mmap
|
||||
{
|
||||
multiboot_uint32_t type;
|
||||
multiboot_uint32_t size;
|
||||
multiboot_uint32_t descr_size;
|
||||
multiboot_uint32_t descr_vers;
|
||||
multiboot_uint8_t efi_mmap[0];
|
||||
};
|
||||
|
||||
struct multiboot_tag_efi32_ih
|
||||
{
|
||||
multiboot_uint32_t type;
|
||||
multiboot_uint32_t size;
|
||||
multiboot_uint32_t pointer;
|
||||
};
|
||||
|
||||
struct multiboot_tag_efi64_ih
|
||||
{
|
||||
multiboot_uint32_t type;
|
||||
multiboot_uint32_t size;
|
||||
multiboot_uint64_t pointer;
|
||||
};
|
||||
|
||||
struct multiboot_tag_load_base_addr
|
||||
{
|
||||
multiboot_uint32_t type;
|
||||
multiboot_uint32_t size;
|
||||
multiboot_uint32_t load_base_addr;
|
||||
};
|
||||
|
||||
#endif /* ! ASM_FILE */
|
||||
|
||||
#endif /* ! MULTIBOOT_HEADER */
|
@ -1,194 +0,0 @@
|
||||
/**
|
||||
* @author (c) Eyal Rozenberg <eyalroz1@gmx.com>
|
||||
* 2021-2022, Haifa, Palestine/Israel
|
||||
* @author (c) Marco Paland (info@paland.com)
|
||||
* 2014-2019, PALANDesign Hannover, Germany
|
||||
*
|
||||
* @note Others have made smaller contributions to this file: see the
|
||||
* contributors page at https://github.com/eyalroz/printf/graphs/contributors
|
||||
* or ask one of the authors.
|
||||
*
|
||||
* @brief Small stand-alone implementation of the printf family of functions
|
||||
* (`(v)printf`, `(v)s(n)printf` etc., geared towards use on embedded systems with
|
||||
* a very limited resources.
|
||||
*
|
||||
* @note the implementations are thread-safe; re-entrant; use no functions from
|
||||
* the standard library; and do not dynamically allocate any memory.
|
||||
*
|
||||
* @license The MIT License (MIT)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef PRINTF_H_
|
||||
#define PRINTF_H_
|
||||
|
||||
#include <types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define ATTR_PRINTF(one_based_format_index, first_arg) \
|
||||
__attribute__((format(__printf__, (one_based_format_index), (first_arg))))
|
||||
#define ATTR_VPRINTF(one_based_format_index) ATTR_PRINTF((one_based_format_index), 0)
|
||||
#else
|
||||
#define ATTR_PRINTF((one_based_format_index), (first_arg))
|
||||
#define ATTR_VPRINTF(one_based_format_index)
|
||||
#endif
|
||||
|
||||
#ifndef PRINTF_ALIAS_STANDARD_FUNCTION_NAMES
|
||||
#define PRINTF_ALIAS_STANDARD_FUNCTION_NAMES 0
|
||||
#endif
|
||||
|
||||
#if PRINTF_ALIAS_STANDARD_FUNCTION_NAMES
|
||||
#define printf printf
|
||||
#define sprintf sprintf
|
||||
#define vsprintf vsprintf
|
||||
#define snprintf_ snprintf
|
||||
#define vsnprintf vsnprintf
|
||||
#define vprintf vprintf
|
||||
#endif
|
||||
|
||||
// If you want to include this implementation file directly rather than
|
||||
// link against, this will let you control the functions' visibility,
|
||||
// e.g. make them static so as not to clash with other objects also
|
||||
// using them.
|
||||
#ifndef PRINTF_VISIBILITY
|
||||
#define PRINTF_VISIBILITY
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Prints/send a single character to some opaque output entity
|
||||
*
|
||||
* @note This function is not implemented by the library, only declared; you must provide an
|
||||
* implementation if you wish to use the @ref printf / @ref vprintf function (and possibly
|
||||
* for linking against the library, if your toolchain does not support discarding unused functions)
|
||||
*
|
||||
* @note The output could be as simple as a wrapper for the `write()` system call on a Unix-like
|
||||
* system, or even libc's @ref putchar , for replicating actual functionality of libc's @ref printf
|
||||
* function; but on an embedded system it may involve interaction with a special output device,
|
||||
* like a UART, etc.
|
||||
*
|
||||
* @note in libc's @ref putchar, the parameter type is an int; this was intended to support the
|
||||
* representation of either a proper character or EOF in a variable - but this is really not
|
||||
* meaningful to pass into @ref putchar and is discouraged today. See further discussion in:
|
||||
* @link https://stackoverflow.com/q/17452847/1593077
|
||||
*
|
||||
* @param c the single character to print
|
||||
*/
|
||||
// PRINTF_VISIBILITY
|
||||
// void putchar(char c);
|
||||
|
||||
/**
|
||||
* An implementation of the C standard's printf/vprintf
|
||||
*
|
||||
* @note you must implement a @ref putchar_ function for using this function - it invokes @ref putchar_
|
||||
* rather than directly performing any I/O (which insulates it from any dependence on the operating system
|
||||
* and external libraries).
|
||||
*
|
||||
* @param format A string specifying the format of the output, with %-marked specifiers of how to interpret
|
||||
* additional arguments.
|
||||
* @param arg Additional arguments to the function, one for each %-specifier in @p format string
|
||||
* @return The number of characters written into @p s, not counting the terminating null character
|
||||
*/
|
||||
///@{
|
||||
PRINTF_VISIBILITY
|
||||
int printf(const char *format, ...) ATTR_PRINTF(1, 2);
|
||||
PRINTF_VISIBILITY
|
||||
int vprintf(const char *format, va_list arg) ATTR_VPRINTF(1);
|
||||
///@}
|
||||
|
||||
/**
|
||||
* An implementation of the C standard's sprintf/vsprintf
|
||||
*
|
||||
* @note For security considerations (the potential for exceeding the buffer bounds), please consider using
|
||||
* the size-constrained variant, @ref snprintf / @ref vsnprintf , instead.
|
||||
*
|
||||
* @param s An array in which to store the formatted string. It must be large enough to fit the formatted
|
||||
* output!
|
||||
* @param format A string specifying the format of the output, with %-marked specifiers of how to interpret
|
||||
* additional arguments.
|
||||
* @param arg Additional arguments to the function, one for each specifier in @p format
|
||||
* @return The number of characters written into @p s, not counting the terminating null character
|
||||
*/
|
||||
///@{
|
||||
PRINTF_VISIBILITY
|
||||
int sprintf(char *s, const char *format, ...) ATTR_PRINTF(2, 3);
|
||||
PRINTF_VISIBILITY
|
||||
int vsprintf(char *s, const char *format, va_list arg) ATTR_VPRINTF(2);
|
||||
///@}
|
||||
|
||||
/**
|
||||
* An implementation of the C standard's snprintf/vsnprintf
|
||||
*
|
||||
* @param s An array in which to store the formatted string. It must be large enough to fit either the
|
||||
* entire formatted output, or at least @p n characters. Alternatively, it can be NULL, in which case
|
||||
* nothing will be printed, and only the number of characters which _could_ have been printed is
|
||||
* tallied and returned.
|
||||
* @param n The maximum number of characters to write to the array, including a terminating null character
|
||||
* @param format A string specifying the format of the output, with %-marked specifiers of how to interpret
|
||||
* additional arguments.
|
||||
* @param arg Additional arguments to the function, one for each specifier in @p format
|
||||
* @return The number of characters that COULD have been written into @p s, not counting the terminating
|
||||
* null character. A value equal or larger than @p n indicates truncation. Only when the returned value
|
||||
* is non-negative and less than @p n, the null-terminated string has been fully and successfully printed.
|
||||
*/
|
||||
///@{
|
||||
PRINTF_VISIBILITY
|
||||
int snprintf(char *s, size_t count, const char *format, ...) ATTR_PRINTF(3, 4);
|
||||
PRINTF_VISIBILITY
|
||||
int vsnprintf(char *s, size_t count, const char *format, va_list arg) ATTR_VPRINTF(3);
|
||||
///@}
|
||||
|
||||
/**
|
||||
* printf/vprintf with user-specified output function
|
||||
*
|
||||
* An alternative to @ref printf, in which the output function is specified dynamically
|
||||
* (rather than @ref putchar_ being used)
|
||||
*
|
||||
* @param out An output function which takes one character and a type-erased additional parameters
|
||||
* @param extra_arg The type-erased argument to pass to the output function @p out with each call
|
||||
* @param format A string specifying the format of the output, with %-marked specifiers of how to interpret
|
||||
* additional arguments.
|
||||
* @param arg Additional arguments to the function, one for each specifier in @p format
|
||||
* @return The number of characters for which the output f unction was invoked, not counting the terminating null character
|
||||
*
|
||||
*/
|
||||
PRINTF_VISIBILITY
|
||||
int fctprintf(void (*out)(char c, void *extra_arg), void *extra_arg, const char *format, ...) ATTR_PRINTF(3, 4);
|
||||
PRINTF_VISIBILITY
|
||||
int vfctprintf(void (*out)(char c, void *extra_arg), void *extra_arg, const char *format, va_list arg) ATTR_VPRINTF(3);
|
||||
|
||||
#if PRINTF_ALIAS_STANDARD_FUNCTION_NAMES
|
||||
#undef printf
|
||||
#undef sprintf
|
||||
#undef vsprintf
|
||||
#undef snprintf_
|
||||
#undef vsnprintf
|
||||
#undef vprintf
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // PRINTF_H_
|
@ -1,343 +0,0 @@
|
||||
#ifndef __FENNIX_KERNEL_TYPES_H__
|
||||
#define __FENNIX_KERNEL_TYPES_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define EXTERNC extern "C"
|
||||
#define START_EXTERNC \
|
||||
EXTERNC \
|
||||
{
|
||||
#define END_EXTERNC \
|
||||
}
|
||||
#else // __cplusplus
|
||||
#define EXTERNC
|
||||
#define START_EXTERNC
|
||||
#define END_EXTERNC
|
||||
#endif // __cplusplus
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define NULL 0
|
||||
#else // __cplusplus
|
||||
#define NULL ((void *)0)
|
||||
#define bool _Bool
|
||||
#endif // __cplusplus
|
||||
|
||||
#define asm __asm__
|
||||
#define asmv __asm__ volatile
|
||||
|
||||
#define true 1
|
||||
#define false 0
|
||||
|
||||
#define inf_loop while (1)
|
||||
#define ilp inf_loop; /* Used for debugging */
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define foreach for
|
||||
#define in :
|
||||
|
||||
#define r_cst(t, v) reinterpret_cast<t>(v)
|
||||
#define c_cst(t, v) const_cast<t>(v)
|
||||
#define s_cst(t, v) static_cast<t>(v)
|
||||
#define d_cst(t, v) dynamic_cast<t>(v)
|
||||
#endif // __cplusplus
|
||||
|
||||
#define UNUSED(x) (void)(x)
|
||||
#define CONCAT(x, y) x##y
|
||||
|
||||
#ifndef __cplusplus /* This conflicts with std */
|
||||
#define toupper(c) ((c)-0x20 * (((c) >= 'a') && ((c) <= 'z')))
|
||||
#define tolower(c) ((c) + 0x20 * (((c) >= 'A') && ((c) <= 'Z')))
|
||||
#endif
|
||||
|
||||
#ifndef __va_list__
|
||||
typedef __builtin_va_list va_list;
|
||||
#endif
|
||||
|
||||
#define va_start(v, l) __builtin_va_start(v, l)
|
||||
#define va_end(v) __builtin_va_end(v)
|
||||
#define va_arg(v, l) __builtin_va_arg(v, l)
|
||||
|
||||
#define ALIGN_UP(x, align) ((__typeof__(x))(((uintptr_t)(x) + ((align)-1)) & (~((align)-1))))
|
||||
#define ALIGN_DOWN(x, align) ((__typeof__(x))((x) & (~((align)-1))))
|
||||
|
||||
#define offsetof(type, member) __builtin_offsetof(type, member)
|
||||
|
||||
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
|
||||
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
|
||||
|
||||
#define VPOKE(type, address) (*((volatile type *)(address)))
|
||||
#define POKE(type, address) (*((type *)(address)))
|
||||
|
||||
#ifndef __cplusplus
|
||||
|
||||
#ifdef __STDC__
|
||||
#ifdef __STDC_VERSION__
|
||||
#if (__STDC_VERSION__ >= 201710L)
|
||||
#define C_LANGUAGE_STANDARD 2018
|
||||
#elif (__STDC_VERSION__ >= 201112L)
|
||||
#define C_LANGUAGE_STANDARD 2011
|
||||
#elif (__STDC_VERSION__ >= 199901L)
|
||||
#define C_LANGUAGE_STANDARD 1999
|
||||
#elif (__STDC_VERSION__ >= 199409L)
|
||||
#define C_LANGUAGE_STANDARD 1995
|
||||
#endif
|
||||
#else
|
||||
#define C_LANGUAGE_STANDARD 1990
|
||||
#endif
|
||||
#else
|
||||
#define C_LANGUAGE_STANDARD 1972
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
#ifdef __STDC__
|
||||
#ifdef __cplusplus
|
||||
#if (__cplusplus >= 202100L)
|
||||
#define CPP_LANGUAGE_STANDARD 2023
|
||||
#elif (__cplusplus >= 202002L)
|
||||
#define CPP_LANGUAGE_STANDARD 2020
|
||||
#elif (__cplusplus >= 201703L)
|
||||
#define CPP_LANGUAGE_STANDARD 2017
|
||||
#elif (__cplusplus >= 201402L)
|
||||
#define CPP_LANGUAGE_STANDARD 2014
|
||||
#elif (__cplusplus >= 201103L)
|
||||
#define CPP_LANGUAGE_STANDARD 2011
|
||||
#elif (__cplusplus >= 199711L)
|
||||
#define CPP_LANGUAGE_STANDARD 1998
|
||||
#endif
|
||||
#else
|
||||
#define CPP_LANGUAGE_STANDARD __cplusplus
|
||||
#endif
|
||||
#else
|
||||
#define CPP_LANGUAGE_STANDARD __cplusplus
|
||||
#endif
|
||||
|
||||
#endif // __cplusplus
|
||||
|
||||
#ifndef __SIG_ATOMIC_TYPE__
|
||||
#define __SIG_ATOMIC_TYPE__ int
|
||||
#endif
|
||||
|
||||
typedef __INT8_TYPE__ int8_t;
|
||||
typedef __INT16_TYPE__ int16_t;
|
||||
typedef __INT32_TYPE__ int32_t;
|
||||
typedef __INT64_TYPE__ int64_t;
|
||||
|
||||
typedef __UINT8_TYPE__ uint8_t;
|
||||
typedef __UINT16_TYPE__ uint16_t;
|
||||
typedef __UINT32_TYPE__ uint32_t;
|
||||
typedef __UINT64_TYPE__ uint64_t;
|
||||
|
||||
typedef __INT_LEAST8_TYPE__ int_least8_t;
|
||||
typedef __INT_LEAST16_TYPE__ int_least16_t;
|
||||
typedef __INT_LEAST32_TYPE__ int_least32_t;
|
||||
typedef __INT_LEAST64_TYPE__ int_least64_t;
|
||||
|
||||
typedef __UINT_LEAST8_TYPE__ uint_least8_t;
|
||||
typedef __UINT_LEAST16_TYPE__ uint_least16_t;
|
||||
typedef __UINT_LEAST32_TYPE__ uint_least32_t;
|
||||
typedef __UINT_LEAST64_TYPE__ uint_least64_t;
|
||||
|
||||
typedef __INT_FAST8_TYPE__ int_fast8_t;
|
||||
typedef __INT_FAST16_TYPE__ int_fast16_t;
|
||||
typedef __INT_FAST32_TYPE__ int_fast32_t;
|
||||
typedef __INT_FAST64_TYPE__ int_fast64_t;
|
||||
|
||||
typedef __UINT_FAST8_TYPE__ uint_fast8_t;
|
||||
typedef __UINT_FAST16_TYPE__ uint_fast16_t;
|
||||
typedef __UINT_FAST32_TYPE__ uint_fast32_t;
|
||||
typedef __UINT_FAST64_TYPE__ uint_fast64_t;
|
||||
|
||||
typedef __INTPTR_TYPE__ intptr_t;
|
||||
typedef __UINTPTR_TYPE__ uintptr_t;
|
||||
|
||||
typedef __INTMAX_TYPE__ intmax_t;
|
||||
typedef __UINTMAX_TYPE__ uintmax_t;
|
||||
|
||||
typedef __PTRDIFF_TYPE__ ptrdiff_t;
|
||||
typedef __SIZE_TYPE__ size_t;
|
||||
#ifndef __cplusplus
|
||||
typedef __WCHAR_TYPE__ wchar_t;
|
||||
#endif
|
||||
typedef __WINT_TYPE__ wint_t;
|
||||
typedef __SIG_ATOMIC_TYPE__ sig_atomic_t;
|
||||
// TODO: ssize_t
|
||||
typedef intptr_t ssize_t;
|
||||
|
||||
#define INT8_MAX __INT8_MAX__
|
||||
#define INT8_MIN (-INT8_MAX - 1)
|
||||
#define UINT8_MAX __UINT8_MAX__
|
||||
#define INT16_MAX __INT16_MAX__
|
||||
#define INT16_MIN (-INT16_MAX - 1)
|
||||
#define UINT16_MAX __UINT16_MAX__
|
||||
#define INT32_MAX __INT32_MAX__
|
||||
#define INT32_MIN (-INT32_MAX - 1)
|
||||
#define UINT32_MAX __UINT32_MAX__
|
||||
#define INT64_MAX __INT64_MAX__
|
||||
#define INT64_MIN (-INT64_MAX - 1)
|
||||
#define UINT64_MAX __UINT64_MAX__
|
||||
|
||||
#define INT_LEAST8_MAX __INT_LEAST8_MAX__
|
||||
#define INT_LEAST8_MIN (-INT_LEAST8_MAX - 1)
|
||||
#define UINT_LEAST8_MAX __UINT_LEAST8_MAX__
|
||||
#define INT_LEAST16_MAX __INT_LEAST16_MAX__
|
||||
#define INT_LEAST16_MIN (-INT_LEAST16_MAX - 1)
|
||||
#define UINT_LEAST16_MAX __UINT_LEAST16_MAX__
|
||||
#define INT_LEAST32_MAX __INT_LEAST32_MAX__
|
||||
#define INT_LEAST32_MIN (-INT_LEAST32_MAX - 1)
|
||||
#define UINT_LEAST32_MAX __UINT_LEAST32_MAX__
|
||||
#define INT_LEAST64_MAX __INT_LEAST64_MAX__
|
||||
#define INT_LEAST64_MIN (-INT_LEAST64_MAX - 1)
|
||||
#define UINT_LEAST64_MAX __UINT_LEAST64_MAX__
|
||||
|
||||
#define INT_FAST8_MAX __INT_FAST8_MAX__
|
||||
#define INT_FAST8_MIN (-INT_FAST8_MAX - 1)
|
||||
#define UINT_FAST8_MAX __UINT_FAST8_MAX__
|
||||
#define INT_FAST16_MAX __INT_FAST16_MAX__
|
||||
#define INT_FAST16_MIN (-INT_FAST16_MAX - 1)
|
||||
#define UINT_FAST16_MAX __UINT_FAST16_MAX__
|
||||
#define INT_FAST32_MAX __INT_FAST32_MAX__
|
||||
#define INT_FAST32_MIN (-INT_FAST32_MAX - 1)
|
||||
#define UINT_FAST32_MAX __UINT_FAST32_MAX__
|
||||
#define INT_FAST64_MAX __INT_FAST64_MAX__
|
||||
#define INT_FAST64_MIN (-INT_FAST64_MAX - 1)
|
||||
#define UINT_FAST64_MAX __UINT_FAST64_MAX__
|
||||
|
||||
#define INTPTR_MAX __INTPTR_MAX__
|
||||
#define INTPTR_MIN (-INTPTR_MAX - 1)
|
||||
#define UINTPTR_MAX __UINTPTR_MAX__
|
||||
|
||||
#define INTMAX_MAX __INTMAX_MAX__
|
||||
#define INTMAX_MIN (-INTMAX_MAX - 1)
|
||||
#define UINTMAX_MAX __UINTMAX_MAX__
|
||||
|
||||
#define PTRDIFF_MAX __PTRDIFF_MAX__
|
||||
#define PTRDIFF_MIN (-PTRDIFF_MAX - 1)
|
||||
|
||||
#define SIG_ATOMIC_MAX __SIG_ATOMIC_MAX__
|
||||
#define SIG_ATOMIC_MIN __SIG_ATOMIC_MIN__
|
||||
|
||||
#define SIZE_MAX __SIZE_MAX__
|
||||
|
||||
#define WCHAR_MAX __WCHAR_MAX__
|
||||
#define WCHAR_MIN __WCHAR_MIN__
|
||||
|
||||
#define WINT_MAX __WINT_MAX__
|
||||
#define WINT_MIN __WINT_MIN__
|
||||
|
||||
#define BREAK __asm__ __volatile__("int $0x3" \
|
||||
: \
|
||||
: \
|
||||
: "memory");
|
||||
|
||||
#ifdef __INT48_TYPE__
|
||||
typedef __INT48_TYPE__ int48_t;
|
||||
typedef __UINT48_TYPE__ uint48_t;
|
||||
typedef int48_t int_least48_t;
|
||||
typedef uint48_t uint_least48_t;
|
||||
typedef int48_t int_fast48_t;
|
||||
typedef uint48_t uint_fast48_t;
|
||||
#else // __INT48_TYPE__
|
||||
typedef __INT64_TYPE__ int48_t;
|
||||
typedef __UINT64_TYPE__ uint48_t;
|
||||
typedef int48_t int_least48_t;
|
||||
typedef uint48_t uint_least48_t;
|
||||
typedef int48_t int_fast48_t;
|
||||
typedef uint48_t uint_fast48_t;
|
||||
#endif // __INT48_TYPE__
|
||||
|
||||
#define b4(x) ((x & 0x0F) << 4 | (x & 0xF0) >> 4)
|
||||
#define b8(x) ((x)&0xFF)
|
||||
#define b16(x) __builtin_bswap16(x)
|
||||
#define b32(x) __builtin_bswap32(x)
|
||||
#define b48(x) (((((x)&0x0000000000ff) << 40) | \
|
||||
(((x)&0x00000000ff00) << 24) | \
|
||||
(((x)&0x000000ff0000) << 8) | \
|
||||
(((x)&0x0000ff000000) >> 8) | \
|
||||
(((x)&0x00ff00000000) >> 24) | \
|
||||
(((x)&0xff0000000000) >> 40)))
|
||||
#define b64(x) __builtin_bswap64(x)
|
||||
|
||||
/* https://gcc.gnu.org/onlinedocs/gcc-9.5.0/gnat_ugn/Optimization-Levels.html */
|
||||
|
||||
/** @brief No optimization (the default); generates unoptimized code but has the fastest compilation time. */
|
||||
#define O0 __attribute__((optimize("O0")))
|
||||
/** @brief Moderate optimization; optimizes reasonably well but does not degrade compilation time significantly. */
|
||||
#define O1 __attribute__((optimize("O1")))
|
||||
/** @brief Full optimization; generates highly optimized code and has the slowest compilation time. */
|
||||
#define O2 __attribute__((optimize("O2")))
|
||||
/** @brief Full optimization as in -O2; also uses more aggressive automatic inlining of subprograms within a unit (Inlining of Subprograms) and attempts to vectorize loops. */
|
||||
#define O3 __attribute__((optimize("O3")))
|
||||
/** @brief Optimize space usage (code and data) of resulting program. */
|
||||
#define Os __attribute__((optimize("Os")))
|
||||
/** @brief Disregard strict standards compliance. -Ofast enables all -O3 optimizations. It also enables optimizations that are not valid for all standard-compliant programs. */
|
||||
#define Ofast __attribute__((optimize("Ofast")))
|
||||
|
||||
#define __unused __attribute__((unused))
|
||||
#define __packed __attribute__((packed))
|
||||
#define __naked __attribute__((naked))
|
||||
#define __aligned(x) __attribute__((aligned(x)))
|
||||
#define __section(x) __attribute__((section(x)))
|
||||
#define __noreturn __attribute__((noreturn))
|
||||
#define __weak __attribute__((weak))
|
||||
#define __alias(x) __attribute__((alias(x)))
|
||||
#define __always_inline __attribute__((always_inline))
|
||||
#define __noinline __attribute__((noinline))
|
||||
#define __pure __attribute__((pure))
|
||||
#define __const __attribute__((const))
|
||||
#define __malloc __attribute__((malloc))
|
||||
#define __returns_twice __attribute__((returns_twice))
|
||||
#define __used __attribute__((used))
|
||||
#define __deprecated __attribute__((deprecated))
|
||||
#define __deprecated_msg(x) __attribute__((deprecated(x)))
|
||||
#define __weakref(x) __attribute__((weakref(x)))
|
||||
#define __weakrefalias(x) __attribute__((weakref(#x)))
|
||||
#define __visibility(x) __attribute__((visibility(x)))
|
||||
#define __constructor __attribute__((constructor))
|
||||
#define __destructor __attribute__((destructor))
|
||||
#define __cleanup(x) __attribute__((cleanup(x)))
|
||||
#define __fallthrough __attribute__((fallthrough))
|
||||
#define __nonnull(x) __attribute__((nonnull x))
|
||||
#define __nonnull_all __attribute__((nonnull))
|
||||
#define __returns_nonnull __attribute__((returns_nonnull))
|
||||
#define __sentinel __attribute__((sentinel))
|
||||
#define __sentinel_all __attribute__((sentinel(0)))
|
||||
#define __format(x, y, z) __attribute__((format(x, y, z)))
|
||||
#define __format_arg(x) __attribute__((format_arg(x)))
|
||||
#define __nonnull_params(x) __attribute__((nonnull x))
|
||||
#define __nonnull_all __attribute__((nonnull))
|
||||
#define __warn_unused_result __attribute__((warn_unused_result))
|
||||
#define __no_stack_protector __attribute__((no_stack_protector))
|
||||
#define __no_instrument_function __attribute__((no_instrument_function))
|
||||
#define __no_debug __attribute__((no_debug))
|
||||
#define __target(x) __attribute__((target(x)))
|
||||
#define __min_vector_width(x) __attribute__((min_vector_width(x)))
|
||||
|
||||
// sanitizer
|
||||
#define __no_sanitize_address __attribute__((no_sanitize_address))
|
||||
#define __no_sanitize_undefined __attribute__((no_sanitize_undefined))
|
||||
#define __no_address_safety_analysis __attribute__((no_address_safety_analysis))
|
||||
#define __no_sanitize_thread __attribute__((no_sanitize_thread))
|
||||
|
||||
#define __synchronize __sync_synchronize()
|
||||
#define __sync __synchronize
|
||||
|
||||
#define likely(x) __builtin_expect(!!(x), 1)
|
||||
#define unlikely(x) __builtin_expect(!!(x), 0)
|
||||
|
||||
#define SafeFunction __no_stack_protector __no_sanitize_address __no_sanitize_undefined __no_address_safety_analysis __no_sanitize_thread
|
||||
|
||||
#define NIF __no_instrument_function
|
||||
|
||||
#define int1 \
|
||||
__asm__ __volatile__("int $0x1" \
|
||||
: \
|
||||
: \
|
||||
: "memory")
|
||||
|
||||
#define int3 \
|
||||
__asm__ __volatile__("int3" \
|
||||
: \
|
||||
: \
|
||||
: "memory")
|
||||
|
||||
#endif // !__FENNIX_KERNEL_TYPES_H__
|
@ -1,34 +0,0 @@
|
||||
#ifndef __FENNIX_KERNEL_UART_H__
|
||||
#define __FENNIX_KERNEL_UART_H__
|
||||
|
||||
#include <types.h>
|
||||
|
||||
namespace UniversalAsynchronousReceiverTransmitter
|
||||
{
|
||||
enum SerialPorts
|
||||
{
|
||||
COMNULL = 0,
|
||||
COM1 = 0x3F8,
|
||||
COM2 = 0x2F8,
|
||||
COM3 = 0x3E8,
|
||||
COM4 = 0x2E8,
|
||||
COM5 = 0x5F8,
|
||||
COM6 = 0x4F8,
|
||||
COM7 = 0x5E8,
|
||||
COM8 = 0x4E8
|
||||
};
|
||||
|
||||
class UART
|
||||
{
|
||||
private:
|
||||
SerialPorts Port;
|
||||
|
||||
public:
|
||||
UART(SerialPorts Port = COMNULL);
|
||||
~UART();
|
||||
void Write(uint8_t Char);
|
||||
uint8_t Read();
|
||||
};
|
||||
}
|
||||
|
||||
#endif // !__FENNIX_KERNEL_UART_H__
|
@ -1,54 +0,0 @@
|
||||
ENTRY(_start)
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
. = 0x100000;
|
||||
_kernel_start = .;
|
||||
|
||||
.text BLOCK(4K) : ALIGN(4K)
|
||||
{
|
||||
*(.multiboot)
|
||||
*(.multiboot2)
|
||||
*(.text)
|
||||
}
|
||||
|
||||
.rodata BLOCK(4K) : ALIGN(4K)
|
||||
{
|
||||
*(.rodata)
|
||||
}
|
||||
|
||||
.data BLOCK(4K) : ALIGN(4K)
|
||||
{
|
||||
*(.data)
|
||||
}
|
||||
|
||||
.init_array :
|
||||
{
|
||||
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 = .);
|
||||
}
|
||||
|
||||
.fini_array :
|
||||
{
|
||||
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 = .);
|
||||
}
|
||||
|
||||
.bss BLOCK(4K) : ALIGN(4K)
|
||||
{
|
||||
*(COMMON)
|
||||
*(.bss)
|
||||
}
|
||||
|
||||
/DISCARD/ :
|
||||
{
|
||||
*(.comment*)
|
||||
*(.note*)
|
||||
}
|
||||
. += CONSTANT(MAXPAGESIZE);
|
||||
_kernel_end = ALIGN(CONSTANT(MAXPAGESIZE));
|
||||
}
|
@ -1,4 +0,0 @@
|
||||
#pragma once
|
||||
#include <types.h>
|
||||
|
||||
bool LoadElfInMemory(void *Address, size_t Length, bool Allow64);
|
File diff suppressed because it is too large
Load Diff
@ -1,94 +0,0 @@
|
||||
#ifndef __FENNIX_KERNEL_UBSAN_H__
|
||||
#define __FENNIX_KERNEL_UBSAN_H__
|
||||
|
||||
#include <types.h>
|
||||
|
||||
struct source_location
|
||||
{
|
||||
const char *file;
|
||||
uint32_t line;
|
||||
uint32_t column;
|
||||
};
|
||||
|
||||
struct type_descriptor
|
||||
{
|
||||
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 out_of_bounds_info
|
||||
{
|
||||
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 negative_vla_data
|
||||
{
|
||||
struct source_location location;
|
||||
struct type_descriptor *type;
|
||||
};
|
||||
|
||||
struct invalid_value_data
|
||||
{
|
||||
struct source_location location;
|
||||
struct type_descriptor *type;
|
||||
};
|
||||
|
||||
struct nonnull_return_data
|
||||
{
|
||||
struct source_location location;
|
||||
};
|
||||
|
||||
struct nonnull_arg_data
|
||||
{
|
||||
struct source_location location;
|
||||
};
|
||||
|
||||
struct unreachable_data
|
||||
{
|
||||
struct source_location location;
|
||||
};
|
||||
|
||||
struct invalid_builtin_data
|
||||
{
|
||||
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 shift_out_of_bounds_data
|
||||
{
|
||||
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;
|
||||
};
|
||||
|
||||
#endif // !__FENNIX_KERNEL_UBSAN_H__
|
6
Makefile
6
Makefile
@ -2,9 +2,6 @@ prepare:
|
||||
make -C BIOS prepare
|
||||
make -C UEFI prepare
|
||||
|
||||
loader:
|
||||
make -C FennixLoader build
|
||||
|
||||
build:
|
||||
make -C BIOS build
|
||||
make -C UEFI build
|
||||
@ -14,5 +11,4 @@ build:
|
||||
clean:
|
||||
make -C BIOS clean
|
||||
make -C UEFI clean
|
||||
make -C FennixLoader clean
|
||||
rm -f loader.bin efi-loader.bin FLDR.elf
|
||||
rm -f loader.bin efi-loader.bin
|
||||
|
Loading…
x
Reference in New Issue
Block a user