mirror of
https://github.com/EnderIce2/Fennix.git
synced 2025-07-01 18:39:16 +00:00
Compare commits
2 Commits
Kernel-mul
...
Kernel-tas
Author | SHA1 | Date | |
---|---|---|---|
9b49f670bd
|
|||
4a8e6eec5f
|
61
Kernel/.github/workflows/codacy.yml
vendored
61
Kernel/.github/workflows/codacy.yml
vendored
@ -1,61 +0,0 @@
|
|||||||
# This workflow uses actions that are not certified by GitHub.
|
|
||||||
# They are provided by a third-party and are governed by
|
|
||||||
# separate terms of service, privacy policy, and support
|
|
||||||
# documentation.
|
|
||||||
|
|
||||||
# This workflow checks out code, performs a Codacy security scan
|
|
||||||
# and integrates the results with the
|
|
||||||
# GitHub Advanced Security code scanning feature. For more information on
|
|
||||||
# the Codacy security scan action usage and parameters, see
|
|
||||||
# https://github.com/codacy/codacy-analysis-cli-action.
|
|
||||||
# For more information on Codacy Analysis CLI in general, see
|
|
||||||
# https://github.com/codacy/codacy-analysis-cli.
|
|
||||||
|
|
||||||
name: Codacy Security Scan
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [ "main" ]
|
|
||||||
pull_request:
|
|
||||||
# The branches below must be a subset of the branches above
|
|
||||||
branches: [ "main" ]
|
|
||||||
schedule:
|
|
||||||
- cron: '27 22 * * 5'
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
codacy-security-scan:
|
|
||||||
permissions:
|
|
||||||
contents: read # for actions/checkout to fetch code
|
|
||||||
security-events: write # for github/codeql-action/upload-sarif to upload SARIF results
|
|
||||||
actions: read # only required for a private repository by github/codeql-action/upload-sarif to get the Action run status
|
|
||||||
name: Codacy Security Scan
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
# Checkout the repository to the GitHub Actions runner
|
|
||||||
- name: Checkout code
|
|
||||||
uses: actions/checkout@v3
|
|
||||||
|
|
||||||
# Execute Codacy Analysis CLI and generate a SARIF output with the security issues identified during the analysis
|
|
||||||
- name: Run Codacy Analysis CLI
|
|
||||||
uses: codacy/codacy-analysis-cli-action@d840f886c4bd4edc059706d09c6a1586111c540b
|
|
||||||
with:
|
|
||||||
# Check https://github.com/codacy/codacy-analysis-cli#project-token to get your project token from your Codacy repository
|
|
||||||
# You can also omit the token and run the tools that support default configurations
|
|
||||||
project-token: ${{ secrets.CODACY_PROJECT_TOKEN }}
|
|
||||||
verbose: true
|
|
||||||
output: results.sarif
|
|
||||||
format: sarif
|
|
||||||
# Adjust severity of non-security issues
|
|
||||||
gh-code-scanning-compat: true
|
|
||||||
# Force 0 exit code to allow SARIF file generation
|
|
||||||
# This will handover control about PR rejection to the GitHub side
|
|
||||||
max-allowed-issues: 2147483647
|
|
||||||
|
|
||||||
# Upload the SARIF file generated in the previous step
|
|
||||||
- name: Upload SARIF results file
|
|
||||||
uses: github/codeql-action/upload-sarif@v2
|
|
||||||
with:
|
|
||||||
sarif_file: results.sarif
|
|
1
Kernel/.gitignore
vendored
1
Kernel/.gitignore
vendored
@ -4,4 +4,5 @@
|
|||||||
*.map
|
*.map
|
||||||
*.fsys
|
*.fsys
|
||||||
*.log
|
*.log
|
||||||
|
Files/*.psf
|
||||||
.dccache
|
.dccache
|
||||||
|
98
Kernel/.vscode/c_cpp_properties.json
vendored
98
Kernel/.vscode/c_cpp_properties.json
vendored
@ -1,9 +1,8 @@
|
|||||||
{
|
{
|
||||||
"configurations": [
|
"configurations": [
|
||||||
{
|
{
|
||||||
"name": "Fennix x64 (Linux, GCC, debug)",
|
"name": "Linux",
|
||||||
"includePath": [
|
"includePath": [
|
||||||
"${workspaceFolder}/include",
|
|
||||||
"${workspaceFolder}/include/**"
|
"${workspaceFolder}/include/**"
|
||||||
],
|
],
|
||||||
"defines": [
|
"defines": [
|
||||||
@ -12,110 +11,37 @@
|
|||||||
"KERNEL_VERSION=\"1.0\"",
|
"KERNEL_VERSION=\"1.0\"",
|
||||||
"GIT_COMMIT=\"0000000000000000000000000000000000000000\"",
|
"GIT_COMMIT=\"0000000000000000000000000000000000000000\"",
|
||||||
"GIT_COMMIT_SHORT=\"0000000\"",
|
"GIT_COMMIT_SHORT=\"0000000\"",
|
||||||
"a64",
|
|
||||||
"DEBUG=\"1\""
|
"DEBUG=\"1\""
|
||||||
],
|
],
|
||||||
"compilerPath": "${workspaceFolder}/../tools/cross/bin/amd64-elf-gcc",
|
"compilerPath": "/usr/bin/gcc",
|
||||||
"cStandard": "c17",
|
"cStandard": "c17",
|
||||||
"cppStandard": "c++20",
|
"cppStandard": "c++20",
|
||||||
"intelliSenseMode": "gcc-x64",
|
"intelliSenseMode": "gcc-x64",
|
||||||
"configurationProvider": "ms-vscode.makefile-tools",
|
"configurationProvider": "ms-vscode.makefile-tools",
|
||||||
"compilerArgs": [
|
"compilerArgs": [
|
||||||
// Compiler flags
|
// "-m32",
|
||||||
"-fno-pic",
|
"-mcmodel=kernel", /* 64-bit only */
|
||||||
"-fno-pie",
|
|
||||||
"-mno-red-zone",
|
|
||||||
"-march=core2",
|
|
||||||
"-pipe",
|
|
||||||
"-mcmodel=kernel",
|
|
||||||
"-fno-builtin",
|
|
||||||
|
|
||||||
// C++ flags
|
|
||||||
"-fno-rtti",
|
"-fno-rtti",
|
||||||
"-fexceptions",
|
"-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": "Fennix x32 (Linux, GCC, debug)",
|
|
||||||
"includePath": [
|
|
||||||
"${workspaceFolder}/include/**"
|
|
||||||
],
|
|
||||||
"defines": [
|
|
||||||
"__debug_vscode__",
|
|
||||||
"KERNEL_NAME=\"Fennix\"",
|
|
||||||
"KERNEL_VERSION=\"1.0\"",
|
|
||||||
"GIT_COMMIT=\"0000000000000000000000000000000000000000\"",
|
|
||||||
"GIT_COMMIT_SHORT=\"0000000\"",
|
|
||||||
"a32",
|
|
||||||
"DEBUG=\"1\""
|
|
||||||
],
|
|
||||||
"compilerPath": "${workspaceFolder}/../tools/cross/bin/i686-elf-gcc",
|
|
||||||
"cStandard": "c17",
|
|
||||||
"cppStandard": "c++20",
|
|
||||||
"intelliSenseMode": "gcc-x86",
|
|
||||||
"configurationProvider": "ms-vscode.makefile-tools",
|
|
||||||
"compilerArgs": [
|
|
||||||
// Compiler flags
|
|
||||||
"-fno-pic",
|
"-fno-pic",
|
||||||
"-fno-pie",
|
"-fno-pie",
|
||||||
"-mno-80387",
|
"-mno-80387",
|
||||||
"-mno-mmx",
|
"-mno-mmx",
|
||||||
"-mno-3dnow",
|
"-mno-3dnow",
|
||||||
"-mno-red-zone",
|
"-mno-red-zone",
|
||||||
"-march=pentium",
|
"-mno-sse",
|
||||||
|
"-mno-sse2",
|
||||||
|
"-march=nehalem",
|
||||||
"-pipe",
|
"-pipe",
|
||||||
"-msoft-float",
|
"-msoft-float",
|
||||||
"-fno-builtin",
|
"-fno-builtin",
|
||||||
|
|
||||||
// C++ flags
|
|
||||||
"-fno-rtti",
|
|
||||||
"-fexceptions",
|
|
||||||
|
|
||||||
// Linker flags
|
|
||||||
"-T${workspaceFolder}/Architecture/i686/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",
|
"-ffreestanding",
|
||||||
"-nostdinc",
|
"-nostdinc",
|
||||||
"-nostdinc++"
|
"-Wl,-static,--no-dynamic-linker,-ztext",
|
||||||
|
"-shared",
|
||||||
|
"-zmax-page-size=0x1000",
|
||||||
|
"-nostdinc++",
|
||||||
|
"-fsanitize=undefined"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
17
Kernel/.vscode/extensions.json
vendored
17
Kernel/.vscode/extensions.json
vendored
@ -1,13 +1,16 @@
|
|||||||
{
|
{
|
||||||
"recommendations": [
|
"recommendations": [
|
||||||
|
"pejmannikram.vscode-auto-scroll",
|
||||||
|
"aaron-bond.better-comments",
|
||||||
"ms-vscode.cpptools",
|
"ms-vscode.cpptools",
|
||||||
"wayou.vscode-todo-highlight",
|
"streetsidesoftware.code-spell-checker",
|
||||||
"gruntfuggly.todo-tree",
|
"naumovs.color-highlight",
|
||||||
"13xforever.language-x86-64-assembly",
|
|
||||||
"webfreak.debug",
|
|
||||||
"zixuanwang.linkerscript",
|
|
||||||
"maziac.hex-hover-converter",
|
|
||||||
"cschlosser.doxdocgen",
|
"cschlosser.doxdocgen",
|
||||||
"streetsidesoftware.code-spell-checker"
|
"ferrierbenjamin.fold-unfold-all-icone",
|
||||||
|
"ajshort.include-autocomplete",
|
||||||
|
"zixuanwang.linkerscript",
|
||||||
|
"ibm.output-colorizer",
|
||||||
|
"christian-kohler.path-intellisense",
|
||||||
|
"Gruntfuggly.todo-tree"
|
||||||
]
|
]
|
||||||
}
|
}
|
5
Kernel/.vscode/settings.json
vendored
5
Kernel/.vscode/settings.json
vendored
@ -8,12 +8,11 @@
|
|||||||
"C_Cpp.default.cppStandard": "c++20",
|
"C_Cpp.default.cppStandard": "c++20",
|
||||||
"C_Cpp.intelliSenseMemoryLimit": 16384,
|
"C_Cpp.intelliSenseMemoryLimit": 16384,
|
||||||
"editor.smoothScrolling": true,
|
"editor.smoothScrolling": true,
|
||||||
"editor.cursorSmoothCaretAnimation": "on",
|
"editor.cursorSmoothCaretAnimation": true,
|
||||||
"C_Cpp.codeAnalysis.clangTidy.checks.disabled": [
|
"C_Cpp.codeAnalysis.clangTidy.checks.disabled": [
|
||||||
"clang-analyzer-security.insecureAPI.strcpy",
|
"clang-analyzer-security.insecureAPI.strcpy",
|
||||||
"clang-diagnostic-unknown-warning-option",
|
"clang-diagnostic-unknown-warning-option",
|
||||||
"clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling",
|
"clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling",
|
||||||
"clang-diagnostic-implicit-exception-spec-mismatch",
|
"clang-diagnostic-implicit-exception-spec-mismatch"
|
||||||
"clang-diagnostic-unknown-attributes"
|
|
||||||
]
|
]
|
||||||
}
|
}
|
@ -1,6 +1,6 @@
|
|||||||
#include <smp.hpp>
|
#include <smp.hpp>
|
||||||
|
|
||||||
#include <ints.hpp>
|
#include <interrupts.hpp>
|
||||||
#include <memory.hpp>
|
#include <memory.hpp>
|
||||||
#include <cpu.hpp>
|
#include <cpu.hpp>
|
||||||
|
|
||||||
|
@ -1,41 +0,0 @@
|
|||||||
[bits 32]
|
|
||||||
section .bootstrap.text
|
|
||||||
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
|
|
||||||
ret
|
|
||||||
.NoCPUID:
|
|
||||||
; mov word [0xb8F00], 0xF00F ; .
|
|
||||||
.Loop:
|
|
||||||
cli
|
|
||||||
hlt
|
|
||||||
jmp .Loop
|
|
||||||
|
|
||||||
global Detect64Bit
|
|
||||||
Detect64Bit:
|
|
||||||
mov eax, 0x80000000
|
|
||||||
cpuid
|
|
||||||
cmp eax, 0x80000001
|
|
||||||
jb .NoLongMode
|
|
||||||
mov eax, 0x80000001
|
|
||||||
cpuid
|
|
||||||
test edx, 1 << 29
|
|
||||||
jz .NoLongMode
|
|
||||||
ret
|
|
||||||
.NoLongMode:
|
|
||||||
; mov word [0xb8F00], 0xF00A ; .
|
|
||||||
.Loop:
|
|
||||||
cli
|
|
||||||
hlt
|
|
||||||
jmp .Loop
|
|
@ -1,152 +0,0 @@
|
|||||||
; https://wiki.osdev.org/Creating_a_64-bit_kernel
|
|
||||||
; https://wiki.osdev.org/Entering_Long_Mode_Directly
|
|
||||||
|
|
||||||
KERNEL_VIRTUAL_BASE equ 0xFFFFFFFF80000000 ; 512GB
|
|
||||||
KERNEL_LMA equ 0x1000000 ; 16MB
|
|
||||||
KERNEL_STACK_SIZE equ 0x4000 ; 16KB
|
|
||||||
|
|
||||||
extern Multiboot2Entry
|
|
||||||
extern BootPageTable
|
|
||||||
extern UpdatePageTable
|
|
||||||
extern UpdatePageTable64
|
|
||||||
extern DetectCPUID
|
|
||||||
extern Detect64Bit
|
|
||||||
extern LoadGDT32
|
|
||||||
global MB2_start
|
|
||||||
extern MB2_start_c
|
|
||||||
|
|
||||||
[bits 32]
|
|
||||||
|
|
||||||
section .bootstrap.data
|
|
||||||
global MB2_HeaderMagic
|
|
||||||
MB2_HeaderMagic:
|
|
||||||
times (0x64) dq 0
|
|
||||||
|
|
||||||
global MB2_HeaderInfo
|
|
||||||
MB2_HeaderInfo:
|
|
||||||
times (0x64) dq 0
|
|
||||||
|
|
||||||
section .bootstrap.text
|
|
||||||
MB2_start:
|
|
||||||
cli
|
|
||||||
; mov word [0xb8F00], 0x072E ; .
|
|
||||||
mov [MB2_HeaderMagic], eax
|
|
||||||
mov [MB2_HeaderInfo], ebx
|
|
||||||
|
|
||||||
; We need to check if the CPU supports 64-bit mode
|
|
||||||
call DetectCPUID
|
|
||||||
call Detect64Bit
|
|
||||||
|
|
||||||
; mov word [0xb8F02], 0x072E ; .
|
|
||||||
|
|
||||||
mov ecx, cr0
|
|
||||||
and ecx, 0x7fffffff ; Clear PG
|
|
||||||
mov cr0, ecx
|
|
||||||
|
|
||||||
mov ecx, cr4
|
|
||||||
or ecx, 0x10 ; Set PSE
|
|
||||||
or ecx, 0x20 ; Set PAE
|
|
||||||
mov cr4, ecx
|
|
||||||
|
|
||||||
; Load the GDT and update the page table
|
|
||||||
call LoadGDT32
|
|
||||||
call UpdatePageTable
|
|
||||||
|
|
||||||
; Load the new page table
|
|
||||||
mov edi, BootPageTable
|
|
||||||
mov cr3, edi
|
|
||||||
|
|
||||||
; mov word [0xb8F04], 0x072E ; .
|
|
||||||
|
|
||||||
; Enable long mode
|
|
||||||
mov ecx, 0xC0000080 ; EFER
|
|
||||||
rdmsr
|
|
||||||
or eax, 0x800 | 0x100 | 0x1 ; Set LME, LMA, SCE
|
|
||||||
wrmsr
|
|
||||||
|
|
||||||
mov ecx, cr0
|
|
||||||
or ecx, (0x80000000 | 0x1) ; Set PG and PE
|
|
||||||
mov cr0, ecx
|
|
||||||
|
|
||||||
|
|
||||||
lgdt [GDT64.Ptr]
|
|
||||||
; xor eax, eax
|
|
||||||
; sgdt [eax]
|
|
||||||
; test eax, eax
|
|
||||||
; jz .InvalidGDT
|
|
||||||
|
|
||||||
; .InvalidGDT:
|
|
||||||
; mov word [0xb8F07], 0x4 ; Red
|
|
||||||
; hlt
|
|
||||||
|
|
||||||
jmp GDT64.code:HigherHalfStart
|
|
||||||
|
|
||||||
[bits 64]
|
|
||||||
HigherHalfStart:
|
|
||||||
cli
|
|
||||||
; mov word [0xb8F06], 0x072E ; .
|
|
||||||
call UpdatePageTable64
|
|
||||||
|
|
||||||
; Load the new page table
|
|
||||||
mov rdi, BootPageTable
|
|
||||||
mov cr3, rdi
|
|
||||||
|
|
||||||
mov ax, GDT64.data
|
|
||||||
mov ds, ax
|
|
||||||
mov es, ax
|
|
||||||
mov fs, ax
|
|
||||||
mov gs, ax
|
|
||||||
mov ss, ax
|
|
||||||
|
|
||||||
; mov word [0xb8F08], 0x072E ; .
|
|
||||||
mov rsp, (KernelStack + KERNEL_STACK_SIZE)
|
|
||||||
mov rbp, (KernelStack + KERNEL_STACK_SIZE)
|
|
||||||
|
|
||||||
cld
|
|
||||||
cli
|
|
||||||
|
|
||||||
call Multiboot2Entry
|
|
||||||
.Loop:
|
|
||||||
hlt
|
|
||||||
jmp .Loop
|
|
||||||
|
|
||||||
section .bootstrap.bss
|
|
||||||
align 16
|
|
||||||
KernelStack:
|
|
||||||
resb KERNEL_STACK_SIZE
|
|
||||||
|
|
||||||
; Access bits
|
|
||||||
PRESENT equ 1 << 7
|
|
||||||
NOT_SYS equ 1 << 4
|
|
||||||
EXEC equ 1 << 3
|
|
||||||
DC equ 1 << 2
|
|
||||||
RW equ 1 << 1
|
|
||||||
ACCESSED equ 1 << 0
|
|
||||||
|
|
||||||
; Flags bits
|
|
||||||
GRAN_4K equ 1 << 7
|
|
||||||
SZ_32 equ 1 << 6
|
|
||||||
LONG_MODE equ 1 << 5
|
|
||||||
|
|
||||||
section .bootstrap.data
|
|
||||||
GDT64:
|
|
||||||
.null: equ $ - GDT64
|
|
||||||
dq 0
|
|
||||||
.code: equ $ - GDT64
|
|
||||||
dd 0xFFFF
|
|
||||||
db 0
|
|
||||||
db PRESENT | NOT_SYS | EXEC | RW
|
|
||||||
db GRAN_4K | LONG_MODE | 0xF
|
|
||||||
db 0
|
|
||||||
.data: equ $ - GDT64
|
|
||||||
dd 0xFFFF
|
|
||||||
db 0
|
|
||||||
db PRESENT | NOT_SYS | RW
|
|
||||||
db GRAN_4K | SZ_32 | 0xF
|
|
||||||
db 0
|
|
||||||
.tss: equ $ - GDT64
|
|
||||||
dd 0x00000068
|
|
||||||
dd 0x00CF8900
|
|
||||||
.Ptr:
|
|
||||||
dw $ - GDT64 - 1
|
|
||||||
dq GDT64
|
|
@ -1,47 +0,0 @@
|
|||||||
[bits 32]
|
|
||||||
section .bootstrap.text
|
|
||||||
|
|
||||||
align 32
|
|
||||||
global gdtr
|
|
||||||
gdtr:
|
|
||||||
dw GDT32_END - GDT32 - 1
|
|
||||||
dd GDT32
|
|
||||||
|
|
||||||
align 32
|
|
||||||
GDT32:
|
|
||||||
dq 0x0
|
|
||||||
|
|
||||||
dw 0xffff
|
|
||||||
dw 0x0000
|
|
||||||
db 0x00
|
|
||||||
dw 0xcf9a
|
|
||||||
db 0x00
|
|
||||||
|
|
||||||
dw 0xffff
|
|
||||||
dw 0x0000
|
|
||||||
db 0x00
|
|
||||||
dw 0xcf92
|
|
||||||
db 0x00
|
|
||||||
|
|
||||||
dw 0x0100
|
|
||||||
dw 0x1000
|
|
||||||
db 0x00
|
|
||||||
dw 0x4092
|
|
||||||
db 0x00
|
|
||||||
GDT32_END:
|
|
||||||
|
|
||||||
global LoadGDT32
|
|
||||||
LoadGDT32:
|
|
||||||
lgdt [gdtr]
|
|
||||||
|
|
||||||
jmp 0x8:ActivateGDT
|
|
||||||
ActivateGDT:
|
|
||||||
mov cx, 0x10
|
|
||||||
mov ss, cx
|
|
||||||
mov ds, cx
|
|
||||||
mov es, cx
|
|
||||||
mov fs, cx
|
|
||||||
mov cx, 0x18
|
|
||||||
mov gs, cx
|
|
||||||
|
|
||||||
ret
|
|
@ -1,60 +0,0 @@
|
|||||||
extern MB2_start
|
|
||||||
|
|
||||||
[bits 32]
|
|
||||||
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_ENTRY_TAG:
|
|
||||||
dw 3
|
|
||||||
dw 0
|
|
||||||
dd MB2_ENTRY_TAG_END - MB2_ENTRY_TAG
|
|
||||||
dd MB2_start
|
|
||||||
MB2_ENTRY_TAG_END:
|
|
||||||
align 8
|
|
||||||
MB2_FRAMEBUFFER_TAG_START:
|
|
||||||
dw 5
|
|
||||||
dw 1
|
|
||||||
dd MB2_FRAMEBUFFER_TAG_END - MB2_FRAMEBUFFER_TAG_START
|
|
||||||
dd 1280 ; Width
|
|
||||||
dd 720 ; Height
|
|
||||||
dd 32 ; Depth
|
|
||||||
MB2_FRAMEBUFFER_TAG_END:
|
|
||||||
align 8
|
|
||||||
MB2_TAG_START:
|
|
||||||
dw 0
|
|
||||||
dw 0
|
|
||||||
dd MB2_TAG_END - MB2_TAG_START
|
|
||||||
MB2_TAG_END:
|
|
||||||
HEADER_END:
|
|
@ -1,285 +0,0 @@
|
|||||||
#include <types.h>
|
|
||||||
|
|
||||||
union __attribute__((packed)) PageTableEntry
|
|
||||||
{
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
bool Present : 1; // 0
|
|
||||||
bool ReadWrite : 1; // 1
|
|
||||||
bool UserSupervisor : 1; // 2
|
|
||||||
bool WriteThrough : 1; // 3
|
|
||||||
bool CacheDisable : 1; // 4
|
|
||||||
bool Accessed : 1; // 5
|
|
||||||
bool Dirty : 1; // 6
|
|
||||||
bool PageAttributeTable : 1; // 7
|
|
||||||
bool Global : 1; // 8
|
|
||||||
uint8_t Available0 : 3; // 9-11
|
|
||||||
uint64_t Address : 40; // 12-51
|
|
||||||
uint32_t Available1 : 7; // 52-58
|
|
||||||
uint8_t ProtectionKey : 4; // 59-62
|
|
||||||
bool ExecuteDisable : 1; // 63
|
|
||||||
};
|
|
||||||
uint64_t raw;
|
|
||||||
|
|
||||||
__always_inline inline SafeFunction NIF void SetAddress(uintptr_t _Address)
|
|
||||||
{
|
|
||||||
_Address &= 0x000000FFFFFFFFFF;
|
|
||||||
this->raw &= 0xFFF0000000000FFF;
|
|
||||||
this->raw |= (_Address << 12);
|
|
||||||
}
|
|
||||||
|
|
||||||
__always_inline inline SafeFunction NIF uintptr_t GetAddress() { return (this->raw & 0x000FFFFFFFFFF000) >> 12; }
|
|
||||||
};
|
|
||||||
|
|
||||||
struct __attribute__((packed)) PageTableEntryPtr
|
|
||||||
{
|
|
||||||
PageTableEntry Entries[511];
|
|
||||||
};
|
|
||||||
|
|
||||||
union __attribute__((packed)) PageDirectoryEntry
|
|
||||||
{
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
bool Present : 1; // 0
|
|
||||||
bool ReadWrite : 1; // 1
|
|
||||||
bool UserSupervisor : 1; // 2
|
|
||||||
bool WriteThrough : 1; // 3
|
|
||||||
bool CacheDisable : 1; // 4
|
|
||||||
bool Accessed : 1; // 5
|
|
||||||
bool Available0 : 1; // 6
|
|
||||||
bool PageSize : 1; // 7
|
|
||||||
uint8_t Available1 : 4; // 8-11
|
|
||||||
uint64_t Address : 40; // 12-51
|
|
||||||
uint32_t Available2 : 11; // 52-62
|
|
||||||
bool ExecuteDisable : 1; // 63
|
|
||||||
};
|
|
||||||
uint64_t raw;
|
|
||||||
|
|
||||||
__always_inline inline SafeFunction NIF void SetAddress(uintptr_t _Address)
|
|
||||||
{
|
|
||||||
_Address &= 0x000000FFFFFFFFFF;
|
|
||||||
this->raw &= 0xFFF0000000000FFF;
|
|
||||||
this->raw |= (_Address << 12);
|
|
||||||
}
|
|
||||||
|
|
||||||
__always_inline inline SafeFunction NIF uintptr_t GetAddress() { return (this->raw & 0x000FFFFFFFFFF000) >> 12; }
|
|
||||||
};
|
|
||||||
|
|
||||||
struct __attribute__((packed)) PageDirectoryEntryPtr
|
|
||||||
{
|
|
||||||
PageDirectoryEntry Entries[511];
|
|
||||||
};
|
|
||||||
|
|
||||||
union __attribute__((packed)) PageDirectoryPointerTableEntry
|
|
||||||
{
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
bool Present : 1; // 0
|
|
||||||
bool ReadWrite : 1; // 1
|
|
||||||
bool UserSupervisor : 1; // 2
|
|
||||||
bool WriteThrough : 1; // 3
|
|
||||||
bool CacheDisable : 1; // 4
|
|
||||||
bool Accessed : 1; // 5
|
|
||||||
bool Available0 : 1; // 6
|
|
||||||
bool PageSize : 1; // 7
|
|
||||||
uint8_t Available1 : 4; // 8-11
|
|
||||||
uint64_t Address : 40; // 12-51
|
|
||||||
uint32_t Available2 : 11; // 52-62
|
|
||||||
bool ExecuteDisable : 1; // 63
|
|
||||||
};
|
|
||||||
uint64_t raw;
|
|
||||||
|
|
||||||
__always_inline inline SafeFunction NIF void SetAddress(uintptr_t _Address)
|
|
||||||
{
|
|
||||||
_Address &= 0x000000FFFFFFFFFF;
|
|
||||||
this->raw &= 0xFFF0000000000FFF;
|
|
||||||
this->raw |= (_Address << 12);
|
|
||||||
}
|
|
||||||
|
|
||||||
__always_inline inline SafeFunction NIF uintptr_t GetAddress() { return (this->raw & 0x000FFFFFFFFFF000) >> 12; }
|
|
||||||
};
|
|
||||||
|
|
||||||
struct __attribute__((packed)) PageDirectoryPointerTableEntryPtr
|
|
||||||
{
|
|
||||||
PageDirectoryPointerTableEntry Entries[511];
|
|
||||||
};
|
|
||||||
|
|
||||||
union __attribute__((packed)) PageMapLevel4
|
|
||||||
{
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
bool Present : 1; // 0
|
|
||||||
bool ReadWrite : 1; // 1
|
|
||||||
bool UserSupervisor : 1; // 2
|
|
||||||
bool WriteThrough : 1; // 3
|
|
||||||
bool CacheDisable : 1; // 4
|
|
||||||
bool Accessed : 1; // 5
|
|
||||||
bool Available0 : 1; // 6
|
|
||||||
bool Reserved0 : 1; // 7
|
|
||||||
uint8_t Available1 : 4; // 8-11
|
|
||||||
uint64_t Address : 40; // 12-51
|
|
||||||
uint32_t Available2 : 11; // 52-62
|
|
||||||
bool ExecuteDisable : 1; // 63
|
|
||||||
};
|
|
||||||
uint64_t raw;
|
|
||||||
|
|
||||||
__always_inline inline SafeFunction NIF void SetAddress(uintptr_t _Address)
|
|
||||||
{
|
|
||||||
_Address &= 0x000000FFFFFFFFFF;
|
|
||||||
this->raw &= 0xFFF0000000000FFF;
|
|
||||||
this->raw |= (_Address << 12);
|
|
||||||
}
|
|
||||||
|
|
||||||
__always_inline inline SafeFunction NIF uintptr_t GetAddress() { return (this->raw & 0x000FFFFFFFFFF000) >> 12; }
|
|
||||||
};
|
|
||||||
|
|
||||||
struct PageTable4
|
|
||||||
{
|
|
||||||
PageMapLevel4 Entries[511];
|
|
||||||
} __attribute__((aligned(0x1000)));
|
|
||||||
|
|
||||||
extern "C" char BootPageTable[];
|
|
||||||
extern uintptr_t _kernel_start, _kernel_end;
|
|
||||||
|
|
||||||
__attribute__((section(".bootstrap.data"))) static PageTable4 *BPTable = (PageTable4 *)BootPageTable;
|
|
||||||
__attribute__((section(".bootstrap.data"))) static size_t BPT_Allocated = 0x4000;
|
|
||||||
|
|
||||||
__always_inline inline SafeFunction NIF void *RequestPage()
|
|
||||||
{
|
|
||||||
void *Page = (void *)(BootPageTable + BPT_Allocated);
|
|
||||||
BPT_Allocated += 0x1000;
|
|
||||||
if (BPT_Allocated >= 0x10000) /* The length of BootPageTable */
|
|
||||||
{
|
|
||||||
while (true)
|
|
||||||
;
|
|
||||||
}
|
|
||||||
return Page;
|
|
||||||
}
|
|
||||||
|
|
||||||
class PageMapIndexer
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
uintptr_t PMLIndex = 0;
|
|
||||||
uintptr_t PDPTEIndex = 0;
|
|
||||||
uintptr_t PDEIndex = 0;
|
|
||||||
uintptr_t PTEIndex = 0;
|
|
||||||
__always_inline inline SafeFunction NIF 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;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
__always_inline inline SafeFunction NIF void Map(void *VirtualAddress, void *PhysicalAddress, uint64_t Flags)
|
|
||||||
{
|
|
||||||
PageMapIndexer Index = PageMapIndexer((uintptr_t)VirtualAddress);
|
|
||||||
// Clear any flags that are not 1 << 0 (Present) - 1 << 5 (Accessed) because rest are for page table entries only
|
|
||||||
uint64_t DirectoryFlags = Flags & 0x3F;
|
|
||||||
|
|
||||||
PageMapLevel4 PML4 = BPTable->Entries[Index.PMLIndex];
|
|
||||||
PageDirectoryPointerTableEntryPtr *PDPTEPtr = nullptr;
|
|
||||||
if (!PML4.Present)
|
|
||||||
{
|
|
||||||
PDPTEPtr = (PageDirectoryPointerTableEntryPtr *)RequestPage();
|
|
||||||
{
|
|
||||||
void *ptr = PDPTEPtr;
|
|
||||||
int value = 0;
|
|
||||||
size_t num = 0x1000;
|
|
||||||
uint8_t *p = (uint8_t *)ptr;
|
|
||||||
for (size_t i = 0; i < num; i++)
|
|
||||||
p[i] = value;
|
|
||||||
}
|
|
||||||
PML4.Present = true;
|
|
||||||
PML4.SetAddress((uintptr_t)PDPTEPtr >> 12);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
PDPTEPtr = (PageDirectoryPointerTableEntryPtr *)((uintptr_t)PML4.GetAddress() << 12);
|
|
||||||
PML4.raw |= DirectoryFlags;
|
|
||||||
BPTable->Entries[Index.PMLIndex] = PML4;
|
|
||||||
|
|
||||||
PageDirectoryPointerTableEntry PDPTE = PDPTEPtr->Entries[Index.PDPTEIndex];
|
|
||||||
PageDirectoryEntryPtr *PDEPtr = nullptr;
|
|
||||||
if (!PDPTE.Present)
|
|
||||||
{
|
|
||||||
PDEPtr = (PageDirectoryEntryPtr *)RequestPage();
|
|
||||||
{
|
|
||||||
void *ptr = PDEPtr;
|
|
||||||
int value = 0;
|
|
||||||
size_t num = 0x1000;
|
|
||||||
uint8_t *p = (uint8_t *)ptr;
|
|
||||||
for (size_t i = 0; i < num; i++)
|
|
||||||
p[i] = value;
|
|
||||||
}
|
|
||||||
PDPTE.Present = true;
|
|
||||||
PDPTE.SetAddress((uintptr_t)PDEPtr >> 12);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
PDEPtr = (PageDirectoryEntryPtr *)((uintptr_t)PDPTE.GetAddress() << 12);
|
|
||||||
PDPTE.raw |= DirectoryFlags;
|
|
||||||
PDPTEPtr->Entries[Index.PDPTEIndex] = PDPTE;
|
|
||||||
|
|
||||||
PageDirectoryEntry PDE = PDEPtr->Entries[Index.PDEIndex];
|
|
||||||
PageTableEntryPtr *PTEPtr = nullptr;
|
|
||||||
if (!PDE.Present)
|
|
||||||
{
|
|
||||||
PTEPtr = (PageTableEntryPtr *)RequestPage();
|
|
||||||
{
|
|
||||||
void *ptr = PTEPtr;
|
|
||||||
int value = 0;
|
|
||||||
size_t num = 0x1000;
|
|
||||||
uint8_t *p = (uint8_t *)ptr;
|
|
||||||
for (size_t i = 0; i < num; i++)
|
|
||||||
p[i] = value;
|
|
||||||
}
|
|
||||||
PDE.Present = true;
|
|
||||||
PDE.SetAddress((uintptr_t)PTEPtr >> 12);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
PTEPtr = (PageTableEntryPtr *)((uintptr_t)PDE.GetAddress() << 12);
|
|
||||||
PDE.raw |= DirectoryFlags;
|
|
||||||
PDEPtr->Entries[Index.PDEIndex] = PDE;
|
|
||||||
|
|
||||||
PageTableEntry PTE = PTEPtr->Entries[Index.PTEIndex];
|
|
||||||
PTE.Present = true;
|
|
||||||
PTE.raw |= Flags;
|
|
||||||
PTE.SetAddress((uintptr_t)PhysicalAddress >> 12);
|
|
||||||
PTEPtr->Entries[Index.PTEIndex] = PTE;
|
|
||||||
asmv("invlpg (%0)"
|
|
||||||
:
|
|
||||||
: "r"(VirtualAddress)
|
|
||||||
: "memory");
|
|
||||||
}
|
|
||||||
|
|
||||||
EXTERNC __attribute__((section(".bootstrap.text"))) SafeFunction NIF __attribute__((section(".bootstrap.text"))) void UpdatePageTable64()
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
TODO: this code corrupts the page table
|
|
||||||
*/
|
|
||||||
|
|
||||||
BPTable = (PageTable4 *)BootPageTable;
|
|
||||||
|
|
||||||
// for (size_t i = 0; i < 0x10000000; i += 0x1000)
|
|
||||||
// Map((void *)i, (void *)i, 0x3);
|
|
||||||
|
|
||||||
uintptr_t KernelStart = (uintptr_t)&_kernel_start;
|
|
||||||
uintptr_t KernelEnd = (uintptr_t)&_kernel_end;
|
|
||||||
uintptr_t PhysicalStart = KernelStart - 0xFFFFFFFF80000000;
|
|
||||||
for (uintptr_t i = KernelStart; i < KernelEnd; i += 0x1000)
|
|
||||||
{
|
|
||||||
Map((void *)i, (void *)PhysicalStart, 0x3);
|
|
||||||
PhysicalStart += 0x1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
asmv("mov %%cr3, %%rax\n"
|
|
||||||
"mov %%rax, %%cr3\n"
|
|
||||||
:
|
|
||||||
:
|
|
||||||
: "rax");
|
|
||||||
}
|
|
@ -1,338 +0,0 @@
|
|||||||
#include <types.h>
|
|
||||||
|
|
||||||
#include <boot/protocols/multiboot2.h>
|
|
||||||
#include <memory.hpp>
|
|
||||||
#include <io.h>
|
|
||||||
|
|
||||||
#include "../../../../kernel.h"
|
|
||||||
|
|
||||||
enum VideoType
|
|
||||||
{
|
|
||||||
VIDEO_TYPE_NONE = 0x00,
|
|
||||||
VIDEO_TYPE_COLOUR = 0x20,
|
|
||||||
VIDEO_TYPE_MONOCHROME = 0x30,
|
|
||||||
};
|
|
||||||
|
|
||||||
uint16_t GetBiosAreaHardware()
|
|
||||||
{
|
|
||||||
const uint16_t *BIOSDataAreaDetectedHardware = (const uint16_t *)0x410;
|
|
||||||
return *BIOSDataAreaDetectedHardware;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum VideoType GetVideoType() { return (enum VideoType)(GetBiosAreaHardware() & 0x30); }
|
|
||||||
|
|
||||||
void GetSMBIOS()
|
|
||||||
{
|
|
||||||
unsigned char *SMBIOSAddress = (unsigned char *)0xF0000;
|
|
||||||
while ((unsigned int)(unsigned long)SMBIOSAddress < 0x100000)
|
|
||||||
{
|
|
||||||
if (SMBIOSAddress[0] == '_' &&
|
|
||||||
SMBIOSAddress[1] == 'S' &&
|
|
||||||
SMBIOSAddress[2] == 'M' &&
|
|
||||||
SMBIOSAddress[3] == '_')
|
|
||||||
{
|
|
||||||
unsigned char Checksum = 0;
|
|
||||||
int Length = SMBIOSAddress[5];
|
|
||||||
for (int i = 0; i < Length; i++)
|
|
||||||
Checksum += SMBIOSAddress[i];
|
|
||||||
|
|
||||||
if (Checksum == 0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
SMBIOSAddress += 16;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((unsigned int)(unsigned long)SMBIOSAddress == 0x100000)
|
|
||||||
{
|
|
||||||
// No SMBIOS found
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" unsigned int MB2_HeaderMagic;
|
|
||||||
extern "C" unsigned long MB2_HeaderInfo;
|
|
||||||
|
|
||||||
EXTERNC void Multiboot2Entry()
|
|
||||||
{
|
|
||||||
unsigned long Info = MB2_HeaderInfo;
|
|
||||||
unsigned int Magic = MB2_HeaderMagic;
|
|
||||||
if (Info == NULL || Magic == NULL)
|
|
||||||
{
|
|
||||||
if (Magic == NULL)
|
|
||||||
error("Multiboot magic is NULL");
|
|
||||||
if (Info == NULL)
|
|
||||||
error("Multiboot info is NULL");
|
|
||||||
CPU::Stop();
|
|
||||||
}
|
|
||||||
else if (Magic != MULTIBOOT2_BOOTLOADER_MAGIC)
|
|
||||||
{
|
|
||||||
error("Multiboot magic is invalid (%#x != %#x)", Magic, MULTIBOOT2_BOOTLOADER_MAGIC);
|
|
||||||
CPU::Stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t div = 1193180 / 1000;
|
|
||||||
outb(0x43, 0xB6);
|
|
||||||
outb(0x42, (uint8_t)div);
|
|
||||||
outb(0x42, (uint8_t)(div >> 8));
|
|
||||||
uint8_t tmp = inb(0x61);
|
|
||||||
if (tmp != (tmp | 3))
|
|
||||||
outb(0x61, tmp | 3);
|
|
||||||
|
|
||||||
BootInfo mb2binfo;
|
|
||||||
uint8_t *VideoBuffer = (uint8_t *)0xB8F00;
|
|
||||||
int pos = 0;
|
|
||||||
auto InfoAddress = Info;
|
|
||||||
for (auto Tag = (struct multiboot_tag *)((uint8_t *)InfoAddress + 8);
|
|
||||||
;
|
|
||||||
Tag = (struct multiboot_tag *)((multiboot_uint8_t *)Tag + ((Tag->size + 7) & ~7)))
|
|
||||||
{
|
|
||||||
VideoBuffer[pos++] = '.';
|
|
||||||
VideoBuffer[pos++] = 0x2;
|
|
||||||
|
|
||||||
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 = module->size;
|
|
||||||
strncpy(mb2binfo.Modules[module_count++].Path, "(null)", 6);
|
|
||||||
strncpy(mb2binfo.Modules[module_count++].CommandLine, module->cmdline,
|
|
||||||
strlen(module->cmdline));
|
|
||||||
debug("Module: %s", mb2binfo.Modules[module_count++].Path);
|
|
||||||
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;
|
|
||||||
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;
|
|
||||||
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;
|
|
||||||
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;
|
|
||||||
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;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
mb2binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr;
|
|
||||||
mb2binfo.Memory.Entry[i].Length = entry.len;
|
|
||||||
mb2binfo.Memory.Entry[i].Type = Unknown;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
debug("Memory entry: [BaseAddress: %#x, Length: %#x, Type: %d]",
|
|
||||||
mb2binfo.Memory.Entry[i].BaseAddress,
|
|
||||||
mb2binfo.Memory.Entry[i].Length,
|
|
||||||
mb2binfo.Memory.Entry[i].Type);
|
|
||||||
}
|
|
||||||
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;
|
|
||||||
mb2binfo.Framebuffer[fb_count].MemoryModel = fb->common.framebuffer_type;
|
|
||||||
switch (fb->common.framebuffer_type)
|
|
||||||
{
|
|
||||||
case MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED:
|
|
||||||
{
|
|
||||||
mb2binfo.Framebuffer[fb_count].Type = Indexed;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case MULTIBOOT_FRAMEBUFFER_TYPE_RGB:
|
|
||||||
{
|
|
||||||
mb2binfo.Framebuffer[fb_count].Type = 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 = EGA;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
debug("Framebuffer %d: %dx%d %d bpp", fb_count, 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->[sections=%#lx num=%d, size=%d, entsize=%d, shndx=%d]",
|
|
||||||
&elf->sections, 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 *)(uint64_t)load_base_addr->load_base_addr;
|
|
||||||
mb2binfo.Kernel.VirtualBase = (void *)(uint64_t)(load_base_addr->load_base_addr + 0xFFFFFFFF80000000);
|
|
||||||
debug("Kernel base: %p (physical) %p (virtual)", mb2binfo.Kernel.PhysicalBase, mb2binfo.Kernel.VirtualBase);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
error("Unknown multiboot2 tag type: %d", Tag->type);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tmp = inb(0x61) & 0xFC;
|
|
||||||
outb(0x61, tmp);
|
|
||||||
|
|
||||||
Entry(&mb2binfo);
|
|
||||||
}
|
|
@ -1,45 +0,0 @@
|
|||||||
PAGE_TABLE_SIZE equ 0x8 ; 2GB
|
|
||||||
[bits 32]
|
|
||||||
|
|
||||||
section .bootstrap.bss
|
|
||||||
align 0x1000
|
|
||||||
global BootPageTable
|
|
||||||
BootPageTable:
|
|
||||||
times (0x10000) dq 0 ; 0x4000
|
|
||||||
|
|
||||||
section .bootstrap.text
|
|
||||||
global UpdatePageTable
|
|
||||||
UpdatePageTable:
|
|
||||||
mov edi, (BootPageTable + 0x0000) ; First PML4E
|
|
||||||
mov eax, (BootPageTable + 0x1000) ; First PDPTE
|
|
||||||
or eax, 11b ; Bitwise OR on rax (PDPTE) with 11b (Present, Write)
|
|
||||||
mov dword [edi], eax ; Write 11b to PML4E
|
|
||||||
|
|
||||||
mov edi, (BootPageTable + 0x1000) ; First PDPTE
|
|
||||||
mov eax, (BootPageTable + 0x2000) ; First PDE
|
|
||||||
or eax, 11b ; Bitwise OR on rax (PDE) with 11b (Present, Write)
|
|
||||||
|
|
||||||
mov ecx, PAGE_TABLE_SIZE ; For loop instruction
|
|
||||||
mov ebx, 0x0 ; Value to store in the next 4 bytes
|
|
||||||
.FillPageTableLevel3:
|
|
||||||
mov dword [edi], eax ; Store modified PDE in PDPTE
|
|
||||||
mov dword [edi + 4], ebx ; Store the rbx value in the next 4 bytes
|
|
||||||
add eax, 0x1000 ; Increment (page size)
|
|
||||||
adc ebx, 0 ; Add 0 to carry flag
|
|
||||||
add edi, 8 ; Add 8 to rdi (next PDE)
|
|
||||||
loop .FillPageTableLevel3 ; Loop until rcx is 0
|
|
||||||
|
|
||||||
mov edi, (BootPageTable + 0x2000) ; First PDE
|
|
||||||
mov eax, 11b | 10000000b ; Present, Write, Large Page
|
|
||||||
|
|
||||||
mov ecx, (512 * PAGE_TABLE_SIZE) ; For loop instruction
|
|
||||||
mov ebx, 0x0 ; Value to store in the next 4 bytes
|
|
||||||
.FillPageTableLevel2:
|
|
||||||
mov dword [edi], eax ; Store modified PDE in PDPTE
|
|
||||||
mov dword [edi + 4], ebx ; Store the rbx value in the next 4 bytes
|
|
||||||
add eax, 1 << 21 ; Increment (page size)
|
|
||||||
adc ebx, 0 ; Add 0 (carry flag) to rbx to increment if there was a carry
|
|
||||||
add edi, 8 ; Add 8 to rdi (next PDE)
|
|
||||||
loop .FillPageTableLevel2 ; Loop until rcx is 0
|
|
||||||
|
|
||||||
ret
|
|
@ -6,7 +6,6 @@
|
|||||||
#include <io.h>
|
#include <io.h>
|
||||||
|
|
||||||
#include "cpu/apic.hpp"
|
#include "cpu/apic.hpp"
|
||||||
#include "../../kernel.h"
|
|
||||||
|
|
||||||
#define ACPI_TIMER 0x0001
|
#define ACPI_TIMER 0x0001
|
||||||
#define ACPI_BUSMASTER 0x0010
|
#define ACPI_BUSMASTER 0x0010
|
||||||
@ -61,7 +60,6 @@ namespace ACPI
|
|||||||
}
|
}
|
||||||
else if (Event & ACPI_POWER_BUTTON)
|
else if (Event & ACPI_POWER_BUTTON)
|
||||||
{
|
{
|
||||||
BeforeShutdown();
|
|
||||||
this->Shutdown();
|
this->Shutdown();
|
||||||
Time::Clock tm = Time::ReadClock();
|
Time::Clock tm = Time::ReadClock();
|
||||||
while (tm.Second == Time::ReadClock().Second)
|
while (tm.Second == Time::ReadClock().Second)
|
||||||
@ -138,7 +136,7 @@ namespace ACPI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DSDT::DSDT(ACPI *acpi) : Interrupts::Handler(acpi->FADT->SCI_Interrupt + CPU::x86::IRQ0)
|
DSDT::DSDT(ACPI *acpi) : Interrupts::Handler(acpi->FADT->SCI_Interrupt + CPU::x64::IRQ0)
|
||||||
{
|
{
|
||||||
this->acpi = acpi;
|
this->acpi = acpi;
|
||||||
uint64_t Address = ((IsCanonical(acpi->FADT->X_Dsdt) && acpi->XSDTSupported) ? acpi->FADT->X_Dsdt : acpi->FADT->Dsdt);
|
uint64_t Address = ((IsCanonical(acpi->FADT->X_Dsdt) && acpi->XSDTSupported) ? acpi->FADT->X_Dsdt : acpi->FADT->Dsdt);
|
||||||
|
@ -3,8 +3,8 @@
|
|||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
#include <convert.h>
|
#include <convert.h>
|
||||||
|
|
||||||
#include "../../../../tools/limine/limine.h"
|
#include "../../../tools/limine/limine.h"
|
||||||
#include "../../../kernel.h"
|
#include "../../kernel.h"
|
||||||
|
|
||||||
void init_limine();
|
void init_limine();
|
||||||
|
|
||||||
@ -42,7 +42,7 @@ static volatile struct limine_smbios_request SmbiosRequest = {
|
|||||||
.id = LIMINE_SMBIOS_REQUEST,
|
.id = LIMINE_SMBIOS_REQUEST,
|
||||||
.revision = 0};
|
.revision = 0};
|
||||||
|
|
||||||
SafeFunction NIF void init_limine()
|
SafeFunction __no_instrument_function void init_limine()
|
||||||
{
|
{
|
||||||
struct BootInfo binfo;
|
struct BootInfo binfo;
|
||||||
struct limine_bootloader_info_response *BootloaderInfoResponse = BootloaderInfoRequest.response;
|
struct limine_bootloader_info_response *BootloaderInfoResponse = BootloaderInfoRequest.response;
|
@ -4,7 +4,7 @@
|
|||||||
#include <types.h>
|
#include <types.h>
|
||||||
|
|
||||||
#include <boot/binfo.h>
|
#include <boot/binfo.h>
|
||||||
#include <ints.hpp>
|
#include <interrupts.hpp>
|
||||||
#include <vector.hpp>
|
#include <vector.hpp>
|
||||||
#include <cpu.hpp>
|
#include <cpu.hpp>
|
||||||
|
|
||||||
|
@ -13,7 +13,6 @@
|
|||||||
NewLock(APICLock);
|
NewLock(APICLock);
|
||||||
|
|
||||||
using namespace CPU::x64;
|
using namespace CPU::x64;
|
||||||
using namespace CPU::x86;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
In constructor ‘APIC::APIC::APIC(int)’:
|
In constructor ‘APIC::APIC::APIC(int)’:
|
||||||
@ -238,42 +237,13 @@ namespace APIC
|
|||||||
this->APICBaseAddress = BaseLow << 12u | BaseHigh << 32u;
|
this->APICBaseAddress = BaseLow << 12u | BaseHigh << 32u;
|
||||||
trace("APIC Address: %#lx", this->APICBaseAddress);
|
trace("APIC Address: %#lx", this->APICBaseAddress);
|
||||||
|
|
||||||
bool x2APICSupported = false;
|
uint32_t rcx;
|
||||||
if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_AMD) == 0)
|
cpuid(1, 0, 0, &rcx, 0);
|
||||||
|
if (rcx & CPUID_FEAT_RCX_x2APIC)
|
||||||
{
|
{
|
||||||
#if defined(a64)
|
// this->x2APICSupported = true;
|
||||||
CPU::x64::AMD::CPUID0x1 cpuid1amd;
|
warn("x2APIC not supported yet.");
|
||||||
#elif defined(a32)
|
// wrmsr(MSR_APIC_BASE, (rdmsr(MSR_APIC_BASE) | (1 << 11)) & ~(1 << 10));
|
||||||
CPU::x32::AMD::CPUID0x1 cpuid1amd;
|
|
||||||
#endif
|
|
||||||
#if defined(a64) || defined(a32)
|
|
||||||
asmv("cpuid"
|
|
||||||
: "=a"(cpuid1amd.EAX.raw), "=b"(cpuid1amd.EBX.raw), "=c"(cpuid1amd.ECX.raw), "=d"(cpuid1amd.EDX.raw)
|
|
||||||
: "a"(0x1));
|
|
||||||
#endif
|
|
||||||
// FIXME: Not sure if I configured this correctly or something else is wrong
|
|
||||||
// x2APICSupported = cpuid1amd.ECX.x2APIC;
|
|
||||||
fixme("AMD does even support x2APIC? ECX->Reserved10: %#lx", cpuid1amd.ECX.Reserved10);
|
|
||||||
}
|
|
||||||
else if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_INTEL) == 0)
|
|
||||||
{
|
|
||||||
#if defined(a64)
|
|
||||||
CPU::x64::Intel::CPUID0x1 cpuid1intel;
|
|
||||||
#elif defined(a32)
|
|
||||||
CPU::x32::Intel::CPUID0x1 cpuid1intel;
|
|
||||||
#endif
|
|
||||||
#if defined(a64) || defined(a32)
|
|
||||||
asmv("cpuid"
|
|
||||||
: "=a"(cpuid1intel.EAX.raw), "=b"(cpuid1intel.EBX.raw), "=c"(cpuid1intel.ECX.raw), "=d"(cpuid1intel.EDX.raw)
|
|
||||||
: "a"(0x1));
|
|
||||||
#endif
|
|
||||||
x2APICSupported = cpuid1intel.ECX.x2APIC;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (x2APICSupported)
|
|
||||||
{
|
|
||||||
this->x2APICSupported = true;
|
|
||||||
wrmsr(MSR_APIC_BASE, (rdmsr(MSR_APIC_BASE) | (1 << 11)) & ~(1 << 10));
|
|
||||||
BaseStruct.EN = 1;
|
BaseStruct.EN = 1;
|
||||||
wrmsr(MSR_APIC_BASE, BaseStruct.raw);
|
wrmsr(MSR_APIC_BASE, BaseStruct.raw);
|
||||||
}
|
}
|
||||||
@ -331,7 +301,7 @@ namespace APIC
|
|||||||
|
|
||||||
APIC::~APIC() {}
|
APIC::~APIC() {}
|
||||||
|
|
||||||
void Timer::OnInterruptReceived(TrapFrame *Frame) { UNUSED(Frame); }
|
void Timer::OnInterruptReceived(TrapFrame *Frame) {}
|
||||||
|
|
||||||
void Timer::OneShot(uint32_t Vector, uint64_t Miliseconds)
|
void Timer::OneShot(uint32_t Vector, uint64_t Miliseconds)
|
||||||
{
|
{
|
||||||
@ -358,7 +328,7 @@ namespace APIC
|
|||||||
this->lapic->Write(APIC_TDCR, Divider);
|
this->lapic->Write(APIC_TDCR, Divider);
|
||||||
this->lapic->Write(APIC_TICR, 0xFFFFFFFF);
|
this->lapic->Write(APIC_TICR, 0xFFFFFFFF);
|
||||||
|
|
||||||
TimeManager->Sleep(1);
|
TimeManager->Sleep(10);
|
||||||
|
|
||||||
// Mask the timer
|
// Mask the timer
|
||||||
this->lapic->Write(APIC_TIMER, 0x10000 /* LVTTimer.Mask flag */);
|
this->lapic->Write(APIC_TIMER, 0x10000 /* LVTTimer.Mask flag */);
|
||||||
|
@ -75,7 +75,7 @@ namespace GlobalDescriptorTable
|
|||||||
// tss
|
// tss
|
||||||
{}};
|
{}};
|
||||||
|
|
||||||
GlobalDescriptorTableEntries GDTEntries[MAX_CPU];
|
static GlobalDescriptorTableEntries GDTEntries[MAX_CPU];
|
||||||
GlobalDescriptorTableDescriptor gdt[MAX_CPU];
|
GlobalDescriptorTableDescriptor gdt[MAX_CPU];
|
||||||
|
|
||||||
TaskStateSegment tss[MAX_CPU] = {
|
TaskStateSegment tss[MAX_CPU] = {
|
||||||
@ -85,7 +85,6 @@ namespace GlobalDescriptorTable
|
|||||||
{0, 0, 0, 0, 0, 0, 0},
|
{0, 0, 0, 0, 0, 0, 0},
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
0,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void *CPUStackPointer[MAX_CPU];
|
void *CPUStackPointer[MAX_CPU];
|
||||||
@ -115,8 +114,6 @@ namespace GlobalDescriptorTable
|
|||||||
: "memory", "rax");
|
: "memory", "rax");
|
||||||
|
|
||||||
CPUStackPointer[Core] = KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE));
|
CPUStackPointer[Core] = KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE));
|
||||||
memset(CPUStackPointer[Core], 0, STACK_SIZE);
|
|
||||||
debug("CPU %d Stack Pointer: %#lx", Core, CPUStackPointer[Core]);
|
|
||||||
|
|
||||||
uint64_t Base = (uint64_t)&tss[Core];
|
uint64_t Base = (uint64_t)&tss[Core];
|
||||||
uint64_t Limit = Base + sizeof(TaskStateSegment);
|
uint64_t Limit = Base + sizeof(TaskStateSegment);
|
||||||
@ -133,32 +130,24 @@ namespace GlobalDescriptorTable
|
|||||||
tss[Core].InterruptStackTable[0] = (uint64_t)KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE)) + STACK_SIZE;
|
tss[Core].InterruptStackTable[0] = (uint64_t)KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE)) + STACK_SIZE;
|
||||||
tss[Core].InterruptStackTable[1] = (uint64_t)KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE)) + STACK_SIZE;
|
tss[Core].InterruptStackTable[1] = (uint64_t)KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE)) + STACK_SIZE;
|
||||||
tss[Core].InterruptStackTable[2] = (uint64_t)KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE)) + STACK_SIZE;
|
tss[Core].InterruptStackTable[2] = (uint64_t)KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE)) + STACK_SIZE;
|
||||||
memset((void *)(tss[Core].InterruptStackTable[0] - STACK_SIZE), 0, STACK_SIZE);
|
|
||||||
memset((void *)(tss[Core].InterruptStackTable[1] - STACK_SIZE), 0, STACK_SIZE);
|
|
||||||
memset((void *)(tss[Core].InterruptStackTable[2] - STACK_SIZE), 0, STACK_SIZE);
|
|
||||||
|
|
||||||
CPU::x64::ltr(GDT_TSS);
|
CPU::x64::ltr(GDT_TSS);
|
||||||
asmv("mov %%rsp, %0"
|
asmv("mov %%rsp, %0"
|
||||||
: "=r"(tss[Core].StackPointer[0]));
|
: "=r"(tss[Core].StackPointer[0]));
|
||||||
|
|
||||||
debug("GDT_KERNEL_CODE: %#lx", GDT_KERNEL_CODE);
|
trace("GDT_KERNEL_CODE: %#lx", GDT_KERNEL_CODE);
|
||||||
debug("GDT_KERNEL_DATA: %#lx", GDT_KERNEL_DATA);
|
trace("GDT_KERNEL_DATA: %#lx", GDT_KERNEL_DATA);
|
||||||
debug("GDT_USER_CODE: %#lx", GDT_USER_CODE);
|
trace("GDT_USER_CODE: %#lx", GDT_USER_CODE);
|
||||||
debug("GDT_USER_DATA: %#lx", GDT_USER_DATA);
|
trace("GDT_USER_DATA: %#lx", GDT_USER_DATA);
|
||||||
debug("GDT_TSS: %#lx", GDT_TSS);
|
trace("GDT_TSS: %#lx", GDT_TSS);
|
||||||
debug("Global Descriptor Table initialized");
|
trace("Global Descriptor Table initialized");
|
||||||
}
|
}
|
||||||
|
|
||||||
SafeFunction void SetKernelStack(void *Stack)
|
SafeFunction void SetKernelStack(void *Stack)
|
||||||
{
|
{
|
||||||
long CPUID = GetCurrentCPU()->ID;
|
if (Stack)
|
||||||
if (Stack != nullptr)
|
tss[GetCurrentCPU()->ID].StackPointer[0] = (uint64_t)Stack;
|
||||||
tss[CPUID].StackPointer[0] = (uint64_t)Stack;
|
|
||||||
else
|
else
|
||||||
tss[CPUID].StackPointer[0] = (uint64_t)CPUStackPointer[CPUID] + STACK_SIZE;
|
tss[GetCurrentCPU()->ID].StackPointer[0] = (uint64_t)CPUStackPointer[GetCurrentCPU()->ID] + STACK_SIZE;
|
||||||
|
|
||||||
// TODO: This may cause problems in the future I guess? This should be checked later
|
|
||||||
asmv("mov %%rsp, %0"
|
|
||||||
: "=r"(tss[CPUID].StackPointer[0]));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
#include "idt.hpp"
|
#include "idt.hpp"
|
||||||
|
|
||||||
#include <memory.hpp>
|
|
||||||
#include <cpu.hpp>
|
#include <cpu.hpp>
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
#include <io.h>
|
#include <io.h>
|
||||||
@ -94,27 +93,13 @@ namespace InterruptDescriptorTable
|
|||||||
// "swapgs\n"
|
// "swapgs\n"
|
||||||
// ".skip_swap_check_2:\n"
|
// ".skip_swap_check_2:\n"
|
||||||
|
|
||||||
"iretq"); // pop CS RIP RFLAGS SS RSP
|
"iretq"); // pop CS RIP RFLAGS SS ESP
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void WarnSwapgs() { warn("swapgs"); }
|
extern "C" void WarnSwapgs() { warn("swapgs"); }
|
||||||
|
|
||||||
// void *OriginalCR3;
|
|
||||||
extern "C" __attribute__((naked, used, no_stack_protector)) void InterruptHandlerStub()
|
extern "C" __attribute__((naked, used, no_stack_protector)) void InterruptHandlerStub()
|
||||||
{
|
{
|
||||||
// // Store cr3 to OriginalCR3
|
|
||||||
// asmv("mov %%cr3, %0"
|
|
||||||
// : "=q"(OriginalCR3)
|
|
||||||
// :
|
|
||||||
// : "memory");
|
|
||||||
// // Set cr3 to KPT (Kernel Page Table)
|
|
||||||
// asmv("mov %0, %%cr3"
|
|
||||||
// :
|
|
||||||
// : "q"(KPT)
|
|
||||||
// : "memory");
|
|
||||||
|
|
||||||
// GlobalDescriptorTable::SetKernelStack(nullptr);
|
|
||||||
|
|
||||||
asm(
|
asm(
|
||||||
// "cmp $0x1000, %rsp\n"
|
// "cmp $0x1000, %rsp\n"
|
||||||
// "jng .skip_swap_check__1\n"
|
// "jng .skip_swap_check__1\n"
|
||||||
@ -142,28 +127,9 @@ namespace InterruptDescriptorTable
|
|||||||
"pushq %r15\n"
|
"pushq %r15\n"
|
||||||
|
|
||||||
"movq %rsp, %rdi\n"
|
"movq %rsp, %rdi\n"
|
||||||
"call MainInterruptHandler\n");
|
"call MainInterruptHandler\n"
|
||||||
|
|
||||||
// // Check if the current cr3 is the same as the KPT
|
"popq %r15\n"
|
||||||
// // If not, then we need to restore the cr3
|
|
||||||
// asmv("pushq %rax\n" // push rax
|
|
||||||
// "pushq %rbx\n" // push rbx
|
|
||||||
// "movq %cr3, %rbx\n"); // mov cr3 to rbx
|
|
||||||
// asmv("movq %0, %%rax\n" // mov KPT to rax
|
|
||||||
// :
|
|
||||||
// : "q"(KPT)
|
|
||||||
// : "memory");
|
|
||||||
// asmv("cmpq %rax, %rbx\n" // compare cr3 to rax
|
|
||||||
// "jne .skip_restore_cr3\n"); // if not equal, skip restore cr3
|
|
||||||
// asmv("movq %0, %%cr3\n" // restore cr3
|
|
||||||
// :
|
|
||||||
// : "q"(OriginalCR3)
|
|
||||||
// : "memory");
|
|
||||||
// asm(".skip_restore_cr3:\n" // skip restore cr3 label
|
|
||||||
// "popq %rax\n" // KPT
|
|
||||||
// "popq %rbx\n"); // cr3
|
|
||||||
|
|
||||||
asm("popq %r15\n"
|
|
||||||
"popq %r14\n"
|
"popq %r14\n"
|
||||||
"popq %r13\n"
|
"popq %r13\n"
|
||||||
"popq %r12\n"
|
"popq %r12\n"
|
||||||
@ -487,7 +453,6 @@ namespace InterruptDescriptorTable
|
|||||||
|
|
||||||
void Init(int Core)
|
void Init(int Core)
|
||||||
{
|
{
|
||||||
UNUSED(Core);
|
|
||||||
static int once = 0;
|
static int once = 0;
|
||||||
if (!once++)
|
if (!once++)
|
||||||
{
|
{
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#include <smp.hpp>
|
#include <smp.hpp>
|
||||||
|
|
||||||
#include <ints.hpp>
|
#include <interrupts.hpp>
|
||||||
#include <memory.hpp>
|
#include <memory.hpp>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <cpu.hpp>
|
#include <cpu.hpp>
|
||||||
@ -27,30 +27,34 @@ volatile bool CPUEnabled = false;
|
|||||||
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
|
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
|
||||||
static __attribute__((aligned(PAGE_SIZE))) CPUData CPUs[MAX_CPU] = {0};
|
static __attribute__((aligned(PAGE_SIZE))) CPUData CPUs[MAX_CPU] = {0};
|
||||||
|
|
||||||
SafeFunction CPUData *GetCPU(long id) { return &CPUs[id]; }
|
CPUData *GetCPU(long id) { return &CPUs[id]; }
|
||||||
|
CPUData *GetCurrentCPU()
|
||||||
SafeFunction CPUData *GetCurrentCPU()
|
|
||||||
{
|
{
|
||||||
if (unlikely(!Interrupts::apic[0]))
|
CPUData *data = (CPUData *)CPU::x64::rdmsr(CPU::x64::MSR_GS_BASE);
|
||||||
return &CPUs[0]; /* No APIC means we are on the BSP. */
|
|
||||||
int CoreID = ((APIC::APIC *)Interrupts::apic[0])->Read(APIC::APIC_ID) >> 24;
|
|
||||||
|
|
||||||
if (unlikely((&CPUs[CoreID])->IsActive != true))
|
if (data == nullptr && Interrupts::apic[0])
|
||||||
|
data = &CPUs[((APIC::APIC *)Interrupts::apic[0])->Read(APIC::APIC_ID) >> 24];
|
||||||
|
|
||||||
|
if (data == nullptr)
|
||||||
|
return nullptr; // The caller should handle this.
|
||||||
|
|
||||||
|
if (!data->IsActive)
|
||||||
{
|
{
|
||||||
error("CPU %d is not active!", CoreID);
|
error("CPU %d is not active!", data->ID);
|
||||||
assert((&CPUs[0])->IsActive == true); /* We can't continue without the BSP. */
|
if ((&CPUs[0])->IsActive)
|
||||||
return &CPUs[0];
|
return &CPUs[0];
|
||||||
|
else
|
||||||
|
return nullptr; // We are in trouble.
|
||||||
}
|
}
|
||||||
|
assert(data->Checksum == CPU_DATA_CHECKSUM); // This should never happen.
|
||||||
assert((&CPUs[CoreID])->Checksum == CPU_DATA_CHECKSUM); /* This should never happen. */
|
return data;
|
||||||
return &CPUs[CoreID];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void StartCPU()
|
extern "C" void StartCPU()
|
||||||
{
|
{
|
||||||
CPU::Interrupts(CPU::Disable);
|
CPU::Interrupts(CPU::Disable);
|
||||||
|
CPU::InitializeFeatures();
|
||||||
uint64_t CoreID = (int)*reinterpret_cast<int *>(CORE);
|
uint64_t CoreID = (int)*reinterpret_cast<int *>(CORE);
|
||||||
CPU::InitializeFeatures(CoreID);
|
|
||||||
// Initialize GDT and IDT
|
// Initialize GDT and IDT
|
||||||
Interrupts::Initialize(CoreID);
|
Interrupts::Initialize(CoreID);
|
||||||
Interrupts::Enable(CoreID);
|
Interrupts::Enable(CoreID);
|
||||||
@ -68,6 +72,12 @@ namespace SMP
|
|||||||
|
|
||||||
void Initialize(void *madt)
|
void Initialize(void *madt)
|
||||||
{
|
{
|
||||||
|
if (strcmp(CPU::Hypervisor(), x86_CPUID_VENDOR_VIRTUALBOX) == 0)
|
||||||
|
{
|
||||||
|
KPrint("VirtualBox detected, disabling SMP");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
int Cores = ((ACPI::MADT *)madt)->CPUCores + 1;
|
int Cores = ((ACPI::MADT *)madt)->CPUCores + 1;
|
||||||
|
|
||||||
if (Config.Cores > ((ACPI::MADT *)madt)->CPUCores + 1)
|
if (Config.Cores > ((ACPI::MADT *)madt)->CPUCores + 1)
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
#include <types.h>
|
#include <types.h>
|
||||||
|
|
||||||
#include <ints.hpp>
|
#include <interrupts.hpp>
|
||||||
#include <cpu.hpp>
|
#include <cpu.hpp>
|
||||||
|
|
||||||
namespace APIC
|
namespace APIC
|
||||||
|
11
Kernel/Architecture/amd64/cpu/fxsr.asm
Normal file
11
Kernel/Architecture/amd64/cpu/fxsr.asm
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
[bits 64]
|
||||||
|
|
||||||
|
[global _amd64_fxsave]
|
||||||
|
_amd64_fxsave:
|
||||||
|
fxsave [rdi]
|
||||||
|
ret
|
||||||
|
|
||||||
|
[global _amd64_fxrstor]
|
||||||
|
_amd64_fxrstor:
|
||||||
|
fxrstor [rdi]
|
||||||
|
ret
|
@ -92,8 +92,7 @@ namespace GlobalDescriptorTable
|
|||||||
uint64_t StackPointer[3];
|
uint64_t StackPointer[3];
|
||||||
uint64_t Reserved1;
|
uint64_t Reserved1;
|
||||||
uint64_t InterruptStackTable[7];
|
uint64_t InterruptStackTable[7];
|
||||||
uint64_t Reserved2;
|
uint16_t Reserved2;
|
||||||
uint16_t Reserved3;
|
|
||||||
uint16_t IOMapBaseAddressOffset;
|
uint16_t IOMapBaseAddressOffset;
|
||||||
} __attribute__((packed)) TaskStateSegment;
|
} __attribute__((packed)) TaskStateSegment;
|
||||||
|
|
||||||
@ -132,7 +131,6 @@ namespace GlobalDescriptorTable
|
|||||||
} __attribute__((packed)) GlobalDescriptorTableDescriptor;
|
} __attribute__((packed)) GlobalDescriptorTableDescriptor;
|
||||||
|
|
||||||
extern void *CPUStackPointer[];
|
extern void *CPUStackPointer[];
|
||||||
extern TaskStateSegment tss[];
|
|
||||||
void Init(int Core);
|
void Init(int Core);
|
||||||
void SetKernelStack(void *Stack);
|
void SetKernelStack(void *Stack);
|
||||||
}
|
}
|
||||||
|
@ -1,53 +1,35 @@
|
|||||||
OUTPUT_FORMAT(elf64-x86-64)
|
OUTPUT_FORMAT(elf64-x86-64)
|
||||||
OUTPUT_ARCH(i386:x86-64)
|
OUTPUT_ARCH(i386:x86-64)
|
||||||
|
|
||||||
KERNEL_LMA = 16M;
|
|
||||||
KERNEL_VMA = 0xFFFFFFFF80000000;
|
|
||||||
|
|
||||||
ENTRY(_start)
|
ENTRY(_start)
|
||||||
|
|
||||||
SECTIONS
|
SECTIONS
|
||||||
{
|
{
|
||||||
. = KERNEL_LMA;
|
. = 0xffffffff80000000;
|
||||||
|
|
||||||
.multiboot2 :
|
|
||||||
{
|
|
||||||
*(.multiboot2 .multiboot2.*)
|
|
||||||
}
|
|
||||||
|
|
||||||
.bootstrap :
|
|
||||||
{
|
|
||||||
*(.bootstrap.text .bootstrap.text.*)
|
|
||||||
*(.bootstrap.data .bootstrap.data.*)
|
|
||||||
*(.bootstrap.rodata .bootstrap.rodata.*)
|
|
||||||
*(.bootstrap.bss .bootstrap.bss.*)
|
|
||||||
}
|
|
||||||
|
|
||||||
. += KERNEL_VMA;
|
|
||||||
|
|
||||||
_kernel_start = .;
|
_kernel_start = .;
|
||||||
.text : AT(ADDR(.text) - KERNEL_VMA)
|
.text :
|
||||||
{
|
{
|
||||||
*(.text .text.*)
|
*(.text .text.*)
|
||||||
}
|
}
|
||||||
_kernel_text_end = ALIGN(CONSTANT(MAXPAGESIZE));
|
_kernel_text_end = ALIGN(CONSTANT(MAXPAGESIZE));
|
||||||
. += CONSTANT(MAXPAGESIZE);
|
. += CONSTANT(MAXPAGESIZE);
|
||||||
|
|
||||||
.data : AT(ADDR(.data) - KERNEL_VMA)
|
.data :
|
||||||
{
|
{
|
||||||
*(.data .data.*)
|
*(.data .data.*)
|
||||||
}
|
}
|
||||||
_kernel_data_end = ALIGN(CONSTANT(MAXPAGESIZE));
|
_kernel_data_end = ALIGN(CONSTANT(MAXPAGESIZE));
|
||||||
. += CONSTANT(MAXPAGESIZE);
|
. += CONSTANT(MAXPAGESIZE);
|
||||||
|
|
||||||
.rodata : AT(ADDR(.rodata) - KERNEL_VMA)
|
.rodata :
|
||||||
{
|
{
|
||||||
*(.rodata .rodata.*)
|
*(.rodata .rodata.*)
|
||||||
}
|
}
|
||||||
_kernel_rodata_end = ALIGN(CONSTANT(MAXPAGESIZE));
|
_kernel_rodata_end = ALIGN(CONSTANT(MAXPAGESIZE));
|
||||||
. += CONSTANT(MAXPAGESIZE);
|
. += CONSTANT(MAXPAGESIZE);
|
||||||
|
|
||||||
.init_array : AT(ADDR(.init_array) - KERNEL_VMA)
|
.init_array :
|
||||||
{
|
{
|
||||||
PROVIDE_HIDDEN(__init_array_start = .);
|
PROVIDE_HIDDEN(__init_array_start = .);
|
||||||
KEEP(*(.init_array .ctors))
|
KEEP(*(.init_array .ctors))
|
||||||
@ -55,7 +37,7 @@ SECTIONS
|
|||||||
PROVIDE_HIDDEN (__init_array_end = .);
|
PROVIDE_HIDDEN (__init_array_end = .);
|
||||||
}
|
}
|
||||||
|
|
||||||
.fini_array : AT(ADDR(.fini_array) - KERNEL_VMA)
|
.fini_array :
|
||||||
{
|
{
|
||||||
PROVIDE_HIDDEN(__fini_array_start = .);
|
PROVIDE_HIDDEN(__fini_array_start = .);
|
||||||
KEEP(*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
|
KEEP(*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
|
||||||
@ -64,7 +46,8 @@ SECTIONS
|
|||||||
}
|
}
|
||||||
. += CONSTANT(MAXPAGESIZE);
|
. += CONSTANT(MAXPAGESIZE);
|
||||||
|
|
||||||
.bss : AT(ADDR(.bss) - KERNEL_VMA)
|
|
||||||
|
.bss :
|
||||||
{
|
{
|
||||||
*(COMMON)
|
*(COMMON)
|
||||||
*(.bss .bss.*)
|
*(.bss .bss.*)
|
||||||
|
@ -6,10 +6,10 @@ int Entry(void *Info);
|
|||||||
|
|
||||||
void _start(void *Raw)
|
void _start(void *Raw)
|
||||||
{
|
{
|
||||||
UNUSED(Raw);
|
|
||||||
error("ERROR! INVALID BOOT PROTOCOL!");
|
error("ERROR! INVALID BOOT PROTOCOL!");
|
||||||
while (1)
|
while (1)
|
||||||
asmv("hlt");
|
asmv("hlt");
|
||||||
Entry(NULL);
|
Entry(NULL);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// C stuff
|
@ -158,7 +158,7 @@ int __ctzdi2(arith64_u64 a)
|
|||||||
|
|
||||||
arith64_u64 __divmoddi4(arith64_u64 a, arith64_u64 b, arith64_u64 *c)
|
arith64_u64 __divmoddi4(arith64_u64 a, arith64_u64 b, arith64_u64 *c)
|
||||||
{
|
{
|
||||||
if (b > a)
|
if (b > a) //
|
||||||
{
|
{
|
||||||
if (c)
|
if (c)
|
||||||
*c = a;
|
*c = a;
|
||||||
@ -283,45 +283,3 @@ int __gedf2(double a, double b) { return a >= b; }
|
|||||||
int __fixdfsi(double a) { return (int)a; }
|
int __fixdfsi(double a) { return (int)a; }
|
||||||
long __fixdfdi(double a) { return (long)a; }
|
long __fixdfdi(double a) { return (long)a; }
|
||||||
int __ledf2(double a, double b) { return a <= b; }
|
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,54 +0,0 @@
|
|||||||
; https://wiki.osdev.org/Higher_Half_x86_Bare_Bones
|
|
||||||
; https://wiki.osdev.org/Higher_Half_x86_Bare_Bones_(Backup)
|
|
||||||
|
|
||||||
KERNEL_VIRTUAL_BASE equ 0xC0000000 ; 3GB
|
|
||||||
KERNEL_STACK_SIZE equ 0x4000 ; 16KB
|
|
||||||
|
|
||||||
extern Multiboot2Entry
|
|
||||||
extern BootPageTable
|
|
||||||
global MB2_start
|
|
||||||
|
|
||||||
section .text
|
|
||||||
MB2_start:
|
|
||||||
cli
|
|
||||||
mov word [0xb8F00], 0x072E ; .
|
|
||||||
|
|
||||||
mov ecx, (BootPageTable - KERNEL_VIRTUAL_BASE)
|
|
||||||
mov cr3, ecx
|
|
||||||
|
|
||||||
mov word [0xb8F02], 0x072E ; .
|
|
||||||
|
|
||||||
mov ecx, cr4
|
|
||||||
or ecx, 0x00000010 ; Set PSE in CR4
|
|
||||||
mov cr4, ecx
|
|
||||||
|
|
||||||
mov word [0xb8F04], 0x072E ; .
|
|
||||||
|
|
||||||
mov ecx, cr0
|
|
||||||
or ecx, 0x80000000 ; Set PG in CR0
|
|
||||||
mov cr0, ecx
|
|
||||||
|
|
||||||
mov word [0xb8F06], 0x072E ; .
|
|
||||||
|
|
||||||
lea ecx, [HigherHalfStart]
|
|
||||||
jmp ecx
|
|
||||||
|
|
||||||
HigherHalfStart:
|
|
||||||
mov word [0xb8F08], 0x072E ; .
|
|
||||||
mov dword [BootPageTable], 0
|
|
||||||
invlpg [0]
|
|
||||||
|
|
||||||
mov esp, KernelStack + KERNEL_STACK_SIZE
|
|
||||||
|
|
||||||
push eax ; Multiboot2 Magic
|
|
||||||
add ebx, KERNEL_VIRTUAL_BASE
|
|
||||||
push ebx ; Multiboot2 Header
|
|
||||||
call Multiboot2Entry
|
|
||||||
Loop:
|
|
||||||
hlt
|
|
||||||
jmp Loop
|
|
||||||
|
|
||||||
section .bss
|
|
||||||
align 16
|
|
||||||
KernelStack:
|
|
||||||
resb KERNEL_STACK_SIZE
|
|
@ -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,13 +0,0 @@
|
|||||||
KERNEL_VIRTUAL_BASE equ 0xC0000000 ; 3GB
|
|
||||||
KERNEL_PAGE_NUMBER equ (KERNEL_VIRTUAL_BASE >> 22) ; 768
|
|
||||||
|
|
||||||
section .data
|
|
||||||
global BootPageTable
|
|
||||||
align 0x1000
|
|
||||||
BootPageTable:
|
|
||||||
dd 0x00000083
|
|
||||||
dd 0x00000083
|
|
||||||
times (KERNEL_PAGE_NUMBER - 2) dd 0
|
|
||||||
dd 0x00000083
|
|
||||||
dd 0x00000083
|
|
||||||
times (1024 - KERNEL_PAGE_NUMBER - 2) dd 0
|
|
@ -1,12 +1,9 @@
|
|||||||
#include <types.h>
|
#include <types.h>
|
||||||
|
|
||||||
#include <boot/protocols/multiboot2.h>
|
#include <boot/protocols/multiboot2.h>
|
||||||
#include <memory.hpp>
|
|
||||||
#include <io.h>
|
#include <io.h>
|
||||||
|
|
||||||
#include "../../../kernel.h"
|
#include "../../kernel.h"
|
||||||
|
|
||||||
BootInfo mb2binfo;
|
|
||||||
|
|
||||||
enum VideoType
|
enum VideoType
|
||||||
{
|
{
|
||||||
@ -50,52 +47,72 @@ void GetSMBIOS()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProcessMB2(unsigned long Info)
|
struct multiboot_info
|
||||||
{
|
{
|
||||||
uint8_t *VideoBuffer = (uint8_t *)0xB8F00 + 0xC0000000;
|
multiboot_uint32_t Size;
|
||||||
int pos = 0;
|
multiboot_uint32_t Reserved;
|
||||||
auto InfoAddress = Info;
|
struct multiboot_tag *Tag;
|
||||||
for (auto Tag = (struct multiboot_tag *)((uint8_t *)InfoAddress + 8);
|
};
|
||||||
;
|
|
||||||
Tag = (struct multiboot_tag *)((multiboot_uint8_t *)Tag + ((Tag->size + 7) & ~7)))
|
|
||||||
{
|
|
||||||
VideoBuffer[pos++] = '.';
|
|
||||||
VideoBuffer[pos++] = 0x2;
|
|
||||||
|
|
||||||
if (Tag->type == MULTIBOOT_TAG_TYPE_END)
|
EXTERNC void x32Multiboot2Entry(multiboot_info *Info, unsigned int Magic)
|
||||||
|
{
|
||||||
|
if (Info == NULL || Magic == NULL)
|
||||||
{
|
{
|
||||||
debug("End of multiboot2 tags");
|
if (Magic == NULL)
|
||||||
break;
|
error("Multiboot magic is NULL");
|
||||||
|
if (Info == NULL)
|
||||||
|
error("Multiboot info is NULL");
|
||||||
|
CPU::Stop();
|
||||||
}
|
}
|
||||||
|
else if (Magic != MULTIBOOT2_BOOTLOADER_MAGIC)
|
||||||
|
{
|
||||||
|
error("Multiboot magic is invalid (%#x != %#x)", Magic, MULTIBOOT2_BOOTLOADER_MAGIC);
|
||||||
|
trace("Hello, World!");
|
||||||
|
CPU::Stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t div = 1193180 / 1000;
|
||||||
|
outb(0x43, 0xB6);
|
||||||
|
outb(0x42, (uint8_t)div);
|
||||||
|
outb(0x42, (uint8_t)(div >> 8));
|
||||||
|
uint8_t tmp = inb(0x61);
|
||||||
|
if (tmp != (tmp | 3))
|
||||||
|
outb(0x61, tmp | 3);
|
||||||
|
|
||||||
|
BootInfo binfo;
|
||||||
|
uint32_t Itr = 0;
|
||||||
|
|
||||||
|
for (uint32_t i = 8; i < Info->Size; i += Itr)
|
||||||
|
{
|
||||||
|
multiboot_tag *Tag = (multiboot_tag *)((uint8_t *)Info + i);
|
||||||
|
if (Tag->type == MULTIBOOT_TAG_TYPE_END)
|
||||||
|
break;
|
||||||
|
|
||||||
switch (Tag->type)
|
switch (Tag->type)
|
||||||
{
|
{
|
||||||
case MULTIBOOT_TAG_TYPE_CMDLINE:
|
case MULTIBOOT_TAG_TYPE_CMDLINE:
|
||||||
{
|
{
|
||||||
strncpy(mb2binfo.Kernel.CommandLine,
|
strncpy(binfo.Kernel.CommandLine,
|
||||||
((multiboot_tag_string *)Tag)->string,
|
((multiboot_tag_string *)Tag)->string,
|
||||||
strlen(((multiboot_tag_string *)Tag)->string));
|
strlen(((multiboot_tag_string *)Tag)->string));
|
||||||
debug("Kernel command line: %s", mb2binfo.Kernel.CommandLine);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME:
|
case MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME:
|
||||||
{
|
{
|
||||||
strncpy(mb2binfo.Bootloader.Name,
|
strncpy(binfo.Bootloader.Name,
|
||||||
((multiboot_tag_string *)Tag)->string,
|
((multiboot_tag_string *)Tag)->string,
|
||||||
strlen(((multiboot_tag_string *)Tag)->string));
|
strlen(((multiboot_tag_string *)Tag)->string));
|
||||||
debug("Bootloader name: %s", mb2binfo.Bootloader.Name);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MULTIBOOT_TAG_TYPE_MODULE:
|
case MULTIBOOT_TAG_TYPE_MODULE:
|
||||||
{
|
{
|
||||||
multiboot_tag_module *module = (multiboot_tag_module *)Tag;
|
multiboot_tag_module *module = (multiboot_tag_module *)Tag;
|
||||||
static int module_count = 0;
|
static int module_count = 0;
|
||||||
mb2binfo.Modules[module_count++].Address = (void *)module->mod_start;
|
binfo.Modules[module_count++].Address = (void *)module->mod_start;
|
||||||
mb2binfo.Modules[module_count++].Size = module->size;
|
binfo.Modules[module_count++].Size = module->size;
|
||||||
strncpy(mb2binfo.Modules[module_count++].Path, "(null)", 6);
|
strncpy(binfo.Modules[module_count++].Path, "(null)", 6);
|
||||||
strncpy(mb2binfo.Modules[module_count++].CommandLine, module->cmdline,
|
strncpy(binfo.Modules[module_count++].CommandLine, module->cmdline,
|
||||||
strlen(module->cmdline));
|
strlen(module->cmdline));
|
||||||
debug("Module: %s", mb2binfo.Modules[module_count++].Path);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MULTIBOOT_TAG_TYPE_BASIC_MEMINFO:
|
case MULTIBOOT_TAG_TYPE_BASIC_MEMINFO:
|
||||||
@ -116,7 +133,8 @@ void ProcessMB2(unsigned long Info)
|
|||||||
{
|
{
|
||||||
multiboot_tag_mmap *mmap = (multiboot_tag_mmap *)Tag;
|
multiboot_tag_mmap *mmap = (multiboot_tag_mmap *)Tag;
|
||||||
uint32_t EntryCount = mmap->size / sizeof(multiboot_mmap_entry);
|
uint32_t EntryCount = mmap->size / sizeof(multiboot_mmap_entry);
|
||||||
mb2binfo.Memory.Entries = EntryCount;
|
|
||||||
|
binfo.Memory.Entries = EntryCount;
|
||||||
for (uint32_t i = 0; i < EntryCount; i++)
|
for (uint32_t i = 0; i < EntryCount; i++)
|
||||||
{
|
{
|
||||||
if (EntryCount > MAX_MEMORY_ENTRIES)
|
if (EntryCount > MAX_MEMORY_ENTRIES)
|
||||||
@ -124,45 +142,42 @@ void ProcessMB2(unsigned long Info)
|
|||||||
warn("Too many memory entries, skipping the rest...");
|
warn("Too many memory entries, skipping the rest...");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
multiboot_mmap_entry entry = mmap->entries[i];
|
multiboot_mmap_entry entry = mmap->entries[i];
|
||||||
mb2binfo.Memory.Size += entry.len;
|
binfo.Memory.Size += entry.len;
|
||||||
switch (entry.type)
|
switch (entry.type)
|
||||||
{
|
{
|
||||||
case MULTIBOOT_MEMORY_AVAILABLE:
|
case MULTIBOOT_MEMORY_AVAILABLE:
|
||||||
mb2binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr;
|
binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr;
|
||||||
mb2binfo.Memory.Entry[i].Length = entry.len;
|
binfo.Memory.Entry[i].Length = entry.len;
|
||||||
mb2binfo.Memory.Entry[i].Type = Usable;
|
binfo.Memory.Entry[i].Type = Usable;
|
||||||
break;
|
break;
|
||||||
case MULTIBOOT_MEMORY_RESERVED:
|
case MULTIBOOT_MEMORY_RESERVED:
|
||||||
mb2binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr;
|
binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr;
|
||||||
mb2binfo.Memory.Entry[i].Length = entry.len;
|
binfo.Memory.Entry[i].Length = entry.len;
|
||||||
mb2binfo.Memory.Entry[i].Type = Reserved;
|
binfo.Memory.Entry[i].Type = Reserved;
|
||||||
break;
|
break;
|
||||||
case MULTIBOOT_MEMORY_ACPI_RECLAIMABLE:
|
case MULTIBOOT_MEMORY_ACPI_RECLAIMABLE:
|
||||||
mb2binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr;
|
binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr;
|
||||||
mb2binfo.Memory.Entry[i].Length = entry.len;
|
binfo.Memory.Entry[i].Length = entry.len;
|
||||||
mb2binfo.Memory.Entry[i].Type = ACPIReclaimable;
|
binfo.Memory.Entry[i].Type = ACPIReclaimable;
|
||||||
break;
|
break;
|
||||||
case MULTIBOOT_MEMORY_NVS:
|
case MULTIBOOT_MEMORY_NVS:
|
||||||
mb2binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr;
|
binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr;
|
||||||
mb2binfo.Memory.Entry[i].Length = entry.len;
|
binfo.Memory.Entry[i].Length = entry.len;
|
||||||
mb2binfo.Memory.Entry[i].Type = ACPINVS;
|
binfo.Memory.Entry[i].Type = ACPINVS;
|
||||||
break;
|
break;
|
||||||
case MULTIBOOT_MEMORY_BADRAM:
|
case MULTIBOOT_MEMORY_BADRAM:
|
||||||
mb2binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr;
|
binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr;
|
||||||
mb2binfo.Memory.Entry[i].Length = entry.len;
|
binfo.Memory.Entry[i].Length = entry.len;
|
||||||
mb2binfo.Memory.Entry[i].Type = BadMemory;
|
binfo.Memory.Entry[i].Type = BadMemory;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
mb2binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr;
|
binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr;
|
||||||
mb2binfo.Memory.Entry[i].Length = entry.len;
|
binfo.Memory.Entry[i].Length = entry.len;
|
||||||
mb2binfo.Memory.Entry[i].Type = Unknown;
|
binfo.Memory.Entry[i].Type = Unknown;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
debug("Memory entry: [BaseAddress: %#x, Length: %#x, Type: %d]",
|
|
||||||
mb2binfo.Memory.Entry[i].BaseAddress,
|
|
||||||
mb2binfo.Memory.Entry[i].Length,
|
|
||||||
mb2binfo.Memory.Entry[i].Type);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -177,12 +192,14 @@ void ProcessMB2(unsigned long Info)
|
|||||||
{
|
{
|
||||||
multiboot_tag_framebuffer *fb = (multiboot_tag_framebuffer *)Tag;
|
multiboot_tag_framebuffer *fb = (multiboot_tag_framebuffer *)Tag;
|
||||||
static int fb_count = 0;
|
static int fb_count = 0;
|
||||||
mb2binfo.Framebuffer[fb_count].BaseAddress = (void *)fb->common.framebuffer_addr;
|
|
||||||
mb2binfo.Framebuffer[fb_count].Width = fb->common.framebuffer_width;
|
binfo.Framebuffer[fb_count].BaseAddress = (void *)fb->common.framebuffer_addr;
|
||||||
mb2binfo.Framebuffer[fb_count].Height = fb->common.framebuffer_height;
|
binfo.Framebuffer[fb_count].Width = fb->common.framebuffer_width;
|
||||||
mb2binfo.Framebuffer[fb_count].Pitch = fb->common.framebuffer_pitch;
|
binfo.Framebuffer[fb_count].Height = fb->common.framebuffer_height;
|
||||||
mb2binfo.Framebuffer[fb_count].BitsPerPixel = fb->common.framebuffer_bpp;
|
binfo.Framebuffer[fb_count].Pitch = fb->common.framebuffer_pitch;
|
||||||
mb2binfo.Framebuffer[fb_count].MemoryModel = fb->common.framebuffer_type;
|
binfo.Framebuffer[fb_count].BitsPerPixel = fb->common.framebuffer_bpp;
|
||||||
|
binfo.Framebuffer[fb_count].MemoryModel = fb->common.framebuffer_type;
|
||||||
|
|
||||||
switch (fb->common.framebuffer_type)
|
switch (fb->common.framebuffer_type)
|
||||||
{
|
{
|
||||||
case MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED:
|
case MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED:
|
||||||
@ -192,12 +209,12 @@ void ProcessMB2(unsigned long Info)
|
|||||||
}
|
}
|
||||||
case MULTIBOOT_FRAMEBUFFER_TYPE_RGB:
|
case MULTIBOOT_FRAMEBUFFER_TYPE_RGB:
|
||||||
{
|
{
|
||||||
mb2binfo.Framebuffer[fb_count].RedMaskSize = fb->framebuffer_red_mask_size;
|
binfo.Framebuffer[fb_count].RedMaskSize = fb->framebuffer_red_mask_size;
|
||||||
mb2binfo.Framebuffer[fb_count].RedMaskShift = fb->framebuffer_red_field_position;
|
binfo.Framebuffer[fb_count].RedMaskShift = fb->framebuffer_red_field_position;
|
||||||
mb2binfo.Framebuffer[fb_count].GreenMaskSize = fb->framebuffer_green_mask_size;
|
binfo.Framebuffer[fb_count].GreenMaskSize = fb->framebuffer_green_mask_size;
|
||||||
mb2binfo.Framebuffer[fb_count].GreenMaskShift = fb->framebuffer_green_field_position;
|
binfo.Framebuffer[fb_count].GreenMaskShift = fb->framebuffer_green_field_position;
|
||||||
mb2binfo.Framebuffer[fb_count].BlueMaskSize = fb->framebuffer_blue_mask_size;
|
binfo.Framebuffer[fb_count].BlueMaskSize = fb->framebuffer_blue_mask_size;
|
||||||
mb2binfo.Framebuffer[fb_count].BlueMaskShift = fb->framebuffer_blue_field_position;
|
binfo.Framebuffer[fb_count].BlueMaskShift = fb->framebuffer_blue_field_position;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT:
|
case MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT:
|
||||||
@ -206,11 +223,12 @@ void ProcessMB2(unsigned long Info)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
debug("Framebuffer %d: %dx%d %d bpp", Tag, fb->common.framebuffer_width, fb->common.framebuffer_height, fb->common.framebuffer_bpp);
|
debug("Framebuffer %d: %dx%d %d bpp", i, 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",
|
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->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_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->framebuffer_green_field_position, fb->framebuffer_blue_mask_size, fb->framebuffer_blue_field_position);
|
||||||
|
|
||||||
fb_count++;
|
fb_count++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -248,14 +266,12 @@ void ProcessMB2(unsigned long Info)
|
|||||||
}
|
}
|
||||||
case MULTIBOOT_TAG_TYPE_ACPI_OLD:
|
case MULTIBOOT_TAG_TYPE_ACPI_OLD:
|
||||||
{
|
{
|
||||||
mb2binfo.RSDP = (BootInfo::RSDPInfo *)((multiboot_tag_old_acpi *)Tag)->rsdp;
|
binfo.RSDP = (BootInfo::RSDPInfo *)((multiboot_tag_old_acpi *)Tag)->rsdp;
|
||||||
debug("OLD ACPI RSDP: %p", mb2binfo.RSDP);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MULTIBOOT_TAG_TYPE_ACPI_NEW:
|
case MULTIBOOT_TAG_TYPE_ACPI_NEW:
|
||||||
{
|
{
|
||||||
mb2binfo.RSDP = (BootInfo::RSDPInfo *)((multiboot_tag_new_acpi *)Tag)->rsdp;
|
binfo.RSDP = (BootInfo::RSDPInfo *)((multiboot_tag_new_acpi *)Tag)->rsdp;
|
||||||
debug("NEW ACPI RSDP: %p", mb2binfo.RSDP);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MULTIBOOT_TAG_TYPE_NETWORK:
|
case MULTIBOOT_TAG_TYPE_NETWORK:
|
||||||
@ -291,49 +307,37 @@ void ProcessMB2(unsigned long Info)
|
|||||||
case MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR:
|
case MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR:
|
||||||
{
|
{
|
||||||
multiboot_tag_load_base_addr *load_base_addr = (multiboot_tag_load_base_addr *)Tag;
|
multiboot_tag_load_base_addr *load_base_addr = (multiboot_tag_load_base_addr *)Tag;
|
||||||
mb2binfo.Kernel.PhysicalBase = (void *)load_base_addr->load_base_addr;
|
binfo.Kernel.PhysicalBase = (void *)load_base_addr->load_base_addr;
|
||||||
mb2binfo.Kernel.VirtualBase = (void *)(load_base_addr->load_base_addr + 0xC0000000);
|
binfo.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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Itr = Tag->size;
|
||||||
|
if ((Itr % 8) != 0)
|
||||||
|
Itr += (8 - Itr % 8);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
EXTERNC void Multiboot2Entry(unsigned long Info, unsigned int Magic)
|
|
||||||
{
|
|
||||||
if (Info == NULL || Magic == NULL)
|
|
||||||
{
|
|
||||||
if (Magic == NULL)
|
|
||||||
error("Multiboot magic is NULL");
|
|
||||||
if (Info == NULL)
|
|
||||||
error("Multiboot info is NULL");
|
|
||||||
CPU::Stop();
|
|
||||||
}
|
|
||||||
else if (Magic != MULTIBOOT2_BOOTLOADER_MAGIC)
|
|
||||||
{
|
|
||||||
error("Multiboot magic is invalid (%#x != %#x)", Magic, MULTIBOOT2_BOOTLOADER_MAGIC);
|
|
||||||
CPU::Stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t div = 1193180 / 1000;
|
|
||||||
outb(0x43, 0xB6);
|
|
||||||
outb(0x42, (uint8_t)div);
|
|
||||||
outb(0x42, (uint8_t)(div >> 8));
|
|
||||||
uint8_t tmp = inb(0x61);
|
|
||||||
if (tmp != (tmp | 3))
|
|
||||||
outb(0x61, tmp | 3);
|
|
||||||
|
|
||||||
ProcessMB2(Info);
|
|
||||||
|
|
||||||
tmp = inb(0x61) & 0xFC;
|
tmp = inb(0x61) & 0xFC;
|
||||||
outb(0x61, tmp);
|
outb(0x61, tmp);
|
||||||
|
|
||||||
|
int *vm = (int *)0xb8000;
|
||||||
|
// "Not supported yet"
|
||||||
|
vm[0] = 0x054E;
|
||||||
|
vm[1] = 0x056F;
|
||||||
|
vm[2] = 0x0574;
|
||||||
|
vm[3] = 0x0520;
|
||||||
|
vm[4] = 0x0573;
|
||||||
|
vm[5] = 0x0575;
|
||||||
|
vm[6] = 0x0570;
|
||||||
|
vm[7] = 0x0570;
|
||||||
|
vm[8] = 0x0572;
|
||||||
|
vm[9] = 0x056F;
|
||||||
|
vm[10] = 0x0574;
|
||||||
|
vm[11] = 0x0520;
|
||||||
|
vm[12] = 0x0579;
|
||||||
|
vm[13] = 0x0565;
|
||||||
|
vm[14] = 0x0574;
|
||||||
|
|
||||||
CPU::Stop();
|
CPU::Stop();
|
||||||
Entry(&mb2binfo);
|
// Entry(&binfo);
|
||||||
}
|
}
|
@ -1,99 +0,0 @@
|
|||||||
#include "gdt.hpp"
|
|
||||||
|
|
||||||
#include <memory.hpp>
|
|
||||||
#include <smp.hpp>
|
|
||||||
#include <cpu.hpp>
|
|
||||||
#include <debug.h>
|
|
||||||
|
|
||||||
namespace GlobalDescriptorTable
|
|
||||||
{
|
|
||||||
static GlobalDescriptorTableEntries GDTEntriesTemplate = {
|
|
||||||
// null
|
|
||||||
{.Length = 0x0,
|
|
||||||
.BaseLow = 0x0,
|
|
||||||
.BaseMiddle = 0x0,
|
|
||||||
.Access = {.Raw = 0x0},
|
|
||||||
.Flags = {.Raw = 0x0},
|
|
||||||
.BaseHigh = 0x0},
|
|
||||||
|
|
||||||
// kernel code
|
|
||||||
{.Length = 0x0,
|
|
||||||
.BaseLow = 0x0,
|
|
||||||
.BaseMiddle = 0x0,
|
|
||||||
.Access = {.A = 0,
|
|
||||||
.RW = 1,
|
|
||||||
.DC = 0,
|
|
||||||
.E = 1,
|
|
||||||
.S = 1,
|
|
||||||
.DPL = 0,
|
|
||||||
.P = 1},
|
|
||||||
.Flags = {.Unknown = 0x0, .L = 1},
|
|
||||||
.BaseHigh = 0x0},
|
|
||||||
|
|
||||||
// kernel data
|
|
||||||
{.Length = 0x0,
|
|
||||||
.BaseLow = 0x0,
|
|
||||||
.BaseMiddle = 0x0,
|
|
||||||
.Access = {.A = 0,
|
|
||||||
.RW = 1,
|
|
||||||
.DC = 0,
|
|
||||||
.E = 0,
|
|
||||||
.S = 1,
|
|
||||||
.DPL = 0,
|
|
||||||
.P = 1},
|
|
||||||
.Flags = {.Raw = 0x0},
|
|
||||||
.BaseHigh = 0x0},
|
|
||||||
|
|
||||||
// user data
|
|
||||||
{.Length = 0x0,
|
|
||||||
.BaseLow = 0x0,
|
|
||||||
.BaseMiddle = 0x0,
|
|
||||||
.Access = {.A = 0,
|
|
||||||
.RW = 1,
|
|
||||||
.DC = 0,
|
|
||||||
.E = 0,
|
|
||||||
.S = 1,
|
|
||||||
.DPL = 3,
|
|
||||||
.P = 1},
|
|
||||||
.Flags = {.Raw = 0x0},
|
|
||||||
.BaseHigh = 0x0},
|
|
||||||
|
|
||||||
// user code
|
|
||||||
{.Length = 0x0,
|
|
||||||
.BaseLow = 0x0,
|
|
||||||
.BaseMiddle = 0x0,
|
|
||||||
.Access = {.A = 0,
|
|
||||||
.RW = 1,
|
|
||||||
.DC = 0,
|
|
||||||
.E = 1,
|
|
||||||
.S = 1,
|
|
||||||
.DPL = 3,
|
|
||||||
.P = 1},
|
|
||||||
.Flags = {.Unknown = 0x0, .L = 1},
|
|
||||||
.BaseHigh = 0x0},
|
|
||||||
|
|
||||||
// tss
|
|
||||||
{}};
|
|
||||||
|
|
||||||
GlobalDescriptorTableEntries GDTEntries[MAX_CPU];
|
|
||||||
GlobalDescriptorTableDescriptor gdt[MAX_CPU];
|
|
||||||
|
|
||||||
TaskStateSegment tss[MAX_CPU] = {
|
|
||||||
0,
|
|
||||||
{0, 0, 0},
|
|
||||||
0,
|
|
||||||
{0, 0, 0, 0, 0, 0, 0},
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
};
|
|
||||||
|
|
||||||
void *CPUStackPointer[MAX_CPU];
|
|
||||||
|
|
||||||
SafeFunction void Init(int Core)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
SafeFunction void SetKernelStack(void *Stack)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,6 +1,6 @@
|
|||||||
#include <smp.hpp>
|
#include <smp.hpp>
|
||||||
|
|
||||||
#include <ints.hpp>
|
#include <interrupts.hpp>
|
||||||
#include <memory.hpp>
|
#include <memory.hpp>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <cpu.hpp>
|
#include <cpu.hpp>
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
#include <types.h>
|
#include <types.h>
|
||||||
|
|
||||||
#include <ints.hpp>
|
#include <interrupts.hpp>
|
||||||
#include <cpu.hpp>
|
#include <cpu.hpp>
|
||||||
|
|
||||||
namespace APIC
|
namespace APIC
|
||||||
@ -324,7 +324,7 @@ namespace APIC
|
|||||||
private:
|
private:
|
||||||
APIC *lapic;
|
APIC *lapic;
|
||||||
uint64_t Ticks = 0;
|
uint64_t Ticks = 0;
|
||||||
void OnInterruptReceived(CPU::x32::TrapFrame *Frame);
|
void OnInterruptReceived(CPU::x64::TrapFrame *Frame);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
uint64_t GetTicks() { return Ticks; }
|
uint64_t GetTicks() { return Ticks; }
|
||||||
|
11
Kernel/Architecture/i686/cpu/fxsr.asm
Normal file
11
Kernel/Architecture/i686/cpu/fxsr.asm
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
[bits 64]
|
||||||
|
|
||||||
|
[global _i386_fxsave]
|
||||||
|
_i386_fxsave:
|
||||||
|
fxsave [edi]
|
||||||
|
ret
|
||||||
|
|
||||||
|
[global _i386_fxrstor]
|
||||||
|
_i386_fxrstor:
|
||||||
|
fxrstor [edi]
|
||||||
|
ret
|
@ -5,141 +5,7 @@
|
|||||||
|
|
||||||
namespace GlobalDescriptorTable
|
namespace GlobalDescriptorTable
|
||||||
{
|
{
|
||||||
/** @brief The GDT Access Table
|
|
||||||
* @details For more information, see https://wiki.osdev.org/Global_Descriptor_Table
|
|
||||||
*/
|
|
||||||
union GlobalDescriptorTableAccess
|
|
||||||
{
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
/** @brief Access bit.
|
|
||||||
* @note The CPU sets this bit to 1 when the segment is accessed.
|
|
||||||
*/
|
|
||||||
uint8_t A : 1;
|
|
||||||
|
|
||||||
/** @brief Readable bit for code segments, writable bit for data segments.
|
|
||||||
* @details For code segments, this bit must be 1 for the segment to be readable.
|
|
||||||
* @details For data segments, this bit must be 1 for the segment to be writable.
|
|
||||||
*/
|
|
||||||
uint8_t RW : 1;
|
|
||||||
|
|
||||||
/** @brief Direction bit for data segments, conforming bit for code segments.
|
|
||||||
* @details For data segments, this bit must be 1 for the segment to grow up (higher addresses).
|
|
||||||
* @details For code segments, this bit must be 1 for code in the segment to be able to be executed from an equal or lower privilege level.
|
|
||||||
*/
|
|
||||||
uint8_t DC : 1;
|
|
||||||
|
|
||||||
/** @brief Executable bit.
|
|
||||||
* @details This bit must be 1 for code-segment descriptors.
|
|
||||||
* @details This bit must be 0 for data-segment and system descriptors.
|
|
||||||
*/
|
|
||||||
uint8_t E : 1;
|
|
||||||
|
|
||||||
/** @brief Descriptor type.
|
|
||||||
* @details This bit must be 0 for system descriptors.
|
|
||||||
* @details This bit must be 1 for code or data segment descriptor.
|
|
||||||
*/
|
|
||||||
uint8_t S : 1;
|
|
||||||
|
|
||||||
/** @brief Descriptor privilege level.
|
|
||||||
* @details This field determines the privilege level of the segment.
|
|
||||||
* @details 0 = kernel mode, 3 = user mode.
|
|
||||||
*/
|
|
||||||
uint8_t DPL : 2;
|
|
||||||
|
|
||||||
/** @brief Present bit.
|
|
||||||
* @details This bit must be 1 for all valid descriptors.
|
|
||||||
*/
|
|
||||||
uint8_t P : 1;
|
|
||||||
} __attribute__((packed));
|
|
||||||
uint8_t Raw;
|
|
||||||
};
|
|
||||||
|
|
||||||
union GlobalDescriptorTableFlags
|
|
||||||
{
|
|
||||||
// TODO: Add more flags.
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
/** @brief Unknown. */
|
|
||||||
uint8_t Unknown : 5;
|
|
||||||
|
|
||||||
/** @brief Long mode.
|
|
||||||
* @details If the long mode bit is clear, the segment is in 32-bit protected mode.
|
|
||||||
* @details If the long mode bit is set, the segment is in 64-bit long mode.
|
|
||||||
*/
|
|
||||||
uint8_t L : 1;
|
|
||||||
} __attribute__((packed));
|
|
||||||
uint8_t Raw;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct _TaskStateSegmentEntry
|
|
||||||
{
|
|
||||||
/* LOW */
|
|
||||||
uint16_t Length;
|
|
||||||
uint16_t BaseLow;
|
|
||||||
uint8_t BaseMiddle;
|
|
||||||
GlobalDescriptorTableAccess Flags;
|
|
||||||
uint8_t Granularity;
|
|
||||||
uint8_t BaseHigh;
|
|
||||||
/* HIGH */
|
|
||||||
uint32_t BaseUpper;
|
|
||||||
uint32_t Reserved;
|
|
||||||
} __attribute__((packed)) TaskStateSegmentEntry;
|
|
||||||
|
|
||||||
typedef struct _TaskStateSegment
|
|
||||||
{
|
|
||||||
uint32_t Reserved0 __attribute__((aligned(16)));
|
|
||||||
uint64_t StackPointer[3];
|
|
||||||
uint64_t Reserved1;
|
|
||||||
uint64_t InterruptStackTable[7];
|
|
||||||
uint16_t Reserved2;
|
|
||||||
uint16_t IOMapBaseAddressOffset;
|
|
||||||
} __attribute__((packed)) TaskStateSegment;
|
|
||||||
|
|
||||||
typedef struct _GlobalDescriptorTableEntry
|
|
||||||
{
|
|
||||||
/** @brief Length */
|
|
||||||
uint16_t Length;
|
|
||||||
/** @brief Low Base */
|
|
||||||
uint16_t BaseLow;
|
|
||||||
/** @brief Middle Base */
|
|
||||||
uint8_t BaseMiddle;
|
|
||||||
/** @brief Access */
|
|
||||||
GlobalDescriptorTableAccess Access;
|
|
||||||
/** @brief Flags */
|
|
||||||
GlobalDescriptorTableFlags Flags;
|
|
||||||
/** @brief High Base */
|
|
||||||
uint8_t BaseHigh;
|
|
||||||
} __attribute__((packed)) GlobalDescriptorTableEntry;
|
|
||||||
|
|
||||||
typedef struct _GlobalDescriptorTableEntries
|
|
||||||
{
|
|
||||||
GlobalDescriptorTableEntry Null;
|
|
||||||
GlobalDescriptorTableEntry Code;
|
|
||||||
GlobalDescriptorTableEntry Data;
|
|
||||||
GlobalDescriptorTableEntry UserData;
|
|
||||||
GlobalDescriptorTableEntry UserCode;
|
|
||||||
TaskStateSegmentEntry TaskStateSegment;
|
|
||||||
} __attribute__((packed)) GlobalDescriptorTableEntries;
|
|
||||||
|
|
||||||
typedef struct _GlobalDescriptorTableDescriptor
|
|
||||||
{
|
|
||||||
/** @brief GDT entries length */
|
|
||||||
uint16_t Length;
|
|
||||||
/** @brief GDT entries address */
|
|
||||||
GlobalDescriptorTableEntries *Entries;
|
|
||||||
} __attribute__((packed)) GlobalDescriptorTableDescriptor;
|
|
||||||
|
|
||||||
extern void *CPUStackPointer[];
|
|
||||||
extern TaskStateSegment tss[];
|
|
||||||
void Init(int Core);
|
void Init(int Core);
|
||||||
void SetKernelStack(void *Stack);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define GDT_KERNEL_CODE offsetof(GlobalDescriptorTable::GlobalDescriptorTableEntries, Code)
|
|
||||||
#define GDT_KERNEL_DATA offsetof(GlobalDescriptorTable::GlobalDescriptorTableEntries, Data)
|
|
||||||
#define GDT_USER_CODE (offsetof(GlobalDescriptorTable::GlobalDescriptorTableEntries, UserCode) | 3)
|
|
||||||
#define GDT_USER_DATA (offsetof(GlobalDescriptorTable::GlobalDescriptorTableEntries, UserData) | 3)
|
|
||||||
#define GDT_TSS (offsetof(GlobalDescriptorTable::GlobalDescriptorTableEntries, TaskStateSegment) | 3)
|
|
||||||
|
|
||||||
#endif // !__FENNIX_KERNEL_GDT_H__
|
#endif // !__FENNIX_KERNEL_GDT_H__
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
OUTPUT_FORMAT(elf32-i386)
|
OUTPUT_FORMAT(elf32-i386)
|
||||||
OUTPUT_ARCH(i386)
|
OUTPUT_ARCH(i386)
|
||||||
|
|
||||||
ENTRY(MB2_start)
|
ENTRY(_start)
|
||||||
|
|
||||||
SECTIONS
|
SECTIONS
|
||||||
{
|
{
|
||||||
@ -27,23 +27,6 @@ SECTIONS
|
|||||||
}
|
}
|
||||||
_kernel_rodata_end = .;
|
_kernel_rodata_end = .;
|
||||||
|
|
||||||
.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 = .);
|
|
||||||
}
|
|
||||||
. += CONSTANT(MAXPAGESIZE);
|
|
||||||
|
|
||||||
.bss ALIGN (4096) : AT(ADDR(.bss) - 0xC0000000)
|
.bss ALIGN (4096) : AT(ADDR(.bss) - 0xC0000000)
|
||||||
{
|
{
|
||||||
*(COMMON)
|
*(COMMON)
|
||||||
|
69
Kernel/Architecture/i686/runtime/crt1.asm
Normal file
69
Kernel/Architecture/i686/runtime/crt1.asm
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
; Inspired From: https://github.com/MQuy/mos/blob/master/src/kernel/boot.asm
|
||||||
|
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_TAG_START:
|
||||||
|
dw 0
|
||||||
|
dw 0
|
||||||
|
dd MB2_TAG_END - MB2_TAG_START
|
||||||
|
MB2_TAG_END:
|
||||||
|
HEADER_END:
|
||||||
|
|
||||||
|
KERNEL_VIRTUAL_BASE equ 0xC0000000 ; 3GB
|
||||||
|
KERNEL_PAGE_NUMBER equ (KERNEL_VIRTUAL_BASE >> 22) ; 768
|
||||||
|
KERNEL_STACK_SIZE equ 0x4000 ; 16KB
|
||||||
|
|
||||||
|
extern x32Multiboot2Entry
|
||||||
|
global _start
|
||||||
|
|
||||||
|
section .data
|
||||||
|
align 0x1000
|
||||||
|
BootPageTable:
|
||||||
|
dd 0x00000083
|
||||||
|
times ((KERNEL_PAGE_NUMBER) - 1) dd 0
|
||||||
|
dd 0x00000083
|
||||||
|
times (1024 - KERNEL_PAGE_NUMBER - 1) dd 0
|
||||||
|
|
||||||
|
section .text
|
||||||
|
_start:
|
||||||
|
mov word [0xb8000], 0x074C ; L
|
||||||
|
mov word [0xb8002], 0x076F ; o
|
||||||
|
mov word [0xb8004], 0x0761 ; a
|
||||||
|
mov word [0xb8006], 0x0764 ; d
|
||||||
|
mov word [0xb8008], 0x0769 ; i
|
||||||
|
mov word [0xb800a], 0x076E ; n
|
||||||
|
mov word [0xb800c], 0x0767 ; g
|
||||||
|
mov word [0xb800e], 0x072E ; .
|
||||||
|
mov word [0xb8010], 0x072E ; .
|
||||||
|
mov word [0xb8012], 0x072E ; .
|
||||||
|
mov ecx, (BootPageTable - KERNEL_VIRTUAL_BASE)
|
||||||
|
mov cr3, ecx
|
||||||
|
mov ecx, cr4
|
||||||
|
or ecx, 0x00000010 ; Set PSE in CR4
|
||||||
|
mov cr4, ecx
|
||||||
|
mov ecx, cr0
|
||||||
|
or ecx, 0x80000000 ; Set PG in CR0
|
||||||
|
mov cr0, ecx
|
||||||
|
lea ecx, [HigherHalfStart]
|
||||||
|
jmp ecx
|
||||||
|
|
||||||
|
HigherHalfStart:
|
||||||
|
mov esp, KernelStack + KERNEL_STACK_SIZE
|
||||||
|
|
||||||
|
push eax ; Multiboot2 Magic
|
||||||
|
add ebx, KERNEL_VIRTUAL_BASE
|
||||||
|
push ebx ; Multiboot2 Header
|
||||||
|
call x32Multiboot2Entry
|
||||||
|
Loop:
|
||||||
|
hlt
|
||||||
|
jmp Loop
|
||||||
|
|
||||||
|
section .bss
|
||||||
|
align 16
|
||||||
|
KernelStack :
|
||||||
|
resb KERNEL_STACK_SIZE
|
@ -1,15 +0,0 @@
|
|||||||
#include <types.h>
|
|
||||||
|
|
||||||
#include <debug.h>
|
|
||||||
|
|
||||||
int Entry(void *Info);
|
|
||||||
|
|
||||||
void _start(void *Raw)
|
|
||||||
{
|
|
||||||
UNUSED(Raw);
|
|
||||||
error("ERROR! INVALID BOOT PROTOCOL!");
|
|
||||||
while (1)
|
|
||||||
asmv("hlt");
|
|
||||||
Entry(NULL);
|
|
||||||
return;
|
|
||||||
}
|
|
@ -3,30 +3,27 @@
|
|||||||
#include <memory.hpp>
|
#include <memory.hpp>
|
||||||
#include <convert.h>
|
#include <convert.h>
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
#include <smp.hpp>
|
|
||||||
|
|
||||||
#include "../kernel.h"
|
#include "../kernel.h"
|
||||||
|
|
||||||
namespace CPU
|
namespace CPU
|
||||||
{
|
{
|
||||||
static bool SSEEnabled = false;
|
|
||||||
|
|
||||||
char *Vendor()
|
char *Vendor()
|
||||||
{
|
{
|
||||||
static char Vendor[13];
|
static char Vendor[13];
|
||||||
#if defined(a64)
|
#if defined(__amd64__)
|
||||||
uint32_t eax, ebx, ecx, edx;
|
uint32_t rax, rbx, rcx, rdx;
|
||||||
x64::cpuid(0x0, &eax, &ebx, &ecx, &edx);
|
x64::cpuid(0x0, &rax, &rbx, &rcx, &rdx);
|
||||||
memcpy_unsafe(Vendor + 0, &ebx, 4);
|
memcpy(Vendor + 0, &rbx, 4);
|
||||||
memcpy_unsafe(Vendor + 4, &edx, 4);
|
memcpy(Vendor + 4, &rdx, 4);
|
||||||
memcpy_unsafe(Vendor + 8, &ecx, 4);
|
memcpy(Vendor + 8, &rcx, 4);
|
||||||
#elif defined(a32)
|
#elif defined(__i386__)
|
||||||
uint32_t eax, ebx, ecx, edx;
|
uint32_t rax, rbx, rcx, rdx;
|
||||||
x32::cpuid(0x0, &eax, &ebx, &ecx, &edx);
|
x32::cpuid(0x0, &rax, &rbx, &rcx, &rdx);
|
||||||
memcpy_unsafe(Vendor + 0, &ebx, 4);
|
memcpy(Vendor + 0, &rbx, 4);
|
||||||
memcpy_unsafe(Vendor + 4, &edx, 4);
|
memcpy(Vendor + 4, &rdx, 4);
|
||||||
memcpy_unsafe(Vendor + 8, &ecx, 4);
|
memcpy(Vendor + 8, &rcx, 4);
|
||||||
#elif defined(aa64)
|
#elif defined(__aarch64__)
|
||||||
asmv("mrs %0, MIDR_EL1"
|
asmv("mrs %0, MIDR_EL1"
|
||||||
: "=r"(Vendor[0]));
|
: "=r"(Vendor[0]));
|
||||||
#endif
|
#endif
|
||||||
@ -36,41 +33,41 @@ namespace CPU
|
|||||||
char *Name()
|
char *Name()
|
||||||
{
|
{
|
||||||
static char Name[49];
|
static char Name[49];
|
||||||
#if defined(a64)
|
#if defined(__amd64__)
|
||||||
uint32_t eax, ebx, ecx, edx;
|
uint32_t rax, rbx, rcx, rdx;
|
||||||
x64::cpuid(0x80000002, &eax, &ebx, &ecx, &edx);
|
x64::cpuid(0x80000002, &rax, &rbx, &rcx, &rdx);
|
||||||
memcpy_unsafe(Name + 0, &eax, 4);
|
memcpy(Name + 0, &rax, 4);
|
||||||
memcpy_unsafe(Name + 4, &ebx, 4);
|
memcpy(Name + 4, &rbx, 4);
|
||||||
memcpy_unsafe(Name + 8, &ecx, 4);
|
memcpy(Name + 8, &rcx, 4);
|
||||||
memcpy_unsafe(Name + 12, &edx, 4);
|
memcpy(Name + 12, &rdx, 4);
|
||||||
x64::cpuid(0x80000003, &eax, &ebx, &ecx, &edx);
|
x64::cpuid(0x80000003, &rax, &rbx, &rcx, &rdx);
|
||||||
memcpy_unsafe(Name + 16, &eax, 4);
|
memcpy(Name + 16, &rax, 4);
|
||||||
memcpy_unsafe(Name + 20, &ebx, 4);
|
memcpy(Name + 20, &rbx, 4);
|
||||||
memcpy_unsafe(Name + 24, &ecx, 4);
|
memcpy(Name + 24, &rcx, 4);
|
||||||
memcpy_unsafe(Name + 28, &edx, 4);
|
memcpy(Name + 28, &rdx, 4);
|
||||||
x64::cpuid(0x80000004, &eax, &ebx, &ecx, &edx);
|
x64::cpuid(0x80000004, &rax, &rbx, &rcx, &rdx);
|
||||||
memcpy_unsafe(Name + 32, &eax, 4);
|
memcpy(Name + 32, &rax, 4);
|
||||||
memcpy_unsafe(Name + 36, &ebx, 4);
|
memcpy(Name + 36, &rbx, 4);
|
||||||
memcpy_unsafe(Name + 40, &ecx, 4);
|
memcpy(Name + 40, &rcx, 4);
|
||||||
memcpy_unsafe(Name + 44, &edx, 4);
|
memcpy(Name + 44, &rdx, 4);
|
||||||
#elif defined(a32)
|
#elif defined(__i386__)
|
||||||
uint32_t eax, ebx, ecx, edx;
|
uint32_t rax, rbx, rcx, rdx;
|
||||||
x32::cpuid(0x80000002, &eax, &ebx, &ecx, &edx);
|
x32::cpuid(0x80000002, &rax, &rbx, &rcx, &rdx);
|
||||||
memcpy_unsafe(Name + 0, &eax, 4);
|
memcpy(Name + 0, &rax, 4);
|
||||||
memcpy_unsafe(Name + 4, &ebx, 4);
|
memcpy(Name + 4, &rbx, 4);
|
||||||
memcpy_unsafe(Name + 8, &ecx, 4);
|
memcpy(Name + 8, &rcx, 4);
|
||||||
memcpy_unsafe(Name + 12, &edx, 4);
|
memcpy(Name + 12, &rdx, 4);
|
||||||
x32::cpuid(0x80000003, &eax, &ebx, &ecx, &edx);
|
x32::cpuid(0x80000003, &rax, &rbx, &rcx, &rdx);
|
||||||
memcpy_unsafe(Name + 16, &eax, 4);
|
memcpy(Name + 16, &rax, 4);
|
||||||
memcpy_unsafe(Name + 20, &ebx, 4);
|
memcpy(Name + 20, &rbx, 4);
|
||||||
memcpy_unsafe(Name + 24, &ecx, 4);
|
memcpy(Name + 24, &rcx, 4);
|
||||||
memcpy_unsafe(Name + 28, &edx, 4);
|
memcpy(Name + 28, &rdx, 4);
|
||||||
x32::cpuid(0x80000004, &eax, &ebx, &ecx, &edx);
|
x32::cpuid(0x80000004, &rax, &rbx, &rcx, &rdx);
|
||||||
memcpy_unsafe(Name + 32, &eax, 4);
|
memcpy(Name + 32, &rax, 4);
|
||||||
memcpy_unsafe(Name + 36, &ebx, 4);
|
memcpy(Name + 36, &rbx, 4);
|
||||||
memcpy_unsafe(Name + 40, &ecx, 4);
|
memcpy(Name + 40, &rcx, 4);
|
||||||
memcpy_unsafe(Name + 44, &edx, 4);
|
memcpy(Name + 44, &rdx, 4);
|
||||||
#elif defined(aa64)
|
#elif defined(__aarch64__)
|
||||||
asmv("mrs %0, MIDR_EL1"
|
asmv("mrs %0, MIDR_EL1"
|
||||||
: "=r"(Name[0]));
|
: "=r"(Name[0]));
|
||||||
#endif
|
#endif
|
||||||
@ -80,19 +77,19 @@ namespace CPU
|
|||||||
char *Hypervisor()
|
char *Hypervisor()
|
||||||
{
|
{
|
||||||
static char Hypervisor[13];
|
static char Hypervisor[13];
|
||||||
#if defined(a64)
|
#if defined(__amd64__)
|
||||||
uint32_t eax, ebx, ecx, edx;
|
uint32_t rax, rbx, rcx, rdx;
|
||||||
x64::cpuid(0x40000000, &eax, &ebx, &ecx, &edx);
|
x64::cpuid(0x40000000, &rax, &rbx, &rcx, &rdx);
|
||||||
memcpy_unsafe(Hypervisor + 0, &ebx, 4);
|
memcpy(Hypervisor + 0, &rbx, 4);
|
||||||
memcpy_unsafe(Hypervisor + 4, &ecx, 4);
|
memcpy(Hypervisor + 4, &rcx, 4);
|
||||||
memcpy_unsafe(Hypervisor + 8, &edx, 4);
|
memcpy(Hypervisor + 8, &rdx, 4);
|
||||||
#elif defined(a32)
|
#elif defined(__i386__)
|
||||||
uint32_t eax, ebx, ecx, edx;
|
uint32_t rax, rbx, rcx, rdx;
|
||||||
x64::cpuid(0x40000000, &eax, &ebx, &ecx, &edx);
|
x64::cpuid(0x40000000, &rax, &rbx, &rcx, &rdx);
|
||||||
memcpy_unsafe(Hypervisor + 0, &ebx, 4);
|
memcpy(Hypervisor + 0, &rbx, 4);
|
||||||
memcpy_unsafe(Hypervisor + 4, &ecx, 4);
|
memcpy(Hypervisor + 4, &rcx, 4);
|
||||||
memcpy_unsafe(Hypervisor + 8, &edx, 4);
|
memcpy(Hypervisor + 8, &rdx, 4);
|
||||||
#elif defined(aa64)
|
#elif defined(__aarch64__)
|
||||||
asmv("mrs %0, MIDR_EL1"
|
asmv("mrs %0, MIDR_EL1"
|
||||||
: "=r"(Hypervisor[0]));
|
: "=r"(Hypervisor[0]));
|
||||||
#endif
|
#endif
|
||||||
@ -105,37 +102,39 @@ namespace CPU
|
|||||||
{
|
{
|
||||||
case Check:
|
case Check:
|
||||||
{
|
{
|
||||||
uintptr_t Flags;
|
#if defined(__amd64__)
|
||||||
#if defined(a64)
|
uint64_t rflags;
|
||||||
asmv("pushfq");
|
asmv("pushfq");
|
||||||
asmv("popq %0"
|
asmv("popq %0"
|
||||||
: "=r"(Flags));
|
: "=r"(rflags));
|
||||||
return Flags & (1 << 9);
|
return rflags & (1 << 9);
|
||||||
#elif defined(a32)
|
#elif defined(__i386__)
|
||||||
|
uint32_t rflags;
|
||||||
asmv("pushfl");
|
asmv("pushfl");
|
||||||
asmv("popl %0"
|
asmv("popl %0"
|
||||||
: "=r"(Flags));
|
: "=r"(rflags));
|
||||||
return Flags & (1 << 9);
|
return rflags & (1 << 9);
|
||||||
#elif defined(aa64)
|
#elif defined(__aarch64__)
|
||||||
|
uint64_t daif;
|
||||||
asmv("mrs %0, daif"
|
asmv("mrs %0, daif"
|
||||||
: "=r"(Flags));
|
: "=r"(daif));
|
||||||
return !(Flags & (1 << 2));
|
return !(daif & (1 << 2));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
case Enable:
|
case Enable:
|
||||||
{
|
{
|
||||||
#if defined(a64) || defined(a32)
|
#if defined(__amd64__) || defined(__i386__)
|
||||||
asmv("sti");
|
asmv("sti");
|
||||||
#elif defined(aa64)
|
#elif defined(__aarch64__)
|
||||||
asmv("msr daifclr, #2");
|
asmv("msr daifclr, #2");
|
||||||
#endif
|
#endif
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case Disable:
|
case Disable:
|
||||||
{
|
{
|
||||||
#if defined(a64) || defined(a32)
|
#if defined(__amd64__) || defined(__i386__)
|
||||||
asmv("cli");
|
asmv("cli");
|
||||||
#elif defined(aa64)
|
#elif defined(__aarch64__)
|
||||||
asmv("msr daifset, #2");
|
asmv("msr daifset, #2");
|
||||||
#endif
|
#endif
|
||||||
return true;
|
return true;
|
||||||
@ -146,7 +145,7 @@ namespace CPU
|
|||||||
|
|
||||||
void *PageTable(void *PT)
|
void *PageTable(void *PT)
|
||||||
{
|
{
|
||||||
#if defined(a64)
|
#if defined(__amd64__)
|
||||||
if (PT)
|
if (PT)
|
||||||
asmv("movq %0, %%cr3"
|
asmv("movq %0, %%cr3"
|
||||||
:
|
:
|
||||||
@ -154,7 +153,7 @@ namespace CPU
|
|||||||
else
|
else
|
||||||
asmv("movq %%cr3, %0"
|
asmv("movq %%cr3, %0"
|
||||||
: "=r"(PT));
|
: "=r"(PT));
|
||||||
#elif defined(a32)
|
#elif defined(__i386__)
|
||||||
if (PT)
|
if (PT)
|
||||||
asmv("movl %0, %%cr3"
|
asmv("movl %0, %%cr3"
|
||||||
:
|
:
|
||||||
@ -162,7 +161,7 @@ namespace CPU
|
|||||||
else
|
else
|
||||||
asmv("movl %%cr3, %0"
|
asmv("movl %%cr3, %0"
|
||||||
: "=r"(PT));
|
: "=r"(PT));
|
||||||
#elif defined(aa64)
|
#elif defined(__aarch64__)
|
||||||
if (PT)
|
if (PT)
|
||||||
asmv("msr ttbr0_el1, %0"
|
asmv("msr ttbr0_el1, %0"
|
||||||
:
|
:
|
||||||
@ -174,57 +173,15 @@ namespace CPU
|
|||||||
return PT;
|
return PT;
|
||||||
}
|
}
|
||||||
|
|
||||||
void InitializeFeatures(long Core)
|
void InitializeFeatures()
|
||||||
{
|
{
|
||||||
bool PGESupport = false;
|
#if defined(__amd64__)
|
||||||
bool SSESupport = false;
|
|
||||||
#if defined(a64)
|
|
||||||
static int BSP = 0;
|
static int BSP = 0;
|
||||||
x64::CR0 cr0 = x64::readcr0();
|
x64::CR0 cr0 = x64::readcr0();
|
||||||
x64::CR4 cr4 = x64::readcr4();
|
x64::CR4 cr4 = x64::readcr4();
|
||||||
|
uint32_t rax, rbx, rcx, rdx;
|
||||||
if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_AMD) == 0)
|
x64::cpuid(0x1, &rax, &rbx, &rcx, &rdx);
|
||||||
{
|
if (rdx & x64::CPUID_FEAT_RDX_PGE)
|
||||||
#if defined(a64)
|
|
||||||
CPU::x64::AMD::CPUID0x1 cpuid1amd;
|
|
||||||
#elif defined(a32)
|
|
||||||
CPU::x32::AMD::CPUID0x1 cpuid1amd;
|
|
||||||
#endif
|
|
||||||
#if defined(a64) || defined(a32)
|
|
||||||
asmv("cpuid"
|
|
||||||
: "=a"(cpuid1amd.EAX.raw), "=b"(cpuid1amd.EBX.raw), "=c"(cpuid1amd.ECX.raw), "=d"(cpuid1amd.EDX.raw)
|
|
||||||
: "a"(0x1));
|
|
||||||
#endif
|
|
||||||
if (cpuid1amd.EDX.PGE)
|
|
||||||
PGESupport = true;
|
|
||||||
if (cpuid1amd.EDX.SSE)
|
|
||||||
SSESupport = true;
|
|
||||||
}
|
|
||||||
else if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_INTEL) == 0)
|
|
||||||
{
|
|
||||||
#if defined(a64)
|
|
||||||
CPU::x64::Intel::CPUID0x1 cpuid1intel;
|
|
||||||
#elif defined(a32)
|
|
||||||
CPU::x32::Intel::CPUID0x1 cpuid1intel;
|
|
||||||
#endif
|
|
||||||
#if defined(a64) || defined(a32)
|
|
||||||
asmv("cpuid"
|
|
||||||
: "=a"(cpuid1intel.EAX.raw), "=b"(cpuid1intel.EBX.raw), "=c"(cpuid1intel.ECX.raw), "=d"(cpuid1intel.EDX.raw)
|
|
||||||
: "a"(0x1));
|
|
||||||
#endif
|
|
||||||
if (cpuid1intel.EDX.PGE)
|
|
||||||
PGESupport = true;
|
|
||||||
if (cpuid1intel.EDX.SSE)
|
|
||||||
SSESupport = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Config.SIMD == false)
|
|
||||||
{
|
|
||||||
debug("Disabling SSE support...");
|
|
||||||
SSESupport = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (PGESupport)
|
|
||||||
{
|
{
|
||||||
debug("Enabling global pages support...");
|
debug("Enabling global pages support...");
|
||||||
if (!BSP)
|
if (!BSP)
|
||||||
@ -232,12 +189,7 @@ namespace CPU
|
|||||||
cr4.PGE = 1;
|
cr4.PGE = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SSEEnableAfter = false;
|
if (rdx & x64::CPUID_FEAT_RDX_SSE)
|
||||||
|
|
||||||
/* Not sure if my code is not working properly or something else is the issue. */
|
|
||||||
if ((strcmp(Hypervisor(), x86_CPUID_VENDOR_TCG) != 0 &&
|
|
||||||
strcmp(Hypervisor(), x86_CPUID_VENDOR_VIRTUALBOX) != 0) &&
|
|
||||||
SSESupport)
|
|
||||||
{
|
{
|
||||||
debug("Enabling SSE support...");
|
debug("Enabling SSE support...");
|
||||||
if (!BSP)
|
if (!BSP)
|
||||||
@ -246,16 +198,6 @@ namespace CPU
|
|||||||
cr0.MP = 1;
|
cr0.MP = 1;
|
||||||
cr4.OSFXSR = 1;
|
cr4.OSFXSR = 1;
|
||||||
cr4.OSXMMEXCPT = 1;
|
cr4.OSXMMEXCPT = 1;
|
||||||
|
|
||||||
CPUData *CoreData = GetCPU(Core);
|
|
||||||
CoreData->Data.FPU = (CPU::x64::FXState *)KernelAllocator.RequestPages(TO_PAGES(sizeof(CPU::x64::FXState)));
|
|
||||||
memset(CoreData->Data.FPU, 0, FROM_PAGES(TO_PAGES(sizeof(CPU::x64::FXState))));
|
|
||||||
CoreData->Data.FPU->mxcsr = 0b0001111110000000;
|
|
||||||
CoreData->Data.FPU->mxcsrmask = 0b1111111110111111;
|
|
||||||
CoreData->Data.FPU->fcw = 0b0000001100111111;
|
|
||||||
CPU::x64::fxrstor(CoreData->Data.FPU);
|
|
||||||
|
|
||||||
SSEEnableAfter = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!BSP)
|
if (!BSP)
|
||||||
@ -267,46 +209,39 @@ namespace CPU
|
|||||||
|
|
||||||
x64::writecr0(cr0);
|
x64::writecr0(cr0);
|
||||||
|
|
||||||
// FIXME: I don't think this is reporting correctly. This has to be fixed asap.
|
|
||||||
debug("Enabling UMIP, SMEP & SMAP support...");
|
debug("Enabling UMIP, SMEP & SMAP support...");
|
||||||
uint32_t eax, ebx, ecx, edx;
|
x64::cpuid(0x1, &rax, &rbx, &rcx, &rdx);
|
||||||
x64::cpuid(0x1, &eax, &ebx, &ecx, &edx);
|
if (rdx & x64::CPUID_FEAT_RDX_UMIP)
|
||||||
if (edx & (1 << 2)) // https://en.wikipedia.org/wiki/Control_register
|
|
||||||
{
|
{
|
||||||
if (!BSP)
|
if (!BSP)
|
||||||
KPrint("UMIP is supported.");
|
KPrint("UMIP is supported.");
|
||||||
debug("UMIP is supported.");
|
fixme("Not going to enable UMIP.");
|
||||||
// cr4.UMIP = 1;
|
// cr4.UMIP = 1;
|
||||||
}
|
}
|
||||||
if (edx & (1 << 7)) // https://en.wikipedia.org/wiki/Control_register#SMEP
|
if (rdx & x64::CPUID_FEAT_RDX_SMEP)
|
||||||
// https://web.archive.org/web/20160312223150/http://ncsi.com/nsatc11/presentations/wednesday/emerging_technologies/fischer.pdf
|
|
||||||
{
|
{
|
||||||
if (!BSP)
|
if (!BSP)
|
||||||
KPrint("SMEP is supported.");
|
KPrint("SMEP is supported.");
|
||||||
debug("SMEP is supported.");
|
fixme("Not going to enable SMEP.");
|
||||||
// cr4.SMEP = 1;
|
// cr4.SMEP = 1;
|
||||||
}
|
}
|
||||||
if (edx & (1 << 20)) // https://en.wikipedia.org/wiki/Supervisor_Mode_Access_Prevention
|
if (rdx & x64::CPUID_FEAT_RDX_SMAP)
|
||||||
{
|
{
|
||||||
if (!BSP)
|
if (!BSP)
|
||||||
KPrint("SMAP is supported.");
|
KPrint("SMAP is supported.");
|
||||||
debug("SMAP is supported.");
|
fixme("Not going to enable SMAP.");
|
||||||
// cr4.SMAP = 1;
|
// cr4.SMAP = 1;
|
||||||
}
|
}
|
||||||
if (strcmp(Hypervisor(), x86_CPUID_VENDOR_VIRTUALBOX) != 0 &&
|
if (strcmp(Hypervisor(), x86_CPUID_VENDOR_VIRTUALBOX) != 0 &&
|
||||||
strcmp(Hypervisor(), x86_CPUID_VENDOR_TCG) != 0)
|
strcmp(Hypervisor(), x86_CPUID_VENDOR_TCG) != 0)
|
||||||
{
|
|
||||||
debug("Writing CR4...");
|
|
||||||
x64::writecr4(cr4);
|
x64::writecr4(cr4);
|
||||||
debug("Wrote CR4.");
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!BSP)
|
if (!BSP)
|
||||||
{
|
{
|
||||||
if (strcmp(Hypervisor(), x86_CPUID_VENDOR_VIRTUALBOX) == 0)
|
if (strcmp(Hypervisor(), x86_CPUID_VENDOR_VIRTUALBOX) != 0)
|
||||||
KPrint("VirtualBox detected. Not using UMIP, SMEP & SMAP");
|
KPrint("VirtualBox detected. Not using UMIP, SMEP & SMAP");
|
||||||
else if (strcmp(Hypervisor(), x86_CPUID_VENDOR_TCG) == 0)
|
else if (strcmp(Hypervisor(), x86_CPUID_VENDOR_TCG) != 0)
|
||||||
KPrint("QEMU (TCG) detected. Not using UMIP, SMEP & SMAP");
|
KPrint("QEMU (TCG) detected. Not using UMIP, SMEP & SMAP");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -314,176 +249,26 @@ namespace CPU
|
|||||||
x64::wrmsr(x64::MSR_CR_PAT, 0x6 | (0x0 << 8) | (0x1 << 16));
|
x64::wrmsr(x64::MSR_CR_PAT, 0x6 | (0x0 << 8) | (0x1 << 16));
|
||||||
if (!BSP++)
|
if (!BSP++)
|
||||||
trace("Features for BSP initialized.");
|
trace("Features for BSP initialized.");
|
||||||
if (SSEEnableAfter)
|
#elif defined(__i386__)
|
||||||
SSEEnabled = true;
|
#elif defined(__aarch64__)
|
||||||
#elif defined(a32)
|
|
||||||
#elif defined(aa64)
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
uintptr_t Counter()
|
uint64_t Counter()
|
||||||
{
|
{
|
||||||
// TODO: Get the counter from the x2APIC or any other timer that is available. (TSC is not available on all CPUs)
|
// TODO: Get the counter from the x2APIC or any other timer that is available. (TSC is not available on all CPUs)
|
||||||
uintptr_t Counter;
|
#if defined(__amd64__)
|
||||||
#if defined(a64)
|
uint64_t counter;
|
||||||
asmv("rdtsc"
|
asmv("rdtsc"
|
||||||
: "=A"(Counter));
|
: "=A"(counter));
|
||||||
#elif defined(a32)
|
return counter;
|
||||||
asmv("rdtsc"
|
#elif defined(__i386__)
|
||||||
: "=A"(Counter));
|
return 0;
|
||||||
#elif defined(aa64)
|
#elif defined(__aarch64__)
|
||||||
|
uint64_t counter;
|
||||||
asmv("mrs %0, cntvct_el0"
|
asmv("mrs %0, cntvct_el0"
|
||||||
: "=r"(Counter));
|
: "=r"(counter));
|
||||||
|
return counter;
|
||||||
#endif
|
#endif
|
||||||
return Counter;
|
|
||||||
}
|
|
||||||
|
|
||||||
x86SIMDType CheckSIMD()
|
|
||||||
{
|
|
||||||
#if defined(a32)
|
|
||||||
return SIMD_NONE; /* TODO: Support x86 SIMD on x32 */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (unlikely(!SSEEnabled))
|
|
||||||
return SIMD_NONE;
|
|
||||||
|
|
||||||
static x86SIMDType SIMDType = SIMD_NONE;
|
|
||||||
|
|
||||||
if (likely(SIMDType != SIMD_NONE))
|
|
||||||
return SIMDType;
|
|
||||||
|
|
||||||
if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_AMD) == 0)
|
|
||||||
{
|
|
||||||
#if defined(a64)
|
|
||||||
CPU::x64::AMD::CPUID0x1 cpuid1amd;
|
|
||||||
#elif defined(a32)
|
|
||||||
CPU::x32::AMD::CPUID0x1 cpuid1amd;
|
|
||||||
#endif
|
|
||||||
#if defined(a64) || defined(a32)
|
|
||||||
asmv("cpuid"
|
|
||||||
: "=a"(cpuid1amd.EAX.raw), "=b"(cpuid1amd.EBX.raw), "=c"(cpuid1amd.ECX.raw), "=d"(cpuid1amd.EDX.raw)
|
|
||||||
: "a"(0x1));
|
|
||||||
#endif
|
|
||||||
if (cpuid1amd.ECX.SSE4_2)
|
|
||||||
SIMDType = SIMD_SSE42;
|
|
||||||
else if (cpuid1amd.ECX.SSE4_1)
|
|
||||||
SIMDType = SIMD_SSE41;
|
|
||||||
else if (cpuid1amd.ECX.SSE3)
|
|
||||||
SIMDType = SIMD_SSE3;
|
|
||||||
else if (cpuid1amd.EDX.SSE2)
|
|
||||||
SIMDType = SIMD_SSE2;
|
|
||||||
else if (cpuid1amd.EDX.SSE)
|
|
||||||
SIMDType = SIMD_SSE;
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
if (cpuid1amd.ECX.SSE4_2)
|
|
||||||
debug("SSE4.2 is supported.");
|
|
||||||
if (cpuid1amd.ECX.SSE4_1)
|
|
||||||
debug("SSE4.1 is supported.");
|
|
||||||
if (cpuid1amd.ECX.SSE3)
|
|
||||||
debug("SSE3 is supported.");
|
|
||||||
if (cpuid1amd.EDX.SSE2)
|
|
||||||
debug("SSE2 is supported.");
|
|
||||||
if (cpuid1amd.EDX.SSE)
|
|
||||||
debug("SSE is supported.");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return SIMDType;
|
|
||||||
}
|
|
||||||
else if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_INTEL) == 0)
|
|
||||||
{
|
|
||||||
#if defined(a64)
|
|
||||||
CPU::x64::Intel::CPUID0x1 cpuid1intel;
|
|
||||||
#elif defined(a32)
|
|
||||||
CPU::x32::Intel::CPUID0x1 cpuid1intel;
|
|
||||||
#endif
|
|
||||||
#if defined(a64) || defined(a32)
|
|
||||||
asmv("cpuid"
|
|
||||||
: "=a"(cpuid1intel.EAX.raw), "=b"(cpuid1intel.EBX.raw), "=c"(cpuid1intel.ECX.raw), "=d"(cpuid1intel.EDX.raw)
|
|
||||||
: "a"(0x1));
|
|
||||||
#endif
|
|
||||||
if (cpuid1intel.ECX.SSE4_2)
|
|
||||||
SIMDType = SIMD_SSE42;
|
|
||||||
else if (cpuid1intel.ECX.SSE4_1)
|
|
||||||
SIMDType = SIMD_SSE41;
|
|
||||||
else if (cpuid1intel.ECX.SSE3)
|
|
||||||
SIMDType = SIMD_SSE3;
|
|
||||||
else if (cpuid1intel.EDX.SSE2)
|
|
||||||
SIMDType = SIMD_SSE2;
|
|
||||||
else if (cpuid1intel.EDX.SSE)
|
|
||||||
SIMDType = SIMD_SSE;
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
if (cpuid1intel.ECX.SSE4_2)
|
|
||||||
debug("SSE4.2 is supported.");
|
|
||||||
if (cpuid1intel.ECX.SSE4_1)
|
|
||||||
debug("SSE4.1 is supported.");
|
|
||||||
if (cpuid1intel.ECX.SSE3)
|
|
||||||
debug("SSE3 is supported.");
|
|
||||||
if (cpuid1intel.EDX.SSE2)
|
|
||||||
debug("SSE2 is supported.");
|
|
||||||
if (cpuid1intel.EDX.SSE)
|
|
||||||
debug("SSE is supported.");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return SIMDType;
|
|
||||||
}
|
|
||||||
|
|
||||||
return SIMD_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CheckSIMD(x86SIMDType Type)
|
|
||||||
{
|
|
||||||
if (unlikely(!SSEEnabled))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_AMD) == 0)
|
|
||||||
{
|
|
||||||
#if defined(a64)
|
|
||||||
CPU::x64::AMD::CPUID0x1 cpuid1amd;
|
|
||||||
#elif defined(a32)
|
|
||||||
CPU::x32::AMD::CPUID0x1 cpuid1amd;
|
|
||||||
#endif
|
|
||||||
#if defined(a64) || defined(a32)
|
|
||||||
asmv("cpuid"
|
|
||||||
: "=a"(cpuid1amd.EAX.raw), "=b"(cpuid1amd.EBX.raw), "=c"(cpuid1amd.ECX.raw), "=d"(cpuid1amd.EDX.raw)
|
|
||||||
: "a"(0x1));
|
|
||||||
#endif
|
|
||||||
if (Type == SIMD_SSE42)
|
|
||||||
return cpuid1amd.ECX.SSE4_2;
|
|
||||||
else if (Type == SIMD_SSE41)
|
|
||||||
return cpuid1amd.ECX.SSE4_1;
|
|
||||||
else if (Type == SIMD_SSE3)
|
|
||||||
return cpuid1amd.ECX.SSE3;
|
|
||||||
else if (Type == SIMD_SSE2)
|
|
||||||
return cpuid1amd.EDX.SSE2;
|
|
||||||
else if (Type == SIMD_SSE)
|
|
||||||
return cpuid1amd.EDX.SSE;
|
|
||||||
}
|
|
||||||
else if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_INTEL) == 0)
|
|
||||||
{
|
|
||||||
#if defined(a64)
|
|
||||||
CPU::x64::Intel::CPUID0x1 cpuid1intel;
|
|
||||||
#elif defined(a32)
|
|
||||||
CPU::x32::Intel::CPUID0x1 cpuid1intel;
|
|
||||||
#endif
|
|
||||||
#if defined(a64) || defined(a32)
|
|
||||||
asmv("cpuid"
|
|
||||||
: "=a"(cpuid1intel.EAX.raw), "=b"(cpuid1intel.EBX.raw), "=c"(cpuid1intel.ECX.raw), "=d"(cpuid1intel.EDX.raw)
|
|
||||||
: "a"(0x1));
|
|
||||||
#endif
|
|
||||||
if (Type == SIMD_SSE42)
|
|
||||||
return cpuid1intel.ECX.SSE4_2;
|
|
||||||
else if (Type == SIMD_SSE41)
|
|
||||||
return cpuid1intel.ECX.SSE4_1;
|
|
||||||
else if (Type == SIMD_SSE3)
|
|
||||||
return cpuid1intel.ECX.SSE3;
|
|
||||||
else if (Type == SIMD_SSE2)
|
|
||||||
return cpuid1intel.EDX.SSE2;
|
|
||||||
else if (Type == SIMD_SSE)
|
|
||||||
return cpuid1intel.EDX.SSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,15 +7,15 @@
|
|||||||
#include <smp.hpp>
|
#include <smp.hpp>
|
||||||
#include <cpu.hpp>
|
#include <cpu.hpp>
|
||||||
|
|
||||||
#if defined(a64)
|
#if defined(__amd64__)
|
||||||
#include "../../Architecture/amd64/cpu/gdt.hpp"
|
#include "../../Architecture/amd64/cpu/gdt.hpp"
|
||||||
#elif defined(a32)
|
#elif defined(__i386__)
|
||||||
#elif defined(aa64)
|
#elif defined(__aarch64__)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "../../kernel.h"
|
#include "../../kernel.h"
|
||||||
|
|
||||||
static const char *PageFaultDescriptions[8] = {
|
static const char *PagefaultDescriptions[8] = {
|
||||||
"Supervisory process tried to read a non-present page entry\n",
|
"Supervisory process tried to read a non-present page entry\n",
|
||||||
"Supervisory process tried to read a page and caused a protection fault\n",
|
"Supervisory process tried to read a page and caused a protection fault\n",
|
||||||
"Supervisory process tried to write to a non-present page entry\n",
|
"Supervisory process tried to write to a non-present page entry\n",
|
||||||
@ -28,92 +28,49 @@ static const char *PageFaultDescriptions[8] = {
|
|||||||
SafeFunction void DivideByZeroExceptionHandler(CHArchTrapFrame *Frame)
|
SafeFunction void DivideByZeroExceptionHandler(CHArchTrapFrame *Frame)
|
||||||
{
|
{
|
||||||
fixme("Divide by zero exception\n");
|
fixme("Divide by zero exception\n");
|
||||||
UNUSED(Frame);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SafeFunction void DebugExceptionHandler(CHArchTrapFrame *Frame)
|
SafeFunction void DebugExceptionHandler(CHArchTrapFrame *Frame)
|
||||||
{
|
{
|
||||||
|
CrashHandler::EHPrint("\eDD2920System crashed!\n");
|
||||||
CrashHandler::EHPrint("Kernel triggered debug exception.\n");
|
CrashHandler::EHPrint("Kernel triggered debug exception.\n");
|
||||||
UNUSED(Frame);
|
|
||||||
}
|
}
|
||||||
|
SafeFunction void NonMaskableInterruptExceptionHandler(CHArchTrapFrame *Frame) { fixme("NMI exception"); }
|
||||||
SafeFunction void NonMaskableInterruptExceptionHandler(CHArchTrapFrame *Frame)
|
SafeFunction void BreakpointExceptionHandler(CHArchTrapFrame *Frame) { fixme("Breakpoint exception"); }
|
||||||
{
|
SafeFunction void OverflowExceptionHandler(CHArchTrapFrame *Frame) { fixme("Overflow exception"); }
|
||||||
fixme("NMI exception");
|
SafeFunction void BoundRangeExceptionHandler(CHArchTrapFrame *Frame) { fixme("Bound range exception"); }
|
||||||
UNUSED(Frame);
|
|
||||||
}
|
|
||||||
|
|
||||||
SafeFunction void BreakpointExceptionHandler(CHArchTrapFrame *Frame)
|
|
||||||
{
|
|
||||||
fixme("Breakpoint exception");
|
|
||||||
UNUSED(Frame);
|
|
||||||
}
|
|
||||||
|
|
||||||
SafeFunction void OverflowExceptionHandler(CHArchTrapFrame *Frame)
|
|
||||||
{
|
|
||||||
fixme("Overflow exception");
|
|
||||||
UNUSED(Frame);
|
|
||||||
}
|
|
||||||
|
|
||||||
SafeFunction void BoundRangeExceptionHandler(CHArchTrapFrame *Frame)
|
|
||||||
{
|
|
||||||
fixme("Bound range exception");
|
|
||||||
UNUSED(Frame);
|
|
||||||
}
|
|
||||||
|
|
||||||
SafeFunction void InvalidOpcodeExceptionHandler(CHArchTrapFrame *Frame)
|
SafeFunction void InvalidOpcodeExceptionHandler(CHArchTrapFrame *Frame)
|
||||||
{
|
{
|
||||||
|
CrashHandler::EHPrint("\eDD2920System crashed!\n");
|
||||||
CrashHandler::EHPrint("Kernel tried to execute an invalid opcode.\n");
|
CrashHandler::EHPrint("Kernel tried to execute an invalid opcode.\n");
|
||||||
UNUSED(Frame);
|
|
||||||
}
|
}
|
||||||
|
SafeFunction void DeviceNotAvailableExceptionHandler(CHArchTrapFrame *Frame) { fixme("Device not available exception"); }
|
||||||
SafeFunction void DeviceNotAvailableExceptionHandler(CHArchTrapFrame *Frame)
|
SafeFunction void DoubleFaultExceptionHandler(CHArchTrapFrame *Frame) { fixme("Double fault exception"); }
|
||||||
{
|
SafeFunction void CoprocessorSegmentOverrunExceptionHandler(CHArchTrapFrame *Frame) { fixme("Coprocessor segment overrun exception"); }
|
||||||
fixme("Device not available exception");
|
SafeFunction void InvalidTSSExceptionHandler(CHArchTrapFrame *Frame) { fixme("Invalid TSS exception"); }
|
||||||
UNUSED(Frame);
|
SafeFunction void SegmentNotPresentExceptionHandler(CHArchTrapFrame *Frame) { fixme("Segment not present exception"); }
|
||||||
}
|
|
||||||
|
|
||||||
SafeFunction void DoubleFaultExceptionHandler(CHArchTrapFrame *Frame)
|
|
||||||
{
|
|
||||||
fixme("Double fault exception");
|
|
||||||
UNUSED(Frame);
|
|
||||||
}
|
|
||||||
|
|
||||||
SafeFunction void CoprocessorSegmentOverrunExceptionHandler(CHArchTrapFrame *Frame)
|
|
||||||
{
|
|
||||||
fixme("Coprocessor segment overrun exception");
|
|
||||||
UNUSED(Frame);
|
|
||||||
}
|
|
||||||
|
|
||||||
SafeFunction void InvalidTSSExceptionHandler(CHArchTrapFrame *Frame)
|
|
||||||
{
|
|
||||||
fixme("Invalid TSS exception");
|
|
||||||
UNUSED(Frame);
|
|
||||||
}
|
|
||||||
|
|
||||||
SafeFunction void SegmentNotPresentExceptionHandler(CHArchTrapFrame *Frame)
|
|
||||||
{
|
|
||||||
fixme("Segment not present exception");
|
|
||||||
UNUSED(Frame);
|
|
||||||
}
|
|
||||||
|
|
||||||
SafeFunction void StackFaultExceptionHandler(CHArchTrapFrame *Frame)
|
SafeFunction void StackFaultExceptionHandler(CHArchTrapFrame *Frame)
|
||||||
{
|
{
|
||||||
CPU::x64::SelectorErrorCode SelCode = {.raw = Frame->ErrorCode};
|
CPU::x64::SelectorErrorCode SelCode = {.raw = Frame->ErrorCode};
|
||||||
#if defined(a64)
|
CrashHandler::EHPrint("\eDD2920System crashed!\n");
|
||||||
|
CrashHandler::EHPrint("More info about the exception:\n");
|
||||||
|
#if defined(__amd64__)
|
||||||
CrashHandler::EHPrint("Stack segment fault at address %#lx\n", Frame->rip);
|
CrashHandler::EHPrint("Stack segment fault at address %#lx\n", Frame->rip);
|
||||||
#elif defined(a32)
|
#elif defined(__i386__)
|
||||||
CrashHandler::EHPrint("Stack segment fault at address %#lx\n", Frame->eip);
|
CrashHandler::EHPrint("Stack segment fault at address %#lx\n", Frame->eip);
|
||||||
#elif defined(aa64)
|
#elif defined(__aarch64__)
|
||||||
#endif
|
#endif
|
||||||
CrashHandler::EHPrint("External: %d\n", SelCode.External);
|
CrashHandler::EHPrint("External: %d\n", SelCode.External);
|
||||||
CrashHandler::EHPrint("Table: %d\n", SelCode.Table);
|
CrashHandler::EHPrint("Table: %d\n", SelCode.Table);
|
||||||
CrashHandler::EHPrint("Index: %#x\n", SelCode.Idx);
|
CrashHandler::EHPrint("Index: %#x\n", SelCode.Idx);
|
||||||
CrashHandler::EHPrint("Error code: %#lx\n", Frame->ErrorCode);
|
CrashHandler::EHPrint("Error code: %#lx\n", Frame->ErrorCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
SafeFunction void GeneralProtectionExceptionHandler(CHArchTrapFrame *Frame)
|
SafeFunction void GeneralProtectionExceptionHandler(CHArchTrapFrame *Frame)
|
||||||
{
|
{
|
||||||
|
// staticbuffer(descbuf);
|
||||||
|
// staticbuffer(desc_ext);
|
||||||
|
// staticbuffer(desc_table);
|
||||||
|
// staticbuffer(desc_idx);
|
||||||
|
// staticbuffer(desc_tmp);
|
||||||
CPU::x64::SelectorErrorCode SelCode = {.raw = Frame->ErrorCode};
|
CPU::x64::SelectorErrorCode SelCode = {.raw = Frame->ErrorCode};
|
||||||
// switch (SelCode.Table)
|
// switch (SelCode.Table)
|
||||||
// {
|
// {
|
||||||
@ -133,20 +90,22 @@ SafeFunction void GeneralProtectionExceptionHandler(CHArchTrapFrame *Frame)
|
|||||||
// memcpy(desc_tmp, "Unknown", 7);
|
// memcpy(desc_tmp, "Unknown", 7);
|
||||||
// break;
|
// break;
|
||||||
// }
|
// }
|
||||||
|
CrashHandler::EHPrint("\eDD2920System crashed!\n");
|
||||||
CrashHandler::EHPrint("Kernel performed an illegal operation.\n");
|
CrashHandler::EHPrint("Kernel performed an illegal operation.\n");
|
||||||
|
CrashHandler::EHPrint("More info about the exception:\n");
|
||||||
CrashHandler::EHPrint("External: %d\n", SelCode.External);
|
CrashHandler::EHPrint("External: %d\n", SelCode.External);
|
||||||
CrashHandler::EHPrint("Table: %d\n", SelCode.Table);
|
CrashHandler::EHPrint("Table: %d\n", SelCode.Table);
|
||||||
CrashHandler::EHPrint("Index: %#x\n", SelCode.Idx);
|
CrashHandler::EHPrint("Index: %#x\n", SelCode.Idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
SafeFunction void PageFaultExceptionHandler(CHArchTrapFrame *Frame)
|
SafeFunction void PageFaultExceptionHandler(CHArchTrapFrame *Frame)
|
||||||
{
|
{
|
||||||
CPU::x64::PageFaultErrorCode params = {.raw = (uint32_t)Frame->ErrorCode};
|
CPU::x64::PageFaultErrorCode params = {.raw = (uint32_t)Frame->ErrorCode};
|
||||||
#if defined(a64)
|
CrashHandler::EHPrint("\eDD2920System crashed!\n\eFFFFFF");
|
||||||
CrashHandler::EHPrint("\eAFAFAFAn exception occurred at %#lx by %#lx\n", CrashHandler::PageFaultAddress, Frame->rip);
|
#if defined(__amd64__)
|
||||||
#elif defined(a32)
|
CrashHandler::EHPrint("An exception occurred at %#lx by %#lx\n", CPU::x64::readcr2().PFLA, Frame->rip);
|
||||||
CrashHandler::EHPrint("\eAFAFAFAn exception occurred at %#lx by %#lx\n", CrashHandler::PageFaultAddress, Frame->eip);
|
#elif defined(__i386__)
|
||||||
#elif defined(aa64)
|
CrashHandler::EHPrint("An exception occurred at %#lx by %#lx\n", CPU::x64::readcr2().PFLA, Frame->eip);
|
||||||
|
#elif defined(__aarch64__)
|
||||||
#endif
|
#endif
|
||||||
CrashHandler::EHPrint("Page: %s\n", params.P ? "Present" : "Not Present");
|
CrashHandler::EHPrint("Page: %s\n", params.P ? "Present" : "Not Present");
|
||||||
CrashHandler::EHPrint("Write Operation: %s\n", params.W ? "Read-Only" : "Read-Write");
|
CrashHandler::EHPrint("Write Operation: %s\n", params.W ? "Read-Only" : "Read-Write");
|
||||||
@ -159,166 +118,12 @@ SafeFunction void PageFaultExceptionHandler(CHArchTrapFrame *Frame)
|
|||||||
if (Frame->ErrorCode & 0x00000008)
|
if (Frame->ErrorCode & 0x00000008)
|
||||||
CrashHandler::EHPrint("One or more page directory entries contain reserved bits which are set to 1.\n");
|
CrashHandler::EHPrint("One or more page directory entries contain reserved bits which are set to 1.\n");
|
||||||
else
|
else
|
||||||
CrashHandler::EHPrint(PageFaultDescriptions[Frame->ErrorCode & 0b111]);
|
CrashHandler::EHPrint(PagefaultDescriptions[Frame->ErrorCode & 0b111]);
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
uintptr_t CheckPageFaultAddress = 0;
|
|
||||||
CheckPageFaultAddress = CrashHandler::PageFaultAddress;
|
|
||||||
if (CheckPageFaultAddress == 0)
|
|
||||||
#ifdef a64
|
|
||||||
CheckPageFaultAddress = Frame->rip;
|
|
||||||
#elif defined(a32)
|
|
||||||
CheckPageFaultAddress = Frame->eip;
|
|
||||||
#elif defined(aa64)
|
|
||||||
CheckPageFaultAddress = 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(a64)
|
|
||||||
Memory::Virtual vma = Memory::Virtual(((Memory::PageTable4 *)CPU::x64::readcr3().raw));
|
|
||||||
#elif defined(a32)
|
|
||||||
Memory::Virtual vma = Memory::Virtual(((Memory::PageTable4 *)CPU::x32::readcr3().raw));
|
|
||||||
#elif defined(aa64)
|
|
||||||
#endif
|
|
||||||
bool PageAvailable = vma.Check((void *)CheckPageFaultAddress);
|
|
||||||
debug("Page available (Check(...)): %s. %s",
|
|
||||||
PageAvailable ? "Yes" : "No",
|
|
||||||
(params.P && !PageAvailable) ? "CR2 == Present; Check() != Present??????" : "CR2 confirms Check() result.");
|
|
||||||
|
|
||||||
if (PageAvailable)
|
|
||||||
{
|
|
||||||
bool Present = vma.Check((void *)CheckPageFaultAddress);
|
|
||||||
bool ReadWrite = vma.Check((void *)CheckPageFaultAddress, Memory::PTFlag::RW);
|
|
||||||
bool User = vma.Check((void *)CheckPageFaultAddress, Memory::PTFlag::US);
|
|
||||||
bool WriteThrough = vma.Check((void *)CheckPageFaultAddress, Memory::PTFlag::PWT);
|
|
||||||
bool CacheDisabled = vma.Check((void *)CheckPageFaultAddress, Memory::PTFlag::PCD);
|
|
||||||
bool Accessed = vma.Check((void *)CheckPageFaultAddress, Memory::PTFlag::A);
|
|
||||||
bool Dirty = vma.Check((void *)CheckPageFaultAddress, Memory::PTFlag::D);
|
|
||||||
bool Global = vma.Check((void *)CheckPageFaultAddress, Memory::PTFlag::G);
|
|
||||||
/* ... */
|
|
||||||
|
|
||||||
debug("Page available: %s", Present ? "Yes" : "No");
|
|
||||||
debug("Page read/write: %s", ReadWrite ? "Yes" : "No");
|
|
||||||
debug("Page user/kernel: %s", User ? "User" : "Kernel");
|
|
||||||
debug("Page write-through: %s", WriteThrough ? "Yes" : "No");
|
|
||||||
debug("Page cache disabled: %s", CacheDisabled ? "Yes" : "No");
|
|
||||||
debug("Page accessed: %s", Accessed ? "Yes" : "No");
|
|
||||||
debug("Page dirty: %s", Dirty ? "Yes" : "No");
|
|
||||||
debug("Page global: %s", Global ? "Yes" : "No");
|
|
||||||
|
|
||||||
if (Present)
|
|
||||||
{
|
|
||||||
uintptr_t CheckPageFaultLinearAddress = (uintptr_t)CheckPageFaultAddress;
|
|
||||||
CheckPageFaultLinearAddress &= 0xFFFFFFFFFFFFF000;
|
|
||||||
debug("%#lx -> %#lx", CheckPageFaultAddress, CheckPageFaultLinearAddress);
|
|
||||||
|
|
||||||
Memory::Virtual::PageMapIndexer Index = Memory::Virtual::PageMapIndexer((uintptr_t)CheckPageFaultLinearAddress);
|
|
||||||
debug("Index for %#lx is PML:%d PDPTE:%d PDE:%d PTE:%d",
|
|
||||||
CheckPageFaultLinearAddress,
|
|
||||||
Index.PMLIndex,
|
|
||||||
Index.PDPTEIndex,
|
|
||||||
Index.PDEIndex,
|
|
||||||
Index.PTEIndex);
|
|
||||||
#if defined(a64)
|
|
||||||
Memory::PageMapLevel4 PML4 = ((Memory::PageTable4 *)CPU::x64::readcr3().raw)->Entries[Index.PMLIndex];
|
|
||||||
#elif defined(a32)
|
|
||||||
Memory::PageMapLevel4 PML4 = ((Memory::PageTable4 *)CPU::x32::readcr3().raw)->Entries[Index.PMLIndex];
|
|
||||||
#elif defined(aa64)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
Memory::PageDirectoryPointerTableEntryPtr *PDPTE = (Memory::PageDirectoryPointerTableEntryPtr *)((uintptr_t)PML4.GetAddress() << 12);
|
|
||||||
Memory::PageDirectoryEntryPtr *PDE = (Memory::PageDirectoryEntryPtr *)((uintptr_t)PDPTE->Entries[Index.PDPTEIndex].GetAddress() << 12);
|
|
||||||
Memory::PageTableEntryPtr *PTE = (Memory::PageTableEntryPtr *)((uintptr_t)PDE->Entries[Index.PDEIndex].GetAddress() << 12);
|
|
||||||
|
|
||||||
debug("# %03d-%03d-%03d-%03d: P:%s RW:%s US:%s PWT:%s PCB:%s A:%s NX:%s Address:%#lx",
|
|
||||||
Index.PMLIndex, 0, 0, 0,
|
|
||||||
PML4.Present ? "1" : "0",
|
|
||||||
PML4.ReadWrite ? "1" : "0",
|
|
||||||
PML4.UserSupervisor ? "1" : "0",
|
|
||||||
PML4.WriteThrough ? "1" : "0",
|
|
||||||
PML4.CacheDisable ? "1" : "0",
|
|
||||||
PML4.Accessed ? "1" : "0",
|
|
||||||
PML4.ExecuteDisable ? "1" : "0",
|
|
||||||
PML4.GetAddress() << 12);
|
|
||||||
|
|
||||||
debug("# %03d-%03d-%03d-%03d: P:%s RW:%s US:%s PWT:%s PCB:%s A:%s NX:%s Address:%#lx",
|
|
||||||
Index.PMLIndex, Index.PDPTEIndex, 0, 0,
|
|
||||||
PDPTE->Entries[Index.PDPTEIndex].Present ? "1" : "0",
|
|
||||||
PDPTE->Entries[Index.PDPTEIndex].ReadWrite ? "1" : "0",
|
|
||||||
PDPTE->Entries[Index.PDPTEIndex].UserSupervisor ? "1" : "0",
|
|
||||||
PDPTE->Entries[Index.PDPTEIndex].WriteThrough ? "1" : "0",
|
|
||||||
PDPTE->Entries[Index.PDPTEIndex].CacheDisable ? "1" : "0",
|
|
||||||
PDPTE->Entries[Index.PDPTEIndex].Accessed ? "1" : "0",
|
|
||||||
PDPTE->Entries[Index.PDPTEIndex].ExecuteDisable ? "1" : "0",
|
|
||||||
PDPTE->Entries[Index.PDPTEIndex].GetAddress() << 12);
|
|
||||||
|
|
||||||
debug("# %03d-%03d-%03d-%03d: P:%s RW:%s US:%s PWT:%s PCB:%s A:%s NX:%s Address:%#lx",
|
|
||||||
Index.PMLIndex, Index.PDPTEIndex, Index.PDEIndex, 0,
|
|
||||||
PDE->Entries[Index.PDEIndex].Present ? "1" : "0",
|
|
||||||
PDE->Entries[Index.PDEIndex].ReadWrite ? "1" : "0",
|
|
||||||
PDE->Entries[Index.PDEIndex].UserSupervisor ? "1" : "0",
|
|
||||||
PDE->Entries[Index.PDEIndex].WriteThrough ? "1" : "0",
|
|
||||||
PDE->Entries[Index.PDEIndex].CacheDisable ? "1" : "0",
|
|
||||||
PDE->Entries[Index.PDEIndex].Accessed ? "1" : "0",
|
|
||||||
PDE->Entries[Index.PDEIndex].ExecuteDisable ? "1" : "0",
|
|
||||||
PDE->Entries[Index.PDEIndex].GetAddress() << 12);
|
|
||||||
|
|
||||||
debug("# %03d-%03d-%03d-%03d: P:%s RW:%s US:%s PWT:%s PCB:%s A:%s D:%s PAT:%s G:%s PK:%d NX:%s Address:%#lx",
|
|
||||||
Index.PMLIndex, Index.PDPTEIndex, Index.PDEIndex, Index.PTEIndex,
|
|
||||||
PTE->Entries[Index.PTEIndex].Present ? "1" : "0",
|
|
||||||
PTE->Entries[Index.PTEIndex].ReadWrite ? "1" : "0",
|
|
||||||
PTE->Entries[Index.PTEIndex].UserSupervisor ? "1" : "0",
|
|
||||||
PTE->Entries[Index.PTEIndex].WriteThrough ? "1" : "0",
|
|
||||||
PTE->Entries[Index.PTEIndex].CacheDisable ? "1" : "0",
|
|
||||||
PTE->Entries[Index.PTEIndex].Accessed ? "1" : "0",
|
|
||||||
PTE->Entries[Index.PTEIndex].Dirty ? "1" : "0",
|
|
||||||
PTE->Entries[Index.PTEIndex].PageAttributeTable ? "1" : "0",
|
|
||||||
PTE->Entries[Index.PTEIndex].Global ? "1" : "0",
|
|
||||||
PTE->Entries[Index.PTEIndex].ProtectionKey,
|
|
||||||
PTE->Entries[Index.PTEIndex].ExecuteDisable ? "1" : "0",
|
|
||||||
PTE->Entries[Index.PTEIndex].GetAddress() << 12);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
SafeFunction void x87FloatingPointExceptionHandler(CHArchTrapFrame *Frame)
|
|
||||||
{
|
|
||||||
fixme("x87 floating point exception");
|
|
||||||
UNUSED(Frame);
|
|
||||||
}
|
|
||||||
|
|
||||||
SafeFunction void AlignmentCheckExceptionHandler(CHArchTrapFrame *Frame)
|
|
||||||
{
|
|
||||||
fixme("Alignment check exception");
|
|
||||||
UNUSED(Frame);
|
|
||||||
}
|
|
||||||
|
|
||||||
SafeFunction void MachineCheckExceptionHandler(CHArchTrapFrame *Frame)
|
|
||||||
{
|
|
||||||
fixme("Machine check exception");
|
|
||||||
UNUSED(Frame);
|
|
||||||
}
|
|
||||||
|
|
||||||
SafeFunction void SIMDFloatingPointExceptionHandler(CHArchTrapFrame *Frame)
|
|
||||||
{
|
|
||||||
fixme("SIMD floating point exception");
|
|
||||||
UNUSED(Frame);
|
|
||||||
}
|
|
||||||
|
|
||||||
SafeFunction void VirtualizationExceptionHandler(CHArchTrapFrame *Frame)
|
|
||||||
{
|
|
||||||
fixme("Virtualization exception");
|
|
||||||
UNUSED(Frame);
|
|
||||||
}
|
|
||||||
|
|
||||||
SafeFunction void SecurityExceptionHandler(CHArchTrapFrame *Frame)
|
|
||||||
{
|
|
||||||
fixme("Security exception");
|
|
||||||
UNUSED(Frame);
|
|
||||||
}
|
|
||||||
|
|
||||||
SafeFunction void UnknownExceptionHandler(CHArchTrapFrame *Frame)
|
|
||||||
{
|
|
||||||
fixme("Unknown exception");
|
|
||||||
UNUSED(Frame);
|
|
||||||
}
|
}
|
||||||
|
SafeFunction void x87FloatingPointExceptionHandler(CHArchTrapFrame *Frame) { fixme("x87 floating point exception"); }
|
||||||
|
SafeFunction void AlignmentCheckExceptionHandler(CHArchTrapFrame *Frame) { fixme("Alignment check exception"); }
|
||||||
|
SafeFunction void MachineCheckExceptionHandler(CHArchTrapFrame *Frame) { fixme("Machine check exception"); }
|
||||||
|
SafeFunction void SIMDFloatingPointExceptionHandler(CHArchTrapFrame *Frame) { fixme("SIMD floating point exception"); }
|
||||||
|
SafeFunction void VirtualizationExceptionHandler(CHArchTrapFrame *Frame) { fixme("Virtualization exception"); }
|
||||||
|
SafeFunction void SecurityExceptionHandler(CHArchTrapFrame *Frame) { fixme("Security exception"); }
|
||||||
|
SafeFunction void UnknownExceptionHandler(CHArchTrapFrame *Frame) { fixme("Unknown exception"); }
|
||||||
|
@ -6,34 +6,42 @@
|
|||||||
#include <convert.h>
|
#include <convert.h>
|
||||||
#include <printf.h>
|
#include <printf.h>
|
||||||
#include <lock.hpp>
|
#include <lock.hpp>
|
||||||
#include <rand.hpp>
|
|
||||||
#include <uart.hpp>
|
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
#include <smp.hpp>
|
#include <smp.hpp>
|
||||||
#include <cpu.hpp>
|
#include <cpu.hpp>
|
||||||
#include <io.h>
|
#include <io.h>
|
||||||
|
|
||||||
#if defined(a64)
|
#if defined(__amd64__)
|
||||||
#include "../../Architecture/amd64/cpu/gdt.hpp"
|
#include "../../Architecture/amd64/cpu/gdt.hpp"
|
||||||
#include "../Architecture/amd64/cpu/apic.hpp"
|
#elif defined(__i386__)
|
||||||
#elif defined(a32)
|
#elif defined(__aarch64__)
|
||||||
#include "../../Architecture/i686/cpu/gdt.hpp"
|
|
||||||
#include "../Architecture/i686/cpu/apic.hpp"
|
|
||||||
#elif defined(aa64)
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "../../kernel.h"
|
#include "../../kernel.h"
|
||||||
#include "../../DAPI.hpp"
|
|
||||||
|
|
||||||
NewLock(UserInputLock);
|
NewLock(UserInputLock);
|
||||||
|
|
||||||
|
#define TRACE_PAGE_TABLE(x, itr, depth) \
|
||||||
|
EHPrint("\e888888#%s\eAABBCC%03d\e4500F5: P:%s RW:%s US:%s PWT:%s PCB:%s A:%s D:%s PS:%s G:%s Address:\e888888%#lx\n", \
|
||||||
|
depth, \
|
||||||
|
itr, \
|
||||||
|
x.Value.Present ? "\e00AA00Yes\e4500F5" : "\eAA0000No \e4500F5", \
|
||||||
|
x.Value.ReadWrite ? "\e00AA00Yes\e4500F5" : "\eAA0000No \e4500F5", \
|
||||||
|
x.Value.UserSupervisor ? "\e00AA00Yes\e4500F5" : "\eAA0000No \e4500F5", \
|
||||||
|
x.Value.WriteThrough ? "\e00AA00Yes\e4500F5" : "\eAA0000No \e4500F5", \
|
||||||
|
x.Value.CacheDisable ? "\e00AA00Yes\e4500F5" : "\eAA0000No \e4500F5", \
|
||||||
|
x.Value.Accessed ? "\e00AA00Yes\e4500F5" : "\eAA0000No \e4500F5", \
|
||||||
|
x.Value.Dirty ? "\e00AA00Yes\e4500F5" : "\eAA0000No \e4500F5", \
|
||||||
|
x.Value.PageSize ? "\e00AA00Yes\e4500F5" : "\eAA0000No \e4500F5", \
|
||||||
|
x.Value.Global ? "\e00AA00Yes\e4500F5" : "\eAA0000No \e4500F5", \
|
||||||
|
x.GetAddress() << 12); \
|
||||||
|
Display->SetBuffer(SBIdx);
|
||||||
|
|
||||||
namespace CrashHandler
|
namespace CrashHandler
|
||||||
{
|
{
|
||||||
uintptr_t PageFaultAddress = 0;
|
|
||||||
void *EHIntFrames[INT_FRAMES_MAX];
|
void *EHIntFrames[INT_FRAMES_MAX];
|
||||||
static bool ExceptionOccurred = false;
|
static bool ExceptionOccurred = false;
|
||||||
int SBIdx = 255;
|
int SBIdx = 255;
|
||||||
|
|
||||||
SafeFunction void printfWrapper(char c, void *unused)
|
SafeFunction void printfWrapper(char c, void *unused)
|
||||||
{
|
{
|
||||||
Display->Print(c, SBIdx, true);
|
Display->Print(c, SBIdx, true);
|
||||||
@ -48,42 +56,6 @@ namespace CrashHandler
|
|||||||
va_end(args);
|
va_end(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
SafeFunction void EHDumpData(void *Address, unsigned long Length)
|
|
||||||
{
|
|
||||||
EHPrint("-------------------------------------------------------------------------\n");
|
|
||||||
Display->SetBuffer(SBIdx);
|
|
||||||
unsigned char *AddressChar = (unsigned char *)Address;
|
|
||||||
unsigned char Buffer[17];
|
|
||||||
unsigned long Iterate;
|
|
||||||
for (Iterate = 0; Iterate < Length; Iterate++)
|
|
||||||
{
|
|
||||||
if ((Iterate % 16) == 0)
|
|
||||||
{
|
|
||||||
if (Iterate != 0)
|
|
||||||
EHPrint(" \e8A78FF%s\eAABBCC\n", Buffer);
|
|
||||||
EHPrint(" \e9E9E9E%04x\eAABBCC ", Iterate);
|
|
||||||
Display->SetBuffer(SBIdx);
|
|
||||||
}
|
|
||||||
EHPrint(" \e4287f5%02x\eAABBCC", AddressChar[Iterate]);
|
|
||||||
if ((AddressChar[Iterate] < 0x20) || (AddressChar[Iterate] > 0x7e))
|
|
||||||
Buffer[Iterate % 16] = '.';
|
|
||||||
else
|
|
||||||
Buffer[Iterate % 16] = AddressChar[Iterate];
|
|
||||||
Buffer[(Iterate % 16) + 1] = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
while ((Iterate % 16) != 0)
|
|
||||||
{
|
|
||||||
EHPrint(" ");
|
|
||||||
Display->SetBuffer(SBIdx);
|
|
||||||
Iterate++;
|
|
||||||
}
|
|
||||||
|
|
||||||
EHPrint(" \e8A78FF%s\eAABBCC\n", Buffer);
|
|
||||||
EHPrint("-------------------------------------------------------------------------\n\n.");
|
|
||||||
Display->SetBuffer(SBIdx);
|
|
||||||
}
|
|
||||||
|
|
||||||
SafeFunction char *TrimWhiteSpace(char *str)
|
SafeFunction char *TrimWhiteSpace(char *str)
|
||||||
{
|
{
|
||||||
char *end;
|
char *end;
|
||||||
@ -152,70 +124,6 @@ namespace CrashHandler
|
|||||||
EHPrint(" \eAAF00F%s", CPU::Vendor());
|
EHPrint(" \eAAF00F%s", CPU::Vendor());
|
||||||
EHPrint(" \eAA00FF%s", CPU::Name());
|
EHPrint(" \eAA00FF%s", CPU::Name());
|
||||||
Display->SetBufferCursor(SBIdx, 0, fi.Height + 10);
|
Display->SetBufferCursor(SBIdx, 0, fi.Height + 10);
|
||||||
|
|
||||||
/* https://imgflip.com/i/77slbl */
|
|
||||||
if ((Random::rand32() % 100) >= 98)
|
|
||||||
{
|
|
||||||
debug("Easter egg activated!");
|
|
||||||
int BaseXOffset = sb->Width - 14;
|
|
||||||
int BaseYOffset = 8;
|
|
||||||
Display->SetPixel(BaseXOffset + 3, BaseYOffset + 0, 0x21852E, SBIdx);
|
|
||||||
Display->SetPixel(BaseXOffset + 4, BaseYOffset + 0, 0x21852E, SBIdx);
|
|
||||||
Display->SetPixel(BaseXOffset + 6, BaseYOffset + 0, 0x21852E, SBIdx);
|
|
||||||
Display->SetPixel(BaseXOffset + 7, BaseYOffset + 0, 0x21852E, SBIdx);
|
|
||||||
|
|
||||||
Display->SetPixel(BaseXOffset + 2, BaseYOffset + 1, 0x21852E, SBIdx);
|
|
||||||
Display->SetPixel(BaseXOffset + 3, BaseYOffset + 1, 0x21852E, SBIdx);
|
|
||||||
Display->SetPixel(BaseXOffset + 4, BaseYOffset + 1, 0x21852E, SBIdx);
|
|
||||||
Display->SetPixel(BaseXOffset + 5, BaseYOffset + 1, 0x21852E, SBIdx);
|
|
||||||
Display->SetPixel(BaseXOffset + 6, BaseYOffset + 1, 0x21852E, SBIdx);
|
|
||||||
Display->SetPixel(BaseXOffset + 7, BaseYOffset + 1, 0x21852E, SBIdx);
|
|
||||||
Display->SetPixel(BaseXOffset + 8, BaseYOffset + 1, 0x21852E, SBIdx);
|
|
||||||
|
|
||||||
Display->SetPixel(BaseXOffset + 1, BaseYOffset + 2, 0x21852E, SBIdx);
|
|
||||||
Display->SetPixel(BaseXOffset + 2, BaseYOffset + 2, 0x21852E, SBIdx);
|
|
||||||
Display->SetPixel(BaseXOffset + 3, BaseYOffset + 2, 0xFFFFFF, SBIdx);
|
|
||||||
Display->SetPixel(BaseXOffset + 4, BaseYOffset + 2, 0x000000, SBIdx);
|
|
||||||
Display->SetPixel(BaseXOffset + 5, BaseYOffset + 2, 0x21852E, SBIdx);
|
|
||||||
Display->SetPixel(BaseXOffset + 6, BaseYOffset + 2, 0xFFFFFF, SBIdx);
|
|
||||||
Display->SetPixel(BaseXOffset + 7, BaseYOffset + 2, 0x000000, SBIdx);
|
|
||||||
Display->SetPixel(BaseXOffset + 8, BaseYOffset + 2, 0x21852E, SBIdx);
|
|
||||||
|
|
||||||
Display->SetPixel(BaseXOffset + 1, BaseYOffset + 3, 0x21852E, SBIdx);
|
|
||||||
Display->SetPixel(BaseXOffset + 2, BaseYOffset + 3, 0x21852E, SBIdx);
|
|
||||||
Display->SetPixel(BaseXOffset + 3, BaseYOffset + 3, 0x21852E, SBIdx);
|
|
||||||
Display->SetPixel(BaseXOffset + 4, BaseYOffset + 3, 0x21852E, SBIdx);
|
|
||||||
Display->SetPixel(BaseXOffset + 5, BaseYOffset + 3, 0x21852E, SBIdx);
|
|
||||||
Display->SetPixel(BaseXOffset + 6, BaseYOffset + 3, 0x21852E, SBIdx);
|
|
||||||
Display->SetPixel(BaseXOffset + 7, BaseYOffset + 3, 0x21852E, SBIdx);
|
|
||||||
|
|
||||||
Display->SetPixel(BaseXOffset + 0, BaseYOffset + 4, 0x21852E, SBIdx);
|
|
||||||
Display->SetPixel(BaseXOffset + 1, BaseYOffset + 4, 0x21852E, SBIdx);
|
|
||||||
Display->SetPixel(BaseXOffset + 2, BaseYOffset + 4, 0x21852E, SBIdx);
|
|
||||||
Display->SetPixel(BaseXOffset + 3, BaseYOffset + 4, 0x21852E, SBIdx);
|
|
||||||
Display->SetPixel(BaseXOffset + 4, BaseYOffset + 4, 0xA84832, SBIdx);
|
|
||||||
Display->SetPixel(BaseXOffset + 5, BaseYOffset + 4, 0xA84832, SBIdx);
|
|
||||||
Display->SetPixel(BaseXOffset + 6, BaseYOffset + 4, 0xA84832, SBIdx);
|
|
||||||
Display->SetPixel(BaseXOffset + 7, BaseYOffset + 4, 0xA84832, SBIdx);
|
|
||||||
|
|
||||||
Display->SetPixel(BaseXOffset + 0, BaseYOffset + 5, 0x21852E, SBIdx);
|
|
||||||
Display->SetPixel(BaseXOffset + 1, BaseYOffset + 5, 0x21852E, SBIdx);
|
|
||||||
Display->SetPixel(BaseXOffset + 2, BaseYOffset + 5, 0x21852E, SBIdx);
|
|
||||||
Display->SetPixel(BaseXOffset + 3, BaseYOffset + 5, 0x21852E, SBIdx);
|
|
||||||
Display->SetPixel(BaseXOffset + 4, BaseYOffset + 5, 0x21852E, SBIdx);
|
|
||||||
Display->SetPixel(BaseXOffset + 5, BaseYOffset + 5, 0x21852E, SBIdx);
|
|
||||||
Display->SetPixel(BaseXOffset + 6, BaseYOffset + 5, 0x21852E, SBIdx);
|
|
||||||
|
|
||||||
Display->SetPixel(BaseXOffset + 0, BaseYOffset + 6, 0x1216FF, SBIdx);
|
|
||||||
Display->SetPixel(BaseXOffset + 1, BaseYOffset + 6, 0x1216FF, SBIdx);
|
|
||||||
Display->SetPixel(BaseXOffset + 2, BaseYOffset + 6, 0x1216FF, SBIdx);
|
|
||||||
Display->SetPixel(BaseXOffset + 3, BaseYOffset + 6, 0x1216FF, SBIdx);
|
|
||||||
Display->SetPixel(BaseXOffset + 4, BaseYOffset + 6, 0x1216FF, SBIdx);
|
|
||||||
Display->SetPixel(BaseXOffset + 5, BaseYOffset + 6, 0x1216FF, SBIdx);
|
|
||||||
Display->SetPixel(BaseXOffset + 6, BaseYOffset + 6, 0x1216FF, SBIdx);
|
|
||||||
|
|
||||||
Display->SetBuffer(SBIdx);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SafeFunction void DisplayBottomOverlay()
|
SafeFunction void DisplayBottomOverlay()
|
||||||
@ -316,24 +224,18 @@ namespace CrashHandler
|
|||||||
EHPrint("exit - Shutdown the OS.\n");
|
EHPrint("exit - Shutdown the OS.\n");
|
||||||
EHPrint("reboot - Reboot the OS.\n");
|
EHPrint("reboot - Reboot the OS.\n");
|
||||||
EHPrint("help - Display this help message.\n");
|
EHPrint("help - Display this help message.\n");
|
||||||
EHPrint("showbuf,sb <INDEX> - Display the contents of a screen buffer.\n");
|
EHPrint("showbuf <INDEX> - Display the contents of a screen buffer.\n");
|
||||||
EHPrint(" - A sleep timer will be enabled. This will cause the OS to sleep for an unknown amount of time.\n");
|
EHPrint(" - A sleep timer will be enabled. This will cause the OS to sleep for an unknown amount of time.\n");
|
||||||
EHPrint(" - \eFF4400WARNING: This can crash the system if a wrong buffer is selected.\eFAFAFA\n");
|
EHPrint(" - \eFF4400WARNING: This can crash the system if a wrong buffer is selected.\eFAFAFA\n");
|
||||||
EHPrint("ifr <COUNT> - Show interrupt frames.\n");
|
EHPrint("ifr <COUNT> - Show interrupt frames.\n");
|
||||||
EHPrint("tlb <ADDRESS> - Print the page table entries\n");
|
EHPrint("tlb <ADDRESS> - Print the page table entries\n");
|
||||||
EHPrint("bitmap - Print the memory bitmap\n");
|
EHPrint("bitmap - Print the memory bitmap\n");
|
||||||
EHPrint("mem - Print the memory allocation\n");
|
|
||||||
EHPrint("cr<INDEX> - Print the CPU control register\n");
|
|
||||||
EHPrint("tss <CORE> - Print the CPU task state segment\n");
|
|
||||||
EHPrint("dump <ADDRESS HEX> <LENGTH DEC> - Dump memory\n");
|
|
||||||
EHPrint(" - \eFF4400WARNING: This can crash the system if you try to read from an unmapped page.\eFAFAFA\n");
|
|
||||||
EHPrint("uartmemdmp <INDEX> <SKIP INACCESSIBLE (bool 0,1)> - Dump the memory of a UART.\n");
|
|
||||||
EHPrint("main - Show the main screen.\n");
|
EHPrint("main - Show the main screen.\n");
|
||||||
EHPrint("details - Show the details screen.\n");
|
EHPrint("details - Show the details screen.\n");
|
||||||
EHPrint("frames - Show the stack frame screen.\n");
|
EHPrint("frames - Show the stack frame screen.\n");
|
||||||
EHPrint("tasks - Show the tasks screen.\n");
|
EHPrint("tasks - Show the tasks screen.\n");
|
||||||
EHPrint("console - Show the console screen.\n");
|
EHPrint("console - Show the console screen.\n");
|
||||||
EHPrint("Also, you can use the arrow keys to navigate between the screens.\n");
|
EHPrint("Also, you can use the arrow keys to navigate the menu.\n");
|
||||||
EHPrint("=========================================================================\n");
|
EHPrint("=========================================================================\n");
|
||||||
EHPrint("Kernel Compiled at: %s %s with C++ Standard: %d\n", __DATE__, __TIME__, CPP_LANGUAGE_STANDARD);
|
EHPrint("Kernel Compiled at: %s %s with C++ Standard: %d\n", __DATE__, __TIME__, CPP_LANGUAGE_STANDARD);
|
||||||
EHPrint("C++ Language Version (__cplusplus): %ld\n", __cplusplus);
|
EHPrint("C++ Language Version (__cplusplus): %ld\n", __cplusplus);
|
||||||
@ -352,7 +254,7 @@ namespace CrashHandler
|
|||||||
Display->SetBuffer(SBIdx);
|
Display->SetBuffer(SBIdx);
|
||||||
CPU::Stop();
|
CPU::Stop();
|
||||||
}
|
}
|
||||||
else if (strncmp(Input, "showbuf", 7) == 0 || strncmp(Input, "sb", 2) == 0)
|
else if (strncmp(Input, "showbuf", 7) == 0)
|
||||||
{
|
{
|
||||||
char *arg = TrimWhiteSpace(Input + 7);
|
char *arg = TrimWhiteSpace(Input + 7);
|
||||||
int tmpidx = SBIdx;
|
int tmpidx = SBIdx;
|
||||||
@ -366,19 +268,19 @@ namespace CrashHandler
|
|||||||
else if (strncmp(Input, "ifr", 3) == 0)
|
else if (strncmp(Input, "ifr", 3) == 0)
|
||||||
{
|
{
|
||||||
char *arg = TrimWhiteSpace(Input + 3);
|
char *arg = TrimWhiteSpace(Input + 3);
|
||||||
int CountI = atoi(arg);
|
uint64_t CountI = atoi(arg);
|
||||||
int TotalCount = sizeof(EHIntFrames) / sizeof(EHIntFrames[0]);
|
uint64_t TotalCount = sizeof(EHIntFrames) / sizeof(EHIntFrames[0]);
|
||||||
|
|
||||||
debug("Printing %ld interrupt frames.", CountI);
|
debug("Printing %ld interrupt frames.", CountI);
|
||||||
|
|
||||||
if (CountI > TotalCount)
|
if (CountI > TotalCount)
|
||||||
{
|
{
|
||||||
EHPrint("\eFF4400Count too big! Maximum allowed is %ld\eFAFAFA\n", TotalCount);
|
EHPrint("eFF4400Count too big! Maximum allowed is %ld\eFAFAFA\n", TotalCount);
|
||||||
Display->SetBuffer(SBIdx);
|
Display->SetBuffer(SBIdx);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for (int i = 0; i < CountI; i++)
|
for (uint64_t i = 0; i < CountI; i++)
|
||||||
{
|
{
|
||||||
if (EHIntFrames[i])
|
if (EHIntFrames[i])
|
||||||
{
|
{
|
||||||
@ -386,13 +288,13 @@ namespace CrashHandler
|
|||||||
continue;
|
continue;
|
||||||
EHPrint("\n\e2565CC%p", EHIntFrames[i]);
|
EHPrint("\n\e2565CC%p", EHIntFrames[i]);
|
||||||
EHPrint("\e7925CC-");
|
EHPrint("\e7925CC-");
|
||||||
#if defined(a64)
|
#if defined(__amd64__)
|
||||||
if ((uintptr_t)EHIntFrames[i] >= 0xFFFFFFFF80000000 && (uintptr_t)EHIntFrames[i] <= (uintptr_t)&_kernel_end)
|
if ((uint64_t)EHIntFrames[i] >= 0xFFFFFFFF80000000 && (uint64_t)EHIntFrames[i] <= (uint64_t)&_kernel_end)
|
||||||
#elif defined(a32)
|
#elif defined(__i386__)
|
||||||
if ((uintptr_t)EHIntFrames[i] >= 0xC0000000 && (uintptr_t)EHIntFrames[i] <= (uintptr_t)&_kernel_end)
|
if ((uint64_t)EHIntFrames[i] >= 0xC0000000 && (uint64_t)EHIntFrames[i] <= (uint64_t)&_kernel_end)
|
||||||
#elif defined(aa64)
|
#elif defined(__aarch64__)
|
||||||
#endif
|
#endif
|
||||||
EHPrint("\e25CCC9%s", KernelSymbolTable->GetSymbolFromAddress((uintptr_t)EHIntFrames[i]));
|
EHPrint("\e25CCC9%s", KernelSymbolTable->GetSymbolFromAddress((uint64_t)EHIntFrames[i]));
|
||||||
else
|
else
|
||||||
EHPrint("\eFF4CA9Outside Kernel");
|
EHPrint("\eFF4CA9Outside Kernel");
|
||||||
for (int i = 0; i < 20000; i++)
|
for (int i = 0; i < 20000; i++)
|
||||||
@ -405,88 +307,52 @@ namespace CrashHandler
|
|||||||
else if (strncmp(Input, "tlb", 3) == 0)
|
else if (strncmp(Input, "tlb", 3) == 0)
|
||||||
{
|
{
|
||||||
char *arg = TrimWhiteSpace(Input + 3);
|
char *arg = TrimWhiteSpace(Input + 3);
|
||||||
uintptr_t Address = NULL;
|
uint64_t Address = NULL;
|
||||||
Address = strtol(arg, NULL, 16);
|
Address = strtol(arg, NULL, 16);
|
||||||
debug("Converted %s to %#lx", arg, Address);
|
debug("Converted %s to %#lx", arg, Address);
|
||||||
Memory::PageTable4 *BasePageTable = (Memory::PageTable4 *)Address;
|
Memory::PageTable *BasePageTable = (Memory::PageTable *)Address;
|
||||||
if (Memory::Virtual().Check(BasePageTable))
|
if (Memory::Virtual().Check(BasePageTable))
|
||||||
|
for (int Index = 0; Index < 512; Index++)
|
||||||
{
|
{
|
||||||
for (int PMLIndex = 0; PMLIndex < 512; PMLIndex++)
|
if (BasePageTable->Entries[Index].Value.raw == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
TRACE_PAGE_TABLE(BasePageTable->Entries[Index], Index, "");
|
||||||
|
for (int i = 0; i < 10000; i++)
|
||||||
|
inb(0x80);
|
||||||
|
|
||||||
|
if (BasePageTable->Entries[Index].GetFlag(Memory::PTFlag::P))
|
||||||
{
|
{
|
||||||
Memory::PageMapLevel4 PML4 = BasePageTable->Entries[PMLIndex];
|
Memory::PageTable *PDP = (Memory::PageTable *)((uint64_t)BasePageTable->Entries[Index].GetAddress() << 12);
|
||||||
EHPrint("\e888888# \eAABBCC%03d-%03d-%03d-%03d\e4500F5: P:%s RW:%s US:%s PWT:%s PCB:%s A:%s NX:%s Address:\e888888%#lx\n",
|
for (int PDPIndex = 0; PDPIndex < 512; PDPIndex++)
|
||||||
PMLIndex, 0, 0, 0,
|
|
||||||
PML4.Present ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5",
|
|
||||||
PML4.ReadWrite ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5",
|
|
||||||
PML4.UserSupervisor ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5",
|
|
||||||
PML4.WriteThrough ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5",
|
|
||||||
PML4.CacheDisable ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5",
|
|
||||||
PML4.Accessed ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5",
|
|
||||||
PML4.ExecuteDisable ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5",
|
|
||||||
PML4.GetAddress() << 12);
|
|
||||||
Display->SetBuffer(SBIdx);
|
|
||||||
if (PML4.Present)
|
|
||||||
{
|
{
|
||||||
Memory::PageDirectoryPointerTableEntryPtr *PDPTE = (Memory::PageDirectoryPointerTableEntryPtr *)((uintptr_t)PML4.GetAddress() << 12);
|
if (PDP->Entries[PDPIndex].Value.raw == 0)
|
||||||
if (PDPTE)
|
continue;
|
||||||
|
TRACE_PAGE_TABLE(PDP->Entries[PDPIndex], PDPIndex, " ");
|
||||||
|
for (int i = 0; i < 10000; i++)
|
||||||
|
inb(0x80);
|
||||||
|
|
||||||
|
if (PDP->Entries[PDPIndex].GetFlag(Memory::PTFlag::P))
|
||||||
{
|
{
|
||||||
for (int PDPTEIndex = 0; PDPTEIndex < 512; PDPTEIndex++)
|
Memory::PageTable *PD = (Memory::PageTable *)((uint64_t)PDP->Entries[PDPIndex].GetAddress() << 12);
|
||||||
|
for (int PDIndex = 0; PDIndex < 512; PDIndex++)
|
||||||
{
|
{
|
||||||
EHPrint("\e888888# \eAABBCC%03d-%03d-%03d-%03d\e4500F5: P:%s RW:%s US:%s PWT:%s PCB:%s A:%s NX:%s Address:\e888888%#lx\n",
|
if (PD->Entries[PDIndex].Value.raw == 0)
|
||||||
PMLIndex, PDPTEIndex, 0, 0,
|
continue;
|
||||||
PDPTE->Entries[PDPTEIndex].Present ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5",
|
TRACE_PAGE_TABLE(PD->Entries[PDIndex], PDIndex, " ");
|
||||||
PDPTE->Entries[PDPTEIndex].ReadWrite ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5",
|
for (int i = 0; i < 10000; i++)
|
||||||
PDPTE->Entries[PDPTEIndex].UserSupervisor ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5",
|
inb(0x80);
|
||||||
PDPTE->Entries[PDPTEIndex].WriteThrough ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5",
|
|
||||||
PDPTE->Entries[PDPTEIndex].CacheDisable ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5",
|
if (PD->Entries[PDIndex].GetFlag(Memory::PTFlag::P))
|
||||||
PDPTE->Entries[PDPTEIndex].Accessed ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5",
|
|
||||||
PDPTE->Entries[PDPTEIndex].ExecuteDisable ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5",
|
|
||||||
PDPTE->Entries[PDPTEIndex].GetAddress() << 12);
|
|
||||||
Display->SetBuffer(SBIdx);
|
|
||||||
if ((PDPTE->Entries[PDPTEIndex].Present))
|
|
||||||
{
|
{
|
||||||
Memory::PageDirectoryEntryPtr *PDE = (Memory::PageDirectoryEntryPtr *)((uintptr_t)PDPTE->Entries[PDPTEIndex].GetAddress() << 12);
|
Memory::PageTable *PT = (Memory::PageTable *)((uint64_t)PD->Entries[PDIndex].GetAddress() << 12);
|
||||||
if (PDE)
|
for (int PIndex = 0; PIndex < 512; PIndex++)
|
||||||
{
|
{
|
||||||
for (int PDEIndex = 0; PDEIndex < 512; PDEIndex++)
|
if (PT->Entries[PIndex].Value.raw == 0)
|
||||||
{
|
continue;
|
||||||
EHPrint("\e888888# \eAABBCC%03d-%03d-%03d-%03d\e4500F5: P:%s RW:%s US:%s PWT:%s PCB:%s A:%s NX:%s Address:\e888888%#lx\n",
|
TRACE_PAGE_TABLE(PT->Entries[PIndex], PIndex, " ");
|
||||||
PMLIndex, PDPTEIndex, PDEIndex, 0,
|
for (int i = 0; i < 10000; i++)
|
||||||
PDE->Entries[PDEIndex].Present ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5",
|
inb(0x80);
|
||||||
PDE->Entries[PDEIndex].ReadWrite ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5",
|
|
||||||
PDE->Entries[PDEIndex].UserSupervisor ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5",
|
|
||||||
PDE->Entries[PDEIndex].WriteThrough ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5",
|
|
||||||
PDE->Entries[PDEIndex].CacheDisable ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5",
|
|
||||||
PDE->Entries[PDEIndex].Accessed ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5",
|
|
||||||
PDE->Entries[PDEIndex].ExecuteDisable ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5",
|
|
||||||
PDE->Entries[PDEIndex].GetAddress() << 12);
|
|
||||||
Display->SetBuffer(SBIdx);
|
|
||||||
if ((PDE->Entries[PDEIndex].Present))
|
|
||||||
{
|
|
||||||
Memory::PageTableEntryPtr *PTE = (Memory::PageTableEntryPtr *)((uintptr_t)PDE->Entries[PDEIndex].GetAddress() << 12);
|
|
||||||
if (PTE)
|
|
||||||
{
|
|
||||||
for (int PTEIndex = 0; PTEIndex < 512; PTEIndex++)
|
|
||||||
{
|
|
||||||
EHPrint("\e888888# \eAABBCC%03d-%03d-%03d-%03d\e4500F5: P:%s RW:%s US:%s PWT:%s PCB:%s A:%s D:%s PAT:%s G:%s PK:%d NX:%s Address:\e888888%#lx\n",
|
|
||||||
PMLIndex, PDPTEIndex, PDEIndex, PTEIndex,
|
|
||||||
PTE->Entries[PTEIndex].Present ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5",
|
|
||||||
PTE->Entries[PTEIndex].ReadWrite ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5",
|
|
||||||
PTE->Entries[PTEIndex].UserSupervisor ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5",
|
|
||||||
PTE->Entries[PTEIndex].WriteThrough ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5",
|
|
||||||
PTE->Entries[PTEIndex].CacheDisable ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5",
|
|
||||||
PTE->Entries[PTEIndex].Accessed ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5",
|
|
||||||
PTE->Entries[PTEIndex].Dirty ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5",
|
|
||||||
PTE->Entries[PTEIndex].PageAttributeTable ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5",
|
|
||||||
PTE->Entries[PTEIndex].Global ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5",
|
|
||||||
PTE->Entries[PTEIndex].ProtectionKey,
|
|
||||||
PTE->Entries[PTEIndex].ExecuteDisable ? "\e00FF001\e4500F5" : "\eFF00000\e4500F5",
|
|
||||||
PTE->Entries[PTEIndex].GetAddress() << 12);
|
|
||||||
Display->SetBuffer(SBIdx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -499,8 +365,8 @@ namespace CrashHandler
|
|||||||
{
|
{
|
||||||
Bitmap bm = KernelAllocator.GetPageBitmap();
|
Bitmap bm = KernelAllocator.GetPageBitmap();
|
||||||
|
|
||||||
EHPrint("\n\eFAFAFA[0%%] %08ld: ", 0);
|
EHPrint("\n\eFAFAFA%08ld: ", 0);
|
||||||
for (size_t i = 0; i < bm.Size; i++)
|
for (uint64_t i = 0; i < bm.Size; i++)
|
||||||
{
|
{
|
||||||
if (bm.Get(i))
|
if (bm.Get(i))
|
||||||
EHPrint("\eFF00001");
|
EHPrint("\eFF00001");
|
||||||
@ -508,207 +374,13 @@ namespace CrashHandler
|
|||||||
EHPrint("\e00FF000");
|
EHPrint("\e00FF000");
|
||||||
if (i % 128 == 127)
|
if (i % 128 == 127)
|
||||||
{
|
{
|
||||||
short Percentage = (i * 100) / bm.Size;
|
EHPrint("\n\eFAFAFA%08ld: ", i);
|
||||||
EHPrint("\n\eFAFAFA[%03ld%%] %08ld: ", Percentage, i);
|
|
||||||
Display->SetBuffer(SBIdx);
|
Display->SetBuffer(SBIdx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
EHPrint("\n\e22AA44--- END OF BITMAP ---\nBitmap size: %ld\n\n.", bm.Size);
|
EHPrint("\n\e22AA44--- END OF BITMAP ---\nBitmap size: %ld\n", bm.Size);
|
||||||
Display->SetBuffer(SBIdx);
|
Display->SetBuffer(SBIdx);
|
||||||
}
|
}
|
||||||
else if (strcmp(Input, "mem") == 0)
|
|
||||||
{
|
|
||||||
uint64_t Total = KernelAllocator.GetTotalMemory();
|
|
||||||
uint64_t Used = KernelAllocator.GetUsedMemory();
|
|
||||||
uint64_t Free = KernelAllocator.GetFreeMemory();
|
|
||||||
uint64_t Reserved = KernelAllocator.GetReservedMemory();
|
|
||||||
|
|
||||||
EHPrint("\e22AA44Total: %ld bytes\n\eFF0000Used: %ld bytes\n\e00FF00Free: %ld bytes\n\eFF00FFReserved: %ld bytes\n", Total, Used, Free, Reserved);
|
|
||||||
int Progress = (Used * 100) / Total;
|
|
||||||
int ReservedProgress = (Reserved * 100) / Total;
|
|
||||||
EHPrint("\e22AA44%3d%% \eCCCCCC[", Progress);
|
|
||||||
for (int i = 0; i < Progress; i++)
|
|
||||||
EHPrint("\eFF0000|");
|
|
||||||
for (int i = 0; i < 100 - Progress; i++)
|
|
||||||
EHPrint("\e00FF00|");
|
|
||||||
for (int i = 0; i < ReservedProgress; i++)
|
|
||||||
EHPrint("\eFF00FF|");
|
|
||||||
EHPrint("\eCCCCCC]\n");
|
|
||||||
|
|
||||||
Display->SetBuffer(SBIdx);
|
|
||||||
}
|
|
||||||
else if (strncmp(Input, "cr", 2) == 0)
|
|
||||||
{
|
|
||||||
char *cr = TrimWhiteSpace(Input + 2);
|
|
||||||
switch (cr[0])
|
|
||||||
{
|
|
||||||
case '0':
|
|
||||||
{
|
|
||||||
#if defined(a64)
|
|
||||||
EHPrint("\e44AA000: %#lx\n", CPU::x64::readcr0());
|
|
||||||
#elif defined(a32)
|
|
||||||
EHPrint("\e44AA000: %#lx\n", CPU::x32::readcr0());
|
|
||||||
#endif
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case '2':
|
|
||||||
{
|
|
||||||
#if defined(a64)
|
|
||||||
EHPrint("\e44AA002: %#lx\n", PageFaultAddress);
|
|
||||||
#elif defined(a32)
|
|
||||||
EHPrint("\e44AA002: %#lx\n", CPU::x32::readcr2());
|
|
||||||
#endif
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case '3':
|
|
||||||
{
|
|
||||||
#if defined(a64)
|
|
||||||
EHPrint("\e44AA003: %#lx\n", CPU::x64::readcr3());
|
|
||||||
#elif defined(a32)
|
|
||||||
EHPrint("\e44AA003: %#lx\n", CPU::x32::readcr3());
|
|
||||||
#endif
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case '4':
|
|
||||||
{
|
|
||||||
#if defined(a64)
|
|
||||||
EHPrint("\e44AA004: %#lx\n", CPU::x64::readcr4());
|
|
||||||
#elif defined(a32)
|
|
||||||
EHPrint("\e44AA004: %#lx\n", CPU::x32::readcr4());
|
|
||||||
#endif
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case '8':
|
|
||||||
{
|
|
||||||
#if defined(a64)
|
|
||||||
EHPrint("\e44AA008: %#lx\n", CPU::x64::readcr8());
|
|
||||||
#elif defined(a32)
|
|
||||||
EHPrint("\e44AA008: %#lx\n", CPU::x32::readcr8());
|
|
||||||
#endif
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
EHPrint("\eFF0000Invalid CR\n");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (strncmp(Input, "tss", 3) == 0)
|
|
||||||
{
|
|
||||||
char *arg = TrimWhiteSpace(Input + 3);
|
|
||||||
int TSSIndex = atoi(arg);
|
|
||||||
if (TSSIndex > SMP::CPUCores)
|
|
||||||
{
|
|
||||||
EHPrint("\eFF0000Invalid TSS index\n");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
GlobalDescriptorTable::TaskStateSegment tss = GlobalDescriptorTable::tss[TSSIndex];
|
|
||||||
EHPrint("\eFAFAFAStack Pointer 0: \eAABB22%#lx\n", tss.StackPointer[0]);
|
|
||||||
EHPrint("\eFAFAFAStack Pointer 1: \eAABB22%#lx\n", tss.StackPointer[1]);
|
|
||||||
EHPrint("\eFAFAFAStack Pointer 2: \eAABB22%#lx\n", tss.StackPointer[2]);
|
|
||||||
|
|
||||||
EHPrint("\eFAFAFAInterrupt Stack Table: \eAABB22%#lx\n", tss.InterruptStackTable[0]);
|
|
||||||
EHPrint("\eFAFAFAInterrupt Stack Table: \eAABB22%#lx\n", tss.InterruptStackTable[1]);
|
|
||||||
EHPrint("\eFAFAFAInterrupt Stack Table: \eAABB22%#lx\n", tss.InterruptStackTable[2]);
|
|
||||||
EHPrint("\eFAFAFAInterrupt Stack Table: \eAABB22%#lx\n", tss.InterruptStackTable[3]);
|
|
||||||
EHPrint("\eFAFAFAInterrupt Stack Table: \eAABB22%#lx\n", tss.InterruptStackTable[4]);
|
|
||||||
EHPrint("\eFAFAFAInterrupt Stack Table: \eAABB22%#lx\n", tss.InterruptStackTable[5]);
|
|
||||||
EHPrint("\eFAFAFAInterrupt Stack Table: \eAABB22%#lx\n", tss.InterruptStackTable[6]);
|
|
||||||
|
|
||||||
EHPrint("\eFAFAFAI/O Map Base Address Offset: \eAABB22%#lx\n", tss.IOMapBaseAddressOffset);
|
|
||||||
|
|
||||||
EHPrint("\eFAFAFAReserved 0: \eAABB22%#lx\n", tss.Reserved0);
|
|
||||||
EHPrint("\eFAFAFAReserved 1: \eAABB22%#lx\n", tss.Reserved1);
|
|
||||||
EHPrint("\eFAFAFAReserved 2: \eAABB22%#lx\n", tss.Reserved2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (strncmp(Input, "dump", 4) == 0)
|
|
||||||
{
|
|
||||||
char *arg = TrimWhiteSpace(Input + 4);
|
|
||||||
char *addr = strtok(arg, " ");
|
|
||||||
char *len = strtok(NULL, " ");
|
|
||||||
if (addr == NULL || len == NULL)
|
|
||||||
{
|
|
||||||
EHPrint("\eFF0000Invalid arguments\n");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
uint64_t Address = strtoul(addr, NULL, 16);
|
|
||||||
uint64_t Length = strtoul(len, NULL, 10);
|
|
||||||
debug("Dumping %ld bytes from %#lx\n", Length, Address);
|
|
||||||
EHDumpData((void *)Address, Length);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (strncmp(Input, "uartmemdmp", 10) == 0)
|
|
||||||
{
|
|
||||||
char *arg = TrimWhiteSpace(Input + 10);
|
|
||||||
char *cPort = strtok(arg, " ");
|
|
||||||
char *cBoolSkip = strtok(NULL, " ");
|
|
||||||
UniversalAsynchronousReceiverTransmitter::SerialPorts port = UniversalAsynchronousReceiverTransmitter::SerialPorts::COM1;
|
|
||||||
switch (cPort[0])
|
|
||||||
{
|
|
||||||
case '1':
|
|
||||||
port = UniversalAsynchronousReceiverTransmitter::SerialPorts::COM1;
|
|
||||||
break;
|
|
||||||
case '2':
|
|
||||||
port = UniversalAsynchronousReceiverTransmitter::SerialPorts::COM2;
|
|
||||||
break;
|
|
||||||
case '3':
|
|
||||||
port = UniversalAsynchronousReceiverTransmitter::SerialPorts::COM3;
|
|
||||||
break;
|
|
||||||
case '4':
|
|
||||||
port = UniversalAsynchronousReceiverTransmitter::SerialPorts::COM4;
|
|
||||||
break;
|
|
||||||
case '5':
|
|
||||||
port = UniversalAsynchronousReceiverTransmitter::SerialPorts::COM5;
|
|
||||||
break;
|
|
||||||
case '6':
|
|
||||||
port = UniversalAsynchronousReceiverTransmitter::SerialPorts::COM6;
|
|
||||||
break;
|
|
||||||
case '7':
|
|
||||||
port = UniversalAsynchronousReceiverTransmitter::SerialPorts::COM7;
|
|
||||||
break;
|
|
||||||
case '8':
|
|
||||||
port = UniversalAsynchronousReceiverTransmitter::SerialPorts::COM8;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
EHPrint("\eFF0000Invalid port! Defaulting to 1.\n");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
EHPrint("\eF8F8F8Dumping memory to UART port %c (%#lx) and %s inaccessible pages.\n", cPort[0], port, cBoolSkip[0] == '1' ? "skipping" : "zeroing");
|
|
||||||
Display->SetBuffer(SBIdx);
|
|
||||||
uint64_t Length = KernelAllocator.GetTotalMemory();
|
|
||||||
uint64_t ProgressLength = Length;
|
|
||||||
UniversalAsynchronousReceiverTransmitter::UART uart(port);
|
|
||||||
Memory::Virtual vma;
|
|
||||||
uint8_t *Address = reinterpret_cast<uint8_t *>(0x0);
|
|
||||||
int Progress = 0;
|
|
||||||
for (size_t i = 0; i < Length; i++)
|
|
||||||
{
|
|
||||||
if (vma.Check(Address))
|
|
||||||
uart.Write(*Address);
|
|
||||||
else if (cBoolSkip[0] == '0')
|
|
||||||
uart.Write((uint8_t)0);
|
|
||||||
else
|
|
||||||
ProgressLength--;
|
|
||||||
Address++;
|
|
||||||
|
|
||||||
if (unlikely(i % 0x1000 == 0))
|
|
||||||
{
|
|
||||||
int NewProgress = (i * 100) / ProgressLength;
|
|
||||||
if (unlikely(NewProgress != Progress))
|
|
||||||
{
|
|
||||||
Progress = NewProgress;
|
|
||||||
EHPrint("\n%d%%\n", Progress);
|
|
||||||
Display->SetBuffer(SBIdx);
|
|
||||||
}
|
|
||||||
Display->Print('.', SBIdx);
|
|
||||||
if (unlikely(i % 0x500 == 0))
|
|
||||||
Display->SetBuffer(SBIdx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
EHPrint("\nDone.\n");
|
|
||||||
}
|
|
||||||
else if (strcmp(Input, "main") == 0)
|
else if (strcmp(Input, "main") == 0)
|
||||||
{
|
{
|
||||||
SBIdx = 255;
|
SBIdx = 255;
|
||||||
@ -744,78 +416,44 @@ namespace CrashHandler
|
|||||||
DisplayConsoleScreen(crashdata);
|
DisplayConsoleScreen(crashdata);
|
||||||
Display->SetBuffer(SBIdx);
|
Display->SetBuffer(SBIdx);
|
||||||
}
|
}
|
||||||
else if (strlen(Input) > 0)
|
else
|
||||||
|
{
|
||||||
|
if (strlen(Input) > 0)
|
||||||
EHPrint("Unknown command: %s", Input);
|
EHPrint("Unknown command: %s", Input);
|
||||||
|
}
|
||||||
DisplayBottomOverlay();
|
DisplayBottomOverlay();
|
||||||
Display->SetBuffer(SBIdx);
|
Display->SetBuffer(SBIdx);
|
||||||
}
|
}
|
||||||
|
|
||||||
SafeFunction void StopAllCores()
|
|
||||||
{
|
|
||||||
#if defined(a64) || defined(a32)
|
|
||||||
/* FIXME: Can't send IPIs to other cores
|
|
||||||
* because it causes another exception on
|
|
||||||
* the other cores.
|
|
||||||
*
|
|
||||||
* Also it makes every core to stay at 100% usage for some reason.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// if (SMP::CPUCores > 1)
|
|
||||||
// {
|
|
||||||
// for (int i = 1; i < SMP::CPUCores; i++)
|
|
||||||
// {
|
|
||||||
// APIC::InterruptCommandRegisterLow icr;
|
|
||||||
// icr.Vector = CPU::x86::IRQ29;
|
|
||||||
// icr.Level = APIC::APICLevel::Assert;
|
|
||||||
// ((APIC::APIC *)Interrupts::apic[i])->IPI(i, icr);
|
|
||||||
// __sync;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// APIC::InterruptCommandRegisterLow icr;
|
|
||||||
// icr.Vector = CPU::x86::IRQ29;
|
|
||||||
// icr.Level = APIC::APICLevel::Assert;
|
|
||||||
// icr.DestinationShorthand = APIC::APICDestinationShorthand::AllExcludingSelf;
|
|
||||||
// ((APIC::APIC *)Interrupts::apic[0])->IPI(0, icr);
|
|
||||||
// CPU::Interrupts(CPU::Enable);
|
|
||||||
__sync;
|
|
||||||
CPU::Interrupts(CPU::Disable);
|
|
||||||
// }
|
|
||||||
#elif defined(aa64)
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
SafeFunction void Handle(void *Data)
|
SafeFunction void Handle(void *Data)
|
||||||
{
|
{
|
||||||
// TODO: SUPPORT SMP
|
// TODO: SUPPORT SMP
|
||||||
CPU::Interrupts(CPU::Disable);
|
CPU::Interrupts(CPU::Disable);
|
||||||
SBIdx = 255;
|
|
||||||
CHArchTrapFrame *Frame = (CHArchTrapFrame *)Data;
|
|
||||||
#if defined(a64)
|
|
||||||
error("An exception occurred!");
|
error("An exception occurred!");
|
||||||
error("Exception: %#llx", Frame->InterruptNumber);
|
|
||||||
for (size_t i = 0; i < INT_FRAMES_MAX; i++)
|
for (size_t i = 0; i < INT_FRAMES_MAX; i++)
|
||||||
EHIntFrames[i] = Interrupts::InterruptFrames[i];
|
EHIntFrames[i] = Interrupts::InterruptFrames[i];
|
||||||
PageFaultAddress = CPU::x64::readcr2().PFLA;
|
|
||||||
|
SBIdx = 255;
|
||||||
|
CHArchTrapFrame *Frame = (CHArchTrapFrame *)Data;
|
||||||
|
#if defined(__amd64__)
|
||||||
|
error("Exception: %#llx", Frame->InterruptNumber);
|
||||||
|
|
||||||
if (Frame->cs != GDT_USER_CODE && Frame->cs != GDT_USER_DATA)
|
if (Frame->cs != GDT_USER_CODE && Frame->cs != GDT_USER_DATA)
|
||||||
{
|
{
|
||||||
debug("Exception in kernel mode (ip: %#lx (%s), cr2: %#lx)", Frame->rip, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress(Frame->rip) : "No symbol", PageFaultAddress);
|
debug("Exception in kernel mode");
|
||||||
if (TaskManager)
|
if (TaskManager)
|
||||||
TaskManager->Panic();
|
TaskManager->Panic();
|
||||||
ForceUnlock = true;
|
debug("ePanicSchedStop");
|
||||||
Display->CreateBuffer(0, 0, SBIdx);
|
Display->CreateBuffer(0, 0, SBIdx);
|
||||||
StopAllCores();
|
debug("e0");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
debug("Exception in user mode (ip: %#lx (%s), cr2: %#lx)", Frame->rip, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress(Frame->rip) : "No symbol", PageFaultAddress);
|
debug("Exception in user mode");
|
||||||
CPUData *data = GetCurrentCPU();
|
CPUData *data = GetCurrentCPU();
|
||||||
if (!data)
|
if (!data)
|
||||||
{
|
{
|
||||||
ForceUnlock = true;
|
|
||||||
Display->CreateBuffer(0, 0, SBIdx);
|
Display->CreateBuffer(0, 0, SBIdx);
|
||||||
StopAllCores();
|
|
||||||
EHPrint("\eFF0000Cannot get CPU data! This results in a kernel crash!");
|
EHPrint("\eFF0000Cannot get CPU data! This results in a kernel crash!");
|
||||||
error("Cannot get CPU data! This results in a kernel crash!");
|
error("Cannot get CPU data! This results in a kernel crash!");
|
||||||
error("This should never happen!");
|
error("This should never happen!");
|
||||||
@ -823,16 +461,7 @@ namespace CrashHandler
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
debug("CPU %ld data is valid", data->ID);
|
debug("CPU %ld data is valid", data->ID);
|
||||||
if (data->CurrentThread->Security.IsCritical)
|
if (data->CurrentThread)
|
||||||
{
|
|
||||||
debug("Critical thread \"%s\"(%d) died", data->CurrentThread->Name, data->CurrentThread->ID);
|
|
||||||
if (TaskManager)
|
|
||||||
TaskManager->Panic();
|
|
||||||
ForceUnlock = true;
|
|
||||||
Display->CreateBuffer(0, 0, SBIdx);
|
|
||||||
StopAllCores();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
debug("Current thread is valid %#lx", data->CurrentThread);
|
debug("Current thread is valid %#lx", data->CurrentThread);
|
||||||
UserModeExceptionHandler(Frame);
|
UserModeExceptionHandler(Frame);
|
||||||
@ -845,20 +474,22 @@ namespace CrashHandler
|
|||||||
{
|
{
|
||||||
SBIdx = 255;
|
SBIdx = 255;
|
||||||
Display->ClearBuffer(SBIdx);
|
Display->ClearBuffer(SBIdx);
|
||||||
|
debug("e0-1");
|
||||||
Display->SetBufferCursor(SBIdx, 0, 0);
|
Display->SetBufferCursor(SBIdx, 0, 0);
|
||||||
|
debug("e0-2");
|
||||||
|
|
||||||
CPU::x64::CR0 cr0 = CPU::x64::readcr0();
|
CPU::x64::CR0 cr0 = CPU::x64::readcr0();
|
||||||
CPU::x64::CR2 cr2 = CPU::x64::CR2{.PFLA = PageFaultAddress};
|
CPU::x64::CR2 cr2 = CPU::x64::readcr2();
|
||||||
CPU::x64::CR3 cr3 = CPU::x64::readcr3();
|
CPU::x64::CR3 cr3 = CPU::x64::readcr3();
|
||||||
CPU::x64::CR4 cr4 = CPU::x64::readcr4();
|
CPU::x64::CR4 cr4 = CPU::x64::readcr4();
|
||||||
CPU::x64::CR8 cr8 = CPU::x64::readcr8();
|
CPU::x64::CR8 cr8 = CPU::x64::readcr8();
|
||||||
CPU::x64::EFER efer;
|
CPU::x64::EFER efer;
|
||||||
efer.raw = CPU::x64::rdmsr(CPU::x64::MSR_EFER);
|
efer.raw = CPU::x64::rdmsr(CPU::x64::MSR_EFER);
|
||||||
uintptr_t ds;
|
uint64_t ds;
|
||||||
asmv("mov %%ds, %0"
|
asmv("mov %%ds, %0"
|
||||||
: "=r"(ds));
|
: "=r"(ds));
|
||||||
|
|
||||||
EHPrint("\eFF2525FS=%#llx GS=%#llx SS=%#llx CS=%#llx DS=%#llx\n",
|
EHPrint("\eFF0000FS=%#llx GS=%#llx SS=%#llx CS=%#llx DS=%#llx\n",
|
||||||
CPU::x64::rdmsr(CPU::x64::MSR_FS_BASE), CPU::x64::rdmsr(CPU::x64::MSR_GS_BASE),
|
CPU::x64::rdmsr(CPU::x64::MSR_FS_BASE), CPU::x64::rdmsr(CPU::x64::MSR_GS_BASE),
|
||||||
Frame->ss, Frame->cs, ds);
|
Frame->ss, Frame->cs, ds);
|
||||||
EHPrint("R8=%#llx R9=%#llx R10=%#llx R11=%#llx\n", Frame->r8, Frame->r9, Frame->r10, Frame->r11);
|
EHPrint("R8=%#llx R9=%#llx R10=%#llx R11=%#llx\n", Frame->r8, Frame->r9, Frame->r10, Frame->r11);
|
||||||
@ -898,24 +529,21 @@ namespace CrashHandler
|
|||||||
|
|
||||||
EHPrint("\nException occurred while handling exception! HALTED!");
|
EHPrint("\nException occurred while handling exception! HALTED!");
|
||||||
Display->SetBuffer(SBIdx);
|
Display->SetBuffer(SBIdx);
|
||||||
Interrupts::RemoveAll();
|
|
||||||
CPU::Stop();
|
CPU::Stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
ExceptionOccurred = true;
|
ExceptionOccurred = true;
|
||||||
|
Interrupts::RemoveAll();
|
||||||
if (DriverManager)
|
|
||||||
DriverManager->UnloadAllDrivers();
|
|
||||||
|
|
||||||
debug("Reading control registers...");
|
debug("Reading control registers...");
|
||||||
crashdata.Frame = Frame;
|
crashdata.Frame = Frame;
|
||||||
crashdata.cr0 = CPU::x64::readcr0();
|
crashdata.cr0 = CPU::x64::readcr0();
|
||||||
crashdata.cr2 = CPU::x64::CR2{.PFLA = PageFaultAddress};
|
crashdata.cr2 = CPU::x64::readcr2();
|
||||||
crashdata.cr3 = CPU::x64::readcr3();
|
crashdata.cr3 = CPU::x64::readcr3();
|
||||||
crashdata.cr4 = CPU::x64::readcr4();
|
crashdata.cr4 = CPU::x64::readcr4();
|
||||||
crashdata.cr8 = CPU::x64::readcr8();
|
crashdata.cr8 = CPU::x64::readcr8();
|
||||||
crashdata.efer.raw = CPU::x64::rdmsr(CPU::x64::MSR_EFER);
|
crashdata.efer.raw = CPU::x64::rdmsr(CPU::x64::MSR_EFER);
|
||||||
uintptr_t ds;
|
uint64_t ds;
|
||||||
asmv("mov %%ds, %0"
|
asmv("mov %%ds, %0"
|
||||||
: "=r"(ds));
|
: "=r"(ds));
|
||||||
|
|
||||||
@ -961,8 +589,8 @@ namespace CrashHandler
|
|||||||
|
|
||||||
if (TaskManager && cpudata != nullptr)
|
if (TaskManager && cpudata != nullptr)
|
||||||
{
|
{
|
||||||
crashdata.Process = cpudata->CurrentProcess.Load();
|
crashdata.Process = cpudata->CurrentProcess;
|
||||||
crashdata.Thread = cpudata->CurrentThread.Load();
|
crashdata.Thread = cpudata->CurrentThread;
|
||||||
|
|
||||||
error("Current Process: %s(%ld)",
|
error("Current Process: %s(%ld)",
|
||||||
cpudata->CurrentProcess->Name,
|
cpudata->CurrentProcess->Name,
|
||||||
@ -1028,8 +656,8 @@ namespace CrashHandler
|
|||||||
}
|
}
|
||||||
goto CrashEnd;
|
goto CrashEnd;
|
||||||
|
|
||||||
#elif defined(a32)
|
#elif defined(__i386__)
|
||||||
#elif defined(aa64)
|
#elif defined(__aarch64__)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
CrashEnd:
|
CrashEnd:
|
||||||
|
@ -9,10 +9,10 @@
|
|||||||
#include <cpu.hpp>
|
#include <cpu.hpp>
|
||||||
#include <io.h>
|
#include <io.h>
|
||||||
|
|
||||||
#if defined(a64)
|
#if defined(__amd64__)
|
||||||
#include "../../Architecture/amd64/cpu/gdt.hpp"
|
#include "../../Architecture/amd64/cpu/gdt.hpp"
|
||||||
#elif defined(a32)
|
#elif defined(__i386__)
|
||||||
#elif defined(aa64)
|
#elif defined(__aarch64__)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "../../kernel.h"
|
#include "../../kernel.h"
|
||||||
@ -77,7 +77,7 @@ static inline int GetLetterFromScanCode(uint8_t ScanCode)
|
|||||||
|
|
||||||
namespace CrashHandler
|
namespace CrashHandler
|
||||||
{
|
{
|
||||||
CrashKeyboardDriver::CrashKeyboardDriver() : Interrupts::Handler(CPU::x86::IRQ1)
|
CrashKeyboardDriver::CrashKeyboardDriver() : Interrupts::Handler(CPU::x64::IRQ1)
|
||||||
{
|
{
|
||||||
while (inb(0x64) & 0x1)
|
while (inb(0x64) & 0x1)
|
||||||
inb(0x60);
|
inb(0x60);
|
||||||
@ -102,15 +102,14 @@ namespace CrashHandler
|
|||||||
int BackSpaceLimit = 0;
|
int BackSpaceLimit = 0;
|
||||||
static char UserInputBuffer[1024];
|
static char UserInputBuffer[1024];
|
||||||
|
|
||||||
#if defined(a64)
|
#if defined(__amd64__)
|
||||||
SafeFunction void CrashKeyboardDriver::OnInterruptReceived(CPU::x64::TrapFrame *Frame)
|
SafeFunction void CrashKeyboardDriver::OnInterruptReceived(CPU::x64::TrapFrame *Frame)
|
||||||
#elif defined(a32)
|
#elif defined(__i386__)
|
||||||
SafeFunction void CrashKeyboardDriver::OnInterruptReceived(CPU::x32::TrapFrame *Frame)
|
SafeFunction void CrashKeyboardDriver::OnInterruptReceived(void *Frame)
|
||||||
#elif defined(aa64)
|
#elif defined(__aarch64__)
|
||||||
SafeFunction void CrashKeyboardDriver::OnInterruptReceived(void *Frame)
|
SafeFunction void CrashKeyboardDriver::OnInterruptReceived(void *Frame)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
UNUSED(Frame);
|
|
||||||
uint8_t scanCode = inb(0x60);
|
uint8_t scanCode = inb(0x60);
|
||||||
if (scanCode == KEY_D_TAB ||
|
if (scanCode == KEY_D_TAB ||
|
||||||
scanCode == KEY_D_LCTRL ||
|
scanCode == KEY_D_LCTRL ||
|
||||||
|
@ -7,10 +7,10 @@
|
|||||||
#include <smp.hpp>
|
#include <smp.hpp>
|
||||||
#include <cpu.hpp>
|
#include <cpu.hpp>
|
||||||
|
|
||||||
#if defined(a64)
|
#if defined(__amd64__)
|
||||||
#include "../../Architecture/amd64/cpu/gdt.hpp"
|
#include "../../Architecture/amd64/cpu/gdt.hpp"
|
||||||
#elif defined(a32)
|
#elif defined(__i386__)
|
||||||
#elif defined(aa64)
|
#elif defined(__aarch64__)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "../../kernel.h"
|
#include "../../kernel.h"
|
||||||
@ -20,78 +20,55 @@ namespace CrashHandler
|
|||||||
struct StackFrame
|
struct StackFrame
|
||||||
{
|
{
|
||||||
struct StackFrame *rbp;
|
struct StackFrame *rbp;
|
||||||
uintptr_t rip;
|
uint64_t rip;
|
||||||
};
|
};
|
||||||
|
|
||||||
SafeFunction void TraceFrames(CHArchTrapFrame *Frame, int Count, SymbolResolver::Symbols *SymHandle, bool Kernel)
|
SafeFunction void TraceFrames(CHArchTrapFrame *Frame, int Count)
|
||||||
{
|
{
|
||||||
if (!Memory::Virtual().Check(Frame))
|
|
||||||
{
|
|
||||||
EHPrint("Invalid frame pointer: %p\n", Frame);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(a64)
|
#if defined(__amd64__)
|
||||||
struct StackFrame *frames = (struct StackFrame *)Frame->rbp; // (struct StackFrame *)__builtin_frame_address(0);
|
struct StackFrame *frames = (struct StackFrame *)Frame->rbp; // (struct StackFrame *)__builtin_frame_address(0);
|
||||||
if (!Memory::Virtual().Check((void *)Frame->rbp))
|
#elif defined(__i386__)
|
||||||
#elif defined(a32)
|
|
||||||
struct StackFrame *frames = (struct StackFrame *)Frame->ebp; // (struct StackFrame *)__builtin_frame_address(0);
|
struct StackFrame *frames = (struct StackFrame *)Frame->ebp; // (struct StackFrame *)__builtin_frame_address(0);
|
||||||
if (!Memory::Virtual().Check((void *)Frame->ebp))
|
#elif defined(__aarch64__)
|
||||||
#elif defined(aa64)
|
|
||||||
#endif
|
#endif
|
||||||
{
|
debug("Stack tracing...");
|
||||||
#if defined(a64)
|
|
||||||
EHPrint("Invalid rbp pointer: %p\n", Frame->rbp);
|
|
||||||
#elif defined(a32)
|
|
||||||
EHPrint("Invalid ebp pointer: %p\n", Frame->ebp);
|
|
||||||
#elif defined(aa64)
|
|
||||||
#endif
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Memory::Virtual().Check(SymHandle))
|
|
||||||
{
|
|
||||||
EHPrint("Invalid symbol handle: %p\n", SymHandle);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
debug("\nStack tracing... %p %d %p %d", Frame, Count, frames, Kernel);
|
|
||||||
EHPrint("\e7981FC\nStack Trace:\n");
|
EHPrint("\e7981FC\nStack Trace:\n");
|
||||||
if (!frames || !frames->rip || !frames->rbp)
|
if (!frames || !frames->rip || !frames->rbp)
|
||||||
{
|
{
|
||||||
#if defined(a64)
|
#if defined(__amd64__)
|
||||||
EHPrint("\e2565CC%p", (void *)Frame->rip);
|
EHPrint("\e2565CC%p", (void *)Frame->rip);
|
||||||
#elif defined(a32)
|
#elif defined(__i386__)
|
||||||
EHPrint("\e2565CC%p", (void *)Frame->eip);
|
EHPrint("\e2565CC%p", (void *)Frame->eip);
|
||||||
#elif defined(aa64)
|
#elif defined(__aarch64__)
|
||||||
#endif
|
#endif
|
||||||
EHPrint("\e7925CC-");
|
EHPrint("\e7925CC-");
|
||||||
#if defined(a64)
|
#if defined(__amd64__)
|
||||||
EHPrint("\eAA25CC%s", SymHandle->GetSymbolFromAddress(Frame->rip));
|
EHPrint("\eAA25CC%s", KernelSymbolTable->GetSymbolFromAddress(Frame->rip));
|
||||||
#elif defined(a32)
|
#elif defined(__i386__)
|
||||||
EHPrint("\eAA25CC%s", SymHandle->GetSymbolFromAddress(Frame->eip));
|
EHPrint("\eAA25CC%s", KernelSymbolTable->GetSymbolFromAddress(Frame->eip));
|
||||||
#elif defined(aa64)
|
#elif defined(__aarch64__)
|
||||||
#endif
|
#endif
|
||||||
EHPrint("\e7981FC <- Exception");
|
EHPrint("\e7981FC <- Exception");
|
||||||
EHPrint("\eFF0000\n< No stack trace available. >\n");
|
EHPrint("\eFF0000\n< No stack trace available. >\n");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
#if defined(a64)
|
#if defined(__amd64__)
|
||||||
EHPrint("\e2565CC%p", (void *)Frame->rip);
|
EHPrint("\e2565CC%p", (void *)Frame->rip);
|
||||||
EHPrint("\e7925CC-");
|
EHPrint("\e7925CC-");
|
||||||
if ((Frame->rip >= 0xFFFFFFFF80000000 && Frame->rip <= (uintptr_t)&_kernel_end) || !Kernel)
|
if (Frame->rip >= 0xFFFFFFFF80000000 && Frame->rip <= (uint64_t)&_kernel_end)
|
||||||
EHPrint("\eAA25CC%s", SymHandle->GetSymbolFromAddress(Frame->rip));
|
EHPrint("\eAA25CC%s", KernelSymbolTable->GetSymbolFromAddress(Frame->rip));
|
||||||
else
|
else
|
||||||
EHPrint("Outside Kernel");
|
EHPrint("Outside Kernel");
|
||||||
#elif defined(a32)
|
#elif defined(__i386__)
|
||||||
EHPrint("\e2565CC%p", (void *)Frame->eip);
|
EHPrint("\e2565CC%p", (void *)Frame->eip);
|
||||||
EHPrint("\e7925CC-");
|
EHPrint("\e7925CC-");
|
||||||
if ((Frame->eip >= 0xC0000000 && Frame->eip <= (uintptr_t)&_kernel_end) || !Kernel)
|
if (Frame->eip >= 0xC0000000 && Frame->eip <= (uint64_t)&_kernel_end)
|
||||||
EHPrint("\eAA25CC%s", SymHandle->GetSymbolFromAddress(Frame->eip));
|
EHPrint("\eAA25CC%s", KernelSymbolTable->GetSymbolFromAddress(Frame->eip));
|
||||||
else
|
else
|
||||||
EHPrint("Outside Kernel");
|
EHPrint("Outside Kernel");
|
||||||
#elif defined(aa64)
|
#elif defined(__aarch64__)
|
||||||
#endif
|
#endif
|
||||||
EHPrint("\e7981FC <- Exception");
|
EHPrint("\e7981FC <- Exception");
|
||||||
for (int frame = 0; frame < Count; ++frame)
|
for (int frame = 0; frame < Count; ++frame)
|
||||||
@ -100,13 +77,13 @@ namespace CrashHandler
|
|||||||
break;
|
break;
|
||||||
EHPrint("\n\e2565CC%p", (void *)frames->rip);
|
EHPrint("\n\e2565CC%p", (void *)frames->rip);
|
||||||
EHPrint("\e7925CC-");
|
EHPrint("\e7925CC-");
|
||||||
#if defined(a64)
|
#if defined(__amd64__)
|
||||||
if ((frames->rip >= 0xFFFFFFFF80000000 && frames->rip <= (uintptr_t)&_kernel_end) || !Kernel)
|
if (frames->rip >= 0xFFFFFFFF80000000 && frames->rip <= (uint64_t)&_kernel_end)
|
||||||
#elif defined(a32)
|
#elif defined(__i386__)
|
||||||
if ((frames->rip >= 0xC0000000 && frames->rip <= (uintptr_t)&_kernel_end) || !Kernel)
|
if (frames->rip >= 0xC0000000 && frames->rip <= (uint64_t)&_kernel_end)
|
||||||
#elif defined(aa64)
|
#elif defined(__aarch64__)
|
||||||
#endif
|
#endif
|
||||||
EHPrint("\e25CCC9%s", SymHandle->GetSymbolFromAddress(frames->rip));
|
EHPrint("\e25CCC9%s", KernelSymbolTable->GetSymbolFromAddress(frames->rip));
|
||||||
else
|
else
|
||||||
EHPrint("\eFF4CA9Outside Kernel");
|
EHPrint("\eFF4CA9Outside Kernel");
|
||||||
|
|
||||||
@ -115,6 +92,5 @@ namespace CrashHandler
|
|||||||
frames = frames->rbp;
|
frames = frames->rbp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
EHPrint("\n");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,10 +7,10 @@
|
|||||||
#include <smp.hpp>
|
#include <smp.hpp>
|
||||||
#include <cpu.hpp>
|
#include <cpu.hpp>
|
||||||
|
|
||||||
#if defined(a64)
|
#if defined(__amd64__)
|
||||||
#include "../../../Architecture/amd64/cpu/gdt.hpp"
|
#include "../../../Architecture/amd64/cpu/gdt.hpp"
|
||||||
#elif defined(a32)
|
#elif defined(__i386__)
|
||||||
#elif defined(aa64)
|
#elif defined(__aarch64__)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "../../../kernel.h"
|
#include "../../../kernel.h"
|
||||||
@ -20,6 +20,5 @@ namespace CrashHandler
|
|||||||
SafeFunction void DisplayConsoleScreen(CRData data)
|
SafeFunction void DisplayConsoleScreen(CRData data)
|
||||||
{
|
{
|
||||||
EHPrint("TODO");
|
EHPrint("TODO");
|
||||||
UNUSED(data);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -7,10 +7,10 @@
|
|||||||
#include <smp.hpp>
|
#include <smp.hpp>
|
||||||
#include <cpu.hpp>
|
#include <cpu.hpp>
|
||||||
|
|
||||||
#if defined(a64)
|
#if defined(__amd64__)
|
||||||
#include "../../../Architecture/amd64/cpu/gdt.hpp"
|
#include "../../../Architecture/amd64/cpu/gdt.hpp"
|
||||||
#elif defined(a32)
|
#elif defined(__i386__)
|
||||||
#elif defined(aa64)
|
#elif defined(__aarch64__)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "../../../kernel.h"
|
#include "../../../kernel.h"
|
||||||
@ -28,46 +28,48 @@ namespace CrashHandler
|
|||||||
data.Thread->Name,
|
data.Thread->Name,
|
||||||
data.Thread->ID);
|
data.Thread->ID);
|
||||||
EHPrint("\e7981FCTechnical Informations on CPU %lld:\n", data.ID);
|
EHPrint("\e7981FCTechnical Informations on CPU %lld:\n", data.ID);
|
||||||
uintptr_t ds;
|
#if defined(__amd64__)
|
||||||
#if defined(a64)
|
|
||||||
|
|
||||||
CPUData *cpu = (CPUData *)data.CPUData;
|
CPUData *cpu = (CPUData *)data.CPUData;
|
||||||
if (cpu)
|
if (cpu)
|
||||||
{
|
{
|
||||||
EHPrint("\eE46CEBCPU Data Address: %#lx\n", cpu);
|
EHPrint("\eE46CEBCPU Data Address: %#lx\n", cpu);
|
||||||
EHPrint("Syscalls Stack: %#lx, TempStack: %#lx\n", cpu->SystemCallStack, cpu->TempStack);
|
EHPrint("Syscalls Stack: %#lx\n", cpu->SystemCallStack);
|
||||||
EHPrint("Core Stack: %#lx, Core ID: %ld, Error Code: %ld\n", cpu->Stack, cpu->ID, cpu->ErrorCode);
|
EHPrint("TempStack: %#lx\n", cpu->TempStack);
|
||||||
|
EHPrint("Core Stack: %#lx\n", cpu->Stack);
|
||||||
|
EHPrint("Core ID: %ld\n", cpu->ID);
|
||||||
|
EHPrint("Error Code: %ld\n", cpu->ErrorCode);
|
||||||
EHPrint("Is Active: %s\n", cpu->IsActive ? "true" : "false");
|
EHPrint("Is Active: %s\n", cpu->IsActive ? "true" : "false");
|
||||||
EHPrint("Current Process: %#lx, Current Thread: %#lx\n", cpu->CurrentProcess, cpu->CurrentThread);
|
EHPrint("Current Process: %#lx\n", cpu->CurrentProcess);
|
||||||
|
EHPrint("Current Thread: %#lx\n", cpu->CurrentThread);
|
||||||
EHPrint("Arch Specific Data: %#lx\n", cpu->Data);
|
EHPrint("Arch Specific Data: %#lx\n", cpu->Data);
|
||||||
EHPrint("Checksum: 0x%X\n", cpu->Checksum);
|
EHPrint("Checksum: 0x%X\n", cpu->Checksum);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint64_t ds;
|
||||||
asmv("mov %%ds, %0"
|
asmv("mov %%ds, %0"
|
||||||
: "=r"(ds));
|
: "=r"(ds));
|
||||||
#elif defined(a32)
|
#elif defined(__i386__)
|
||||||
|
uint32_t ds;
|
||||||
asmv("mov %%ds, %0"
|
asmv("mov %%ds, %0"
|
||||||
: "=r"(ds));
|
: "=r"(ds));
|
||||||
#elif defined(aa64)
|
#elif defined(__aarch64__)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(a64)
|
|
||||||
EHPrint("\e7981FCFS=%#llx GS=%#llx SS=%#llx CS=%#llx DS=%#llx\n",
|
EHPrint("\e7981FCFS=%#llx GS=%#llx SS=%#llx CS=%#llx DS=%#llx\n",
|
||||||
CPU::x64::rdmsr(CPU::x64::MSR_FS_BASE), CPU::x64::rdmsr(CPU::x64::MSR_GS_BASE),
|
CPU::x64::rdmsr(CPU::x64::MSR_FS_BASE), CPU::x64::rdmsr(CPU::x64::MSR_GS_BASE),
|
||||||
data.Frame->ss, data.Frame->cs, ds);
|
data.Frame->ss, data.Frame->cs, ds);
|
||||||
|
#if defined(__amd64__)
|
||||||
EHPrint("R8=%#llx R9=%#llx R10=%#llx R11=%#llx\n", data.Frame->r8, data.Frame->r9, data.Frame->r10, data.Frame->r11);
|
EHPrint("R8=%#llx R9=%#llx R10=%#llx R11=%#llx\n", data.Frame->r8, data.Frame->r9, data.Frame->r10, data.Frame->r11);
|
||||||
EHPrint("R12=%#llx R13=%#llx R14=%#llx R15=%#llx\n", data.Frame->r12, data.Frame->r13, data.Frame->r14, data.Frame->r15);
|
EHPrint("R12=%#llx R13=%#llx R14=%#llx R15=%#llx\n", data.Frame->r12, data.Frame->r13, data.Frame->r14, data.Frame->r15);
|
||||||
EHPrint("RAX=%#llx RBX=%#llx RCX=%#llx RDX=%#llx\n", data.Frame->rax, data.Frame->rbx, data.Frame->rcx, data.Frame->rdx);
|
EHPrint("RAX=%#llx RBX=%#llx RCX=%#llx RDX=%#llx\n", data.Frame->rax, data.Frame->rbx, data.Frame->rcx, data.Frame->rdx);
|
||||||
EHPrint("RSI=%#llx RDI=%#llx RBP=%#llx RSP=%#llx\n", data.Frame->rsi, data.Frame->rdi, data.Frame->rbp, data.Frame->rsp);
|
EHPrint("RSI=%#llx RDI=%#llx RBP=%#llx RSP=%#llx\n", data.Frame->rsi, data.Frame->rdi, data.Frame->rbp, data.Frame->rsp);
|
||||||
EHPrint("RIP=%#llx RFL=%#llx INT=%#llx ERR=%#llx EFER=%#llx\n", data.Frame->rip, data.Frame->rflags.raw, data.Frame->InterruptNumber, data.Frame->ErrorCode, data.efer.raw);
|
EHPrint("RIP=%#llx RFL=%#llx INT=%#llx ERR=%#llx EFER=%#llx\n", data.Frame->rip, data.Frame->rflags.raw, data.Frame->InterruptNumber, data.Frame->ErrorCode, data.efer.raw);
|
||||||
#elif defined(a32)
|
#elif defined(__i386__)
|
||||||
EHPrint("\e7981FCFS=%#llx GS=%#llx SS=%#llx CS=%#llx DS=%#llx\n",
|
|
||||||
CPU::x32::rdmsr(CPU::x32::MSR_FS_BASE), CPU::x32::rdmsr(CPU::x32::MSR_GS_BASE),
|
|
||||||
data.Frame->ss, data.Frame->cs, ds);
|
|
||||||
EHPrint("EAX=%#llx EBX=%#llx ECX=%#llx EDX=%#llx\n", data.Frame->eax, data.Frame->ebx, data.Frame->ecx, data.Frame->edx);
|
EHPrint("EAX=%#llx EBX=%#llx ECX=%#llx EDX=%#llx\n", data.Frame->eax, data.Frame->ebx, data.Frame->ecx, data.Frame->edx);
|
||||||
EHPrint("ESI=%#llx EDI=%#llx EBP=%#llx ESP=%#llx\n", data.Frame->esi, data.Frame->edi, data.Frame->ebp, data.Frame->esp);
|
EHPrint("ESI=%#llx EDI=%#llx EBP=%#llx ESP=%#llx\n", data.Frame->esi, data.Frame->edi, data.Frame->ebp, data.Frame->esp);
|
||||||
EHPrint("EIP=%#llx EFL=%#llx INT=%#llx ERR=%#llx EFER=%#llx\n", data.Frame->eip, data.Frame->eflags.raw, data.Frame->InterruptNumber, data.Frame->ErrorCode, data.efer.raw);
|
EHPrint("EIP=%#llx EFL=%#llx INT=%#llx ERR=%#llx EFER=%#llx\n", data.Frame->eip, data.Frame->eflags.raw, data.Frame->InterruptNumber, data.Frame->ErrorCode, data.efer.raw);
|
||||||
#elif defined(aa64)
|
#elif defined(__aarch64__)
|
||||||
#endif
|
#endif
|
||||||
EHPrint("CR0=%#llx CR2=%#llx CR3=%#llx CR4=%#llx CR8=%#llx\n", data.cr0.raw, data.cr2.raw, data.cr3.raw, data.cr4.raw, data.cr8.raw);
|
EHPrint("CR0=%#llx CR2=%#llx CR3=%#llx CR4=%#llx CR8=%#llx\n", data.cr0.raw, data.cr2.raw, data.cr3.raw, data.cr4.raw, data.cr8.raw);
|
||||||
EHPrint("DR0=%#llx DR1=%#llx DR2=%#llx DR3=%#llx DR6=%#llx DR7=%#llx\n", data.dr0, data.dr1, data.dr2, data.dr3, data.dr6, data.dr7.raw);
|
EHPrint("DR0=%#llx DR1=%#llx DR2=%#llx DR3=%#llx DR6=%#llx DR7=%#llx\n", data.dr0, data.dr1, data.dr2, data.dr3, data.dr6, data.dr7.raw);
|
||||||
@ -90,16 +92,16 @@ namespace CrashHandler
|
|||||||
data.cr4.PCE ? "True " : "False", data.cr4.UMIP ? "True " : "False", data.cr4.OSFXSR ? "True " : "False", data.cr4.OSXMMEXCPT ? "True " : "False",
|
data.cr4.PCE ? "True " : "False", data.cr4.UMIP ? "True " : "False", data.cr4.OSFXSR ? "True " : "False", data.cr4.OSXMMEXCPT ? "True " : "False",
|
||||||
data.cr4.LA57 ? "True " : "False", data.cr4.VMXE ? "True " : "False", data.cr4.SMXE ? "True " : "False", data.cr4.PCIDE ? "True " : "False",
|
data.cr4.LA57 ? "True " : "False", data.cr4.VMXE ? "True " : "False", data.cr4.SMXE ? "True " : "False", data.cr4.PCIDE ? "True " : "False",
|
||||||
data.cr4.OSXSAVE ? "True " : "False", data.cr4.SMEP ? "True " : "False", data.cr4.SMAP ? "True " : "False", data.cr4.PKE ? "True " : "False",
|
data.cr4.OSXSAVE ? "True " : "False", data.cr4.SMEP ? "True " : "False", data.cr4.SMAP ? "True " : "False", data.cr4.PKE ? "True " : "False",
|
||||||
#if defined(a64)
|
#if defined(__amd64__)
|
||||||
data.cr4.Reserved0, data.cr4.Reserved1, data.cr4.Reserved2);
|
data.cr4.Reserved0, data.cr4.Reserved1, data.cr4.Reserved2);
|
||||||
#elif defined(a32)
|
#elif defined(__i386__)
|
||||||
data.cr4.Reserved0, data.cr4.Reserved1, 0);
|
data.cr4.Reserved0, data.cr4.Reserved1, 0);
|
||||||
#elif defined(aa64)
|
#elif defined(__aarch64__)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
EHPrint("\e79FCF5CR8: TPL:%d\n", data.cr8.TPL);
|
EHPrint("\e79FCF5CR8: TPL:%d\n", data.cr8.TPL);
|
||||||
|
|
||||||
#if defined(a64)
|
#if defined(__amd64__)
|
||||||
EHPrint("\eFCFC02RFL: CF:%s PF:%s AF:%s ZF:%s\n SF:%s TF:%s IF:%s DF:%s\n OF:%s IOPL:%s NT:%s RF:%s\n VM:%s AC:%s VIF:%s VIP:%s\n ID:%s AlwaysOne:%d\n R0:%#x R1:%#x R2:%#x R3:%#x\n",
|
EHPrint("\eFCFC02RFL: CF:%s PF:%s AF:%s ZF:%s\n SF:%s TF:%s IF:%s DF:%s\n OF:%s IOPL:%s NT:%s RF:%s\n VM:%s AC:%s VIF:%s VIP:%s\n ID:%s AlwaysOne:%d\n R0:%#x R1:%#x R2:%#x R3:%#x\n",
|
||||||
data.Frame->rflags.CF ? "True " : "False", data.Frame->rflags.PF ? "True " : "False", data.Frame->rflags.AF ? "True " : "False", data.Frame->rflags.ZF ? "True " : "False",
|
data.Frame->rflags.CF ? "True " : "False", data.Frame->rflags.PF ? "True " : "False", data.Frame->rflags.AF ? "True " : "False", data.Frame->rflags.ZF ? "True " : "False",
|
||||||
data.Frame->rflags.SF ? "True " : "False", data.Frame->rflags.TF ? "True " : "False", data.Frame->rflags.IF ? "True " : "False", data.Frame->rflags.DF ? "True " : "False",
|
data.Frame->rflags.SF ? "True " : "False", data.Frame->rflags.TF ? "True " : "False", data.Frame->rflags.IF ? "True " : "False", data.Frame->rflags.DF ? "True " : "False",
|
||||||
@ -107,7 +109,7 @@ namespace CrashHandler
|
|||||||
data.Frame->rflags.VM ? "True " : "False", data.Frame->rflags.AC ? "True " : "False", data.Frame->rflags.VIF ? "True " : "False", data.Frame->rflags.VIP ? "True " : "False",
|
data.Frame->rflags.VM ? "True " : "False", data.Frame->rflags.AC ? "True " : "False", data.Frame->rflags.VIF ? "True " : "False", data.Frame->rflags.VIP ? "True " : "False",
|
||||||
data.Frame->rflags.ID ? "True " : "False", data.Frame->rflags.AlwaysOne,
|
data.Frame->rflags.ID ? "True " : "False", data.Frame->rflags.AlwaysOne,
|
||||||
data.Frame->rflags.Reserved0, data.Frame->rflags.Reserved1, data.Frame->rflags.Reserved2, data.Frame->rflags.Reserved3);
|
data.Frame->rflags.Reserved0, data.Frame->rflags.Reserved1, data.Frame->rflags.Reserved2, data.Frame->rflags.Reserved3);
|
||||||
#elif defined(a32)
|
#elif defined(__i386__)
|
||||||
EHPrint("\eFCFC02EFL: CF:%s PF:%s AF:%s ZF:%s\n SF:%s TF:%s IF:%s DF:%s\n OF:%s IOPL:%s NT:%s RF:%s\n VM:%s AC:%s VIF:%s VIP:%s\n ID:%s AlwaysOne:%d\n R0:%#x R1:%#x R2:%#x\n",
|
EHPrint("\eFCFC02EFL: CF:%s PF:%s AF:%s ZF:%s\n SF:%s TF:%s IF:%s DF:%s\n OF:%s IOPL:%s NT:%s RF:%s\n VM:%s AC:%s VIF:%s VIP:%s\n ID:%s AlwaysOne:%d\n R0:%#x R1:%#x R2:%#x\n",
|
||||||
data.Frame->eflags.CF ? "True " : "False", data.Frame->eflags.PF ? "True " : "False", data.Frame->eflags.AF ? "True " : "False", data.Frame->eflags.ZF ? "True " : "False",
|
data.Frame->eflags.CF ? "True " : "False", data.Frame->eflags.PF ? "True " : "False", data.Frame->eflags.AF ? "True " : "False", data.Frame->eflags.ZF ? "True " : "False",
|
||||||
data.Frame->eflags.SF ? "True " : "False", data.Frame->eflags.TF ? "True " : "False", data.Frame->eflags.IF ? "True " : "False", data.Frame->eflags.DF ? "True " : "False",
|
data.Frame->eflags.SF ? "True " : "False", data.Frame->eflags.TF ? "True " : "False", data.Frame->eflags.IF ? "True " : "False", data.Frame->eflags.DF ? "True " : "False",
|
||||||
@ -115,7 +117,7 @@ namespace CrashHandler
|
|||||||
data.Frame->eflags.VM ? "True " : "False", data.Frame->eflags.AC ? "True " : "False", data.Frame->eflags.VIF ? "True " : "False", data.Frame->eflags.VIP ? "True " : "False",
|
data.Frame->eflags.VM ? "True " : "False", data.Frame->eflags.AC ? "True " : "False", data.Frame->eflags.VIF ? "True " : "False", data.Frame->eflags.VIP ? "True " : "False",
|
||||||
data.Frame->eflags.ID ? "True " : "False", data.Frame->eflags.AlwaysOne,
|
data.Frame->eflags.ID ? "True " : "False", data.Frame->eflags.AlwaysOne,
|
||||||
data.Frame->eflags.Reserved0, data.Frame->eflags.Reserved1, data.Frame->eflags.Reserved2);
|
data.Frame->eflags.Reserved0, data.Frame->eflags.Reserved1, data.Frame->eflags.Reserved2);
|
||||||
#elif defined(aa64)
|
#elif defined(__aarch64__)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
EHPrint("\eA0F0F0DR7: LDR0:%s GDR0:%s LDR1:%s GDR1:%s\n LDR2:%s GDR2:%s LDR3:%s GDR3:%s\n CDR0:%s SDR0:%s CDR1:%s SDR1:%s\n CDR2:%s SDR2:%s CDR3:%s SDR3:%s\n R:%#x\n",
|
EHPrint("\eA0F0F0DR7: LDR0:%s GDR0:%s LDR1:%s GDR1:%s\n LDR2:%s GDR2:%s LDR3:%s GDR3:%s\n CDR0:%s SDR0:%s CDR1:%s SDR1:%s\n CDR2:%s SDR2:%s CDR3:%s SDR3:%s\n R:%#x\n",
|
||||||
@ -132,107 +134,107 @@ namespace CrashHandler
|
|||||||
|
|
||||||
switch (data.Frame->InterruptNumber)
|
switch (data.Frame->InterruptNumber)
|
||||||
{
|
{
|
||||||
case CPU::x86::DivideByZero:
|
case CPU::x64::DivideByZero:
|
||||||
{
|
{
|
||||||
DivideByZeroExceptionHandler(data.Frame);
|
DivideByZeroExceptionHandler(data.Frame);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CPU::x86::Debug:
|
case CPU::x64::Debug:
|
||||||
{
|
{
|
||||||
DebugExceptionHandler(data.Frame);
|
DebugExceptionHandler(data.Frame);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CPU::x86::NonMaskableInterrupt:
|
case CPU::x64::NonMaskableInterrupt:
|
||||||
{
|
{
|
||||||
NonMaskableInterruptExceptionHandler(data.Frame);
|
NonMaskableInterruptExceptionHandler(data.Frame);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CPU::x86::Breakpoint:
|
case CPU::x64::Breakpoint:
|
||||||
{
|
{
|
||||||
BreakpointExceptionHandler(data.Frame);
|
BreakpointExceptionHandler(data.Frame);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CPU::x86::Overflow:
|
case CPU::x64::Overflow:
|
||||||
{
|
{
|
||||||
OverflowExceptionHandler(data.Frame);
|
OverflowExceptionHandler(data.Frame);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CPU::x86::BoundRange:
|
case CPU::x64::BoundRange:
|
||||||
{
|
{
|
||||||
BoundRangeExceptionHandler(data.Frame);
|
BoundRangeExceptionHandler(data.Frame);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CPU::x86::InvalidOpcode:
|
case CPU::x64::InvalidOpcode:
|
||||||
{
|
{
|
||||||
InvalidOpcodeExceptionHandler(data.Frame);
|
InvalidOpcodeExceptionHandler(data.Frame);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CPU::x86::DeviceNotAvailable:
|
case CPU::x64::DeviceNotAvailable:
|
||||||
{
|
{
|
||||||
DeviceNotAvailableExceptionHandler(data.Frame);
|
DeviceNotAvailableExceptionHandler(data.Frame);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CPU::x86::DoubleFault:
|
case CPU::x64::DoubleFault:
|
||||||
{
|
{
|
||||||
DoubleFaultExceptionHandler(data.Frame);
|
DoubleFaultExceptionHandler(data.Frame);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CPU::x86::CoprocessorSegmentOverrun:
|
case CPU::x64::CoprocessorSegmentOverrun:
|
||||||
{
|
{
|
||||||
CoprocessorSegmentOverrunExceptionHandler(data.Frame);
|
CoprocessorSegmentOverrunExceptionHandler(data.Frame);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CPU::x86::InvalidTSS:
|
case CPU::x64::InvalidTSS:
|
||||||
{
|
{
|
||||||
InvalidTSSExceptionHandler(data.Frame);
|
InvalidTSSExceptionHandler(data.Frame);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CPU::x86::SegmentNotPresent:
|
case CPU::x64::SegmentNotPresent:
|
||||||
{
|
{
|
||||||
SegmentNotPresentExceptionHandler(data.Frame);
|
SegmentNotPresentExceptionHandler(data.Frame);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CPU::x86::StackSegmentFault:
|
case CPU::x64::StackSegmentFault:
|
||||||
{
|
{
|
||||||
StackFaultExceptionHandler(data.Frame);
|
StackFaultExceptionHandler(data.Frame);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CPU::x86::GeneralProtectionFault:
|
case CPU::x64::GeneralProtectionFault:
|
||||||
{
|
{
|
||||||
GeneralProtectionExceptionHandler(data.Frame);
|
GeneralProtectionExceptionHandler(data.Frame);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CPU::x86::PageFault:
|
case CPU::x64::PageFault:
|
||||||
{
|
{
|
||||||
PageFaultExceptionHandler(data.Frame);
|
PageFaultExceptionHandler(data.Frame);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CPU::x86::x87FloatingPoint:
|
case CPU::x64::x87FloatingPoint:
|
||||||
{
|
{
|
||||||
x87FloatingPointExceptionHandler(data.Frame);
|
x87FloatingPointExceptionHandler(data.Frame);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CPU::x86::AlignmentCheck:
|
case CPU::x64::AlignmentCheck:
|
||||||
{
|
{
|
||||||
AlignmentCheckExceptionHandler(data.Frame);
|
AlignmentCheckExceptionHandler(data.Frame);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CPU::x86::MachineCheck:
|
case CPU::x64::MachineCheck:
|
||||||
{
|
{
|
||||||
MachineCheckExceptionHandler(data.Frame);
|
MachineCheckExceptionHandler(data.Frame);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CPU::x86::SIMDFloatingPoint:
|
case CPU::x64::SIMDFloatingPoint:
|
||||||
{
|
{
|
||||||
SIMDFloatingPointExceptionHandler(data.Frame);
|
SIMDFloatingPointExceptionHandler(data.Frame);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CPU::x86::Virtualization:
|
case CPU::x64::Virtualization:
|
||||||
{
|
{
|
||||||
VirtualizationExceptionHandler(data.Frame);
|
VirtualizationExceptionHandler(data.Frame);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CPU::x86::Security:
|
case CPU::x64::Security:
|
||||||
{
|
{
|
||||||
SecurityExceptionHandler(data.Frame);
|
SecurityExceptionHandler(data.Frame);
|
||||||
break;
|
break;
|
||||||
|
@ -7,10 +7,10 @@
|
|||||||
#include <smp.hpp>
|
#include <smp.hpp>
|
||||||
#include <cpu.hpp>
|
#include <cpu.hpp>
|
||||||
|
|
||||||
#if defined(a64)
|
#if defined(__amd64__)
|
||||||
#include "../../../Architecture/amd64/cpu/gdt.hpp"
|
#include "../../../Architecture/amd64/cpu/gdt.hpp"
|
||||||
#elif defined(a32)
|
#elif defined(__i386__)
|
||||||
#elif defined(aa64)
|
#elif defined(__aarch64__)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "../../../kernel.h"
|
#include "../../../kernel.h"
|
||||||
@ -44,67 +44,67 @@ namespace CrashHandler
|
|||||||
|
|
||||||
switch (Frame->InterruptNumber)
|
switch (Frame->InterruptNumber)
|
||||||
{
|
{
|
||||||
case CPU::x86::DivideByZero:
|
case CPU::x64::DivideByZero:
|
||||||
{
|
{
|
||||||
EHPrint("Exception: Divide By Zero\n");
|
EHPrint("Exception: Divide By Zero\n");
|
||||||
EHPrint("The processor attempted to divide a number by zero.\n");
|
EHPrint("The processor attempted to divide a number by zero.\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CPU::x86::Debug:
|
case CPU::x64::Debug:
|
||||||
{
|
{
|
||||||
EHPrint("Exception: Debug\n");
|
EHPrint("Exception: Debug\n");
|
||||||
EHPrint("A debug exception has occurred.\n");
|
EHPrint("A debug exception has occurred.\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CPU::x86::NonMaskableInterrupt:
|
case CPU::x64::NonMaskableInterrupt:
|
||||||
{
|
{
|
||||||
EHPrint("Exception: Non-Maskable Interrupt\n");
|
EHPrint("Exception: Non-Maskable Interrupt\n");
|
||||||
EHPrint("A non-maskable interrupt was received.\n");
|
EHPrint("A non-maskable interrupt was received.\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CPU::x86::Breakpoint:
|
case CPU::x64::Breakpoint:
|
||||||
{
|
{
|
||||||
EHPrint("Exception: Breakpoint\n");
|
EHPrint("Exception: Breakpoint\n");
|
||||||
EHPrint("The processor encountered a breakpoint.\n");
|
EHPrint("The processor encountered a breakpoint.\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CPU::x86::Overflow:
|
case CPU::x64::Overflow:
|
||||||
{
|
{
|
||||||
EHPrint("Exception: Overflow\n");
|
EHPrint("Exception: Overflow\n");
|
||||||
EHPrint("The processor attempted to add a number to a number that was too large.\n");
|
EHPrint("The processor attempted to add a number to a number that was too large.\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CPU::x86::BoundRange:
|
case CPU::x64::BoundRange:
|
||||||
{
|
{
|
||||||
EHPrint("Exception: Bound Range\n");
|
EHPrint("Exception: Bound Range\n");
|
||||||
EHPrint("The processor attempted to access an array element that is out of bounds.\n");
|
EHPrint("The processor attempted to access an array element that is out of bounds.\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CPU::x86::InvalidOpcode:
|
case CPU::x64::InvalidOpcode:
|
||||||
{
|
{
|
||||||
EHPrint("Exception: Invalid Opcode\n");
|
EHPrint("Exception: Invalid Opcode\n");
|
||||||
EHPrint("The processor attempted to execute an invalid opcode.\n");
|
EHPrint("The processor attempted to execute an invalid opcode.\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CPU::x86::DeviceNotAvailable:
|
case CPU::x64::DeviceNotAvailable:
|
||||||
{
|
{
|
||||||
EHPrint("Exception: Device Not Available\n");
|
EHPrint("Exception: Device Not Available\n");
|
||||||
EHPrint("The processor attempted to use a device that is not available.\n");
|
EHPrint("The processor attempted to use a device that is not available.\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CPU::x86::DoubleFault:
|
case CPU::x64::DoubleFault:
|
||||||
{
|
{
|
||||||
EHPrint("Exception: Double Fault\n");
|
EHPrint("Exception: Double Fault\n");
|
||||||
EHPrint("The processor encountered a double fault.\n");
|
EHPrint("The processor encountered a double fault.\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CPU::x86::CoprocessorSegmentOverrun:
|
case CPU::x64::CoprocessorSegmentOverrun:
|
||||||
{
|
{
|
||||||
EHPrint("Exception: Coprocessor Segment Overrun\n");
|
EHPrint("Exception: Coprocessor Segment Overrun\n");
|
||||||
EHPrint("The processor attempted to access a segment that is not available.\n");
|
EHPrint("The processor attempted to access a segment that is not available.\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CPU::x86::InvalidTSS:
|
case CPU::x64::InvalidTSS:
|
||||||
{
|
{
|
||||||
EHPrint("Exception: Invalid TSS\n");
|
EHPrint("Exception: Invalid TSS\n");
|
||||||
EHPrint("The processor attempted to access a task state segment that is not available or valid.\n");
|
EHPrint("The processor attempted to access a task state segment that is not available or valid.\n");
|
||||||
@ -144,7 +144,7 @@ namespace CrashHandler
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CPU::x86::SegmentNotPresent:
|
case CPU::x64::SegmentNotPresent:
|
||||||
{
|
{
|
||||||
EHPrint("Exception: Segment Not Present\n");
|
EHPrint("Exception: Segment Not Present\n");
|
||||||
EHPrint("The processor attempted to access a segment that is not present.\n");
|
EHPrint("The processor attempted to access a segment that is not present.\n");
|
||||||
@ -184,7 +184,7 @@ namespace CrashHandler
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CPU::x86::StackSegmentFault:
|
case CPU::x64::StackSegmentFault:
|
||||||
{
|
{
|
||||||
EHPrint("Exception: Stack Segment Fault\n");
|
EHPrint("Exception: Stack Segment Fault\n");
|
||||||
CPU::x64::SelectorErrorCode SelCode = {.raw = Frame->ErrorCode};
|
CPU::x64::SelectorErrorCode SelCode = {.raw = Frame->ErrorCode};
|
||||||
@ -223,7 +223,7 @@ namespace CrashHandler
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CPU::x86::GeneralProtectionFault:
|
case CPU::x64::GeneralProtectionFault:
|
||||||
{
|
{
|
||||||
EHPrint("Exception: General Protection Fault\n");
|
EHPrint("Exception: General Protection Fault\n");
|
||||||
EHPrint("Kernel performed an illegal operation.\n");
|
EHPrint("Kernel performed an illegal operation.\n");
|
||||||
@ -263,17 +263,17 @@ namespace CrashHandler
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CPU::x86::PageFault:
|
case CPU::x64::PageFault:
|
||||||
{
|
{
|
||||||
EHPrint("Exception: Page Fault\n");
|
EHPrint("Exception: Page Fault\n");
|
||||||
EHPrint("The processor attempted to access a page that is not present.\n");
|
EHPrint("The processor attempted to access a page that is not present.\n");
|
||||||
|
|
||||||
CPU::x64::PageFaultErrorCode params = {.raw = (uint32_t)Frame->ErrorCode};
|
CPU::x64::PageFaultErrorCode params = {.raw = (uint32_t)Frame->ErrorCode};
|
||||||
#if defined(a64)
|
#if defined(__amd64__)
|
||||||
EHPrint("At \e8888FF%#lx \eFAFAFAby \e8888FF%#lx\eFAFAFA\n", PageFaultAddress, Frame->rip);
|
EHPrint("At \e8888FF%#lx \eFAFAFAby \e8888FF%#lx\eFAFAFA\n", CPU::x64::readcr2().PFLA, Frame->rip);
|
||||||
#elif defined(a32)
|
#elif defined(__i386__)
|
||||||
EHPrint("At \e8888FF%#lx \eFAFAFAby \e8888FF%#lx\eFAFAFA\n", PageFaultAddress, Frame->eip);
|
EHPrint("At \e8888FF%#lx \eFAFAFAby \e8888FF%#lx\eFAFAFA\n", CPU::x64::readcr2().PFLA, Frame->eip);
|
||||||
#elif defined(aa64)
|
#elif defined(__aarch64__)
|
||||||
#endif
|
#endif
|
||||||
EHPrint("Page: %s\eFAFAFA\n", params.P ? "\e058C19Present" : "\eE85230Not Present");
|
EHPrint("Page: %s\eFAFAFA\n", params.P ? "\e058C19Present" : "\eE85230Not Present");
|
||||||
EHPrint("Write Operation: \e8888FF%s\eFAFAFA\n", params.W ? "Read-Only" : "Read-Write");
|
EHPrint("Write Operation: \e8888FF%s\eFAFAFA\n", params.W ? "Read-Only" : "Read-Write");
|
||||||
@ -291,37 +291,37 @@ namespace CrashHandler
|
|||||||
EHPrint("\eFAFAFA");
|
EHPrint("\eFAFAFA");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CPU::x86::x87FloatingPoint:
|
case CPU::x64::x87FloatingPoint:
|
||||||
{
|
{
|
||||||
EHPrint("Exception: x87 Floating Point\n");
|
EHPrint("Exception: x87 Floating Point\n");
|
||||||
EHPrint("The x87 FPU generated an error.\n");
|
EHPrint("The x87 FPU generated an error.\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CPU::x86::AlignmentCheck:
|
case CPU::x64::AlignmentCheck:
|
||||||
{
|
{
|
||||||
EHPrint("Exception: Alignment Check\n");
|
EHPrint("Exception: Alignment Check\n");
|
||||||
EHPrint("The CPU detected an unaligned memory access.\n");
|
EHPrint("The CPU detected an unaligned memory access.\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CPU::x86::MachineCheck:
|
case CPU::x64::MachineCheck:
|
||||||
{
|
{
|
||||||
EHPrint("Exception: Machine Check\n");
|
EHPrint("Exception: Machine Check\n");
|
||||||
EHPrint("The CPU detected a hardware error.\n");
|
EHPrint("The CPU detected a hardware error.\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CPU::x86::SIMDFloatingPoint:
|
case CPU::x64::SIMDFloatingPoint:
|
||||||
{
|
{
|
||||||
EHPrint("Exception: SIMD Floating Point\n");
|
EHPrint("Exception: SIMD Floating Point\n");
|
||||||
EHPrint("The CPU detected an error in the SIMD unit.\n");
|
EHPrint("The CPU detected an error in the SIMD unit.\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CPU::x86::Virtualization:
|
case CPU::x64::Virtualization:
|
||||||
{
|
{
|
||||||
EHPrint("Exception: Virtualization\n");
|
EHPrint("Exception: Virtualization\n");
|
||||||
EHPrint("The CPU detected a virtualization error.\n");
|
EHPrint("The CPU detected a virtualization error.\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CPU::x86::Security:
|
case CPU::x64::Security:
|
||||||
{
|
{
|
||||||
EHPrint("Exception: Security\n");
|
EHPrint("Exception: Security\n");
|
||||||
EHPrint("The CPU detected a security violation.\n");
|
EHPrint("The CPU detected a security violation.\n");
|
||||||
@ -335,11 +335,11 @@ namespace CrashHandler
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(a64)
|
#if defined(__amd64__)
|
||||||
EHPrint("The exception happened at \e8888FF%#lx\eFAFAFA\n", Frame->rip);
|
EHPrint("The exception happened at \e8888FF%#lx\eFAFAFA\n", Frame->rip);
|
||||||
#elif defined(a32)
|
#elif defined(__i386__)
|
||||||
EHPrint("The exception happened at \e8888FF%#lx\eFAFAFA\n", Frame->eip);
|
EHPrint("The exception happened at \e8888FF%#lx\eFAFAFA\n", Frame->eip);
|
||||||
#elif defined(aa64)
|
#elif defined(__aarch64__)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,17 +1,17 @@
|
|||||||
#include "../../crashhandler.hpp"
|
#include "../../crashhandler.hpp"
|
||||||
#include "../chfcts.hpp"
|
#include "../chfcts.hpp"
|
||||||
|
|
||||||
#include <ints.hpp>
|
#include <interrupts.hpp>
|
||||||
#include <display.hpp>
|
#include <display.hpp>
|
||||||
#include <printf.h>
|
#include <printf.h>
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
#include <smp.hpp>
|
#include <smp.hpp>
|
||||||
#include <cpu.hpp>
|
#include <cpu.hpp>
|
||||||
|
|
||||||
#if defined(a64)
|
#if defined(__amd64__)
|
||||||
#include "../../../Architecture/amd64/cpu/gdt.hpp"
|
#include "../../../Architecture/amd64/cpu/gdt.hpp"
|
||||||
#elif defined(a32)
|
#elif defined(__i386__)
|
||||||
#elif defined(aa64)
|
#elif defined(__aarch64__)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "../../../kernel.h"
|
#include "../../../kernel.h"
|
||||||
@ -20,19 +20,10 @@ namespace CrashHandler
|
|||||||
{
|
{
|
||||||
SafeFunction void DisplayStackFrameScreen(CRData data)
|
SafeFunction void DisplayStackFrameScreen(CRData data)
|
||||||
{
|
{
|
||||||
EHPrint("\eFAFAFATracing 10 frames...");
|
EHPrint("\eFAFAFATracing 40 frames...\n");
|
||||||
TraceFrames(data.Frame, 10, KernelSymbolTable, true);
|
TraceFrames(data.Frame, 40);
|
||||||
if (data.Process)
|
EHPrint("\n\n\eFAFAFATracing interrupt frames...\n");
|
||||||
{
|
for (uint64_t i = 0; i < 8; i++)
|
||||||
EHPrint("\n\eFAFAFATracing 10 process frames...");
|
|
||||||
SymbolResolver::Symbols *sh = data.Process->ELFSymbolTable;
|
|
||||||
if (!sh)
|
|
||||||
EHPrint("\n\eFF0000< No symbol table available. >\n");
|
|
||||||
else
|
|
||||||
TraceFrames(data.Frame, 10, sh, false);
|
|
||||||
}
|
|
||||||
EHPrint("\n\eFAFAFATracing interrupt frames...");
|
|
||||||
for (short i = 0; i < 8; i++)
|
|
||||||
{
|
{
|
||||||
if (EHIntFrames[i])
|
if (EHIntFrames[i])
|
||||||
{
|
{
|
||||||
@ -40,42 +31,16 @@ namespace CrashHandler
|
|||||||
continue;
|
continue;
|
||||||
EHPrint("\n\e2565CC%p", EHIntFrames[i]);
|
EHPrint("\n\e2565CC%p", EHIntFrames[i]);
|
||||||
EHPrint("\e7925CC-");
|
EHPrint("\e7925CC-");
|
||||||
#if defined(a64)
|
#if defined(__amd64__)
|
||||||
if ((uintptr_t)EHIntFrames[i] >= 0xFFFFFFFF80000000 && (uintptr_t)EHIntFrames[i] <= (uintptr_t)&_kernel_end)
|
if ((uint64_t)EHIntFrames[i] >= 0xFFFFFFFF80000000 && (uint64_t)EHIntFrames[i] <= (uint64_t)&_kernel_end)
|
||||||
#elif defined(a32)
|
#elif defined(__i386__)
|
||||||
if ((uintptr_t)EHIntFrames[i] >= 0xC0000000 && (uintptr_t)EHIntFrames[i] <= (uintptr_t)&_kernel_end)
|
if ((uint64_t)EHIntFrames[i] >= 0xC0000000 && (uint64_t)EHIntFrames[i] <= (uint64_t)&_kernel_end)
|
||||||
#elif defined(aa64)
|
#elif defined(__aarch64__)
|
||||||
#endif
|
#endif
|
||||||
EHPrint("\e25CCC9%s", KernelSymbolTable->GetSymbolFromAddress((uintptr_t)EHIntFrames[i]));
|
EHPrint("\e25CCC9%s", KernelSymbolTable->GetSymbolFromAddress((uint64_t)EHIntFrames[i]));
|
||||||
else
|
else
|
||||||
EHPrint("\eFF4CA9Outside Kernel");
|
EHPrint("\eFF4CA9Outside Kernel");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (data.Process && data.Thread)
|
|
||||||
{
|
|
||||||
EHPrint("\n\n\eFAFAFATracing thread instruction pointer history...");
|
|
||||||
SymbolResolver::Symbols *sh = data.Process->ELFSymbolTable;
|
|
||||||
if (!sh)
|
|
||||||
EHPrint("\n\eFFA500Warning: No symbol table available.");
|
|
||||||
int SameItr = 0;
|
|
||||||
uintptr_t LastRIP = 0;
|
|
||||||
for (size_t i = 0; i < sizeof(data.Thread->IPHistory) / sizeof(data.Thread->IPHistory[0]); i++)
|
|
||||||
{
|
|
||||||
if (data.Thread->IPHistory[i] == LastRIP)
|
|
||||||
{
|
|
||||||
SameItr++;
|
|
||||||
if (SameItr > 2)
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
SameItr = 0;
|
|
||||||
LastRIP = data.Thread->IPHistory[i];
|
|
||||||
if (!sh)
|
|
||||||
EHPrint("\n\eCCCCCC%d: \e2565CC%p", i, data.Thread->IPHistory[i]);
|
|
||||||
else
|
|
||||||
EHPrint("\n\eCCCCCC%d: \e2565CC%p\e7925CC-\e25CCC9%s", i, data.Thread->IPHistory[i], sh->GetSymbolFromAddress(data.Thread->IPHistory[i]));
|
|
||||||
}
|
|
||||||
EHPrint("\n\e7925CCNote: \e2565CCSame instruction pointers are not shown more than 3 times.\n");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,10 +7,10 @@
|
|||||||
#include <smp.hpp>
|
#include <smp.hpp>
|
||||||
#include <cpu.hpp>
|
#include <cpu.hpp>
|
||||||
|
|
||||||
#if defined(a64)
|
#if defined(__amd64__)
|
||||||
#include "../../../Architecture/amd64/cpu/gdt.hpp"
|
#include "../../../Architecture/amd64/cpu/gdt.hpp"
|
||||||
#elif defined(a32)
|
#elif defined(__i386__)
|
||||||
#elif defined(aa64)
|
#elif defined(__aarch64__)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "../../../kernel.h"
|
#include "../../../kernel.h"
|
||||||
@ -44,11 +44,11 @@ namespace CrashHandler
|
|||||||
if (TaskManager)
|
if (TaskManager)
|
||||||
{
|
{
|
||||||
if (data.Thread)
|
if (data.Thread)
|
||||||
#if defined(a64)
|
#if defined(__amd64__)
|
||||||
EHPrint("\eFAFAFACrash occurred in thread \eAA0F0F%s\eFAFAFA(%ld) at \e00AAAA%#lx\n", data.Thread->Name, data.Thread->ID, data.Frame->rip);
|
EHPrint("\eFAFAFACrash occured in thread \eAA0F0F%s\eFAFAFA(%ld) at \e00AAAA%#lx\n", data.Thread->Name, data.Thread->ID, data.Frame->rip);
|
||||||
#elif defined(a32)
|
#elif defined(__i386__)
|
||||||
EHPrint("\eFAFAFACrash occurred in thread \eAA0F0F%s\eFAFAFA(%ld) at \e00AAAA%#lx\n", data.Thread->Name, data.Thread->ID, data.Frame->eip);
|
EHPrint("\eFAFAFACrash occured in thread \eAA0F0F%s\eFAFAFA(%ld) at \e00AAAA%#lx\n", data.Thread->Name, data.Thread->ID, data.Frame->eip);
|
||||||
#elif defined(aa64)
|
#elif defined(__aarch64__)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
EHPrint("\eFAFAFAProcess list (%ld):\n", Plist.size());
|
EHPrint("\eFAFAFAProcess list (%ld):\n", Plist.size());
|
||||||
|
@ -7,10 +7,10 @@
|
|||||||
#include <smp.hpp>
|
#include <smp.hpp>
|
||||||
#include <cpu.hpp>
|
#include <cpu.hpp>
|
||||||
|
|
||||||
#if defined(a64)
|
#if defined(__amd64__)
|
||||||
#include "../../Architecture/amd64/cpu/gdt.hpp"
|
#include "../../Architecture/amd64/cpu/gdt.hpp"
|
||||||
#elif defined(a32)
|
#elif defined(__i386__)
|
||||||
#elif defined(aa64)
|
#elif defined(__aarch64__)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "../../kernel.h"
|
#include "../../kernel.h"
|
||||||
@ -34,9 +34,8 @@ SafeFunction void UserModeExceptionHandler(CHArchTrapFrame *Frame)
|
|||||||
CPUData *CurCPU = GetCurrentCPU();
|
CPUData *CurCPU = GetCurrentCPU();
|
||||||
|
|
||||||
{
|
{
|
||||||
#if defined(a64)
|
|
||||||
CPU::x64::CR0 cr0 = CPU::x64::readcr0();
|
CPU::x64::CR0 cr0 = CPU::x64::readcr0();
|
||||||
CPU::x64::CR2 cr2 = CPU::x64::CR2{.PFLA = CrashHandler::PageFaultAddress};
|
CPU::x64::CR2 cr2 = CPU::x64::readcr2();
|
||||||
CPU::x64::CR3 cr3 = CPU::x64::readcr3();
|
CPU::x64::CR3 cr3 = CPU::x64::readcr3();
|
||||||
CPU::x64::CR4 cr4 = CPU::x64::readcr4();
|
CPU::x64::CR4 cr4 = CPU::x64::readcr4();
|
||||||
CPU::x64::CR8 cr8 = CPU::x64::readcr8();
|
CPU::x64::CR8 cr8 = CPU::x64::readcr8();
|
||||||
@ -44,42 +43,30 @@ SafeFunction void UserModeExceptionHandler(CHArchTrapFrame *Frame)
|
|||||||
efer.raw = CPU::x64::rdmsr(CPU::x64::MSR_EFER);
|
efer.raw = CPU::x64::rdmsr(CPU::x64::MSR_EFER);
|
||||||
|
|
||||||
error("Technical Informations on CPU %lld:", CurCPU->ID);
|
error("Technical Informations on CPU %lld:", CurCPU->ID);
|
||||||
uintptr_t ds;
|
#if defined(__amd64__)
|
||||||
|
uint64_t ds;
|
||||||
asmv("mov %%ds, %0"
|
asmv("mov %%ds, %0"
|
||||||
: "=r"(ds));
|
: "=r"(ds));
|
||||||
#elif defined(a32)
|
#elif defined(__i386__)
|
||||||
CPU::x32::CR0 cr0 = CPU::x32::readcr0();
|
uint32_t ds;
|
||||||
CPU::x32::CR2 cr2 = CPU::x32::CR2{.PFLA = CrashHandler::PageFaultAddress};
|
|
||||||
CPU::x32::CR3 cr3 = CPU::x32::readcr3();
|
|
||||||
CPU::x32::CR4 cr4 = CPU::x32::readcr4();
|
|
||||||
CPU::x32::CR8 cr8 = CPU::x32::readcr8();
|
|
||||||
CPU::x32::EFER efer;
|
|
||||||
efer.raw = CPU::x32::rdmsr(CPU::x32::MSR_EFER);
|
|
||||||
|
|
||||||
error("Technical Informations on CPU %lld:", CurCPU->ID);
|
|
||||||
uintptr_t ds;
|
|
||||||
asmv("mov %%ds, %0"
|
asmv("mov %%ds, %0"
|
||||||
: "=r"(ds));
|
: "=r"(ds));
|
||||||
#elif defined(aa64)
|
#elif defined(__aarch64__)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(a64)
|
|
||||||
error("FS=%#llx GS=%#llx SS=%#llx CS=%#llx DS=%#llx",
|
error("FS=%#llx GS=%#llx SS=%#llx CS=%#llx DS=%#llx",
|
||||||
CPU::x64::rdmsr(CPU::x64::MSR_FS_BASE), CPU::x64::rdmsr(CPU::x64::MSR_GS_BASE),
|
CPU::x64::rdmsr(CPU::x64::MSR_FS_BASE), CPU::x64::rdmsr(CPU::x64::MSR_GS_BASE),
|
||||||
Frame->ss, Frame->cs, ds);
|
Frame->ss, Frame->cs, ds);
|
||||||
|
#if defined(__amd64__)
|
||||||
error("R8=%#llx R9=%#llx R10=%#llx R11=%#llx", Frame->r8, Frame->r9, Frame->r10, Frame->r11);
|
error("R8=%#llx R9=%#llx R10=%#llx R11=%#llx", Frame->r8, Frame->r9, Frame->r10, Frame->r11);
|
||||||
error("R12=%#llx R13=%#llx R14=%#llx R15=%#llx", Frame->r12, Frame->r13, Frame->r14, Frame->r15);
|
error("R12=%#llx R13=%#llx R14=%#llx R15=%#llx", Frame->r12, Frame->r13, Frame->r14, Frame->r15);
|
||||||
error("RAX=%#llx RBX=%#llx RCX=%#llx RDX=%#llx", Frame->rax, Frame->rbx, Frame->rcx, Frame->rdx);
|
error("RAX=%#llx RBX=%#llx RCX=%#llx RDX=%#llx", Frame->rax, Frame->rbx, Frame->rcx, Frame->rdx);
|
||||||
error("RSI=%#llx RDI=%#llx RBP=%#llx RSP=%#llx", Frame->rsi, Frame->rdi, Frame->rbp, Frame->rsp);
|
error("RSI=%#llx RDI=%#llx RBP=%#llx RSP=%#llx", Frame->rsi, Frame->rdi, Frame->rbp, Frame->rsp);
|
||||||
error("RIP=%#llx RFL=%#llx INT=%#llx ERR=%#llx EFER=%#llx", Frame->rip, Frame->rflags.raw, Frame->InterruptNumber, Frame->ErrorCode, efer.raw);
|
error("RIP=%#llx RFL=%#llx INT=%#llx ERR=%#llx EFER=%#llx", Frame->rip, Frame->rflags.raw, Frame->InterruptNumber, Frame->ErrorCode, efer.raw);
|
||||||
#elif defined(a32)
|
#elif defined(__i386__)
|
||||||
error("FS=%#llx GS=%#llx SS=%#llx CS=%#llx DS=%#llx",
|
|
||||||
CPU::x32::rdmsr(CPU::x32::MSR_FS_BASE), CPU::x32::rdmsr(CPU::x32::MSR_GS_BASE),
|
|
||||||
Frame->ss, Frame->cs, ds);
|
|
||||||
error("EAX=%#llx EBX=%#llx ECX=%#llx EDX=%#llx", Frame->eax, Frame->ebx, Frame->ecx, Frame->edx);
|
error("EAX=%#llx EBX=%#llx ECX=%#llx EDX=%#llx", Frame->eax, Frame->ebx, Frame->ecx, Frame->edx);
|
||||||
error("ESI=%#llx EDI=%#llx EBP=%#llx ESP=%#llx", Frame->esi, Frame->edi, Frame->ebp, Frame->esp);
|
error("ESI=%#llx EDI=%#llx EBP=%#llx ESP=%#llx", Frame->esi, Frame->edi, Frame->ebp, Frame->esp);
|
||||||
error("EIP=%#llx EFL=%#llx INT=%#llx ERR=%#llx EFER=%#llx", Frame->eip, Frame->eflags.raw, Frame->InterruptNumber, Frame->ErrorCode, efer.raw);
|
error("EIP=%#llx EFL=%#llx INT=%#llx ERR=%#llx EFER=%#llx", Frame->eip, Frame->eflags.raw, Frame->InterruptNumber, Frame->ErrorCode, efer.raw);
|
||||||
#elif defined(aa64)
|
#elif defined(__aarch64__)
|
||||||
#endif
|
#endif
|
||||||
error("CR0=%#llx CR2=%#llx CR3=%#llx CR4=%#llx CR8=%#llx", cr0.raw, cr2.raw, cr3.raw, cr4.raw, cr8.raw);
|
error("CR0=%#llx CR2=%#llx CR3=%#llx CR4=%#llx CR8=%#llx", cr0.raw, cr2.raw, cr3.raw, cr4.raw, cr8.raw);
|
||||||
|
|
||||||
@ -95,7 +82,6 @@ SafeFunction void UserModeExceptionHandler(CHArchTrapFrame *Frame)
|
|||||||
error("CR3: PWT:%s PCD:%s PDBR:%#llx",
|
error("CR3: PWT:%s PCD:%s PDBR:%#llx",
|
||||||
cr3.PWT ? "True " : "False", cr3.PCD ? "True " : "False", cr3.PDBR);
|
cr3.PWT ? "True " : "False", cr3.PCD ? "True " : "False", cr3.PDBR);
|
||||||
|
|
||||||
#if defined(a64)
|
|
||||||
error("CR4: VME:%s PVI:%s TSD:%s DE:%s PSE:%s PAE:%s MCE:%s PGE:%s PCE:%s UMIP:%s OSFXSR:%s OSXMMEXCPT:%s LA57:%s VMXE:%s SMXE:%s PCIDE:%s OSXSAVE:%s SMEP:%s SMAP:%s PKE:%s R0:%#x R1:%#x R2:%#x",
|
error("CR4: VME:%s PVI:%s TSD:%s DE:%s PSE:%s PAE:%s MCE:%s PGE:%s PCE:%s UMIP:%s OSFXSR:%s OSXMMEXCPT:%s LA57:%s VMXE:%s SMXE:%s PCIDE:%s OSXSAVE:%s SMEP:%s SMAP:%s PKE:%s R0:%#x R1:%#x R2:%#x",
|
||||||
cr4.VME ? "True " : "False", cr4.PVI ? "True " : "False", cr4.TSD ? "True " : "False", cr4.DE ? "True " : "False",
|
cr4.VME ? "True " : "False", cr4.PVI ? "True " : "False", cr4.TSD ? "True " : "False", cr4.DE ? "True " : "False",
|
||||||
cr4.PSE ? "True " : "False", cr4.PAE ? "True " : "False", cr4.MCE ? "True " : "False", cr4.PGE ? "True " : "False",
|
cr4.PSE ? "True " : "False", cr4.PAE ? "True " : "False", cr4.MCE ? "True " : "False", cr4.PGE ? "True " : "False",
|
||||||
@ -103,19 +89,10 @@ SafeFunction void UserModeExceptionHandler(CHArchTrapFrame *Frame)
|
|||||||
cr4.LA57 ? "True " : "False", cr4.VMXE ? "True " : "False", cr4.SMXE ? "True " : "False", cr4.PCIDE ? "True " : "False",
|
cr4.LA57 ? "True " : "False", cr4.VMXE ? "True " : "False", cr4.SMXE ? "True " : "False", cr4.PCIDE ? "True " : "False",
|
||||||
cr4.OSXSAVE ? "True " : "False", cr4.SMEP ? "True " : "False", cr4.SMAP ? "True " : "False", cr4.PKE ? "True " : "False",
|
cr4.OSXSAVE ? "True " : "False", cr4.SMEP ? "True " : "False", cr4.SMAP ? "True " : "False", cr4.PKE ? "True " : "False",
|
||||||
cr4.Reserved0, cr4.Reserved1, cr4.Reserved2);
|
cr4.Reserved0, cr4.Reserved1, cr4.Reserved2);
|
||||||
#elif defined(a32)
|
|
||||||
error("CR4: VME:%s PVI:%s TSD:%s DE:%s PSE:%s PAE:%s MCE:%s PGE:%s PCE:%s UMIP:%s OSFXSR:%s OSXMMEXCPT:%s LA57:%s VMXE:%s SMXE:%s PCIDE:%s OSXSAVE:%s SMEP:%s SMAP:%s PKE:%s R0:%#x R1:%#x",
|
|
||||||
cr4.VME ? "True " : "False", cr4.PVI ? "True " : "False", cr4.TSD ? "True " : "False", cr4.DE ? "True " : "False",
|
|
||||||
cr4.PSE ? "True " : "False", cr4.PAE ? "True " : "False", cr4.MCE ? "True " : "False", cr4.PGE ? "True " : "False",
|
|
||||||
cr4.PCE ? "True " : "False", cr4.UMIP ? "True " : "False", cr4.OSFXSR ? "True " : "False", cr4.OSXMMEXCPT ? "True " : "False",
|
|
||||||
cr4.LA57 ? "True " : "False", cr4.VMXE ? "True " : "False", cr4.SMXE ? "True " : "False", cr4.PCIDE ? "True " : "False",
|
|
||||||
cr4.OSXSAVE ? "True " : "False", cr4.SMEP ? "True " : "False", cr4.SMAP ? "True " : "False", cr4.PKE ? "True " : "False",
|
|
||||||
cr4.Reserved0, cr4.Reserved1);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
error("CR8: TPL:%d", cr8.TPL);
|
error("CR8: TPL:%d", cr8.TPL);
|
||||||
|
|
||||||
#if defined(a64)
|
#if defined(__amd64__)
|
||||||
error("RFL: CF:%s PF:%s AF:%s ZF:%s SF:%s TF:%s IF:%s DF:%s OF:%s IOPL:%s NT:%s RF:%s VM:%s AC:%s VIF:%s VIP:%s ID:%s AlwaysOne:%d R0:%#x R1:%#x R2:%#x R3:%#x",
|
error("RFL: CF:%s PF:%s AF:%s ZF:%s SF:%s TF:%s IF:%s DF:%s OF:%s IOPL:%s NT:%s RF:%s VM:%s AC:%s VIF:%s VIP:%s ID:%s AlwaysOne:%d R0:%#x R1:%#x R2:%#x R3:%#x",
|
||||||
Frame->rflags.CF ? "True " : "False", Frame->rflags.PF ? "True " : "False", Frame->rflags.AF ? "True " : "False", Frame->rflags.ZF ? "True " : "False",
|
Frame->rflags.CF ? "True " : "False", Frame->rflags.PF ? "True " : "False", Frame->rflags.AF ? "True " : "False", Frame->rflags.ZF ? "True " : "False",
|
||||||
Frame->rflags.SF ? "True " : "False", Frame->rflags.TF ? "True " : "False", Frame->rflags.IF ? "True " : "False", Frame->rflags.DF ? "True " : "False",
|
Frame->rflags.SF ? "True " : "False", Frame->rflags.TF ? "True " : "False", Frame->rflags.IF ? "True " : "False", Frame->rflags.DF ? "True " : "False",
|
||||||
@ -123,7 +100,7 @@ SafeFunction void UserModeExceptionHandler(CHArchTrapFrame *Frame)
|
|||||||
Frame->rflags.VM ? "True " : "False", Frame->rflags.AC ? "True " : "False", Frame->rflags.VIF ? "True " : "False", Frame->rflags.VIP ? "True " : "False",
|
Frame->rflags.VM ? "True " : "False", Frame->rflags.AC ? "True " : "False", Frame->rflags.VIF ? "True " : "False", Frame->rflags.VIP ? "True " : "False",
|
||||||
Frame->rflags.ID ? "True " : "False", Frame->rflags.AlwaysOne,
|
Frame->rflags.ID ? "True " : "False", Frame->rflags.AlwaysOne,
|
||||||
Frame->rflags.Reserved0, Frame->rflags.Reserved1, Frame->rflags.Reserved2, Frame->rflags.Reserved3);
|
Frame->rflags.Reserved0, Frame->rflags.Reserved1, Frame->rflags.Reserved2, Frame->rflags.Reserved3);
|
||||||
#elif defined(a32)
|
#elif defined(__i386__)
|
||||||
error("EFL: CF:%s PF:%s AF:%s ZF:%s SF:%s TF:%s IF:%s DF:%s OF:%s IOPL:%s NT:%s RF:%s VM:%s AC:%s VIF:%s VIP:%s ID:%s AlwaysOne:%d R0:%#x R1:%#x R2:%#x",
|
error("EFL: CF:%s PF:%s AF:%s ZF:%s SF:%s TF:%s IF:%s DF:%s OF:%s IOPL:%s NT:%s RF:%s VM:%s AC:%s VIF:%s VIP:%s ID:%s AlwaysOne:%d R0:%#x R1:%#x R2:%#x",
|
||||||
Frame->eflags.CF ? "True " : "False", Frame->eflags.PF ? "True " : "False", Frame->eflags.AF ? "True " : "False", Frame->eflags.ZF ? "True " : "False",
|
Frame->eflags.CF ? "True " : "False", Frame->eflags.PF ? "True " : "False", Frame->eflags.AF ? "True " : "False", Frame->eflags.ZF ? "True " : "False",
|
||||||
Frame->eflags.SF ? "True " : "False", Frame->eflags.TF ? "True " : "False", Frame->eflags.IF ? "True " : "False", Frame->eflags.DF ? "True " : "False",
|
Frame->eflags.SF ? "True " : "False", Frame->eflags.TF ? "True " : "False", Frame->eflags.IF ? "True " : "False", Frame->eflags.DF ? "True " : "False",
|
||||||
@ -131,7 +108,7 @@ SafeFunction void UserModeExceptionHandler(CHArchTrapFrame *Frame)
|
|||||||
Frame->eflags.VM ? "True " : "False", Frame->eflags.AC ? "True " : "False", Frame->eflags.VIF ? "True " : "False", Frame->eflags.VIP ? "True " : "False",
|
Frame->eflags.VM ? "True " : "False", Frame->eflags.AC ? "True " : "False", Frame->eflags.VIF ? "True " : "False", Frame->eflags.VIP ? "True " : "False",
|
||||||
Frame->eflags.ID ? "True " : "False", Frame->eflags.AlwaysOne,
|
Frame->eflags.ID ? "True " : "False", Frame->eflags.AlwaysOne,
|
||||||
Frame->eflags.Reserved0, Frame->eflags.Reserved1, Frame->eflags.Reserved2);
|
Frame->eflags.Reserved0, Frame->eflags.Reserved1, Frame->eflags.Reserved2);
|
||||||
#elif defined(aa64)
|
#elif defined(__aarch64__)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
error("EFER: SCE:%s LME:%s LMA:%s NXE:%s SVME:%s LMSLE:%s FFXSR:%s TCE:%s R0:%#x R1:%#x R2:%#x",
|
error("EFER: SCE:%s LME:%s LMA:%s NXE:%s SVME:%s LMSLE:%s FFXSR:%s TCE:%s R0:%#x R1:%#x R2:%#x",
|
||||||
@ -142,75 +119,70 @@ SafeFunction void UserModeExceptionHandler(CHArchTrapFrame *Frame)
|
|||||||
|
|
||||||
switch (Frame->InterruptNumber)
|
switch (Frame->InterruptNumber)
|
||||||
{
|
{
|
||||||
case CPU::x86::DivideByZero:
|
case CPU::x64::DivideByZero:
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CPU::x86::Debug:
|
case CPU::x64::Debug:
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CPU::x86::NonMaskableInterrupt:
|
case CPU::x64::NonMaskableInterrupt:
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CPU::x86::Breakpoint:
|
case CPU::x64::Breakpoint:
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CPU::x86::Overflow:
|
case CPU::x64::Overflow:
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CPU::x86::BoundRange:
|
case CPU::x64::BoundRange:
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CPU::x86::InvalidOpcode:
|
case CPU::x64::InvalidOpcode:
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CPU::x86::DeviceNotAvailable:
|
case CPU::x64::DeviceNotAvailable:
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CPU::x86::DoubleFault:
|
case CPU::x64::DoubleFault:
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CPU::x86::CoprocessorSegmentOverrun:
|
case CPU::x64::CoprocessorSegmentOverrun:
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CPU::x86::InvalidTSS:
|
case CPU::x64::InvalidTSS:
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CPU::x86::SegmentNotPresent:
|
case CPU::x64::SegmentNotPresent:
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CPU::x86::StackSegmentFault:
|
case CPU::x64::StackSegmentFault:
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CPU::x86::GeneralProtectionFault:
|
case CPU::x64::GeneralProtectionFault:
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CPU::x86::PageFault:
|
case CPU::x64::PageFault:
|
||||||
{
|
{
|
||||||
uintptr_t CheckPageFaultAddress = 0;
|
|
||||||
CPU::x64::PageFaultErrorCode params = {.raw = (uint32_t)Frame->ErrorCode};
|
CPU::x64::PageFaultErrorCode params = {.raw = (uint32_t)Frame->ErrorCode};
|
||||||
#if defined(a64)
|
#if defined(__amd64__)
|
||||||
CheckPageFaultAddress = CrashHandler::PageFaultAddress;
|
error("An exception occurred at %#lx by %#lx", CPU::x64::readcr2().PFLA, Frame->rip);
|
||||||
if (CheckPageFaultAddress == 0)
|
#elif defined(__i386__)
|
||||||
CheckPageFaultAddress = Frame->rip;
|
error("An exception occurred at %#lx by %#lx", CPU::x64::readcr2().PFLA, Frame->eip);
|
||||||
|
#elif defined(__aarch64__)
|
||||||
error("An exception occurred at %#lx by %#lx", CrashHandler::PageFaultAddress, Frame->rip);
|
|
||||||
#elif defined(a32)
|
|
||||||
error("An exception occurred at %#lx by %#lx", CrashHandler::PageFaultAddress, Frame->eip);
|
|
||||||
#elif defined(aa64)
|
|
||||||
#endif
|
#endif
|
||||||
error("Page: %s", params.P ? "Present" : "Not Present");
|
error("Page: %s", params.P ? "Present" : "Not Present");
|
||||||
error("Write Operation: %s", params.W ? "Read-Only" : "Read-Write");
|
error("Write Operation: %s", params.W ? "Read-Only" : "Read-Write");
|
||||||
@ -229,21 +201,21 @@ SafeFunction void UserModeExceptionHandler(CHArchTrapFrame *Frame)
|
|||||||
if (CurCPU)
|
if (CurCPU)
|
||||||
{
|
{
|
||||||
Memory::Virtual vma = Memory::Virtual(CurCPU->CurrentProcess->PageTable);
|
Memory::Virtual vma = Memory::Virtual(CurCPU->CurrentProcess->PageTable);
|
||||||
bool PageAvailable = vma.Check((void *)CheckPageFaultAddress);
|
bool PageAvailable = vma.Check((void *)CPU::x64::readcr2().PFLA);
|
||||||
debug("Page available (Check(...)): %s. %s",
|
debug("Page available (Check(...)): %s. %s",
|
||||||
PageAvailable ? "Yes" : "No",
|
PageAvailable ? "Yes" : "No",
|
||||||
(params.P && !PageAvailable) ? "CR2 == Present; Check() != Present??????" : "CR2 confirms Check() result.");
|
(params.P && !PageAvailable) ? "CR2 == Present; Check() != Present??????" : "CR2 confirms Check() result.");
|
||||||
|
|
||||||
if (PageAvailable)
|
if (PageAvailable)
|
||||||
{
|
{
|
||||||
bool Present = vma.Check((void *)CheckPageFaultAddress);
|
bool Present = vma.Check((void *)CPU::x64::readcr2().PFLA);
|
||||||
bool ReadWrite = vma.Check((void *)CheckPageFaultAddress, Memory::PTFlag::RW);
|
bool ReadWrite = vma.Check((void *)CPU::x64::readcr2().PFLA, Memory::PTFlag::RW);
|
||||||
bool User = vma.Check((void *)CheckPageFaultAddress, Memory::PTFlag::US);
|
bool User = vma.Check((void *)CPU::x64::readcr2().PFLA, Memory::PTFlag::US);
|
||||||
bool WriteThrough = vma.Check((void *)CheckPageFaultAddress, Memory::PTFlag::PWT);
|
bool WriteThrough = vma.Check((void *)CPU::x64::readcr2().PFLA, Memory::PTFlag::PWT);
|
||||||
bool CacheDisabled = vma.Check((void *)CheckPageFaultAddress, Memory::PTFlag::PCD);
|
bool CacheDisabled = vma.Check((void *)CPU::x64::readcr2().PFLA, Memory::PTFlag::PCD);
|
||||||
bool Accessed = vma.Check((void *)CheckPageFaultAddress, Memory::PTFlag::A);
|
bool Accessed = vma.Check((void *)CPU::x64::readcr2().PFLA, Memory::PTFlag::A);
|
||||||
bool Dirty = vma.Check((void *)CheckPageFaultAddress, Memory::PTFlag::D);
|
bool Dirty = vma.Check((void *)CPU::x64::readcr2().PFLA, Memory::PTFlag::D);
|
||||||
bool Global = vma.Check((void *)CheckPageFaultAddress, Memory::PTFlag::G);
|
bool Global = vma.Check((void *)CPU::x64::readcr2().PFLA, Memory::PTFlag::G);
|
||||||
/* ... */
|
/* ... */
|
||||||
|
|
||||||
debug("Page available: %s", Present ? "Yes" : "No");
|
debug("Page available: %s", Present ? "Yes" : "No");
|
||||||
@ -254,80 +226,12 @@ SafeFunction void UserModeExceptionHandler(CHArchTrapFrame *Frame)
|
|||||||
debug("Page accessed: %s", Accessed ? "Yes" : "No");
|
debug("Page accessed: %s", Accessed ? "Yes" : "No");
|
||||||
debug("Page dirty: %s", Dirty ? "Yes" : "No");
|
debug("Page dirty: %s", Dirty ? "Yes" : "No");
|
||||||
debug("Page global: %s", Global ? "Yes" : "No");
|
debug("Page global: %s", Global ? "Yes" : "No");
|
||||||
|
|
||||||
if (Present)
|
|
||||||
{
|
|
||||||
uintptr_t CheckPageFaultLinearAddress = (uintptr_t)CheckPageFaultAddress;
|
|
||||||
CheckPageFaultLinearAddress &= 0xFFFFFFFFFFFFF000;
|
|
||||||
debug("%#lx -> %#lx", CheckPageFaultAddress, CheckPageFaultLinearAddress);
|
|
||||||
|
|
||||||
Memory::Virtual::PageMapIndexer Index = Memory::Virtual::PageMapIndexer((uintptr_t)CheckPageFaultLinearAddress);
|
|
||||||
debug("Index for %#lx is PML:%d PDPTE:%d PDE:%d PTE:%d",
|
|
||||||
CheckPageFaultLinearAddress,
|
|
||||||
Index.PMLIndex,
|
|
||||||
Index.PDPTEIndex,
|
|
||||||
Index.PDEIndex,
|
|
||||||
Index.PTEIndex);
|
|
||||||
Memory::PageMapLevel4 PML4 = CurCPU->CurrentProcess->PageTable->Entries[Index.PMLIndex];
|
|
||||||
|
|
||||||
Memory::PageDirectoryPointerTableEntryPtr *PDPTE = (Memory::PageDirectoryPointerTableEntryPtr *)((uintptr_t)PML4.GetAddress() << 12);
|
|
||||||
Memory::PageDirectoryEntryPtr *PDE = (Memory::PageDirectoryEntryPtr *)((uintptr_t)PDPTE->Entries[Index.PDPTEIndex].GetAddress() << 12);
|
|
||||||
Memory::PageTableEntryPtr *PTE = (Memory::PageTableEntryPtr *)((uintptr_t)PDE->Entries[Index.PDEIndex].GetAddress() << 12);
|
|
||||||
|
|
||||||
debug("# %03d-%03d-%03d-%03d: P:%s RW:%s US:%s PWT:%s PCB:%s A:%s NX:%s Address:%#lx",
|
|
||||||
Index.PMLIndex, 0, 0, 0,
|
|
||||||
PML4.Present ? "1" : "0",
|
|
||||||
PML4.ReadWrite ? "1" : "0",
|
|
||||||
PML4.UserSupervisor ? "1" : "0",
|
|
||||||
PML4.WriteThrough ? "1" : "0",
|
|
||||||
PML4.CacheDisable ? "1" : "0",
|
|
||||||
PML4.Accessed ? "1" : "0",
|
|
||||||
PML4.ExecuteDisable ? "1" : "0",
|
|
||||||
PML4.GetAddress() << 12);
|
|
||||||
|
|
||||||
debug("# %03d-%03d-%03d-%03d: P:%s RW:%s US:%s PWT:%s PCB:%s A:%s NX:%s Address:%#lx",
|
|
||||||
Index.PMLIndex, Index.PDPTEIndex, 0, 0,
|
|
||||||
PDPTE->Entries[Index.PDPTEIndex].Present ? "1" : "0",
|
|
||||||
PDPTE->Entries[Index.PDPTEIndex].ReadWrite ? "1" : "0",
|
|
||||||
PDPTE->Entries[Index.PDPTEIndex].UserSupervisor ? "1" : "0",
|
|
||||||
PDPTE->Entries[Index.PDPTEIndex].WriteThrough ? "1" : "0",
|
|
||||||
PDPTE->Entries[Index.PDPTEIndex].CacheDisable ? "1" : "0",
|
|
||||||
PDPTE->Entries[Index.PDPTEIndex].Accessed ? "1" : "0",
|
|
||||||
PDPTE->Entries[Index.PDPTEIndex].ExecuteDisable ? "1" : "0",
|
|
||||||
PDPTE->Entries[Index.PDPTEIndex].GetAddress() << 12);
|
|
||||||
|
|
||||||
debug("# %03d-%03d-%03d-%03d: P:%s RW:%s US:%s PWT:%s PCB:%s A:%s NX:%s Address:%#lx",
|
|
||||||
Index.PMLIndex, Index.PDPTEIndex, Index.PDEIndex, 0,
|
|
||||||
PDE->Entries[Index.PDEIndex].Present ? "1" : "0",
|
|
||||||
PDE->Entries[Index.PDEIndex].ReadWrite ? "1" : "0",
|
|
||||||
PDE->Entries[Index.PDEIndex].UserSupervisor ? "1" : "0",
|
|
||||||
PDE->Entries[Index.PDEIndex].WriteThrough ? "1" : "0",
|
|
||||||
PDE->Entries[Index.PDEIndex].CacheDisable ? "1" : "0",
|
|
||||||
PDE->Entries[Index.PDEIndex].Accessed ? "1" : "0",
|
|
||||||
PDE->Entries[Index.PDEIndex].ExecuteDisable ? "1" : "0",
|
|
||||||
PDE->Entries[Index.PDEIndex].GetAddress() << 12);
|
|
||||||
|
|
||||||
debug("# %03d-%03d-%03d-%03d: P:%s RW:%s US:%s PWT:%s PCB:%s A:%s D:%s PAT:%s G:%s PK:%d NX:%s Address:%#lx",
|
|
||||||
Index.PMLIndex, Index.PDPTEIndex, Index.PDEIndex, Index.PTEIndex,
|
|
||||||
PTE->Entries[Index.PTEIndex].Present ? "1" : "0",
|
|
||||||
PTE->Entries[Index.PTEIndex].ReadWrite ? "1" : "0",
|
|
||||||
PTE->Entries[Index.PTEIndex].UserSupervisor ? "1" : "0",
|
|
||||||
PTE->Entries[Index.PTEIndex].WriteThrough ? "1" : "0",
|
|
||||||
PTE->Entries[Index.PTEIndex].CacheDisable ? "1" : "0",
|
|
||||||
PTE->Entries[Index.PTEIndex].Accessed ? "1" : "0",
|
|
||||||
PTE->Entries[Index.PTEIndex].Dirty ? "1" : "0",
|
|
||||||
PTE->Entries[Index.PTEIndex].PageAttributeTable ? "1" : "0",
|
|
||||||
PTE->Entries[Index.PTEIndex].Global ? "1" : "0",
|
|
||||||
PTE->Entries[Index.PTEIndex].ProtectionKey,
|
|
||||||
PTE->Entries[Index.PTEIndex].ExecuteDisable ? "1" : "0",
|
|
||||||
PTE->Entries[Index.PTEIndex].GetAddress() << 12);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (CurCPU)
|
if (CurCPU)
|
||||||
if (CurCPU->CurrentThread->Stack->Expand(CrashHandler::PageFaultAddress))
|
if (CurCPU->CurrentThread->Stack->Expand(CPU::x64::readcr2().raw))
|
||||||
{
|
{
|
||||||
debug("Stack expanded");
|
debug("Stack expanded");
|
||||||
TaskManager->GetCurrentThread()->Status = Tasking::TaskStatus::Ready;
|
TaskManager->GetCurrentThread()->Status = Tasking::TaskStatus::Ready;
|
||||||
@ -335,27 +239,27 @@ SafeFunction void UserModeExceptionHandler(CHArchTrapFrame *Frame)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CPU::x86::x87FloatingPoint:
|
case CPU::x64::x87FloatingPoint:
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CPU::x86::AlignmentCheck:
|
case CPU::x64::AlignmentCheck:
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CPU::x86::MachineCheck:
|
case CPU::x64::MachineCheck:
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CPU::x86::SIMDFloatingPoint:
|
case CPU::x64::SIMDFloatingPoint:
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CPU::x86::Virtualization:
|
case CPU::x64::Virtualization:
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CPU::x86::Security:
|
case CPU::x64::Security:
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -366,7 +270,7 @@ SafeFunction void UserModeExceptionHandler(CHArchTrapFrame *Frame)
|
|||||||
}
|
}
|
||||||
|
|
||||||
TaskManager->GetCurrentThread()->Status = Tasking::TaskStatus::Terminated;
|
TaskManager->GetCurrentThread()->Status = Tasking::TaskStatus::Terminated;
|
||||||
__sync;
|
__sync_synchronize();
|
||||||
error("End of report.");
|
error("End of report.");
|
||||||
CPU::Interrupts(CPU::Enable);
|
CPU::Interrupts(CPU::Enable);
|
||||||
debug("Interrupts enabled back.");
|
debug("Interrupts enabled back.");
|
||||||
|
@ -3,11 +3,11 @@
|
|||||||
|
|
||||||
#include <types.h>
|
#include <types.h>
|
||||||
|
|
||||||
#include <ints.hpp>
|
#include <interrupts.hpp>
|
||||||
#include <task.hpp>
|
#include <task.hpp>
|
||||||
#include <cpu.hpp>
|
#include <cpu.hpp>
|
||||||
|
|
||||||
#if defined(a64)
|
#if defined(__amd64__)
|
||||||
typedef struct CPU::x64::TrapFrame CHArchTrapFrame;
|
typedef struct CPU::x64::TrapFrame CHArchTrapFrame;
|
||||||
|
|
||||||
struct CRData
|
struct CRData
|
||||||
@ -20,7 +20,7 @@ struct CRData
|
|||||||
CPU::x64::CR4 cr4;
|
CPU::x64::CR4 cr4;
|
||||||
CPU::x64::CR8 cr8;
|
CPU::x64::CR8 cr8;
|
||||||
CPU::x64::EFER efer;
|
CPU::x64::EFER efer;
|
||||||
uintptr_t dr0, dr1, dr2, dr3, dr6;
|
uint64_t dr0, dr1, dr2, dr3, dr6;
|
||||||
CPU::x64::DR7 dr7;
|
CPU::x64::DR7 dr7;
|
||||||
|
|
||||||
long ID;
|
long ID;
|
||||||
@ -29,7 +29,7 @@ struct CRData
|
|||||||
Tasking::TCB *Thread;
|
Tasking::TCB *Thread;
|
||||||
};
|
};
|
||||||
|
|
||||||
#elif defined(a32)
|
#elif defined(__i386__)
|
||||||
typedef struct CPU::x32::TrapFrame CHArchTrapFrame;
|
typedef struct CPU::x32::TrapFrame CHArchTrapFrame;
|
||||||
|
|
||||||
struct CRData
|
struct CRData
|
||||||
@ -42,14 +42,14 @@ struct CRData
|
|||||||
CPU::x32::CR4 cr4;
|
CPU::x32::CR4 cr4;
|
||||||
CPU::x32::CR8 cr8;
|
CPU::x32::CR8 cr8;
|
||||||
CPU::x32::EFER efer;
|
CPU::x32::EFER efer;
|
||||||
uintptr_t dr0, dr1, dr2, dr3, dr6;
|
uint64_t dr0, dr1, dr2, dr3, dr6;
|
||||||
CPU::x32::DR7 dr7;
|
CPU::x32::DR7 dr7;
|
||||||
|
|
||||||
long ID;
|
long ID;
|
||||||
Tasking::PCB *Process;
|
Tasking::PCB *Process;
|
||||||
Tasking::TCB *Thread;
|
Tasking::TCB *Thread;
|
||||||
};
|
};
|
||||||
#elif defined(aa64)
|
#elif defined(__aarch64__)
|
||||||
typedef struct CPU::aarch64::TrapFrame CHArchTrapFrame;
|
typedef struct CPU::aarch64::TrapFrame CHArchTrapFrame;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -244,11 +244,11 @@ namespace CrashHandler
|
|||||||
class CrashKeyboardDriver : public Interrupts::Handler
|
class CrashKeyboardDriver : public Interrupts::Handler
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
#if defined(a64)
|
#if defined(__amd64__)
|
||||||
void OnInterruptReceived(CPU::x64::TrapFrame *Frame);
|
void OnInterruptReceived(CPU::x64::TrapFrame *Frame);
|
||||||
#elif defined(a32)
|
#elif defined(__i386__)
|
||||||
void OnInterruptReceived(CPU::x32::TrapFrame *Frame);
|
void OnInterruptReceived(void *Frame);
|
||||||
#elif defined(aa64)
|
#elif defined(__aarch64__)
|
||||||
void OnInterruptReceived(void *Frame);
|
void OnInterruptReceived(void *Frame);
|
||||||
#endif
|
#endif
|
||||||
public:
|
public:
|
||||||
@ -256,7 +256,7 @@ namespace CrashHandler
|
|||||||
~CrashKeyboardDriver();
|
~CrashKeyboardDriver();
|
||||||
};
|
};
|
||||||
|
|
||||||
void TraceFrames(CHArchTrapFrame *Frame, int Count, SymbolResolver::Symbols *SymHandle, bool Kernel);
|
void TraceFrames(CHArchTrapFrame *Frame, int Count);
|
||||||
|
|
||||||
void ArrowInput(uint8_t key);
|
void ArrowInput(uint8_t key);
|
||||||
void UserInput(char *Input);
|
void UserInput(char *Input);
|
||||||
|
@ -8,13 +8,13 @@ NewLock(DebuggerLock);
|
|||||||
|
|
||||||
using namespace UniversalAsynchronousReceiverTransmitter;
|
using namespace UniversalAsynchronousReceiverTransmitter;
|
||||||
|
|
||||||
static inline NIF void uart_wrapper(char c, void *unused)
|
static inline __no_instrument_function void uart_wrapper(char c, void *unused)
|
||||||
{
|
{
|
||||||
UART(COM1).Write(c);
|
UART(COM1).Write(c);
|
||||||
UNUSED(unused);
|
(void)unused;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline NIF void WritePrefix(DebugLevel Level, const char *File, int Line, const char *Function)
|
static inline __no_instrument_function void WritePrefix(DebugLevel Level, const char *File, int Line, const char *Function)
|
||||||
{
|
{
|
||||||
const char *DbgLvlString;
|
const char *DbgLvlString;
|
||||||
switch (Level)
|
switch (Level)
|
||||||
@ -52,7 +52,7 @@ static inline NIF void WritePrefix(DebugLevel Level, const char *File, int Line,
|
|||||||
|
|
||||||
namespace SysDbg
|
namespace SysDbg
|
||||||
{
|
{
|
||||||
NIF void Write(DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...)
|
__no_instrument_function void Write(DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...)
|
||||||
{
|
{
|
||||||
WritePrefix(Level, File, Line, Function);
|
WritePrefix(Level, File, Line, Function);
|
||||||
va_list args;
|
va_list args;
|
||||||
@ -61,29 +61,9 @@ namespace SysDbg
|
|||||||
va_end(args);
|
va_end(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
NIF void WriteLine(DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...)
|
__no_instrument_function void WriteLine(DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...)
|
||||||
{
|
{
|
||||||
WritePrefix(Level, File, Line, Function);
|
// SmartLock(DebuggerLock);
|
||||||
va_list args;
|
|
||||||
va_start(args, Format);
|
|
||||||
vfctprintf(uart_wrapper, nullptr, Format, args);
|
|
||||||
va_end(args);
|
|
||||||
uart_wrapper('\n', nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
NIF void LockedWrite(DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...)
|
|
||||||
{
|
|
||||||
SmartTimeoutLock(DebuggerLock, 1000);
|
|
||||||
WritePrefix(Level, File, Line, Function);
|
|
||||||
va_list args;
|
|
||||||
va_start(args, Format);
|
|
||||||
vfctprintf(uart_wrapper, nullptr, Format, args);
|
|
||||||
va_end(args);
|
|
||||||
}
|
|
||||||
|
|
||||||
NIF void LockedWriteLine(DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...)
|
|
||||||
{
|
|
||||||
SmartTimeoutLock(DebuggerLock, 1000);
|
|
||||||
WritePrefix(Level, File, Line, Function);
|
WritePrefix(Level, File, Line, Function);
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, Format);
|
va_start(args, Format);
|
||||||
@ -94,7 +74,7 @@ namespace SysDbg
|
|||||||
}
|
}
|
||||||
|
|
||||||
// C compatibility
|
// C compatibility
|
||||||
extern "C" NIF void SysDbgWrite(enum DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...)
|
extern "C" __no_instrument_function void SysDbgWrite(enum DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...)
|
||||||
{
|
{
|
||||||
WritePrefix(Level, File, Line, Function);
|
WritePrefix(Level, File, Line, Function);
|
||||||
va_list args;
|
va_list args;
|
||||||
@ -104,7 +84,7 @@ extern "C" NIF void SysDbgWrite(enum DebugLevel Level, const char *File, int Lin
|
|||||||
}
|
}
|
||||||
|
|
||||||
// C compatibility
|
// C compatibility
|
||||||
extern "C" NIF void SysDbgWriteLine(enum DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...)
|
extern "C" __no_instrument_function void SysDbgWriteLine(enum DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...)
|
||||||
{
|
{
|
||||||
WritePrefix(Level, File, Line, Function);
|
WritePrefix(Level, File, Line, Function);
|
||||||
va_list args;
|
va_list args;
|
||||||
@ -113,26 +93,3 @@ extern "C" NIF void SysDbgWriteLine(enum DebugLevel Level, const char *File, int
|
|||||||
va_end(args);
|
va_end(args);
|
||||||
uart_wrapper('\n', nullptr);
|
uart_wrapper('\n', nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// C compatibility
|
|
||||||
extern "C" NIF void SysDbgLockedWrite(enum DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...)
|
|
||||||
{
|
|
||||||
SmartTimeoutLock(DebuggerLock, 1000);
|
|
||||||
WritePrefix(Level, File, Line, Function);
|
|
||||||
va_list args;
|
|
||||||
va_start(args, Format);
|
|
||||||
vfctprintf(uart_wrapper, nullptr, Format, args);
|
|
||||||
va_end(args);
|
|
||||||
}
|
|
||||||
|
|
||||||
// C compatibility
|
|
||||||
extern "C" NIF void SysDbgLockedWriteLine(enum DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...)
|
|
||||||
{
|
|
||||||
SmartTimeoutLock(DebuggerLock, 1000);
|
|
||||||
WritePrefix(Level, File, Line, Function);
|
|
||||||
va_list args;
|
|
||||||
va_start(args, Format);
|
|
||||||
vfctprintf(uart_wrapper, nullptr, Format, args);
|
|
||||||
va_end(args);
|
|
||||||
uart_wrapper('\n', nullptr);
|
|
||||||
}
|
|
||||||
|
@ -30,7 +30,7 @@ namespace Disk
|
|||||||
for (unsigned char ItrPort = 0; ItrPort < this->AvailablePorts; ItrPort++)
|
for (unsigned char ItrPort = 0; ItrPort < this->AvailablePorts; ItrPort++)
|
||||||
{
|
{
|
||||||
Drive *drive = new Drive;
|
Drive *drive = new Drive;
|
||||||
sprintf(drive->Name, "sd%ld-%d", DriverUID, this->AvailablePorts);
|
sprintf_(drive->Name, "sd%ld-%d", DriverUID, this->AvailablePorts);
|
||||||
debug("Drive Name: %s", drive->Name);
|
debug("Drive Name: %s", drive->Name);
|
||||||
// TODO: Implement disk type detection. Very useful in the future.
|
// TODO: Implement disk type detection. Very useful in the future.
|
||||||
drive->MechanicalDisk = true;
|
drive->MechanicalDisk = true;
|
||||||
@ -49,7 +49,7 @@ namespace Disk
|
|||||||
memcpy(&drive->Table, RWBuffer, sizeof(PartitionTable));
|
memcpy(&drive->Table, RWBuffer, sizeof(PartitionTable));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
TODO: Add to devfs the disk
|
----> Add to devfs the disk
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (drive->Table.GPT.Signature == GPT_MAGIC)
|
if (drive->Table.GPT.Signature == GPT_MAGIC)
|
||||||
@ -98,10 +98,10 @@ namespace Disk
|
|||||||
drive->Partitions.push_back(partition);
|
drive->Partitions.push_back(partition);
|
||||||
|
|
||||||
char *PartitionName = new char[64];
|
char *PartitionName = new char[64];
|
||||||
sprintf(PartitionName, "sd%ldp%ld", drives.size() - 1, partition->Index);
|
sprintf_(PartitionName, "sd%ldp%ld", drives.size() - 1, partition->Index);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
TODO: Add to devfs the disk
|
----> Add to devfs the disk
|
||||||
*/
|
*/
|
||||||
|
|
||||||
delete[] PartitionName;
|
delete[] PartitionName;
|
||||||
@ -128,10 +128,10 @@ namespace Disk
|
|||||||
drive->Partitions.push_back(partition);
|
drive->Partitions.push_back(partition);
|
||||||
|
|
||||||
char *PartitionName = new char[64];
|
char *PartitionName = new char[64];
|
||||||
sprintf(PartitionName, "sd%ldp%ld", drives.size() - 1, partition->Index);
|
sprintf_(PartitionName, "sd%ldp%ld", drives.size() - 1, partition->Index);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
TODO: Add to devfs the disk
|
----> Add to devfs the disk
|
||||||
*/
|
*/
|
||||||
|
|
||||||
delete[] PartitionName;
|
delete[] PartitionName;
|
||||||
@ -153,6 +153,5 @@ namespace Disk
|
|||||||
|
|
||||||
Manager::~Manager()
|
Manager::~Manager()
|
||||||
{
|
{
|
||||||
debug("Destructor called");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#include <driver.hpp>
|
#include <driver.hpp>
|
||||||
|
|
||||||
#include <ints.hpp>
|
#include <interrupts.hpp>
|
||||||
#include <memory.hpp>
|
#include <memory.hpp>
|
||||||
#include <task.hpp>
|
#include <task.hpp>
|
||||||
#include <lock.hpp>
|
#include <lock.hpp>
|
||||||
@ -28,201 +28,439 @@ namespace Driver
|
|||||||
"Input",
|
"Input",
|
||||||
"Audio"};
|
"Audio"};
|
||||||
|
|
||||||
void Driver::UnloadAllDrivers()
|
|
||||||
{
|
|
||||||
size_t DriversNum = Drivers.size();
|
|
||||||
debug("%ld drivers loaded, [DUIDs: %ld]", DriversNum, DriverUIDs);
|
|
||||||
debug("driver size %ld", DriversNum);
|
|
||||||
for (size_t i = 0; i < DriversNum; i++)
|
|
||||||
{
|
|
||||||
DriverFile *drv = Drivers[i];
|
|
||||||
KernelCallback callback;
|
|
||||||
callback.Reason = StopReason;
|
|
||||||
debug("Stopping & unloading driver %ld [%#lx]", drv->DriverUID, drv->Address);
|
|
||||||
DriverManager->IOCB(drv->DriverUID, (void *)&callback);
|
|
||||||
|
|
||||||
delete drv->MemTrk, drv->MemTrk = nullptr;
|
|
||||||
for (size_t j = 0; j < sizeof(drv->InterruptHook) / sizeof(drv->InterruptHook[0]); j++)
|
|
||||||
{
|
|
||||||
if (!drv->InterruptHook[j])
|
|
||||||
continue;
|
|
||||||
delete drv->InterruptHook[j], drv->InterruptHook[j] = nullptr;
|
|
||||||
}
|
|
||||||
delete drv, drv = nullptr;
|
|
||||||
Drivers.remove(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Driver::UnloadDriver(unsigned long DUID)
|
|
||||||
{
|
|
||||||
debug("Searching for driver %ld", DUID);
|
|
||||||
for (size_t i = 0; i < Drivers.size(); i++)
|
|
||||||
{
|
|
||||||
DriverFile *drv = Drivers[i];
|
|
||||||
if (drv->DriverUID == DUID)
|
|
||||||
{
|
|
||||||
KernelCallback callback;
|
|
||||||
callback.Reason = StopReason;
|
|
||||||
debug("Stopping and unloading driver %ld [%#lx]", drv->DriverUID, drv->Address);
|
|
||||||
this->IOCB(drv->DriverUID, (void *)&callback);
|
|
||||||
|
|
||||||
delete drv->MemTrk, drv->MemTrk = nullptr;
|
|
||||||
for (size_t i = 0; i < sizeof(drv->InterruptHook) / sizeof(drv->InterruptHook[0]); i++)
|
|
||||||
{
|
|
||||||
if (!drv->InterruptHook[i])
|
|
||||||
continue;
|
|
||||||
delete drv->InterruptHook[i], drv->InterruptHook[i] = nullptr;
|
|
||||||
}
|
|
||||||
delete drv, drv = nullptr;
|
|
||||||
Drivers.remove(i);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
int Driver::IOCB(unsigned long DUID, void *KCB)
|
int Driver::IOCB(unsigned long DUID, void *KCB)
|
||||||
{
|
{
|
||||||
foreach (auto Drv in Drivers)
|
foreach (auto var in Drivers)
|
||||||
|
if (var->DriverUID == DUID)
|
||||||
{
|
{
|
||||||
if (Drv->DriverUID == DUID)
|
FexExtended *DrvExtHdr = (FexExtended *)((uint64_t)var->Address + EXTENDED_SECTION_ADDRESS);
|
||||||
{
|
return ((int (*)(void *))((uint64_t)DrvExtHdr->Driver.Callback + (uint64_t)var->Address))(KCB);
|
||||||
FexExtended *DrvExtHdr = (FexExtended *)((uintptr_t)Drv->Address + EXTENDED_SECTION_ADDRESS);
|
|
||||||
int ret = ((int (*)(void *))((uintptr_t)DrvExtHdr->Driver.Callback + (uintptr_t)Drv->Address))(KCB);
|
|
||||||
__sync;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
DriverCode Driver::CallDriverEntryPoint(void *fex, void *KAPIAddress)
|
DriverCode Driver::CallDriverEntryPoint(void *fex)
|
||||||
{
|
{
|
||||||
memcpy(KAPIAddress, &KernelAPITemplate, sizeof(KernelAPI));
|
KernelAPI *API = (KernelAPI *)KernelAllocator.RequestPages(TO_PAGES(sizeof(KernelAPI)));
|
||||||
|
memcpy(API, &KAPI, sizeof(KernelAPI));
|
||||||
|
|
||||||
((KernelAPI *)KAPIAddress)->Info.Offset = (unsigned long)fex;
|
API->Info.Offset = (unsigned long)fex;
|
||||||
((KernelAPI *)KAPIAddress)->Info.DriverUID = DriverUIDs++;
|
API->Info.DriverUID = DriverUIDs++;
|
||||||
|
|
||||||
debug("Calling driver entry point ( %#lx %ld )", (unsigned long)fex, ((KernelAPI *)KAPIAddress)->Info.DriverUID);
|
int ret = ((int (*)(KernelAPI *))((uint64_t)((Fex *)fex)->Pointer + (uint64_t)fex))(API);
|
||||||
int ret = ((int (*)(KernelAPI *))((uintptr_t)((Fex *)fex)->EntryPoint + (uintptr_t)fex))(((KernelAPI *)KAPIAddress));
|
|
||||||
|
|
||||||
if (DriverReturnCode::OK != ret)
|
if (DriverReturnCode::OK != ret)
|
||||||
return DriverCode::DRIVER_RETURNED_ERROR;
|
return DriverCode::DRIVER_RETURNED_ERROR;
|
||||||
return DriverCode::OK;
|
return DriverCode::OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
DriverCode Driver::LoadDriver(uintptr_t DriverAddress, uintptr_t Size)
|
DriverCode Driver::LoadDriver(uint64_t DriverAddress, uint64_t Size)
|
||||||
{
|
{
|
||||||
Fex *DrvHdr = (Fex *)DriverAddress;
|
Fex *DrvHdr = (Fex *)DriverAddress;
|
||||||
if (DrvHdr->Magic[0] != 'F' || DrvHdr->Magic[1] != 'E' || DrvHdr->Magic[2] != 'X' || DrvHdr->Magic[3] != '\0')
|
if (DrvHdr->Magic[0] != 'F' || DrvHdr->Magic[1] != 'E' || DrvHdr->Magic[2] != 'X' || DrvHdr->Magic[3] != '\0')
|
||||||
{
|
|
||||||
if (Size > 0x1000)
|
|
||||||
{
|
|
||||||
Fex *ElfDrvHdr = (Fex *)(DriverAddress + 0x1000);
|
|
||||||
if (ElfDrvHdr->Magic[0] != 'F' || ElfDrvHdr->Magic[1] != 'E' || ElfDrvHdr->Magic[2] != 'X' || ElfDrvHdr->Magic[3] != '\0')
|
|
||||||
return DriverCode::INVALID_FEX_HEADER;
|
return DriverCode::INVALID_FEX_HEADER;
|
||||||
else
|
debug("Fex Magic: \"%s\"; Type: %d; OS: %d; Pointer: %#lx", DrvHdr->Magic, DrvHdr->Type, DrvHdr->OS, DrvHdr->Pointer);
|
||||||
{
|
|
||||||
debug("Fex Magic: \"%s\"; Type: %d; OS: %d; EntryPoint: %#lx", ElfDrvHdr->Magic, ElfDrvHdr->Type, ElfDrvHdr->OS, ElfDrvHdr->EntryPoint);
|
|
||||||
|
|
||||||
if (ElfDrvHdr->Type == FexFormatType::FexFormatType_Driver)
|
|
||||||
{
|
|
||||||
FexExtended *ElfDrvExtHdr = (FexExtended *)((uintptr_t)ElfDrvHdr + EXTENDED_SECTION_ADDRESS);
|
|
||||||
debug("Name: \"%s\"; Type: %d; Callback: %#lx", ElfDrvExtHdr->Driver.Name, ElfDrvExtHdr->Driver.Type, ElfDrvExtHdr->Driver.Callback);
|
|
||||||
|
|
||||||
if (ElfDrvExtHdr->Driver.Bind.Type == DriverBindType::BIND_PCI)
|
|
||||||
return this->DriverLoadBindPCI(ElfDrvExtHdr, DriverAddress, Size, true);
|
|
||||||
else if (ElfDrvExtHdr->Driver.Bind.Type == DriverBindType::BIND_INTERRUPT)
|
|
||||||
return this->DriverLoadBindInterrupt(ElfDrvExtHdr, DriverAddress, Size, true);
|
|
||||||
else if (ElfDrvExtHdr->Driver.Bind.Type == DriverBindType::BIND_PROCESS)
|
|
||||||
return this->DriverLoadBindProcess(ElfDrvExtHdr, DriverAddress, Size, true);
|
|
||||||
else if (ElfDrvExtHdr->Driver.Bind.Type == DriverBindType::BIND_INPUT)
|
|
||||||
return this->DriverLoadBindInput(ElfDrvExtHdr, DriverAddress, Size, true);
|
|
||||||
else
|
|
||||||
error("Unknown driver bind type: %d", ElfDrvExtHdr->Driver.Bind.Type);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return DriverCode::NOT_DRIVER;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return DriverCode::INVALID_FEX_HEADER;
|
|
||||||
}
|
|
||||||
debug("Fex Magic: \"%s\"; Type: %d; OS: %d; EntryPoint: %#lx", DrvHdr->Magic, DrvHdr->Type, DrvHdr->OS, DrvHdr->EntryPoint);
|
|
||||||
|
|
||||||
if (DrvHdr->Type == FexFormatType::FexFormatType_Driver)
|
if (DrvHdr->Type == FexFormatType::FexFormatType_Driver)
|
||||||
{
|
{
|
||||||
FexExtended *DrvExtHdr = (FexExtended *)((uintptr_t)DrvHdr + EXTENDED_SECTION_ADDRESS);
|
FexExtended *DrvExtHdr = (FexExtended *)((uint64_t)DrvHdr + EXTENDED_SECTION_ADDRESS);
|
||||||
debug("Name: \"%s\"; Type: %d; Callback: %#lx", DrvExtHdr->Driver.Name, DrvExtHdr->Driver.Type, DrvExtHdr->Driver.Callback);
|
debug("Name: \"%s\"; Type: %d; Callback: %#lx", DrvExtHdr->Driver.Name, DrvExtHdr->Driver.Type, DrvExtHdr->Driver.Callback);
|
||||||
|
|
||||||
if (DrvExtHdr->Driver.Bind.Type == DriverBindType::BIND_PCI)
|
if (DrvExtHdr->Driver.Bind.Type == DriverBindType::BIND_PCI)
|
||||||
return this->DriverLoadBindPCI(DrvExtHdr, DriverAddress, Size);
|
{
|
||||||
else if (DrvExtHdr->Driver.Bind.Type == DriverBindType::BIND_INTERRUPT)
|
for (unsigned long Vidx = 0; Vidx < sizeof(DrvExtHdr->Driver.Bind.PCI.VendorID) / sizeof(DrvExtHdr->Driver.Bind.PCI.VendorID[0]); Vidx++)
|
||||||
return this->DriverLoadBindInterrupt(DrvExtHdr, DriverAddress, Size);
|
for (unsigned long Didx = 0; Didx < sizeof(DrvExtHdr->Driver.Bind.PCI.DeviceID) / sizeof(DrvExtHdr->Driver.Bind.PCI.DeviceID[0]); Didx++)
|
||||||
else if (DrvExtHdr->Driver.Bind.Type == DriverBindType::BIND_PROCESS)
|
{
|
||||||
return this->DriverLoadBindProcess(DrvExtHdr, DriverAddress, Size);
|
if (Vidx >= sizeof(DrvExtHdr->Driver.Bind.PCI.VendorID) && Didx >= sizeof(DrvExtHdr->Driver.Bind.PCI.DeviceID))
|
||||||
else if (DrvExtHdr->Driver.Bind.Type == DriverBindType::BIND_INPUT)
|
break;
|
||||||
return this->DriverLoadBindInput(DrvExtHdr, DriverAddress, Size);
|
|
||||||
|
if (DrvExtHdr->Driver.Bind.PCI.VendorID[Vidx] == 0 || DrvExtHdr->Driver.Bind.PCI.DeviceID[Didx] == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Vector<PCI::PCIDeviceHeader *> devices = PCIManager->FindPCIDevice(DrvExtHdr->Driver.Bind.PCI.VendorID[Vidx], DrvExtHdr->Driver.Bind.PCI.DeviceID[Didx]);
|
||||||
|
if (devices.size() == 0)
|
||||||
|
continue;
|
||||||
|
foreach (auto PCIDevice in devices)
|
||||||
|
{
|
||||||
|
debug("[%ld] VendorID: %#x; DeviceID: %#x", devices.size(), PCIDevice->VendorID, PCIDevice->DeviceID);
|
||||||
|
Fex *fex = (Fex *)KernelAllocator.RequestPages(TO_PAGES(Size));
|
||||||
|
memcpy(fex, (void *)DriverAddress, Size);
|
||||||
|
FexExtended *fexExtended = (FexExtended *)((uint64_t)fex + EXTENDED_SECTION_ADDRESS);
|
||||||
|
#ifdef DEBUG
|
||||||
|
uint8_t *result = md5File((uint8_t *)fex, Size);
|
||||||
|
debug("MD5: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
|
||||||
|
result[0], result[1], result[2], result[3], result[4], result[5], result[6], result[7],
|
||||||
|
result[8], result[9], result[10], result[11], result[12], result[13], result[14], result[15]);
|
||||||
|
kfree(result);
|
||||||
|
#endif
|
||||||
|
if (CallDriverEntryPoint(fex) != DriverCode::OK)
|
||||||
|
{
|
||||||
|
KernelAllocator.FreePages(fex, TO_PAGES(Size));
|
||||||
|
return DriverCode::DRIVER_RETURNED_ERROR;
|
||||||
|
}
|
||||||
|
debug("Starting driver %s", fexExtended->Driver.Name);
|
||||||
|
|
||||||
|
KernelCallback *KCallback = (KernelCallback *)KernelAllocator.RequestPages(TO_PAGES(sizeof(KernelCallback)));
|
||||||
|
|
||||||
|
switch (fexExtended->Driver.Type)
|
||||||
|
{
|
||||||
|
case FexDriverType::FexDriverType_Generic:
|
||||||
|
{
|
||||||
|
fixme("Generic driver: %s", fexExtended->Driver.Name);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FexDriverType::FexDriverType_Display:
|
||||||
|
{
|
||||||
|
fixme("Display driver: %s", fexExtended->Driver.Name);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FexDriverType::FexDriverType_Network:
|
||||||
|
{
|
||||||
|
DriverInterruptHook *InterruptHook = new DriverInterruptHook(((int)((PCI::PCIHeader0 *)devices[0])->InterruptLine) + 32, // x86
|
||||||
|
(void *)((uint64_t)fexExtended->Driver.Callback + (uint64_t)fex),
|
||||||
|
KCallback);
|
||||||
|
|
||||||
|
KCallback->RawPtr = PCIDevice;
|
||||||
|
KCallback->Reason = CallbackReason::ConfigurationReason;
|
||||||
|
int callbackret = ((int (*)(KernelCallback *))((uint64_t)fexExtended->Driver.Callback + (uint64_t)fex))(KCallback);
|
||||||
|
if (callbackret == DriverReturnCode::NOT_IMPLEMENTED)
|
||||||
|
{
|
||||||
|
KernelAllocator.FreePages(fex, TO_PAGES(Size));
|
||||||
|
KernelAllocator.FreePages(KCallback, TO_PAGES(sizeof(KernelCallback)));
|
||||||
|
delete InterruptHook;
|
||||||
|
error("Driver %s does not implement the configuration callback", fexExtended->Driver.Name);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (callbackret == DriverReturnCode::OK)
|
||||||
|
trace("Device found for driver: %s", fexExtended->Driver.Name);
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
KernelAllocator.FreePages(fex, TO_PAGES(Size));
|
||||||
|
KernelAllocator.FreePages(KCallback, TO_PAGES(sizeof(KernelCallback)));
|
||||||
|
delete InterruptHook;
|
||||||
|
error("Driver %s returned error %d", fexExtended->Driver.Name, callbackret);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(KCallback, 0, sizeof(KernelCallback));
|
||||||
|
KCallback->Reason = CallbackReason::InterruptReason;
|
||||||
|
|
||||||
|
DriverFile *drvfile = new DriverFile;
|
||||||
|
drvfile->DriverUID = KAPI.Info.DriverUID;
|
||||||
|
drvfile->Address = (void *)fex;
|
||||||
|
drvfile->InterruptHook[0] = InterruptHook;
|
||||||
|
Drivers.push_back(drvfile);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FexDriverType::FexDriverType_Storage:
|
||||||
|
{
|
||||||
|
KCallback->RawPtr = PCIDevice;
|
||||||
|
KCallback->Reason = CallbackReason::ConfigurationReason;
|
||||||
|
int callbackret = ((int (*)(KernelCallback *))((uint64_t)fexExtended->Driver.Callback + (uint64_t)fex))(KCallback);
|
||||||
|
if (callbackret == DriverReturnCode::NOT_IMPLEMENTED)
|
||||||
|
{
|
||||||
|
KernelAllocator.FreePages(fex, TO_PAGES(Size));
|
||||||
|
KernelAllocator.FreePages(KCallback, TO_PAGES(sizeof(KernelCallback)));
|
||||||
|
error("Driver %s does not implement the configuration callback", fexExtended->Driver.Name);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (callbackret == DriverReturnCode::OK)
|
||||||
|
trace("Device found for driver: %s", fexExtended->Driver.Name);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
KernelAllocator.FreePages(fex, TO_PAGES(Size));
|
||||||
|
KernelAllocator.FreePages(KCallback, TO_PAGES(sizeof(KernelCallback)));
|
||||||
|
error("Driver %s returned error %d", fexExtended->Driver.Name, callbackret);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
DriverFile *drvfile = new DriverFile;
|
||||||
|
drvfile->DriverUID = KAPI.Info.DriverUID;
|
||||||
|
drvfile->Address = (void *)fex;
|
||||||
|
drvfile->InterruptHook[0] = nullptr;
|
||||||
|
Drivers.push_back(drvfile);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FexDriverType::FexDriverType_FileSystem:
|
||||||
|
{
|
||||||
|
fixme("Filesystem driver: %s", fexExtended->Driver.Name);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FexDriverType::FexDriverType_Input:
|
||||||
|
{
|
||||||
|
fixme("Input driver: %s", fexExtended->Driver.Name);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FexDriverType::FexDriverType_Audio:
|
||||||
|
{
|
||||||
|
fixme("Audio driver: %s", fexExtended->Driver.Name);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
warn("Unknown driver type: %d", fexExtended->Driver.Type);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (DrvExtHdr->Driver.Bind.Type == DriverBindType::BIND_INTERRUPT)
|
||||||
|
{
|
||||||
|
Fex *fex = (Fex *)KernelAllocator.RequestPages(TO_PAGES(Size));
|
||||||
|
memcpy(fex, (void *)DriverAddress, Size);
|
||||||
|
FexExtended *fexExtended = (FexExtended *)((uint64_t)fex + EXTENDED_SECTION_ADDRESS);
|
||||||
|
#ifdef DEBUG
|
||||||
|
uint8_t *result = md5File((uint8_t *)fex, Size);
|
||||||
|
debug("MD5: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
|
||||||
|
result[0], result[1], result[2], result[3], result[4], result[5], result[6], result[7],
|
||||||
|
result[8], result[9], result[10], result[11], result[12], result[13], result[14], result[15]);
|
||||||
|
kfree(result);
|
||||||
|
#endif
|
||||||
|
if (CallDriverEntryPoint(fex) != DriverCode::OK)
|
||||||
|
{
|
||||||
|
KernelAllocator.FreePages(fex, TO_PAGES(Size));
|
||||||
|
return DriverCode::DRIVER_RETURNED_ERROR;
|
||||||
|
}
|
||||||
|
debug("Starting driver %s (offset: %#lx)", fexExtended->Driver.Name, fex);
|
||||||
|
|
||||||
|
KernelCallback *KCallback = (KernelCallback *)KernelAllocator.RequestPages(TO_PAGES(sizeof(KernelCallback)));
|
||||||
|
|
||||||
|
switch (fexExtended->Driver.Type)
|
||||||
|
{
|
||||||
|
case FexDriverType::FexDriverType_Generic:
|
||||||
|
{
|
||||||
|
fixme("Generic driver: %s", fexExtended->Driver.Name);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FexDriverType::FexDriverType_Display:
|
||||||
|
{
|
||||||
|
fixme("Display driver: %s", fexExtended->Driver.Name);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FexDriverType::FexDriverType_Network:
|
||||||
|
{
|
||||||
|
fixme("Network driver: %s", fexExtended->Driver.Name);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FexDriverType::FexDriverType_Storage:
|
||||||
|
{
|
||||||
|
for (unsigned long i = 0; i < sizeof(DrvExtHdr->Driver.Bind.Interrupt.Vector) / sizeof(DrvExtHdr->Driver.Bind.Interrupt.Vector[0]); i++)
|
||||||
|
{
|
||||||
|
if (DrvExtHdr->Driver.Bind.Interrupt.Vector[i] == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
fixme("TODO: MULTIPLE BIND INTERRUPT VECTORS %d", DrvExtHdr->Driver.Bind.Interrupt.Vector[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
fixme("Not implemented");
|
||||||
|
KernelAllocator.FreePages(fex, TO_PAGES(Size));
|
||||||
|
KernelAllocator.FreePages(KCallback, TO_PAGES(sizeof(KernelCallback)));
|
||||||
|
break;
|
||||||
|
|
||||||
|
KCallback->RawPtr = nullptr;
|
||||||
|
KCallback->Reason = CallbackReason::ConfigurationReason;
|
||||||
|
int callbackret = ((int (*)(KernelCallback *))((uint64_t)fexExtended->Driver.Callback + (uint64_t)fex))(KCallback);
|
||||||
|
if (callbackret == DriverReturnCode::NOT_IMPLEMENTED)
|
||||||
|
{
|
||||||
|
KernelAllocator.FreePages(fex, TO_PAGES(Size));
|
||||||
|
KernelAllocator.FreePages(KCallback, TO_PAGES(sizeof(KernelCallback)));
|
||||||
|
error("Driver %s does not implement the configuration callback", fexExtended->Driver.Name);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (callbackret != DriverReturnCode::OK)
|
||||||
|
{
|
||||||
|
KernelAllocator.FreePages(fex, TO_PAGES(Size));
|
||||||
|
KernelAllocator.FreePages(KCallback, TO_PAGES(sizeof(KernelCallback)));
|
||||||
|
error("Driver %s returned error %d", fexExtended->Driver.Name, callbackret);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
KernelAllocator.FreePages(fex, TO_PAGES(Size));
|
||||||
|
KernelAllocator.FreePages(KCallback, TO_PAGES(sizeof(KernelCallback)));
|
||||||
|
|
||||||
|
// DriverFile *drvfile = new DriverFile;
|
||||||
|
// Drivers.push_back(drvfile);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FexDriverType::FexDriverType_FileSystem:
|
||||||
|
{
|
||||||
|
fixme("Filesystem driver: %s", fexExtended->Driver.Name);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FexDriverType::FexDriverType_Input:
|
||||||
|
{
|
||||||
|
DriverInterruptHook *InterruptHook = nullptr;
|
||||||
|
if (DrvExtHdr->Driver.Bind.Interrupt.Vector[0] != 0)
|
||||||
|
InterruptHook = new DriverInterruptHook(DrvExtHdr->Driver.Bind.Interrupt.Vector[0] + 32, // x86
|
||||||
|
(void *)((uint64_t)fexExtended->Driver.Callback + (uint64_t)fex),
|
||||||
|
KCallback);
|
||||||
|
|
||||||
|
for (unsigned long i = 0; i < sizeof(DrvExtHdr->Driver.Bind.Interrupt.Vector) / sizeof(DrvExtHdr->Driver.Bind.Interrupt.Vector[0]); i++)
|
||||||
|
{
|
||||||
|
if (DrvExtHdr->Driver.Bind.Interrupt.Vector[i] == 0)
|
||||||
|
break;
|
||||||
|
// InterruptHook = new DriverInterruptHook(DrvExtHdr->Driver.Bind.Interrupt.Vector[i] + 32, // x86
|
||||||
|
// (void *)((uint64_t)fexExtended->Driver.Callback + (uint64_t)fex),
|
||||||
|
// KCallback);
|
||||||
|
fixme("TODO: MULTIPLE BIND INTERRUPT VECTORS %d", DrvExtHdr->Driver.Bind.Interrupt.Vector[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
KCallback->RawPtr = nullptr;
|
||||||
|
KCallback->Reason = CallbackReason::ConfigurationReason;
|
||||||
|
int callbackret = ((int (*)(KernelCallback *))((uint64_t)fexExtended->Driver.Callback + (uint64_t)fex))(KCallback);
|
||||||
|
if (callbackret == DriverReturnCode::NOT_IMPLEMENTED)
|
||||||
|
{
|
||||||
|
KernelAllocator.FreePages(fex, TO_PAGES(Size));
|
||||||
|
KernelAllocator.FreePages(KCallback, TO_PAGES(sizeof(KernelCallback)));
|
||||||
|
error("Driver %s does not implement the configuration callback", fexExtended->Driver.Name);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (callbackret != DriverReturnCode::OK)
|
||||||
|
{
|
||||||
|
KernelAllocator.FreePages(fex, TO_PAGES(Size));
|
||||||
|
KernelAllocator.FreePages(KCallback, TO_PAGES(sizeof(KernelCallback)));
|
||||||
|
error("Driver %s returned error %d", fexExtended->Driver.Name, callbackret);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(KCallback, 0, sizeof(KernelCallback));
|
||||||
|
KCallback->Reason = CallbackReason::InterruptReason;
|
||||||
|
|
||||||
|
DriverFile *drvfile = new DriverFile;
|
||||||
|
drvfile->DriverUID = KAPI.Info.DriverUID;
|
||||||
|
drvfile->Address = (void *)fex;
|
||||||
|
drvfile->InterruptHook[0] = InterruptHook;
|
||||||
|
Drivers.push_back(drvfile);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FexDriverType::FexDriverType_Audio:
|
||||||
|
{
|
||||||
|
fixme("Audio driver: %s", fexExtended->Driver.Name);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
warn("Unknown driver type: %d", fexExtended->Driver.Type);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (DrvExtHdr->Driver.Bind.Type == DriverBindType::BIND_PROCESS)
|
||||||
|
{
|
||||||
|
fixme("Process driver: %s", DrvExtHdr->Driver.Name);
|
||||||
|
}
|
||||||
|
else if (DrvExtHdr->Driver.Bind.Type == DriverBindType::BIND_INPUT)
|
||||||
|
{
|
||||||
|
Fex *fex = (Fex *)KernelAllocator.RequestPages(TO_PAGES(Size));
|
||||||
|
memcpy(fex, (void *)DriverAddress, Size);
|
||||||
|
FexExtended *fexExtended = (FexExtended *)((uint64_t)fex + EXTENDED_SECTION_ADDRESS);
|
||||||
|
#ifdef DEBUG
|
||||||
|
uint8_t *result = md5File((uint8_t *)fex, Size);
|
||||||
|
debug("MD5: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
|
||||||
|
result[0], result[1], result[2], result[3], result[4], result[5], result[6], result[7],
|
||||||
|
result[8], result[9], result[10], result[11], result[12], result[13], result[14], result[15]);
|
||||||
|
kfree(result);
|
||||||
|
#endif
|
||||||
|
if (CallDriverEntryPoint(fex) != DriverCode::OK)
|
||||||
|
{
|
||||||
|
KernelAllocator.FreePages(fex, TO_PAGES(Size));
|
||||||
|
return DriverCode::DRIVER_RETURNED_ERROR;
|
||||||
|
}
|
||||||
|
debug("Starting driver %s (offset: %#lx)", fexExtended->Driver.Name, fex);
|
||||||
|
|
||||||
|
KernelCallback *KCallback = (KernelCallback *)KernelAllocator.RequestPages(TO_PAGES(sizeof(KernelCallback)));
|
||||||
|
|
||||||
|
switch (fexExtended->Driver.Type)
|
||||||
|
{
|
||||||
|
case FexDriverType::FexDriverType_Input:
|
||||||
|
{
|
||||||
|
fixme("Input driver: %s", fexExtended->Driver.Name);
|
||||||
|
KCallback->RawPtr = nullptr;
|
||||||
|
break;
|
||||||
|
KCallback->Reason = CallbackReason::ConfigurationReason;
|
||||||
|
int callbackret = ((int (*)(KernelCallback *))((uint64_t)fexExtended->Driver.Callback + (uint64_t)fex))(KCallback);
|
||||||
|
if (callbackret == DriverReturnCode::NOT_IMPLEMENTED)
|
||||||
|
{
|
||||||
|
KernelAllocator.FreePages(fex, TO_PAGES(Size));
|
||||||
|
KernelAllocator.FreePages(KCallback, TO_PAGES(sizeof(KernelCallback)));
|
||||||
|
error("Driver %s does not implement the configuration callback", fexExtended->Driver.Name);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (callbackret != DriverReturnCode::OK)
|
||||||
|
{
|
||||||
|
KernelAllocator.FreePages(fex, TO_PAGES(Size));
|
||||||
|
KernelAllocator.FreePages(KCallback, TO_PAGES(sizeof(KernelCallback)));
|
||||||
|
error("Driver %s returned error %d", fexExtended->Driver.Name, callbackret);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
KernelAllocator.FreePages(fex, TO_PAGES(Size));
|
||||||
|
KernelAllocator.FreePages(KCallback, TO_PAGES(sizeof(KernelCallback)));
|
||||||
|
|
||||||
|
DriverFile *drvfile = new DriverFile;
|
||||||
|
drvfile->DriverUID = KAPI.Info.DriverUID;
|
||||||
|
drvfile->Address = (void *)fex;
|
||||||
|
drvfile->InterruptHook[0] = nullptr;
|
||||||
|
Drivers.push_back(drvfile);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
warn("Unknown driver type: %d", fexExtended->Driver.Type);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
error("Unknown driver bind type: %d", DrvExtHdr->Driver.Bind.Type);
|
error("Unknown driver bind type: %d", DrvExtHdr->Driver.Bind.Type);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
return DriverCode::NOT_DRIVER;
|
return DriverCode::NOT_DRIVER;
|
||||||
return DriverCode::ERROR;
|
return DriverCode::OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
Driver::Driver()
|
Driver::Driver()
|
||||||
{
|
{
|
||||||
SmartCriticalSection(DriverInitLock);
|
SmartCriticalSection(DriverInitLock);
|
||||||
shared_ptr<VirtualFileSystem::File> DriverDirectory = vfs->Open(Config.DriverDirectory);
|
FileSystem::FILE *DriverDirectory = vfs->Open(Config.DriverDirectory);
|
||||||
if (DriverDirectory->Status == VirtualFileSystem::FileStatus::OK)
|
if (DriverDirectory->Status == FileSystem::FileStatus::OK)
|
||||||
{
|
foreach (auto driver in DriverDirectory->Node->Children)
|
||||||
foreach (auto driver in DriverDirectory->node->Children)
|
if (driver->Flags == FileSystem::NodeFlags::FS_FILE)
|
||||||
if (driver->Flags == VirtualFileSystem::NodeFlags::FILE)
|
|
||||||
if (cwk_path_has_extension(driver->Name))
|
if (cwk_path_has_extension(driver->Name))
|
||||||
{
|
{
|
||||||
const char *extension;
|
const char *extension;
|
||||||
cwk_path_get_extension(driver->Name, &extension, nullptr);
|
cwk_path_get_extension(driver->Name, &extension, nullptr);
|
||||||
debug("Driver: %s; Extension: %s", driver->Name, extension);
|
if (!strcmp(extension, ".fex"))
|
||||||
if (strcmp(extension, ".fex") == 0 || strcmp(extension, ".elf") == 0)
|
|
||||||
{
|
{
|
||||||
uintptr_t ret = this->LoadDriver(driver->Address, driver->Length);
|
uint64_t ret = this->LoadDriver(driver->Address, driver->Length);
|
||||||
char RetString[128];
|
char retstring[128];
|
||||||
if (ret == DriverCode::OK)
|
if (ret == DriverCode::OK)
|
||||||
strncpy(RetString, "\e058C19OK", 10);
|
strncpy(retstring, "\e058C19OK", 64);
|
||||||
else if (ret == DriverCode::NOT_AVAILABLE)
|
|
||||||
strncpy(RetString, "\eFF7900NOT AVAILABLE", 21);
|
|
||||||
else
|
else
|
||||||
sprintf(RetString, "\eE85230FAILED (%#lx)", ret);
|
sprintf_(retstring, "\eE85230FAILED (%#lx)", ret);
|
||||||
KPrint("%s %s", driver->Name, RetString);
|
KPrint("%s %s", driver->Name, retstring);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
KPrint("\eE85230Failed to open driver directory: %s! (Status: %#lx)", Config.DriverDirectory, DriverDirectory->Status);
|
|
||||||
CPU::Stop();
|
|
||||||
}
|
|
||||||
vfs->Close(DriverDirectory);
|
vfs->Close(DriverDirectory);
|
||||||
}
|
}
|
||||||
|
|
||||||
Driver::~Driver()
|
Driver::~Driver()
|
||||||
{
|
{
|
||||||
debug("Destructor called");
|
|
||||||
this->UnloadAllDrivers();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(a64)
|
#if defined(__amd64__)
|
||||||
SafeFunction void DriverInterruptHook::OnInterruptReceived(CPU::x64::TrapFrame *Frame)
|
void DriverInterruptHook::OnInterruptReceived(CPU::x64::TrapFrame *Frame)
|
||||||
#elif defined(a32)
|
#elif defined(__i386__)
|
||||||
SafeFunction void DriverInterruptHook::OnInterruptReceived(CPU::x32::TrapFrame *Frame)
|
void DriverInterruptHook::OnInterruptReceived(void *Frame)
|
||||||
#elif defined(aa64)
|
#elif defined(__aarch64__)
|
||||||
SafeFunction void DriverInterruptHook::OnInterruptReceived(void *Frame)
|
void DriverInterruptHook::OnInterruptReceived(void *Frame)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
SmartLock(DriverInterruptLock);
|
SmartCriticalSection(DriverInterruptLock);
|
||||||
((int (*)(void *))(Handle))(Data);
|
((int (*)(void *))(Handle))(Data);
|
||||||
UNUSED(Frame);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DriverInterruptHook::DriverInterruptHook(int Interrupt, void *Address, void *ParamData) : Interrupts::Handler(Interrupt)
|
DriverInterruptHook::DriverInterruptHook(int Interrupt, void *Address, void *ParamData) : Interrupts::Handler(Interrupt)
|
||||||
|
@ -7,18 +7,13 @@
|
|||||||
#include "../../Fex.hpp"
|
#include "../../Fex.hpp"
|
||||||
#include "api.hpp"
|
#include "api.hpp"
|
||||||
|
|
||||||
// show debug messages
|
|
||||||
// #define DEBUG_DRIVER_API 1
|
|
||||||
|
|
||||||
#ifdef DEBUG_DRIVER_API
|
|
||||||
#define drvdbg(m, ...) debug(m, ##__VA_ARGS__)
|
|
||||||
#else
|
|
||||||
#define drvdbg(m, ...)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
NewLock(DriverDisplayPrintLock);
|
NewLock(DriverDisplayPrintLock);
|
||||||
|
|
||||||
void DriverDebugPrint(char *String, unsigned long DriverUID) { trace("[%ld] %s", DriverUID, String); }
|
void DriverDebugPrint(char *String, unsigned long DriverUID)
|
||||||
|
{
|
||||||
|
SmartLock(DriverDisplayPrintLock);
|
||||||
|
trace("[%ld] %s", DriverUID, String);
|
||||||
|
}
|
||||||
|
|
||||||
void DriverDisplayPrint(char *String)
|
void DriverDisplayPrint(char *String)
|
||||||
{
|
{
|
||||||
@ -29,117 +24,74 @@ void DriverDisplayPrint(char *String)
|
|||||||
|
|
||||||
void *RequestPage(unsigned long Size)
|
void *RequestPage(unsigned long Size)
|
||||||
{
|
{
|
||||||
|
SmartLock(DriverDisplayPrintLock);
|
||||||
|
// debug("Requesting %ld pages from the kernel...", Size);
|
||||||
void *ret = KernelAllocator.RequestPages(Size);
|
void *ret = KernelAllocator.RequestPages(Size);
|
||||||
drvdbg("Allocated %ld pages (%#lx-%#lx)", Size, (unsigned long)ret, (unsigned long)ret + FROM_PAGES(Size));
|
// debug("Got %#lx", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FreePage(void *Page, unsigned long Size)
|
void FreePage(void *Page, unsigned long Size)
|
||||||
{
|
{
|
||||||
drvdbg("Freeing %ld pages (%#lx-%#lx)", Size, (unsigned long)Page, (unsigned long)Page + FROM_PAGES(Size));
|
SmartLock(DriverDisplayPrintLock);
|
||||||
|
debug("Freeing %ld pages from the address %#lx...", Size, (unsigned long)Page);
|
||||||
KernelAllocator.FreePages(Page, Size);
|
KernelAllocator.FreePages(Page, Size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MapMemory(void *VirtualAddress, void *PhysicalAddress, unsigned long Flags)
|
void MapMemory(void *VirtualAddress, void *PhysicalAddress, unsigned long Flags)
|
||||||
{
|
{
|
||||||
SmartLock(DriverDisplayPrintLock);
|
SmartLock(DriverDisplayPrintLock);
|
||||||
drvdbg("Mapping %#lx to %#lx with flags %#lx...", (unsigned long)VirtualAddress, (unsigned long)PhysicalAddress, Flags);
|
debug("Mapping %#lx to %#lx with flags %#lx...", (unsigned long)VirtualAddress, (unsigned long)PhysicalAddress, Flags);
|
||||||
Memory::Virtual().Map(VirtualAddress, PhysicalAddress, Flags);
|
Memory::Virtual().Map(VirtualAddress, PhysicalAddress, Flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UnmapMemory(void *VirtualAddress)
|
void UnmapMemory(void *VirtualAddress)
|
||||||
{
|
{
|
||||||
SmartLock(DriverDisplayPrintLock);
|
SmartLock(DriverDisplayPrintLock);
|
||||||
drvdbg("Unmapping %#lx...", (unsigned long)VirtualAddress);
|
debug("Unmapping %#lx...", (unsigned long)VirtualAddress);
|
||||||
Memory::Virtual().Unmap(VirtualAddress);
|
Memory::Virtual().Unmap(VirtualAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
void *Drivermemcpy(void *Destination, void *Source, unsigned long Size)
|
void *Drivermemcpy(void *Destination, void *Source, unsigned long Size)
|
||||||
{
|
{
|
||||||
SmartLock(DriverDisplayPrintLock);
|
SmartLock(DriverDisplayPrintLock);
|
||||||
drvdbg("Copying %ld bytes from %#lx-%#lx to %#lx-%#lx...", Size,
|
// debug("Copying %ld bytes from %#lx to %#lx...", Size, (unsigned long)Source, (unsigned long)Destination);
|
||||||
(unsigned long)Source, (unsigned long)Source + Size,
|
|
||||||
(unsigned long)Destination, (unsigned long)Destination + Size);
|
|
||||||
return memcpy(Destination, Source, Size);
|
return memcpy(Destination, Source, Size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void *Drivermemset(void *Destination, int Value, unsigned long Size)
|
void *Drivermemset(void *Destination, int Value, unsigned long Size)
|
||||||
{
|
{
|
||||||
SmartLock(DriverDisplayPrintLock);
|
SmartLock(DriverDisplayPrintLock);
|
||||||
drvdbg("Setting value %#x at %#lx-%#lx (%ld bytes)...", Value,
|
// debug("Setting %ld bytes from %#lx to %#x...", Size, (unsigned long)Destination, Value);
|
||||||
(unsigned long)Destination, (unsigned long)Destination + Size,
|
|
||||||
Size);
|
|
||||||
return memset(Destination, Value, Size);
|
return memset(Destination, Value, Size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DriverNetSend(unsigned int DriverID, unsigned char *Data, unsigned short Size)
|
void DriverNetSend(unsigned int DriverID, unsigned char *Data, unsigned short Size)
|
||||||
{
|
{
|
||||||
// This is useless I guess...
|
DumpData("DriverNetSend", Data, Size);
|
||||||
if (NIManager)
|
|
||||||
NIManager->DrvSend(DriverID, Data, Size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DriverNetReceive(unsigned int DriverID, unsigned char *Data, unsigned short Size)
|
void DriverNetReceive(unsigned int DriverID, unsigned char *Data, unsigned short Size)
|
||||||
{
|
{
|
||||||
if (NIManager)
|
DumpData("DriverNetReceive", Data, Size);
|
||||||
NIManager->DrvReceive(DriverID, Data, Size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DriverAHCIDiskRead(unsigned int DriverID, unsigned long Sector, unsigned char *Data, unsigned int SectorCount, unsigned char Port)
|
void DriverAHCIDiskRead(unsigned int DriverID, unsigned long Sector, unsigned char *Data, unsigned int SectorCount, unsigned char Port)
|
||||||
{
|
{
|
||||||
DumpData("DriverDiskRead", Data, SectorCount * 512);
|
DumpData("DriverDiskRead", Data, SectorCount * 512);
|
||||||
UNUSED(DriverID);
|
|
||||||
UNUSED(Sector);
|
|
||||||
UNUSED(Port);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DriverAHCIDiskWrite(unsigned int DriverID, unsigned long Sector, unsigned char *Data, unsigned int SectorCount, unsigned char Port)
|
void DriverAHCIDiskWrite(unsigned int DriverID, unsigned long Sector, unsigned char *Data, unsigned int SectorCount, unsigned char Port)
|
||||||
{
|
{
|
||||||
DumpData("DriverDiskWrite", Data, SectorCount * 512);
|
DumpData("DriverDiskWrite", Data, SectorCount * 512);
|
||||||
UNUSED(DriverID);
|
|
||||||
UNUSED(Sector);
|
|
||||||
UNUSED(Port);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
char *DriverPCIGetDeviceName(unsigned int VendorID, unsigned int DeviceID)
|
char *DriverPCIGetDeviceName(unsigned int VendorID, unsigned int DeviceID)
|
||||||
{
|
{
|
||||||
UNUSED(VendorID);
|
|
||||||
UNUSED(DeviceID);
|
|
||||||
return (char *)"Unknown";
|
return (char *)"Unknown";
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int DriverGetWidth()
|
KernelAPI KAPI = {
|
||||||
{
|
|
||||||
/* TODO: We won't rely only on display buffers, what about graphics drivers and changing resolutions? */
|
|
||||||
return Display->GetBuffer(0)->Width;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int DriverGetHeight()
|
|
||||||
{
|
|
||||||
/* TODO: We won't rely only on display buffers, what about graphics drivers and changing resolutions? */
|
|
||||||
return Display->GetBuffer(0)->Height;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DriverSleep(unsigned long Milliseconds)
|
|
||||||
{
|
|
||||||
SmartLock(DriverDisplayPrintLock);
|
|
||||||
drvdbg("Sleeping for %ld milliseconds...", Milliseconds);
|
|
||||||
if (TaskManager)
|
|
||||||
TaskManager->Sleep(Milliseconds);
|
|
||||||
else
|
|
||||||
TimeManager->Sleep(Milliseconds);
|
|
||||||
}
|
|
||||||
|
|
||||||
int Driversprintf(char *Buffer, const char *Format, ...)
|
|
||||||
{
|
|
||||||
va_list args;
|
|
||||||
va_start(args, Format);
|
|
||||||
int ret = vsprintf(Buffer, Format, args);
|
|
||||||
va_end(args);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
KernelAPI KernelAPITemplate = {
|
|
||||||
.Version = {
|
.Version = {
|
||||||
.Major = 0,
|
.Major = 0,
|
||||||
.Minor = 0,
|
.Minor = 0,
|
||||||
@ -163,8 +115,6 @@ KernelAPI KernelAPITemplate = {
|
|||||||
.DisplayPrint = DriverDisplayPrint,
|
.DisplayPrint = DriverDisplayPrint,
|
||||||
.memcpy = Drivermemcpy,
|
.memcpy = Drivermemcpy,
|
||||||
.memset = Drivermemset,
|
.memset = Drivermemset,
|
||||||
.Sleep = DriverSleep,
|
|
||||||
.sprintf = Driversprintf,
|
|
||||||
},
|
},
|
||||||
.Command = {
|
.Command = {
|
||||||
.Network = {
|
.Network = {
|
||||||
@ -178,8 +128,4 @@ KernelAPI KernelAPITemplate = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
.Display = {
|
|
||||||
.GetWidth = DriverGetWidth,
|
|
||||||
.GetHeight = DriverGetHeight,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
@ -1,120 +0,0 @@
|
|||||||
#include "../api.hpp"
|
|
||||||
|
|
||||||
#include <ints.hpp>
|
|
||||||
#include <memory.hpp>
|
|
||||||
#include <task.hpp>
|
|
||||||
#include <lock.hpp>
|
|
||||||
#include <printf.h>
|
|
||||||
#include <cwalk.h>
|
|
||||||
#include <md5.h>
|
|
||||||
|
|
||||||
#include "../../../kernel.h"
|
|
||||||
#include "../../../DAPI.hpp"
|
|
||||||
#include "../../../Fex.hpp"
|
|
||||||
|
|
||||||
namespace Driver
|
|
||||||
{
|
|
||||||
DriverCode Driver::BindInputGeneric(Memory::MemMgr *mem, void *fex)
|
|
||||||
{
|
|
||||||
return DriverCode::NOT_IMPLEMENTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
DriverCode Driver::BindInputDisplay(Memory::MemMgr *mem, void *fex)
|
|
||||||
{
|
|
||||||
return DriverCode::NOT_IMPLEMENTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
DriverCode Driver::BindInputNetwork(Memory::MemMgr *mem, void *fex)
|
|
||||||
{
|
|
||||||
return DriverCode::NOT_IMPLEMENTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
DriverCode Driver::BindInputStorage(Memory::MemMgr *mem, void *fex)
|
|
||||||
{
|
|
||||||
return DriverCode::NOT_IMPLEMENTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
DriverCode Driver::BindInputFileSystem(Memory::MemMgr *mem, void *fex)
|
|
||||||
{
|
|
||||||
return DriverCode::NOT_IMPLEMENTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
DriverCode Driver::BindInputInput(Memory::MemMgr *mem, void *fex)
|
|
||||||
{
|
|
||||||
FexExtended *fexExtended = (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
|
|
||||||
KernelCallback *KCallback = (KernelCallback *)mem->RequestPages(TO_PAGES(sizeof(KernelCallback)));
|
|
||||||
|
|
||||||
fixme("Input driver: %s", fexExtended->Driver.Name);
|
|
||||||
KCallback->RawPtr = nullptr;
|
|
||||||
KCallback->Reason = CallbackReason::ConfigurationReason;
|
|
||||||
int CallbackRet = ((int (*)(KernelCallback *))((uintptr_t)fexExtended->Driver.Callback + (uintptr_t)fex))(KCallback);
|
|
||||||
if (CallbackRet == DriverReturnCode::NOT_IMPLEMENTED)
|
|
||||||
{
|
|
||||||
delete mem, mem = nullptr;
|
|
||||||
error("Driver %s is not implemented", fexExtended->Driver.Name);
|
|
||||||
return DriverCode::NOT_IMPLEMENTED;
|
|
||||||
}
|
|
||||||
else if (CallbackRet != DriverReturnCode::OK)
|
|
||||||
{
|
|
||||||
delete mem, mem = nullptr;
|
|
||||||
error("Driver %s returned error %d", fexExtended->Driver.Name, CallbackRet);
|
|
||||||
return DriverCode::DRIVER_RETURNED_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
fixme("Input driver: %s", fexExtended->Driver.Name);
|
|
||||||
|
|
||||||
DriverFile *DrvFile = new DriverFile;
|
|
||||||
DrvFile->Enabled = true;
|
|
||||||
DrvFile->DriverUID = this->DriverUIDs - 1;
|
|
||||||
DrvFile->Address = (void *)fex;
|
|
||||||
DrvFile->MemTrk = mem;
|
|
||||||
DrvFile->InterruptHook[0] = nullptr;
|
|
||||||
Drivers.push_back(DrvFile);
|
|
||||||
return DriverCode::OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
DriverCode Driver::BindInputAudio(Memory::MemMgr *mem, void *fex)
|
|
||||||
{
|
|
||||||
return DriverCode::NOT_IMPLEMENTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
DriverCode Driver::DriverLoadBindInput(void *DrvExtHdr, uintptr_t DriverAddress, size_t Size, bool IsElf)
|
|
||||||
{
|
|
||||||
UNUSED(DrvExtHdr);
|
|
||||||
UNUSED(IsElf);
|
|
||||||
Memory::MemMgr *mem = new Memory::MemMgr(nullptr, TaskManager->GetCurrentProcess()->memDirectory);
|
|
||||||
Fex *fex = (Fex *)mem->RequestPages(TO_PAGES(Size));
|
|
||||||
memcpy(fex, (void *)DriverAddress, Size);
|
|
||||||
FexExtended *fexExtended = (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
|
|
||||||
debug("Driver allocated at %#lx-%#lx", fex, (uintptr_t)fex + Size);
|
|
||||||
#ifdef DEBUG
|
|
||||||
uint8_t *result = md5File((uint8_t *)fex, Size);
|
|
||||||
debug("MD5: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
|
|
||||||
result[0], result[1], result[2], result[3], result[4], result[5], result[6], result[7],
|
|
||||||
result[8], result[9], result[10], result[11], result[12], result[13], result[14], result[15]);
|
|
||||||
kfree(result);
|
|
||||||
#endif
|
|
||||||
KernelAPI *KAPI = (KernelAPI *)mem->RequestPages(TO_PAGES(sizeof(KernelAPI)));
|
|
||||||
|
|
||||||
if (CallDriverEntryPoint(fex, KAPI) != DriverCode::OK)
|
|
||||||
{
|
|
||||||
delete mem, mem = nullptr;
|
|
||||||
return DriverCode::DRIVER_RETURNED_ERROR;
|
|
||||||
}
|
|
||||||
debug("Starting driver %s (offset: %#lx)", fexExtended->Driver.Name, fex);
|
|
||||||
|
|
||||||
switch (fexExtended->Driver.Type)
|
|
||||||
{
|
|
||||||
case FexDriverType::FexDriverType_Input:
|
|
||||||
return BindInputInput(mem, fex);
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
warn("Unknown driver type: %d", fexExtended->Driver.Type);
|
|
||||||
delete mem, mem = nullptr;
|
|
||||||
return DriverCode::UNKNOWN_DRIVER_TYPE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return DriverCode::OK;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,469 +0,0 @@
|
|||||||
#include "../api.hpp"
|
|
||||||
|
|
||||||
#include <ints.hpp>
|
|
||||||
#include <memory.hpp>
|
|
||||||
#include <task.hpp>
|
|
||||||
#include <lock.hpp>
|
|
||||||
#include <printf.h>
|
|
||||||
#include <cwalk.h>
|
|
||||||
#include <md5.h>
|
|
||||||
|
|
||||||
#include "../../../kernel.h"
|
|
||||||
#include "../../../DAPI.hpp"
|
|
||||||
#include "../../../Fex.hpp"
|
|
||||||
|
|
||||||
namespace Driver
|
|
||||||
{
|
|
||||||
DriverCode Driver::BindInterruptGeneric(Memory::MemMgr *mem, void *fex)
|
|
||||||
{
|
|
||||||
FexExtended *fexExtended = (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
|
|
||||||
|
|
||||||
if (fexExtended->Driver.OverrideOnConflict)
|
|
||||||
{
|
|
||||||
Vector<int> DriversToRemove = Vector<int>();
|
|
||||||
foreach (auto Drv in Drivers)
|
|
||||||
{
|
|
||||||
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv->Address + EXTENDED_SECTION_ADDRESS));
|
|
||||||
|
|
||||||
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
|
|
||||||
if (fe->Driver.OverrideOnConflict)
|
|
||||||
return DriverCode::DRIVER_CONFLICT;
|
|
||||||
|
|
||||||
DriversToRemove.push_back(Drv->DriverUID);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (auto DrvID in DriversToRemove)
|
|
||||||
{
|
|
||||||
if (!this->UnloadDriver(DrvID))
|
|
||||||
{
|
|
||||||
error("Failed to unload conflicting driver %d", DrvID);
|
|
||||||
return DriverCode::DRIVER_CONFLICT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
foreach (auto Drv in Drivers)
|
|
||||||
{
|
|
||||||
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv->Address + EXTENDED_SECTION_ADDRESS));
|
|
||||||
|
|
||||||
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
|
|
||||||
if (fe->Driver.OverrideOnConflict)
|
|
||||||
return DriverCode::DRIVER_CONFLICT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fixme("Generic driver: %s", fexExtended->Driver.Name);
|
|
||||||
DriverFile *DrvFile = new DriverFile;
|
|
||||||
DrvFile->Enabled = true;
|
|
||||||
DrvFile->DriverUID = this->DriverUIDs - 1;
|
|
||||||
DrvFile->Address = (void *)fex;
|
|
||||||
DrvFile->MemTrk = mem;
|
|
||||||
Drivers.push_back(DrvFile);
|
|
||||||
return DriverCode::OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
DriverCode Driver::BindInterruptDisplay(Memory::MemMgr *mem, void *fex)
|
|
||||||
{
|
|
||||||
FexExtended *fexExtended = (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
|
|
||||||
|
|
||||||
if (fexExtended->Driver.OverrideOnConflict)
|
|
||||||
{
|
|
||||||
Vector<int> DriversToRemove = Vector<int>();
|
|
||||||
foreach (auto Drv in Drivers)
|
|
||||||
{
|
|
||||||
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv->Address + EXTENDED_SECTION_ADDRESS));
|
|
||||||
|
|
||||||
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
|
|
||||||
if (fe->Driver.OverrideOnConflict)
|
|
||||||
return DriverCode::DRIVER_CONFLICT;
|
|
||||||
|
|
||||||
DriversToRemove.push_back(Drv->DriverUID);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (auto DrvID in DriversToRemove)
|
|
||||||
{
|
|
||||||
if (!this->UnloadDriver(DrvID))
|
|
||||||
{
|
|
||||||
error("Failed to unload conflicting driver %d", DrvID);
|
|
||||||
return DriverCode::DRIVER_CONFLICT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
foreach (auto Drv in Drivers)
|
|
||||||
{
|
|
||||||
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv->Address + EXTENDED_SECTION_ADDRESS));
|
|
||||||
|
|
||||||
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
|
|
||||||
if (fe->Driver.OverrideOnConflict)
|
|
||||||
return DriverCode::DRIVER_CONFLICT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fixme("Display driver: %s", fexExtended->Driver.Name);
|
|
||||||
delete mem, mem = nullptr;
|
|
||||||
return DriverCode::NOT_IMPLEMENTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
DriverCode Driver::BindInterruptNetwork(Memory::MemMgr *mem, void *fex)
|
|
||||||
{
|
|
||||||
FexExtended *fexExtended = (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
|
|
||||||
|
|
||||||
if (fexExtended->Driver.OverrideOnConflict)
|
|
||||||
{
|
|
||||||
Vector<int> DriversToRemove = Vector<int>();
|
|
||||||
foreach (auto Drv in Drivers)
|
|
||||||
{
|
|
||||||
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv->Address + EXTENDED_SECTION_ADDRESS));
|
|
||||||
|
|
||||||
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
|
|
||||||
if (fe->Driver.OverrideOnConflict)
|
|
||||||
return DriverCode::DRIVER_CONFLICT;
|
|
||||||
|
|
||||||
DriversToRemove.push_back(Drv->DriverUID);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (auto DrvID in DriversToRemove)
|
|
||||||
{
|
|
||||||
if (!this->UnloadDriver(DrvID))
|
|
||||||
{
|
|
||||||
error("Failed to unload conflicting driver %d", DrvID);
|
|
||||||
return DriverCode::DRIVER_CONFLICT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
foreach (auto Drv in Drivers)
|
|
||||||
{
|
|
||||||
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv->Address + EXTENDED_SECTION_ADDRESS));
|
|
||||||
|
|
||||||
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
|
|
||||||
if (fe->Driver.OverrideOnConflict)
|
|
||||||
return DriverCode::DRIVER_CONFLICT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fixme("Network driver: %s", fexExtended->Driver.Name);
|
|
||||||
delete mem, mem = nullptr;
|
|
||||||
return DriverCode::NOT_IMPLEMENTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
DriverCode Driver::BindInterruptStorage(Memory::MemMgr *mem, void *fex)
|
|
||||||
{
|
|
||||||
return DriverCode::NOT_IMPLEMENTED; // FIXME
|
|
||||||
|
|
||||||
FexExtended *fexExtended = (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
|
|
||||||
|
|
||||||
if (fexExtended->Driver.OverrideOnConflict)
|
|
||||||
{
|
|
||||||
Vector<int> DriversToRemove = Vector<int>();
|
|
||||||
foreach (auto Drv in Drivers)
|
|
||||||
{
|
|
||||||
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv->Address + EXTENDED_SECTION_ADDRESS));
|
|
||||||
|
|
||||||
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
|
|
||||||
if (fe->Driver.OverrideOnConflict)
|
|
||||||
return DriverCode::DRIVER_CONFLICT;
|
|
||||||
|
|
||||||
DriversToRemove.push_back(Drv->DriverUID);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (auto DrvID in DriversToRemove)
|
|
||||||
{
|
|
||||||
if (!this->UnloadDriver(DrvID))
|
|
||||||
{
|
|
||||||
error("Failed to unload conflicting driver %d", DrvID);
|
|
||||||
return DriverCode::DRIVER_CONFLICT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
foreach (auto Drv in Drivers)
|
|
||||||
{
|
|
||||||
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv->Address + EXTENDED_SECTION_ADDRESS));
|
|
||||||
|
|
||||||
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
|
|
||||||
if (fe->Driver.OverrideOnConflict)
|
|
||||||
return DriverCode::DRIVER_CONFLICT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
KernelCallback *KCallback = (KernelCallback *)mem->RequestPages(TO_PAGES(sizeof(KernelCallback)));
|
|
||||||
UNUSED(KCallback); // Shut up clang
|
|
||||||
for (unsigned long i = 0; i < sizeof(fexExtended->Driver.Bind.Interrupt.Vector) / sizeof(fexExtended->Driver.Bind.Interrupt.Vector[0]); i++)
|
|
||||||
{
|
|
||||||
if (fexExtended->Driver.Bind.Interrupt.Vector[i] == 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
fixme("TODO: MULTIPLE BIND INTERRUPT VECTORS %d", fexExtended->Driver.Bind.Interrupt.Vector[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
KCallback->RawPtr = nullptr;
|
|
||||||
KCallback->Reason = CallbackReason::ConfigurationReason;
|
|
||||||
int CallbackRet = ((int (*)(KernelCallback *))((uintptr_t)fexExtended->Driver.Callback + (uintptr_t)fex))(KCallback);
|
|
||||||
if (CallbackRet == DriverReturnCode::NOT_IMPLEMENTED)
|
|
||||||
{
|
|
||||||
error("Driver %s is not implemented", fexExtended->Driver.Name);
|
|
||||||
delete mem, mem = nullptr;
|
|
||||||
return DriverCode::NOT_IMPLEMENTED;
|
|
||||||
}
|
|
||||||
else if (CallbackRet != DriverReturnCode::OK)
|
|
||||||
{
|
|
||||||
error("Driver %s returned error %d", fexExtended->Driver.Name, CallbackRet);
|
|
||||||
delete mem, mem = nullptr;
|
|
||||||
return DriverCode::DRIVER_RETURNED_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
DriverFile *DrvFile = new DriverFile;
|
|
||||||
DrvFile->Enabled = true;
|
|
||||||
DrvFile->DriverUID = this->DriverUIDs - 1;
|
|
||||||
DrvFile->Address = (void *)fex;
|
|
||||||
DrvFile->MemTrk = mem;
|
|
||||||
Drivers.push_back(DrvFile);
|
|
||||||
return DriverCode::OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
DriverCode Driver::BindInterruptFileSystem(Memory::MemMgr *mem, void *fex)
|
|
||||||
{
|
|
||||||
FexExtended *fexExtended = (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
|
|
||||||
|
|
||||||
if (fexExtended->Driver.OverrideOnConflict)
|
|
||||||
{
|
|
||||||
Vector<int> DriversToRemove = Vector<int>();
|
|
||||||
foreach (auto Drv in Drivers)
|
|
||||||
{
|
|
||||||
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv->Address + EXTENDED_SECTION_ADDRESS));
|
|
||||||
|
|
||||||
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
|
|
||||||
if (fe->Driver.OverrideOnConflict)
|
|
||||||
return DriverCode::DRIVER_CONFLICT;
|
|
||||||
|
|
||||||
DriversToRemove.push_back(Drv->DriverUID);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (auto DrvID in DriversToRemove)
|
|
||||||
{
|
|
||||||
if (!this->UnloadDriver(DrvID))
|
|
||||||
{
|
|
||||||
error("Failed to unload conflicting driver %d", DrvID);
|
|
||||||
return DriverCode::DRIVER_CONFLICT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
foreach (auto Drv in Drivers)
|
|
||||||
{
|
|
||||||
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv->Address + EXTENDED_SECTION_ADDRESS));
|
|
||||||
|
|
||||||
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
|
|
||||||
if (fe->Driver.OverrideOnConflict)
|
|
||||||
return DriverCode::DRIVER_CONFLICT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fixme("Filesystem driver: %s", fexExtended->Driver.Name);
|
|
||||||
delete mem, mem = nullptr;
|
|
||||||
return DriverCode::NOT_IMPLEMENTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
DriverCode Driver::BindInterruptInput(Memory::MemMgr *mem, void *fex)
|
|
||||||
{
|
|
||||||
FexExtended *fexExtended = (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
|
|
||||||
|
|
||||||
debug("Searching for conflicting drivers...");
|
|
||||||
if (fexExtended->Driver.OverrideOnConflict)
|
|
||||||
{
|
|
||||||
Vector<int> DriversToRemove = Vector<int>();
|
|
||||||
foreach (auto Drv in Drivers)
|
|
||||||
{
|
|
||||||
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv->Address + EXTENDED_SECTION_ADDRESS));
|
|
||||||
|
|
||||||
if ((fe->Driver.TypeFlags & FexDriverInputTypes_Mouse &&
|
|
||||||
fexExtended->Driver.TypeFlags & FexDriverInputTypes_Mouse) ||
|
|
||||||
(fe->Driver.TypeFlags & FexDriverInputTypes_Keyboard &&
|
|
||||||
fexExtended->Driver.TypeFlags & FexDriverInputTypes_Keyboard))
|
|
||||||
{
|
|
||||||
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
|
|
||||||
if (fe->Driver.OverrideOnConflict)
|
|
||||||
return DriverCode::DRIVER_CONFLICT;
|
|
||||||
|
|
||||||
DriversToRemove.push_back(Drv->DriverUID);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (auto DrvID in DriversToRemove)
|
|
||||||
{
|
|
||||||
if (!this->UnloadDriver(DrvID))
|
|
||||||
{
|
|
||||||
error("Failed to unload conflicting driver %d", DrvID);
|
|
||||||
return DriverCode::DRIVER_CONFLICT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
foreach (auto Drv in Drivers)
|
|
||||||
{
|
|
||||||
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv->Address + EXTENDED_SECTION_ADDRESS));
|
|
||||||
|
|
||||||
if ((fe->Driver.TypeFlags & FexDriverInputTypes_Mouse &&
|
|
||||||
fexExtended->Driver.TypeFlags & FexDriverInputTypes_Mouse) ||
|
|
||||||
(fe->Driver.TypeFlags & FexDriverInputTypes_Keyboard &&
|
|
||||||
fexExtended->Driver.TypeFlags & FexDriverInputTypes_Keyboard))
|
|
||||||
{
|
|
||||||
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
|
|
||||||
if (fe->Driver.OverrideOnConflict)
|
|
||||||
return DriverCode::DRIVER_CONFLICT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
KernelCallback *KCallback = (KernelCallback *)mem->RequestPages(TO_PAGES(sizeof(KernelCallback)));
|
|
||||||
|
|
||||||
DriverInterruptHook *InterruptHook = nullptr;
|
|
||||||
if (fexExtended->Driver.Bind.Interrupt.Vector[0] != 0)
|
|
||||||
InterruptHook = new DriverInterruptHook(fexExtended->Driver.Bind.Interrupt.Vector[0] + 32, // x86
|
|
||||||
(void *)((uintptr_t)fexExtended->Driver.Callback + (uintptr_t)fex),
|
|
||||||
KCallback);
|
|
||||||
|
|
||||||
for (unsigned long i = 0; i < sizeof(fexExtended->Driver.Bind.Interrupt.Vector) / sizeof(fexExtended->Driver.Bind.Interrupt.Vector[0]); i++)
|
|
||||||
{
|
|
||||||
if (fexExtended->Driver.Bind.Interrupt.Vector[i] == 0)
|
|
||||||
break;
|
|
||||||
// InterruptHook = new DriverInterruptHook((fexExtended->Driver.Bind.Interrupt.Vector[i] + 32, // x86
|
|
||||||
// (void *)((uintptr_t)fexExtended->Driver.Callback + (uintptr_t)fex),
|
|
||||||
// KCallback);
|
|
||||||
fixme("TODO: MULTIPLE BIND INTERRUPT VECTORS %d", fexExtended->Driver.Bind.Interrupt.Vector[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
KCallback->RawPtr = nullptr;
|
|
||||||
KCallback->Reason = CallbackReason::ConfigurationReason;
|
|
||||||
int CallbackRet = ((int (*)(KernelCallback *))((uintptr_t)fexExtended->Driver.Callback + (uintptr_t)fex))(KCallback);
|
|
||||||
if (CallbackRet == DriverReturnCode::NOT_IMPLEMENTED)
|
|
||||||
{
|
|
||||||
error("Driver %s is not implemented", fexExtended->Driver.Name);
|
|
||||||
delete InterruptHook, InterruptHook = nullptr;
|
|
||||||
delete mem, mem = nullptr;
|
|
||||||
return DriverCode::NOT_IMPLEMENTED;
|
|
||||||
}
|
|
||||||
else if (CallbackRet != DriverReturnCode::OK)
|
|
||||||
{
|
|
||||||
error("Driver %s returned error %d", fexExtended->Driver.Name, CallbackRet);
|
|
||||||
delete InterruptHook, InterruptHook = nullptr;
|
|
||||||
delete mem, mem = nullptr;
|
|
||||||
return DriverCode::DRIVER_RETURNED_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(KCallback, 0, sizeof(KernelCallback));
|
|
||||||
KCallback->Reason = CallbackReason::InterruptReason;
|
|
||||||
|
|
||||||
DriverFile *DrvFile = new DriverFile;
|
|
||||||
DrvFile->Enabled = true;
|
|
||||||
DrvFile->DriverUID = this->DriverUIDs - 1;
|
|
||||||
DrvFile->Address = (void *)fex;
|
|
||||||
DrvFile->MemTrk = mem;
|
|
||||||
DrvFile->InterruptHook[0] = InterruptHook;
|
|
||||||
Drivers.push_back(DrvFile);
|
|
||||||
return DriverCode::OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
DriverCode Driver::BindInterruptAudio(Memory::MemMgr *mem, void *fex)
|
|
||||||
{
|
|
||||||
FexExtended *fexExtended = (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
|
|
||||||
|
|
||||||
if (fexExtended->Driver.OverrideOnConflict)
|
|
||||||
{
|
|
||||||
Vector<int> DriversToRemove = Vector<int>();
|
|
||||||
foreach (auto Drv in Drivers)
|
|
||||||
{
|
|
||||||
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv->Address + EXTENDED_SECTION_ADDRESS));
|
|
||||||
|
|
||||||
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
|
|
||||||
if (fe->Driver.OverrideOnConflict)
|
|
||||||
return DriverCode::DRIVER_CONFLICT;
|
|
||||||
|
|
||||||
DriversToRemove.push_back(Drv->DriverUID);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (auto DrvID in DriversToRemove)
|
|
||||||
{
|
|
||||||
if (!this->UnloadDriver(DrvID))
|
|
||||||
{
|
|
||||||
error("Failed to unload conflicting driver %d", DrvID);
|
|
||||||
return DriverCode::DRIVER_CONFLICT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
foreach (auto Drv in Drivers)
|
|
||||||
{
|
|
||||||
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv->Address + EXTENDED_SECTION_ADDRESS));
|
|
||||||
|
|
||||||
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
|
|
||||||
if (fe->Driver.OverrideOnConflict)
|
|
||||||
return DriverCode::DRIVER_CONFLICT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fixme("Audio driver: %s", fexExtended->Driver.Name);
|
|
||||||
delete mem, mem = nullptr;
|
|
||||||
return DriverCode::NOT_IMPLEMENTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
DriverCode Driver::DriverLoadBindInterrupt(void *DrvExtHdr, uintptr_t DriverAddress, size_t Size, bool IsElf)
|
|
||||||
{
|
|
||||||
UNUSED(IsElf);
|
|
||||||
Memory::MemMgr *mem = new Memory::MemMgr(nullptr, TaskManager->GetCurrentProcess()->memDirectory);
|
|
||||||
Fex *fex = (Fex *)mem->RequestPages(TO_PAGES(Size));
|
|
||||||
memcpy(fex, (void *)DriverAddress, Size);
|
|
||||||
FexExtended *fexExtended = (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
|
|
||||||
debug("Driver allocated at %#lx-%#lx", fex, (uintptr_t)fex + Size);
|
|
||||||
#ifdef DEBUG
|
|
||||||
uint8_t *result = md5File((uint8_t *)fex, Size);
|
|
||||||
debug("MD5: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
|
|
||||||
result[0], result[1], result[2], result[3], result[4], result[5], result[6], result[7],
|
|
||||||
result[8], result[9], result[10], result[11], result[12], result[13], result[14], result[15]);
|
|
||||||
kfree(result);
|
|
||||||
#endif
|
|
||||||
KernelAPI *KAPI = (KernelAPI *)mem->RequestPages(TO_PAGES(sizeof(KernelAPI)));
|
|
||||||
|
|
||||||
if (CallDriverEntryPoint(fex, KAPI) != DriverCode::OK)
|
|
||||||
{
|
|
||||||
delete mem, mem = nullptr;
|
|
||||||
return DriverCode::DRIVER_RETURNED_ERROR;
|
|
||||||
}
|
|
||||||
debug("Starting driver %s (offset: %#lx)", fexExtended->Driver.Name, fex);
|
|
||||||
|
|
||||||
switch (fexExtended->Driver.Type)
|
|
||||||
{
|
|
||||||
case FexDriverType::FexDriverType_Generic:
|
|
||||||
return BindInterruptGeneric(mem, fex);
|
|
||||||
case FexDriverType::FexDriverType_Display:
|
|
||||||
return BindInterruptDisplay(mem, fex);
|
|
||||||
case FexDriverType::FexDriverType_Network:
|
|
||||||
return BindInterruptNetwork(mem, fex);
|
|
||||||
case FexDriverType::FexDriverType_Storage:
|
|
||||||
return BindInterruptStorage(mem, fex);
|
|
||||||
case FexDriverType::FexDriverType_FileSystem:
|
|
||||||
return BindInterruptFileSystem(mem, fex);
|
|
||||||
case FexDriverType::FexDriverType_Input:
|
|
||||||
return BindInterruptInput(mem, fex);
|
|
||||||
case FexDriverType::FexDriverType_Audio:
|
|
||||||
return BindInterruptAudio(mem, fex);
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
warn("Unknown driver type: %d", fexExtended->Driver.Type);
|
|
||||||
delete mem, mem = nullptr;
|
|
||||||
return DriverCode::UNKNOWN_DRIVER_TYPE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return DriverCode::OK;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,600 +0,0 @@
|
|||||||
#include "../api.hpp"
|
|
||||||
|
|
||||||
#include <ints.hpp>
|
|
||||||
#include <memory.hpp>
|
|
||||||
#include <task.hpp>
|
|
||||||
#include <lock.hpp>
|
|
||||||
#include <printf.h>
|
|
||||||
#include <cwalk.h>
|
|
||||||
#include <md5.h>
|
|
||||||
|
|
||||||
#include "../../../kernel.h"
|
|
||||||
#include "../../../DAPI.hpp"
|
|
||||||
#include "../../../Fex.hpp"
|
|
||||||
|
|
||||||
namespace Driver
|
|
||||||
{
|
|
||||||
void Driver::MapPCIAddresses(PCI::PCIDeviceHeader *PCIDevice)
|
|
||||||
{
|
|
||||||
Memory::Virtual vma = Memory::Virtual(nullptr);
|
|
||||||
|
|
||||||
debug("Header Type: %d", PCIDevice->HeaderType);
|
|
||||||
switch (PCIDevice->HeaderType)
|
|
||||||
{
|
|
||||||
case 0: // PCI Header 0
|
|
||||||
{
|
|
||||||
uint32_t BAR[6] = {0};
|
|
||||||
size_t BARsSize[6] = {0};
|
|
||||||
|
|
||||||
BAR[0] = ((PCI::PCIHeader0 *)PCIDevice)->BAR0;
|
|
||||||
BAR[1] = ((PCI::PCIHeader0 *)PCIDevice)->BAR1;
|
|
||||||
BAR[2] = ((PCI::PCIHeader0 *)PCIDevice)->BAR2;
|
|
||||||
BAR[3] = ((PCI::PCIHeader0 *)PCIDevice)->BAR3;
|
|
||||||
BAR[4] = ((PCI::PCIHeader0 *)PCIDevice)->BAR4;
|
|
||||||
BAR[5] = ((PCI::PCIHeader0 *)PCIDevice)->BAR5;
|
|
||||||
|
|
||||||
uintptr_t BAR_Type = BAR[0] & 1;
|
|
||||||
uintptr_t BAR_IOBase = BAR[1] & (~3);
|
|
||||||
uintptr_t BAR_MemoryBase = BAR[0] & (~15);
|
|
||||||
|
|
||||||
debug("Type: %d; IOBase: %#lx; MemoryBase: %#lx", BAR_Type, BAR_IOBase, BAR_MemoryBase);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < 6; i++)
|
|
||||||
{
|
|
||||||
if (BAR[i] == 0)
|
|
||||||
continue;
|
|
||||||
debug("BAR%d: %#lx", i, BAR[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* BARs Size */
|
|
||||||
for (size_t i = 0; i < 6; i++)
|
|
||||||
{
|
|
||||||
if (BAR[i] == 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if ((BAR[i] & 1) == 0) // Memory Base
|
|
||||||
{
|
|
||||||
((PCI::PCIHeader0 *)PCIDevice)->BAR0 = 0xFFFFFFFF;
|
|
||||||
size_t size = ((PCI::PCIHeader0 *)PCIDevice)->BAR0;
|
|
||||||
((PCI::PCIHeader0 *)PCIDevice)->BAR0 = BAR[i];
|
|
||||||
BARsSize[i] = size & (~15);
|
|
||||||
BARsSize[i] = ~BARsSize[i] + 1;
|
|
||||||
BARsSize[i] = BARsSize[i] & 0xFFFFFFFF;
|
|
||||||
debug("BAR%dSize: %#lx", i, BARsSize[i]);
|
|
||||||
}
|
|
||||||
else if ((BAR[i] & 1) == 1) // I/O Base
|
|
||||||
{
|
|
||||||
((PCI::PCIHeader0 *)PCIDevice)->BAR1 = 0xFFFFFFFF;
|
|
||||||
size_t size = ((PCI::PCIHeader0 *)PCIDevice)->BAR1;
|
|
||||||
((PCI::PCIHeader0 *)PCIDevice)->BAR1 = BAR[i];
|
|
||||||
BARsSize[i] = size & (~3);
|
|
||||||
BARsSize[i] = ~BARsSize[i] + 1;
|
|
||||||
BARsSize[i] = BARsSize[i] & 0xFFFF;
|
|
||||||
debug("BAR%dSize: %#lx", i, BARsSize[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Mapping the BARs */
|
|
||||||
for (size_t i = 0; i < 6; i++)
|
|
||||||
{
|
|
||||||
if (BAR[i] == 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if ((BAR[i] & 1) == 0) // Memory Base
|
|
||||||
{
|
|
||||||
uintptr_t BARBase = BAR[i] & (~15);
|
|
||||||
size_t BARSize = BARsSize[i];
|
|
||||||
|
|
||||||
debug("Mapping BAR%d from %#lx to %#lx", i, BARBase, BARBase + BARSize);
|
|
||||||
for (uintptr_t j = BARBase;
|
|
||||||
j < (BARBase + BARSize);
|
|
||||||
j += PAGE_SIZE)
|
|
||||||
{
|
|
||||||
vma.Map((void *)j, (void *)j, Memory::PTFlag::RW | Memory::PTFlag::PWT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if ((BAR[i] & 1) == 1) // I/O Base
|
|
||||||
{
|
|
||||||
uintptr_t BARBase = BAR[i] & (~3);
|
|
||||||
uintptr_t BARSize = BARsSize[i];
|
|
||||||
|
|
||||||
debug("Mapping BAR%d from %#x to %#x", i, BARBase, BARBase + BARSize);
|
|
||||||
for (uintptr_t j = BARBase;
|
|
||||||
j < (BARBase + BARSize);
|
|
||||||
j += PAGE_SIZE)
|
|
||||||
{
|
|
||||||
vma.Map((void *)j, (void *)j, Memory::PTFlag::RW | Memory::PTFlag::PWT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 1: // PCI Header 1 (PCI-to-PCI Bridge)
|
|
||||||
{
|
|
||||||
fixme("PCI Header 1 (PCI-to-PCI Bridge) not implemented yet");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 2: // PCI Header 2 (PCI-to-CardBus Bridge)
|
|
||||||
{
|
|
||||||
fixme("PCI Header 2 (PCI-to-CardBus Bridge) not implemented yet");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
error("Unknown header type %d", PCIDevice->HeaderType);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DriverCode Driver::BindPCIGeneric(Memory::MemMgr *mem, void *fex, PCI::PCIDeviceHeader *PCIDevice)
|
|
||||||
{
|
|
||||||
FexExtended *fexExtended = (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
|
|
||||||
|
|
||||||
if (fexExtended->Driver.OverrideOnConflict)
|
|
||||||
{
|
|
||||||
Vector<int> DriversToRemove = Vector<int>();
|
|
||||||
foreach (auto Drv in Drivers)
|
|
||||||
{
|
|
||||||
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv->Address + EXTENDED_SECTION_ADDRESS));
|
|
||||||
|
|
||||||
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
|
|
||||||
if (fe->Driver.OverrideOnConflict)
|
|
||||||
return DriverCode::DRIVER_CONFLICT;
|
|
||||||
|
|
||||||
DriversToRemove.push_back(Drv->DriverUID);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (auto DrvID in DriversToRemove)
|
|
||||||
{
|
|
||||||
if (!this->UnloadDriver(DrvID))
|
|
||||||
{
|
|
||||||
error("Failed to unload conflicting driver %d", DrvID);
|
|
||||||
return DriverCode::DRIVER_CONFLICT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
foreach (auto Drv in Drivers)
|
|
||||||
{
|
|
||||||
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv->Address + EXTENDED_SECTION_ADDRESS));
|
|
||||||
|
|
||||||
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
|
|
||||||
if (fe->Driver.OverrideOnConflict)
|
|
||||||
return DriverCode::DRIVER_CONFLICT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fixme("Generic driver: %s", fexExtended->Driver.Name);
|
|
||||||
delete mem, mem = nullptr;
|
|
||||||
return DriverCode::NOT_IMPLEMENTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
DriverCode Driver::BindPCIDisplay(Memory::MemMgr *mem, void *fex, PCI::PCIDeviceHeader *PCIDevice)
|
|
||||||
{
|
|
||||||
FexExtended *fexExtended = (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
|
|
||||||
|
|
||||||
if (fexExtended->Driver.OverrideOnConflict)
|
|
||||||
{
|
|
||||||
Vector<int> DriversToRemove = Vector<int>();
|
|
||||||
foreach (auto Drv in Drivers)
|
|
||||||
{
|
|
||||||
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv->Address + EXTENDED_SECTION_ADDRESS));
|
|
||||||
|
|
||||||
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
|
|
||||||
if (fe->Driver.OverrideOnConflict)
|
|
||||||
return DriverCode::DRIVER_CONFLICT;
|
|
||||||
|
|
||||||
DriversToRemove.push_back(Drv->DriverUID);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (auto DrvID in DriversToRemove)
|
|
||||||
{
|
|
||||||
if (!this->UnloadDriver(DrvID))
|
|
||||||
{
|
|
||||||
error("Failed to unload conflicting driver %d", DrvID);
|
|
||||||
return DriverCode::DRIVER_CONFLICT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
foreach (auto Drv in Drivers)
|
|
||||||
{
|
|
||||||
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv->Address + EXTENDED_SECTION_ADDRESS));
|
|
||||||
|
|
||||||
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
|
|
||||||
if (fe->Driver.OverrideOnConflict)
|
|
||||||
return DriverCode::DRIVER_CONFLICT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fixme("Display driver: %s", fexExtended->Driver.Name);
|
|
||||||
delete mem, mem = nullptr;
|
|
||||||
return DriverCode::NOT_IMPLEMENTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
DriverCode Driver::BindPCINetwork(Memory::MemMgr *mem, void *fex, PCI::PCIDeviceHeader *PCIDevice)
|
|
||||||
{
|
|
||||||
FexExtended *fexExtended = (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
|
|
||||||
|
|
||||||
if (fexExtended->Driver.OverrideOnConflict)
|
|
||||||
{
|
|
||||||
Vector<int> DriversToRemove = Vector<int>();
|
|
||||||
foreach (auto Drv in Drivers)
|
|
||||||
{
|
|
||||||
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv->Address + EXTENDED_SECTION_ADDRESS));
|
|
||||||
|
|
||||||
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
|
|
||||||
if (fe->Driver.OverrideOnConflict)
|
|
||||||
return DriverCode::DRIVER_CONFLICT;
|
|
||||||
|
|
||||||
DriversToRemove.push_back(Drv->DriverUID);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (auto DrvID in DriversToRemove)
|
|
||||||
{
|
|
||||||
if (!this->UnloadDriver(DrvID))
|
|
||||||
{
|
|
||||||
error("Failed to unload conflicting driver %d", DrvID);
|
|
||||||
return DriverCode::DRIVER_CONFLICT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
foreach (auto Drv in Drivers)
|
|
||||||
{
|
|
||||||
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv->Address + EXTENDED_SECTION_ADDRESS));
|
|
||||||
|
|
||||||
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
|
|
||||||
if (fe->Driver.OverrideOnConflict)
|
|
||||||
return DriverCode::DRIVER_CONFLICT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
KernelCallback *KCallback = (KernelCallback *)mem->RequestPages(TO_PAGES(sizeof(KernelCallback)));
|
|
||||||
|
|
||||||
DriverInterruptHook *InterruptHook = new DriverInterruptHook(((int)((PCI::PCIHeader0 *)PCIDevice)->InterruptLine) + 32, // x86
|
|
||||||
(void *)((uintptr_t)fexExtended->Driver.Callback + (uintptr_t)fex),
|
|
||||||
KCallback);
|
|
||||||
|
|
||||||
KCallback->RawPtr = PCIDevice;
|
|
||||||
KCallback->Reason = CallbackReason::ConfigurationReason;
|
|
||||||
int CallbackRet = ((int (*)(KernelCallback *))((uintptr_t)fexExtended->Driver.Callback + (uintptr_t)fex))(KCallback);
|
|
||||||
if (CallbackRet == DriverReturnCode::NOT_IMPLEMENTED)
|
|
||||||
{
|
|
||||||
error("Driver %s is not implemented", fexExtended->Driver.Name);
|
|
||||||
delete mem, mem = nullptr;
|
|
||||||
delete InterruptHook, InterruptHook = nullptr;
|
|
||||||
return DriverCode::NOT_IMPLEMENTED;
|
|
||||||
}
|
|
||||||
else if (CallbackRet == DriverReturnCode::OK)
|
|
||||||
trace("Device found for driver: %s", fexExtended->Driver.Name);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
error("Driver %s returned error %d", fexExtended->Driver.Name, CallbackRet);
|
|
||||||
delete mem, mem = nullptr;
|
|
||||||
delete InterruptHook, InterruptHook = nullptr;
|
|
||||||
return DriverCode::DRIVER_RETURNED_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(KCallback, 0, sizeof(KernelCallback));
|
|
||||||
KCallback->Reason = CallbackReason::InterruptReason;
|
|
||||||
|
|
||||||
DriverFile *DrvFile = new DriverFile;
|
|
||||||
DrvFile->Enabled = true;
|
|
||||||
DrvFile->DriverUID = this->DriverUIDs - 1;
|
|
||||||
DrvFile->Address = (void *)fex;
|
|
||||||
DrvFile->MemTrk = mem;
|
|
||||||
DrvFile->InterruptHook[0] = InterruptHook;
|
|
||||||
Drivers.push_back(DrvFile);
|
|
||||||
return DriverCode::OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
DriverCode Driver::BindPCIStorage(Memory::MemMgr *mem, void *fex, PCI::PCIDeviceHeader *PCIDevice)
|
|
||||||
{
|
|
||||||
FexExtended *fexExtended = (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
|
|
||||||
|
|
||||||
if (fexExtended->Driver.OverrideOnConflict)
|
|
||||||
{
|
|
||||||
Vector<int> DriversToRemove = Vector<int>();
|
|
||||||
foreach (auto Drv in Drivers)
|
|
||||||
{
|
|
||||||
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv->Address + EXTENDED_SECTION_ADDRESS));
|
|
||||||
|
|
||||||
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
|
|
||||||
if (fe->Driver.OverrideOnConflict)
|
|
||||||
return DriverCode::DRIVER_CONFLICT;
|
|
||||||
|
|
||||||
DriversToRemove.push_back(Drv->DriverUID);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (auto DrvID in DriversToRemove)
|
|
||||||
{
|
|
||||||
if (!this->UnloadDriver(DrvID))
|
|
||||||
{
|
|
||||||
error("Failed to unload conflicting driver %d", DrvID);
|
|
||||||
return DriverCode::DRIVER_CONFLICT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
foreach (auto Drv in Drivers)
|
|
||||||
{
|
|
||||||
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv->Address + EXTENDED_SECTION_ADDRESS));
|
|
||||||
|
|
||||||
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
|
|
||||||
if (fe->Driver.OverrideOnConflict)
|
|
||||||
return DriverCode::DRIVER_CONFLICT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
KernelCallback *KCallback = (KernelCallback *)mem->RequestPages(TO_PAGES(sizeof(KernelCallback)));
|
|
||||||
|
|
||||||
KCallback->RawPtr = PCIDevice;
|
|
||||||
KCallback->Reason = CallbackReason::ConfigurationReason;
|
|
||||||
int CallbackRet = ((int (*)(KernelCallback *))((uintptr_t)fexExtended->Driver.Callback + (uintptr_t)fex))(KCallback);
|
|
||||||
if (CallbackRet == DriverReturnCode::NOT_IMPLEMENTED)
|
|
||||||
{
|
|
||||||
error("Driver %s is not implemented", fexExtended->Driver.Name);
|
|
||||||
delete mem, mem = nullptr;
|
|
||||||
return DriverCode::NOT_IMPLEMENTED;
|
|
||||||
}
|
|
||||||
else if (CallbackRet == DriverReturnCode::OK)
|
|
||||||
trace("Device found for driver: %s", fexExtended->Driver.Name);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
error("Driver %s returned error %d", fexExtended->Driver.Name, CallbackRet);
|
|
||||||
delete mem, mem = nullptr;
|
|
||||||
return DriverCode::DRIVER_RETURNED_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
DriverFile *DrvFile = new DriverFile;
|
|
||||||
DrvFile->Enabled = true;
|
|
||||||
DrvFile->DriverUID = this->DriverUIDs - 1;
|
|
||||||
DrvFile->Address = (void *)fex;
|
|
||||||
DrvFile->MemTrk = mem;
|
|
||||||
DrvFile->InterruptHook[0] = nullptr;
|
|
||||||
Drivers.push_back(DrvFile);
|
|
||||||
return DriverCode::OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
DriverCode Driver::BindPCIFileSystem(Memory::MemMgr *mem, void *fex, PCI::PCIDeviceHeader *PCIDevice)
|
|
||||||
{
|
|
||||||
FexExtended *fexExtended = (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
|
|
||||||
|
|
||||||
if (fexExtended->Driver.OverrideOnConflict)
|
|
||||||
{
|
|
||||||
Vector<int> DriversToRemove = Vector<int>();
|
|
||||||
foreach (auto Drv in Drivers)
|
|
||||||
{
|
|
||||||
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv->Address + EXTENDED_SECTION_ADDRESS));
|
|
||||||
|
|
||||||
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
|
|
||||||
if (fe->Driver.OverrideOnConflict)
|
|
||||||
return DriverCode::DRIVER_CONFLICT;
|
|
||||||
|
|
||||||
DriversToRemove.push_back(Drv->DriverUID);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (auto DrvID in DriversToRemove)
|
|
||||||
{
|
|
||||||
if (!this->UnloadDriver(DrvID))
|
|
||||||
{
|
|
||||||
error("Failed to unload conflicting driver %d", DrvID);
|
|
||||||
return DriverCode::DRIVER_CONFLICT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
foreach (auto Drv in Drivers)
|
|
||||||
{
|
|
||||||
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv->Address + EXTENDED_SECTION_ADDRESS));
|
|
||||||
|
|
||||||
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
|
|
||||||
if (fe->Driver.OverrideOnConflict)
|
|
||||||
return DriverCode::DRIVER_CONFLICT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fixme("Filesystem driver: %s", fexExtended->Driver.Name);
|
|
||||||
delete mem, mem = nullptr;
|
|
||||||
return DriverCode::NOT_IMPLEMENTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
DriverCode Driver::BindPCIInput(Memory::MemMgr *mem, void *fex, PCI::PCIDeviceHeader *PCIDevice)
|
|
||||||
{
|
|
||||||
FexExtended *fexExtended = (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
|
|
||||||
|
|
||||||
if (fexExtended->Driver.OverrideOnConflict)
|
|
||||||
{
|
|
||||||
Vector<int> DriversToRemove = Vector<int>();
|
|
||||||
foreach (auto Drv in Drivers)
|
|
||||||
{
|
|
||||||
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv->Address + EXTENDED_SECTION_ADDRESS));
|
|
||||||
|
|
||||||
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
|
|
||||||
if (fe->Driver.OverrideOnConflict)
|
|
||||||
return DriverCode::DRIVER_CONFLICT;
|
|
||||||
|
|
||||||
DriversToRemove.push_back(Drv->DriverUID);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (auto DrvID in DriversToRemove)
|
|
||||||
{
|
|
||||||
if (!this->UnloadDriver(DrvID))
|
|
||||||
{
|
|
||||||
error("Failed to unload conflicting driver %d", DrvID);
|
|
||||||
return DriverCode::DRIVER_CONFLICT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
foreach (auto Drv in Drivers)
|
|
||||||
{
|
|
||||||
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv->Address + EXTENDED_SECTION_ADDRESS));
|
|
||||||
|
|
||||||
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
|
|
||||||
if (fe->Driver.OverrideOnConflict)
|
|
||||||
return DriverCode::DRIVER_CONFLICT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fixme("Input driver: %s", fexExtended->Driver.Name);
|
|
||||||
delete mem, mem = nullptr;
|
|
||||||
return DriverCode::NOT_IMPLEMENTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
DriverCode Driver::BindPCIAudio(Memory::MemMgr *mem, void *fex, PCI::PCIDeviceHeader *PCIDevice)
|
|
||||||
{
|
|
||||||
FexExtended *fexExtended = (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
|
|
||||||
|
|
||||||
if (fexExtended->Driver.OverrideOnConflict)
|
|
||||||
{
|
|
||||||
Vector<int> DriversToRemove = Vector<int>();
|
|
||||||
foreach (auto Drv in Drivers)
|
|
||||||
{
|
|
||||||
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv->Address + EXTENDED_SECTION_ADDRESS));
|
|
||||||
|
|
||||||
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
|
|
||||||
if (fe->Driver.OverrideOnConflict)
|
|
||||||
return DriverCode::DRIVER_CONFLICT;
|
|
||||||
|
|
||||||
DriversToRemove.push_back(Drv->DriverUID);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (auto DrvID in DriversToRemove)
|
|
||||||
{
|
|
||||||
if (!this->UnloadDriver(DrvID))
|
|
||||||
{
|
|
||||||
error("Failed to unload conflicting driver %d", DrvID);
|
|
||||||
return DriverCode::DRIVER_CONFLICT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
foreach (auto Drv in Drivers)
|
|
||||||
{
|
|
||||||
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv->Address + EXTENDED_SECTION_ADDRESS));
|
|
||||||
|
|
||||||
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
|
|
||||||
if (fe->Driver.OverrideOnConflict)
|
|
||||||
return DriverCode::DRIVER_CONFLICT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
KernelCallback *KCallback = (KernelCallback *)mem->RequestPages(TO_PAGES(sizeof(KernelCallback)));
|
|
||||||
|
|
||||||
DriverInterruptHook *InterruptHook = new DriverInterruptHook(((int)((PCI::PCIHeader0 *)PCIDevice)->InterruptLine) + 32, // x86
|
|
||||||
(void *)((uintptr_t)fexExtended->Driver.Callback + (uintptr_t)fex),
|
|
||||||
KCallback);
|
|
||||||
|
|
||||||
KCallback->RawPtr = PCIDevice;
|
|
||||||
KCallback->Reason = CallbackReason::ConfigurationReason;
|
|
||||||
int CallbackRet = ((int (*)(KernelCallback *))((uintptr_t)fexExtended->Driver.Callback + (uintptr_t)fex))(KCallback);
|
|
||||||
if (CallbackRet == DriverReturnCode::NOT_IMPLEMENTED)
|
|
||||||
{
|
|
||||||
error("Driver %s is not implemented", fexExtended->Driver.Name);
|
|
||||||
delete mem, mem = nullptr;
|
|
||||||
return DriverCode::NOT_IMPLEMENTED;
|
|
||||||
}
|
|
||||||
else if (CallbackRet == DriverReturnCode::OK)
|
|
||||||
trace("Device found for driver: %s", fexExtended->Driver.Name);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
error("Driver %s returned error %d", fexExtended->Driver.Name, CallbackRet);
|
|
||||||
delete mem, mem = nullptr;
|
|
||||||
return DriverCode::DRIVER_RETURNED_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(KCallback, 0, sizeof(KernelCallback));
|
|
||||||
KCallback->Reason = CallbackReason::InterruptReason;
|
|
||||||
|
|
||||||
DriverFile *DrvFile = new DriverFile;
|
|
||||||
DrvFile->Enabled = true;
|
|
||||||
DrvFile->DriverUID = this->DriverUIDs - 1;
|
|
||||||
DrvFile->Address = (void *)fex;
|
|
||||||
DrvFile->MemTrk = mem;
|
|
||||||
DrvFile->InterruptHook[0] = InterruptHook;
|
|
||||||
Drivers.push_back(DrvFile);
|
|
||||||
return DriverCode::OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
DriverCode Driver::DriverLoadBindPCI(void *DrvExtHdr, uintptr_t DriverAddress, size_t Size, bool IsElf)
|
|
||||||
{
|
|
||||||
UNUSED(IsElf);
|
|
||||||
for (unsigned long Vidx = 0; Vidx < sizeof(((FexExtended *)DrvExtHdr)->Driver.Bind.PCI.VendorID) / sizeof(((FexExtended *)DrvExtHdr)->Driver.Bind.PCI.VendorID[0]); Vidx++)
|
|
||||||
{
|
|
||||||
for (unsigned long Didx = 0; Didx < sizeof(((FexExtended *)DrvExtHdr)->Driver.Bind.PCI.DeviceID) / sizeof(((FexExtended *)DrvExtHdr)->Driver.Bind.PCI.DeviceID[0]); Didx++)
|
|
||||||
{
|
|
||||||
if (Vidx >= sizeof(((FexExtended *)DrvExtHdr)->Driver.Bind.PCI.VendorID) && Didx >= sizeof(((FexExtended *)DrvExtHdr)->Driver.Bind.PCI.DeviceID))
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (((FexExtended *)DrvExtHdr)->Driver.Bind.PCI.VendorID[Vidx] == 0 || ((FexExtended *)DrvExtHdr)->Driver.Bind.PCI.DeviceID[Didx] == 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
Vector<PCI::PCIDeviceHeader *> devices = PCIManager->FindPCIDevice(((FexExtended *)DrvExtHdr)->Driver.Bind.PCI.VendorID[Vidx], ((FexExtended *)DrvExtHdr)->Driver.Bind.PCI.DeviceID[Didx]);
|
|
||||||
if (devices.size() == 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
foreach (auto PCIDevice in devices)
|
|
||||||
{
|
|
||||||
debug("[%ld] VendorID: %#x; DeviceID: %#x", devices.size(), PCIDevice->VendorID, PCIDevice->DeviceID);
|
|
||||||
Memory::MemMgr *mem = new Memory::MemMgr(nullptr, TaskManager->GetCurrentProcess()->memDirectory);
|
|
||||||
Fex *fex = (Fex *)mem->RequestPages(TO_PAGES(Size));
|
|
||||||
memcpy(fex, (void *)DriverAddress, Size);
|
|
||||||
FexExtended *fexExtended = (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
|
|
||||||
debug("Driver allocated at %#lx-%#lx", fex, (uintptr_t)fex + Size);
|
|
||||||
#ifdef DEBUG
|
|
||||||
uint8_t *result = md5File((uint8_t *)fex, Size);
|
|
||||||
debug("MD5: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
|
|
||||||
result[0], result[1], result[2], result[3], result[4], result[5], result[6], result[7],
|
|
||||||
result[8], result[9], result[10], result[11], result[12], result[13], result[14], result[15]);
|
|
||||||
kfree(result);
|
|
||||||
#endif
|
|
||||||
KernelAPI *KAPI = (KernelAPI *)mem->RequestPages(TO_PAGES(sizeof(KernelAPI)));
|
|
||||||
|
|
||||||
if (CallDriverEntryPoint(fex, KAPI) != DriverCode::OK)
|
|
||||||
{
|
|
||||||
delete mem, mem = nullptr;
|
|
||||||
return DriverCode::DRIVER_RETURNED_ERROR;
|
|
||||||
}
|
|
||||||
debug("Starting driver %s", fexExtended->Driver.Name);
|
|
||||||
|
|
||||||
MapPCIAddresses(PCIDevice);
|
|
||||||
|
|
||||||
switch (fexExtended->Driver.Type)
|
|
||||||
{
|
|
||||||
case FexDriverType::FexDriverType_Generic:
|
|
||||||
return BindPCIGeneric(mem, fex, PCIDevice);
|
|
||||||
case FexDriverType::FexDriverType_Display:
|
|
||||||
return BindPCIDisplay(mem, fex, PCIDevice);
|
|
||||||
case FexDriverType::FexDriverType_Network:
|
|
||||||
return BindPCINetwork(mem, fex, PCIDevice);
|
|
||||||
case FexDriverType::FexDriverType_Storage:
|
|
||||||
return BindPCIStorage(mem, fex, PCIDevice);
|
|
||||||
case FexDriverType::FexDriverType_FileSystem:
|
|
||||||
return BindPCIFileSystem(mem, fex, PCIDevice);
|
|
||||||
case FexDriverType::FexDriverType_Input:
|
|
||||||
return BindPCIInput(mem, fex, PCIDevice);
|
|
||||||
case FexDriverType::FexDriverType_Audio:
|
|
||||||
return BindPCIAudio(mem, fex, PCIDevice);
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
warn("Unknown driver type: %d", fexExtended->Driver.Type);
|
|
||||||
delete mem, mem = nullptr;
|
|
||||||
return DriverCode::UNKNOWN_DRIVER_TYPE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return DriverCode::PCI_DEVICE_NOT_FOUND;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,60 +0,0 @@
|
|||||||
#include "../api.hpp"
|
|
||||||
|
|
||||||
#include <ints.hpp>
|
|
||||||
#include <memory.hpp>
|
|
||||||
#include <task.hpp>
|
|
||||||
#include <lock.hpp>
|
|
||||||
#include <printf.h>
|
|
||||||
#include <cwalk.h>
|
|
||||||
#include <md5.h>
|
|
||||||
|
|
||||||
#include "../../../kernel.h"
|
|
||||||
#include "../../../DAPI.hpp"
|
|
||||||
#include "../../../Fex.hpp"
|
|
||||||
|
|
||||||
namespace Driver
|
|
||||||
{
|
|
||||||
DriverCode Driver::BindProcessGeneric(Memory::MemMgr *mem, void *fex)
|
|
||||||
{
|
|
||||||
return DriverCode::NOT_IMPLEMENTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
DriverCode Driver::BindProcessDisplay(Memory::MemMgr *mem, void *fex)
|
|
||||||
{
|
|
||||||
return DriverCode::NOT_IMPLEMENTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
DriverCode Driver::BindProcessNetwork(Memory::MemMgr *mem, void *fex)
|
|
||||||
{
|
|
||||||
return DriverCode::NOT_IMPLEMENTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
DriverCode Driver::BindProcessStorage(Memory::MemMgr *mem, void *fex)
|
|
||||||
{
|
|
||||||
return DriverCode::NOT_IMPLEMENTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
DriverCode Driver::BindProcessFileSystem(Memory::MemMgr *mem, void *fex)
|
|
||||||
{
|
|
||||||
return DriverCode::NOT_IMPLEMENTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
DriverCode Driver::BindProcessInput(Memory::MemMgr *mem, void *fex)
|
|
||||||
{
|
|
||||||
return DriverCode::NOT_IMPLEMENTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
DriverCode Driver::BindProcessAudio(Memory::MemMgr *mem, void *fex)
|
|
||||||
{
|
|
||||||
return DriverCode::NOT_IMPLEMENTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
DriverCode Driver::DriverLoadBindProcess(void *DrvExtHdr, uintptr_t DriverAddress, size_t Size, bool IsElf)
|
|
||||||
{
|
|
||||||
fixme("Process driver: %s", ((FexExtended *)DrvExtHdr)->Driver.Name);
|
|
||||||
UNUSED(Size);
|
|
||||||
UNUSED(DriverAddress);
|
|
||||||
UNUSED(IsElf);
|
|
||||||
return DriverCode::NOT_IMPLEMENTED;
|
|
||||||
}
|
|
||||||
}
|
|
@ -5,6 +5,6 @@
|
|||||||
|
|
||||||
#include "../../DAPI.hpp"
|
#include "../../DAPI.hpp"
|
||||||
|
|
||||||
extern KernelAPI KernelAPITemplate;
|
extern KernelAPI KAPI;
|
||||||
|
|
||||||
#endif // !__FENNIX_KERNEL_DRIVER_API_H__
|
#endif // !__FENNIX_KERNEL_DRIVER_API_H__
|
||||||
|
@ -1,47 +1,46 @@
|
|||||||
#include <ints.hpp>
|
#include <interrupts.hpp>
|
||||||
|
|
||||||
#include <syscalls.hpp>
|
#include <syscalls.hpp>
|
||||||
#include <vector.hpp>
|
#include <hashmap.hpp>
|
||||||
#include <smp.hpp>
|
#include <smp.hpp>
|
||||||
#include <io.h>
|
#include <io.h>
|
||||||
|
|
||||||
#if defined(a64)
|
#if defined(__amd64__)
|
||||||
#include "../Architecture/amd64/cpu/gdt.hpp"
|
#include "../Architecture/amd64/cpu/gdt.hpp"
|
||||||
#include "../Architecture/amd64/cpu/idt.hpp"
|
#include "../Architecture/amd64/cpu/idt.hpp"
|
||||||
#include "../Architecture/amd64/acpi.hpp"
|
#include "../Architecture/amd64/acpi.hpp"
|
||||||
#include "../Architecture/amd64/cpu/apic.hpp"
|
#include "../Architecture/amd64/cpu/apic.hpp"
|
||||||
#elif defined(a32)
|
#elif defined(__i386__)
|
||||||
#include "../Architecture/i686/cpu/gdt.hpp"
|
#include "../Architecture/i686/cpu/gdt.hpp"
|
||||||
#include "../Architecture/i686/cpu/idt.hpp"
|
#include "../Architecture/i686/cpu/idt.hpp"
|
||||||
#elif defined(aa64)
|
#elif defined(__aarch64__)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "crashhandler.hpp"
|
#include "../crashhandler.hpp"
|
||||||
#include "../kernel.h"
|
#include "../kernel.h"
|
||||||
|
|
||||||
extern "C" SafeFunction void ExceptionHandler(void *Data) { CrashHandler::Handle(Data); }
|
extern "C" SafeFunction void ExceptionHandler(void *Data) { CrashHandler::Handle(Data); }
|
||||||
|
|
||||||
namespace Interrupts
|
namespace Interrupts
|
||||||
{
|
{
|
||||||
struct Event
|
HashMap<int, uint64_t> *RegisteredEvents;
|
||||||
{
|
|
||||||
int ID;
|
|
||||||
void *Data;
|
|
||||||
};
|
|
||||||
Vector<Event> RegisteredEvents;
|
|
||||||
|
|
||||||
#if defined(a64)
|
#if defined(__amd64__)
|
||||||
/* APIC::APIC */ void *apic[MAX_CPU];
|
/* APIC::APIC */ void *apic[MAX_CPU];
|
||||||
/* APIC::Timer */ void *apicTimer[MAX_CPU];
|
/* APIC::Timer */ void *apicTimer[MAX_CPU];
|
||||||
#elif defined(a32)
|
#elif defined(__i386__)
|
||||||
/* APIC::APIC */ void *apic[MAX_CPU];
|
/* APIC::APIC */ void *apic[MAX_CPU];
|
||||||
#elif defined(aa64)
|
#elif defined(__aarch64__)
|
||||||
#endif
|
#endif
|
||||||
void *InterruptFrames[INT_FRAMES_MAX];
|
void *InterruptFrames[INT_FRAMES_MAX];
|
||||||
|
|
||||||
void Initialize(int Core)
|
void Initialize(int Core)
|
||||||
{
|
{
|
||||||
#if defined(a64)
|
static int once = 0;
|
||||||
|
if (!once++)
|
||||||
|
RegisteredEvents = new HashMap<int, uint64_t>;
|
||||||
|
|
||||||
|
#if defined(__amd64__)
|
||||||
GlobalDescriptorTable::Init(Core);
|
GlobalDescriptorTable::Init(Core);
|
||||||
InterruptDescriptorTable::Init(Core);
|
InterruptDescriptorTable::Init(Core);
|
||||||
CPUData *CoreData = GetCPU(Core);
|
CPUData *CoreData = GetCPU(Core);
|
||||||
@ -50,8 +49,8 @@ namespace Interrupts
|
|||||||
CPU::x64::wrmsr(CPU::x64::MSR_SHADOW_GS_BASE, (uint64_t)CoreData);
|
CPU::x64::wrmsr(CPU::x64::MSR_SHADOW_GS_BASE, (uint64_t)CoreData);
|
||||||
CoreData->ID = Core;
|
CoreData->ID = Core;
|
||||||
CoreData->IsActive = true;
|
CoreData->IsActive = true;
|
||||||
CoreData->SystemCallStack = (uint8_t *)((uintptr_t)KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE)) + STACK_SIZE);
|
CoreData->SystemCallStack = (uint8_t *)((uint64_t)KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE)) + STACK_SIZE);
|
||||||
CoreData->Stack = (uintptr_t)KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE)) + STACK_SIZE;
|
CoreData->Stack = (uint64_t)KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE)) + STACK_SIZE;
|
||||||
if (CoreData->Checksum != CPU_DATA_CHECKSUM)
|
if (CoreData->Checksum != CPU_DATA_CHECKSUM)
|
||||||
{
|
{
|
||||||
KPrint("CPU %d checksum mismatch! %x != %x", Core, CoreData->Checksum, CPU_DATA_CHECKSUM);
|
KPrint("CPU %d checksum mismatch! %x != %x", Core, CoreData->Checksum, CPU_DATA_CHECKSUM);
|
||||||
@ -60,21 +59,20 @@ namespace Interrupts
|
|||||||
debug("Stack for core %d is %#lx (Address: %#lx)", Core, CoreData->Stack, CoreData->Stack - STACK_SIZE);
|
debug("Stack for core %d is %#lx (Address: %#lx)", Core, CoreData->Stack, CoreData->Stack - STACK_SIZE);
|
||||||
asmv("movq %0, %%rsp" ::"r"(CoreData->Stack));
|
asmv("movq %0, %%rsp" ::"r"(CoreData->Stack));
|
||||||
InitializeSystemCalls();
|
InitializeSystemCalls();
|
||||||
#elif defined(a32)
|
#elif defined(__i386__)
|
||||||
warn("i386 is not supported yet");
|
warn("i386 is not supported yet");
|
||||||
#elif defined(aa64)
|
#elif defined(__aarch64__)
|
||||||
warn("aarch64 is not supported yet");
|
warn("aarch64 is not supported yet");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void Enable(int Core)
|
void Enable(int Core)
|
||||||
{
|
{
|
||||||
#if defined(a64)
|
#if defined(__amd64__)
|
||||||
if (((ACPI::MADT *)PowerManager->GetMADT())->LAPICAddress != nullptr)
|
if (((ACPI::MADT *)PowerManager->GetMADT())->LAPICAddress != nullptr)
|
||||||
{
|
{
|
||||||
// TODO: This function is called by SMP too. Do not initialize timers that doesn't support multiple cores.
|
// TODO: This function is called by SMP too. Do not initialize timers that doesn't support multiple cores.
|
||||||
apic[Core] = new APIC::APIC(Core);
|
apic[Core] = new APIC::APIC(Core);
|
||||||
if (Core == Config.IOAPICInterruptCore) // Redirect IRQs to the specified core.
|
|
||||||
((APIC::APIC *)apic[Core])->RedirectIRQs(Core);
|
((APIC::APIC *)apic[Core])->RedirectIRQs(Core);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -82,9 +80,9 @@ namespace Interrupts
|
|||||||
error("LAPIC not found");
|
error("LAPIC not found");
|
||||||
// TODO: PIC
|
// TODO: PIC
|
||||||
}
|
}
|
||||||
#elif defined(a32)
|
#elif defined(__i386__)
|
||||||
warn("i386 is not supported yet");
|
warn("i386 is not supported yet");
|
||||||
#elif defined(aa64)
|
#elif defined(__aarch64__)
|
||||||
warn("aarch64 is not supported yet");
|
warn("aarch64 is not supported yet");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@ -92,28 +90,29 @@ namespace Interrupts
|
|||||||
void InitializeTimer(int Core)
|
void InitializeTimer(int Core)
|
||||||
{
|
{
|
||||||
// TODO: This function is called by SMP too. Do not initialize timers that doesn't support multiple cores.
|
// TODO: This function is called by SMP too. Do not initialize timers that doesn't support multiple cores.
|
||||||
#if defined(a64)
|
#if defined(__amd64__)
|
||||||
if (apic[Core] != nullptr)
|
if (apic[Core] != nullptr)
|
||||||
apicTimer[Core] = new APIC::Timer((APIC::APIC *)apic[Core]);
|
apicTimer[Core] = new APIC::Timer((APIC::APIC *)apic[Core]);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fixme("apic not found");
|
fixme("apic not found");
|
||||||
}
|
}
|
||||||
#elif defined(a32)
|
#elif defined(__i386__)
|
||||||
warn("i386 is not supported yet");
|
warn("i386 is not supported yet");
|
||||||
#elif defined(aa64)
|
#elif defined(__aarch64__)
|
||||||
warn("aarch64 is not supported yet");
|
warn("aarch64 is not supported yet");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
SafeFunction void RemoveAll()
|
void RemoveAll()
|
||||||
{
|
{
|
||||||
RegisteredEvents.clear();
|
for (int i = 0; i < CPU::x64::IRQ223; i++)
|
||||||
|
RegisteredEvents->DeleteNode(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" SafeFunction void MainInterruptHandler(void *Data)
|
extern "C" SafeFunction void MainInterruptHandler(void *Data)
|
||||||
{
|
{
|
||||||
#if defined(a64)
|
#if defined(__amd64__)
|
||||||
CPU::x64::TrapFrame *Frame = (CPU::x64::TrapFrame *)Data;
|
CPU::x64::TrapFrame *Frame = (CPU::x64::TrapFrame *)Data;
|
||||||
|
|
||||||
memmove(InterruptFrames + 1, InterruptFrames, sizeof(InterruptFrames) - sizeof(InterruptFrames[0]));
|
memmove(InterruptFrames + 1, InterruptFrames, sizeof(InterruptFrames) - sizeof(InterruptFrames[0]));
|
||||||
@ -124,32 +123,14 @@ namespace Interrupts
|
|||||||
if (likely(CoreData != nullptr))
|
if (likely(CoreData != nullptr))
|
||||||
Core = CoreData->ID;
|
Core = CoreData->ID;
|
||||||
|
|
||||||
/* If this is false, we have a big problem. */
|
// If this is false, we have a big problem.
|
||||||
if (likely(Frame->InterruptNumber < CPU::x86::IRQ223 && Frame->InterruptNumber > CPU::x86::ISR0))
|
if (likely(Frame->InterruptNumber < CPU::x64::IRQ223 && Frame->InterruptNumber > CPU::x64::ISR0))
|
||||||
{
|
{
|
||||||
/* Halt core interrupt */
|
Handler *handler = (Handler *)RegisteredEvents->Get(Frame->InterruptNumber);
|
||||||
if (unlikely(Frame->InterruptNumber == CPU::x86::IRQ29))
|
if (likely(handler != (Handler *)0xdeadbeef))
|
||||||
CPU::Stop();
|
handler->OnInterruptReceived(Frame);
|
||||||
|
else
|
||||||
bool InterruptHandled = false;
|
error("Unhandled IRQ%ld on CPU %d.", Frame->InterruptNumber - 32, Core);
|
||||||
foreach (auto ev in RegisteredEvents)
|
|
||||||
{
|
|
||||||
if (ev.ID == static_cast<int>(Frame->InterruptNumber))
|
|
||||||
{
|
|
||||||
((Handler *)ev.Data)->OnInterruptReceived(Frame);
|
|
||||||
InterruptHandled = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!InterruptHandled)
|
|
||||||
{
|
|
||||||
error("IRQ%ld is unhandled on CPU %d.", Frame->InterruptNumber - 32, Core);
|
|
||||||
if (Frame->InterruptNumber == CPU::x86::IRQ1)
|
|
||||||
{
|
|
||||||
uint8_t scancode = inb(0x60);
|
|
||||||
warn("IRQ1 is the keyboard interrupt. Scancode: %#x", scancode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (likely(apic[Core]))
|
if (likely(apic[Core]))
|
||||||
{
|
{
|
||||||
@ -159,9 +140,9 @@ namespace Interrupts
|
|||||||
}
|
}
|
||||||
// TODO: PIC
|
// TODO: PIC
|
||||||
}
|
}
|
||||||
#elif defined(a32)
|
#elif defined(__i386__)
|
||||||
void *Frame = Data;
|
void *Frame = Data;
|
||||||
#elif defined(aa64)
|
#elif defined(__aarch64__)
|
||||||
void *Frame = Data;
|
void *Frame = Data;
|
||||||
#endif
|
#endif
|
||||||
error("HALT HALT HALT HALT HALT HALT HALT HALT HALT");
|
error("HALT HALT HALT HALT HALT HALT HALT HALT HALT");
|
||||||
@ -170,42 +151,33 @@ namespace Interrupts
|
|||||||
|
|
||||||
Handler::Handler(int InterruptNumber)
|
Handler::Handler(int InterruptNumber)
|
||||||
{
|
{
|
||||||
foreach (auto ev in RegisteredEvents)
|
if (RegisteredEvents->Get(InterruptNumber) != (uint64_t)0xdeadbeef)
|
||||||
{
|
|
||||||
if (ev.ID == InterruptNumber)
|
|
||||||
{
|
{
|
||||||
warn("IRQ%d is already registered.", InterruptNumber - 32);
|
warn("IRQ%d is already registered.", InterruptNumber - 32);
|
||||||
}
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
debug("Registering interrupt handler for IRQ%d.", InterruptNumber - 32);
|
debug("Registering interrupt handler for IRQ%d.", InterruptNumber - 32);
|
||||||
this->InterruptNumber = InterruptNumber;
|
this->InterruptNumber = InterruptNumber;
|
||||||
RegisteredEvents.push_back({InterruptNumber, this});
|
RegisteredEvents->AddNode(InterruptNumber, (uint64_t)this);
|
||||||
}
|
}
|
||||||
|
|
||||||
Handler::~Handler()
|
Handler::~Handler()
|
||||||
{
|
{
|
||||||
debug("Unregistering interrupt handler for IRQ%d.", InterruptNumber - 32);
|
debug("Unregistering interrupt handler for IRQ%d.", InterruptNumber - 32);
|
||||||
for (size_t i = 0; i < RegisteredEvents.size(); i++)
|
if (RegisteredEvents->DeleteNode(InterruptNumber) == 0xdeadbeef)
|
||||||
{
|
warn("Node %d not found.", InterruptNumber);
|
||||||
if (RegisteredEvents[i].ID == InterruptNumber)
|
|
||||||
{
|
|
||||||
RegisteredEvents.remove(i);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
warn("Event %d not found.", InterruptNumber);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(a64)
|
#if defined(__amd64__)
|
||||||
void Handler::OnInterruptReceived(CPU::x64::TrapFrame *Frame)
|
void Handler::OnInterruptReceived(CPU::x64::TrapFrame *Frame)
|
||||||
{
|
{
|
||||||
trace("Unhandled interrupt IRQ%d", Frame->InterruptNumber - 32);
|
trace("Unhandled interrupt IRQ%d", Frame->InterruptNumber - 32);
|
||||||
#elif defined(a32)
|
#elif defined(__i386__)
|
||||||
void Handler::OnInterruptReceived(CPU::x32::TrapFrame *Frame)
|
void Handler::OnInterruptReceived(void *Frame)
|
||||||
{
|
{
|
||||||
trace("Unhandled interrupt received");
|
trace("Unhandled interrupt received");
|
||||||
#elif defined(aa64)
|
#elif defined(__aarch64__)
|
||||||
void Handler::OnInterruptReceived(void *Frame)
|
void Handler::OnInterruptReceived(void *Frame)
|
||||||
{
|
{
|
||||||
trace("Unhandled interrupt received");
|
trace("Unhandled interrupt received");
|
@ -5,39 +5,26 @@
|
|||||||
|
|
||||||
#include "../kernel.h"
|
#include "../kernel.h"
|
||||||
|
|
||||||
bool ForceUnlock = false;
|
|
||||||
Atomic<size_t> LocksCount = 0;
|
|
||||||
|
|
||||||
size_t GetLocksCount() { return LocksCount; }
|
|
||||||
|
|
||||||
void LockClass::DeadLock(SpinLockData Lock)
|
void LockClass::DeadLock(SpinLockData Lock)
|
||||||
{
|
{
|
||||||
if (ForceUnlock)
|
|
||||||
{
|
|
||||||
warn("Unlocking lock '%s' which it was held by '%s'...", Lock.AttemptingToGet, Lock.CurrentHolder);
|
|
||||||
this->DeadLocks = 0;
|
|
||||||
this->Unlock();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
CPUData *CoreData = GetCurrentCPU();
|
CPUData *CoreData = GetCurrentCPU();
|
||||||
long CCore = 0xdead;
|
long CCore = 0xdead;
|
||||||
if (CoreData != nullptr)
|
if (CoreData != nullptr)
|
||||||
CCore = CoreData->ID;
|
CCore = CoreData->ID;
|
||||||
|
warn("Potential deadlock in lock '%s' held by '%s'! %ld locks in queue. Core %ld is being held by %ld. (%ld times happened)",
|
||||||
warn("Potential deadlock in lock '%s' held by '%s'! %ld %s in queue. Interrupts are %s. Core %ld is being held by %ld. (%ld times happened)",
|
|
||||||
Lock.AttemptingToGet, Lock.CurrentHolder,
|
Lock.AttemptingToGet, Lock.CurrentHolder,
|
||||||
Lock.Count, Lock.Count > 1 ? "locks" : "lock",
|
Lock.Count, CCore, Lock.Core,
|
||||||
CPU::Interrupts(CPU::Check) ? "enabled" : "disabled",
|
this->DeadLocks);
|
||||||
CCore, Lock.Core, this->DeadLocks);
|
|
||||||
|
|
||||||
// TODO: Print on screen too.
|
// TODO: Print on screen too.
|
||||||
|
|
||||||
this->DeadLocks++;
|
this->DeadLocks++;
|
||||||
|
|
||||||
if (Config.UnlockDeadLock && this->DeadLocks.Load() > 10)
|
if (Config.UnlockDeadLock && this->DeadLocks > 10)
|
||||||
{
|
{
|
||||||
warn("Unlocking lock '%s' to prevent deadlock. (this is enabled in the kernel config)", Lock.AttemptingToGet);
|
warn("Unlocking lock '%s' held by '%s'! %ld locks in queue. Core %ld is being held by %ld.",
|
||||||
|
Lock.AttemptingToGet, Lock.CurrentHolder,
|
||||||
|
Lock.Count, CCore, Lock.Core);
|
||||||
this->DeadLocks = 0;
|
this->DeadLocks = 0;
|
||||||
this->Unlock();
|
this->Unlock();
|
||||||
}
|
}
|
||||||
@ -48,91 +35,53 @@ void LockClass::DeadLock(SpinLockData Lock)
|
|||||||
|
|
||||||
int LockClass::Lock(const char *FunctionName)
|
int LockClass::Lock(const char *FunctionName)
|
||||||
{
|
{
|
||||||
|
// LockData.AttemptingToGet = FunctionName;
|
||||||
|
// SpinLock_Lock(&LockData.LockData);
|
||||||
|
// LockData.Count++;
|
||||||
|
// LockData.CurrentHolder = FunctionName;
|
||||||
|
// CPUData *CoreData = GetCurrentCPU();
|
||||||
|
// if (CoreData != nullptr)
|
||||||
|
// LockData.Core = CoreData->ID;
|
||||||
|
// __sync_synchronize();
|
||||||
|
|
||||||
|
// while (!__sync_bool_compare_and_swap(&IsLocked, false, true))
|
||||||
|
// CPU::Pause();
|
||||||
|
// __sync_synchronize();
|
||||||
|
|
||||||
LockData.AttemptingToGet = FunctionName;
|
LockData.AttemptingToGet = FunctionName;
|
||||||
LockData.StackPointerAttempt = (uintptr_t)__builtin_frame_address(0);
|
|
||||||
Retry:
|
Retry:
|
||||||
unsigned int i = 0;
|
unsigned int i = 0;
|
||||||
while (IsLocked.Exchange(true, MemoryOrder::Acquire) && ++i < (DebuggerIsAttached ? 0x100000 : 0x10000000))
|
while (__atomic_exchange_n(&IsLocked, true, __ATOMIC_ACQUIRE) && ++i < 0x10000000)
|
||||||
CPU::Pause();
|
CPU::Pause();
|
||||||
if (i >= (DebuggerIsAttached ? 0x100000 : 0x10000000))
|
if (i >= 0x10000000)
|
||||||
{
|
{
|
||||||
DeadLock(LockData);
|
DeadLock(LockData);
|
||||||
goto Retry;
|
goto Retry;
|
||||||
}
|
}
|
||||||
LockData.Count++;
|
LockData.Count++;
|
||||||
LockData.CurrentHolder = FunctionName;
|
LockData.CurrentHolder = FunctionName;
|
||||||
LockData.StackPointerHolder = (uintptr_t)__builtin_frame_address(0);
|
|
||||||
CPUData *CoreData = GetCurrentCPU();
|
CPUData *CoreData = GetCurrentCPU();
|
||||||
if (CoreData != nullptr)
|
if (CoreData != nullptr)
|
||||||
LockData.Core = CoreData->ID;
|
LockData.Core = CoreData->ID;
|
||||||
LocksCount++;
|
__sync_synchronize();
|
||||||
__sync;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int LockClass::Unlock()
|
int LockClass::Unlock()
|
||||||
{
|
{
|
||||||
__sync;
|
// SpinLock_Unlock(&LockData.LockData);
|
||||||
IsLocked.Store(false, MemoryOrder::Release);
|
// LockData.Count--;
|
||||||
|
// __sync_synchronize();
|
||||||
|
|
||||||
|
// __sync_synchronize();
|
||||||
|
// __atomic_store_n(&IsLocked, false, __ATOMIC_SEQ_CST);
|
||||||
|
// IsLocked = false;
|
||||||
|
|
||||||
|
__sync_synchronize();
|
||||||
|
__atomic_store_n(&IsLocked, false, __ATOMIC_RELEASE);
|
||||||
LockData.Count--;
|
LockData.Count--;
|
||||||
IsLocked = false;
|
IsLocked = false;
|
||||||
LocksCount--;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void LockClass::TimeoutDeadLock(SpinLockData Lock, uint64_t Timeout)
|
|
||||||
{
|
|
||||||
CPUData *CoreData = GetCurrentCPU();
|
|
||||||
long CCore = 0xdead;
|
|
||||||
if (CoreData != nullptr)
|
|
||||||
CCore = CoreData->ID;
|
|
||||||
|
|
||||||
uint64_t Counter = TimeManager->GetCounter();
|
|
||||||
|
|
||||||
warn("Potential deadlock in lock '%s' held by '%s'! %ld %s in queue. Interrupts are %s. Core %ld is being held by %ld. Timeout in %ld (%ld ticks remaining).",
|
|
||||||
Lock.AttemptingToGet, Lock.CurrentHolder,
|
|
||||||
Lock.Count, Lock.Count > 1 ? "locks" : "lock",
|
|
||||||
CPU::Interrupts(CPU::Check) ? "enabled" : "disabled",
|
|
||||||
CCore, Lock.Core, Timeout, Timeout - Counter);
|
|
||||||
|
|
||||||
if (Timeout < Counter)
|
|
||||||
{
|
|
||||||
warn("Unlocking lock '%s' because of timeout. (%ld < %ld)", Lock.AttemptingToGet, Timeout, Counter);
|
|
||||||
this->Unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (TaskManager)
|
|
||||||
TaskManager->Schedule();
|
|
||||||
}
|
|
||||||
|
|
||||||
int LockClass::TimeoutLock(const char *FunctionName, uint64_t Timeout)
|
|
||||||
{
|
|
||||||
if (!TimeManager)
|
|
||||||
return Lock(FunctionName);
|
|
||||||
LockData.AttemptingToGet = FunctionName;
|
|
||||||
LockData.StackPointerAttempt = (uintptr_t)__builtin_frame_address(0);
|
|
||||||
Atomic<uint64_t> Target = 0;
|
|
||||||
Retry:
|
|
||||||
unsigned int i = 0;
|
|
||||||
while (IsLocked.Exchange(true, MemoryOrder::Acquire) && ++i < (DebuggerIsAttached ? 0x100000 : 0x10000000))
|
|
||||||
CPU::Pause();
|
|
||||||
if (i >= (DebuggerIsAttached ? 0x100000 : 0x10000000))
|
|
||||||
{
|
|
||||||
if (Target.Load() == 0)
|
|
||||||
Target.Store(TimeManager->CalculateTarget(Timeout));
|
|
||||||
TimeoutDeadLock(LockData, Target.Load());
|
|
||||||
goto Retry;
|
|
||||||
}
|
|
||||||
LockData.Count++;
|
|
||||||
LockData.CurrentHolder = FunctionName;
|
|
||||||
LockData.StackPointerHolder = (uintptr_t)__builtin_frame_address(0);
|
|
||||||
CPUData *CoreData = GetCurrentCPU();
|
|
||||||
if (CoreData != nullptr)
|
|
||||||
LockData.Core = CoreData->ID;
|
|
||||||
LocksCount++;
|
|
||||||
__sync;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
285
Kernel/Core/Memory/HeapAllocators/Xalloc.cpp
Normal file
285
Kernel/Core/Memory/HeapAllocators/Xalloc.cpp
Normal file
@ -0,0 +1,285 @@
|
|||||||
|
#include "Xalloc.hpp"
|
||||||
|
|
||||||
|
namespace Xalloc
|
||||||
|
{
|
||||||
|
class XLockClass
|
||||||
|
{
|
||||||
|
struct SpinLockData
|
||||||
|
{
|
||||||
|
uint64_t LockData = 0x0;
|
||||||
|
const char *CurrentHolder = "(nul)";
|
||||||
|
const char *AttemptingToGet = "(nul)";
|
||||||
|
uint64_t Count = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
void DeadLock(SpinLockData Lock)
|
||||||
|
{
|
||||||
|
Xalloc_warn("Potential deadlock in lock '%s' held by '%s'! %ld locks in queue.", Lock.AttemptingToGet, Lock.CurrentHolder, Lock.Count);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
SpinLockData LockData;
|
||||||
|
bool IsLocked = false;
|
||||||
|
|
||||||
|
public:
|
||||||
|
int Lock(const char *FunctionName)
|
||||||
|
{
|
||||||
|
LockData.AttemptingToGet = FunctionName;
|
||||||
|
Retry:
|
||||||
|
unsigned int i = 0;
|
||||||
|
while (__atomic_exchange_n(&IsLocked, true, __ATOMIC_ACQUIRE) && ++i < 0x10000000)
|
||||||
|
;
|
||||||
|
if (i >= 0x10000000)
|
||||||
|
{
|
||||||
|
DeadLock(LockData);
|
||||||
|
goto Retry;
|
||||||
|
}
|
||||||
|
LockData.Count++;
|
||||||
|
LockData.CurrentHolder = FunctionName;
|
||||||
|
__sync_synchronize();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Unlock()
|
||||||
|
{
|
||||||
|
__sync_synchronize();
|
||||||
|
__atomic_store_n(&IsLocked, false, __ATOMIC_RELEASE);
|
||||||
|
LockData.Count--;
|
||||||
|
IsLocked = false;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class XSmartLock
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
XLockClass *LockPointer = nullptr;
|
||||||
|
|
||||||
|
public:
|
||||||
|
XSmartLock(XLockClass &Lock, const char *FunctionName)
|
||||||
|
{
|
||||||
|
this->LockPointer = &Lock;
|
||||||
|
this->LockPointer->Lock(FunctionName);
|
||||||
|
}
|
||||||
|
~XSmartLock() { this->LockPointer->Unlock(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
XLockClass XLock;
|
||||||
|
|
||||||
|
#define XSL XSmartLock CONCAT(lock##_, __COUNTER__)(XLock, __FUNCTION__)
|
||||||
|
|
||||||
|
class SmartSMAPClass
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
AllocatorV1 *allocator = nullptr;
|
||||||
|
|
||||||
|
public:
|
||||||
|
SmartSMAPClass(AllocatorV1 *allocator)
|
||||||
|
{
|
||||||
|
this->allocator = allocator;
|
||||||
|
this->allocator->Xstac();
|
||||||
|
}
|
||||||
|
~SmartSMAPClass() { this->allocator->Xclac(); }
|
||||||
|
};
|
||||||
|
#define SmartSMAP SmartSMAPClass XALLOC_CONCAT(SmartSMAP##_, __COUNTER__)(this)
|
||||||
|
|
||||||
|
AllocatorV1::AllocatorV1(void *Address, bool UserMode, bool SMAPEnabled)
|
||||||
|
{
|
||||||
|
SmartSMAP;
|
||||||
|
XSL;
|
||||||
|
void *Position = Address;
|
||||||
|
UserMapping = UserMode;
|
||||||
|
SMAPUsed = SMAPEnabled;
|
||||||
|
for (Xuint64_t i = 0; i < 0x20; i++)
|
||||||
|
{
|
||||||
|
void *Page = Xalloc_REQUEST_PAGE();
|
||||||
|
if (UserMapping)
|
||||||
|
Xalloc_MAP_MEMORY(Position, Page, Xalloc_MAP_MEMORY_READ_WRITE | Xalloc_MAP_MEMORY_USER);
|
||||||
|
else
|
||||||
|
Xalloc_MAP_MEMORY(Position, Page, Xalloc_MAP_MEMORY_READ_WRITE);
|
||||||
|
Xalloc_trace("Preallocate Heap Memory (%#llx-%#llx [%#llx])...", Position, (Xuint64_t)Position + Xalloc_PAGE_SIZE, Page);
|
||||||
|
Position = (void *)((Xuint64_t)Position + Xalloc_PAGE_SIZE);
|
||||||
|
}
|
||||||
|
Xuint64_t HeapLength = 16 * Xalloc_PAGE_SIZE;
|
||||||
|
this->HeapStart = Address;
|
||||||
|
this->HeapEnd = (void *)((Xuint64_t)this->HeapStart + HeapLength);
|
||||||
|
HeapSegment *StartSegment = (HeapSegment *)Address;
|
||||||
|
StartSegment->Length = HeapLength - sizeof(HeapSegment);
|
||||||
|
StartSegment->Next = nullptr;
|
||||||
|
StartSegment->Last = nullptr;
|
||||||
|
StartSegment->IsFree = true;
|
||||||
|
this->LastSegment = StartSegment;
|
||||||
|
}
|
||||||
|
|
||||||
|
AllocatorV1::~AllocatorV1()
|
||||||
|
{
|
||||||
|
SmartSMAP;
|
||||||
|
XSL;
|
||||||
|
Xalloc_trace("Destructor not implemented yet.");
|
||||||
|
}
|
||||||
|
|
||||||
|
void AllocatorV1::ExpandHeap(Xuint64_t Length)
|
||||||
|
{
|
||||||
|
if (Length % Xalloc_PAGE_SIZE)
|
||||||
|
{
|
||||||
|
Length -= Length % Xalloc_PAGE_SIZE;
|
||||||
|
Length += Xalloc_PAGE_SIZE;
|
||||||
|
}
|
||||||
|
Xuint64_t PageCount = Length / Xalloc_PAGE_SIZE;
|
||||||
|
HeapSegment *NewSegment = (HeapSegment *)this->HeapEnd;
|
||||||
|
for (Xuint64_t i = 0; i < PageCount; i++)
|
||||||
|
{
|
||||||
|
void *Page = Xalloc_REQUEST_PAGE();
|
||||||
|
if (UserMapping)
|
||||||
|
Xalloc_MAP_MEMORY(this->HeapEnd, Page, Xalloc_MAP_MEMORY_READ_WRITE | Xalloc_MAP_MEMORY_USER);
|
||||||
|
else
|
||||||
|
Xalloc_MAP_MEMORY(this->HeapEnd, Page, Xalloc_MAP_MEMORY_READ_WRITE);
|
||||||
|
// Xalloc_trace("Expanding Heap Memory (%#llx-%#llx [%#llx])...", this->HeapEnd, (Xuint64_t)this->HeapEnd + Xalloc_PAGE_SIZE, Page);
|
||||||
|
this->HeapEnd = (void *)((Xuint64_t)this->HeapEnd + Xalloc_PAGE_SIZE);
|
||||||
|
}
|
||||||
|
NewSegment->IsFree = true;
|
||||||
|
NewSegment->Last = this->LastSegment;
|
||||||
|
this->LastSegment->Next = NewSegment;
|
||||||
|
this->LastSegment = NewSegment;
|
||||||
|
NewSegment->Next = nullptr;
|
||||||
|
NewSegment->Length = Length - sizeof(HeapSegment);
|
||||||
|
NewSegment->CombineBackward(this->LastSegment);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *AllocatorV1::Malloc(Xuint64_t Size)
|
||||||
|
{
|
||||||
|
SmartSMAP;
|
||||||
|
XSL;
|
||||||
|
if (this->HeapStart == nullptr)
|
||||||
|
{
|
||||||
|
Xalloc_err("Memory allocation not initialized yet!");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Size < 0x10)
|
||||||
|
{
|
||||||
|
// Xalloc_warn("Allocation size is too small, using 0x10 instead!");
|
||||||
|
Size = 0x10;
|
||||||
|
}
|
||||||
|
|
||||||
|
// #ifdef DEBUG
|
||||||
|
// if (Size < 1024)
|
||||||
|
// debug("Allocating %dB", Size);
|
||||||
|
// else if (TO_KB(Size) < 1024)
|
||||||
|
// debug("Allocating %dKB", TO_KB(Size));
|
||||||
|
// else if (TO_MB(Size) < 1024)
|
||||||
|
// debug("Allocating %dMB", TO_MB(Size));
|
||||||
|
// else if (TO_GB(Size) < 1024)
|
||||||
|
// debug("Allocating %dGB", TO_GB(Size));
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
if (Size % 0x10 > 0) // it is not a multiple of 0x10
|
||||||
|
{
|
||||||
|
Size -= (Size % 0x10);
|
||||||
|
Size += 0x10;
|
||||||
|
}
|
||||||
|
if (Size == 0)
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
HeapSegment *CurrentSegment = (HeapSegment *)this->HeapStart;
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
if (CurrentSegment->IsFree)
|
||||||
|
{
|
||||||
|
if (CurrentSegment->Length > Size)
|
||||||
|
{
|
||||||
|
CurrentSegment->Split(Size, this->LastSegment);
|
||||||
|
CurrentSegment->IsFree = false;
|
||||||
|
return (void *)((Xuint64_t)CurrentSegment + sizeof(HeapSegment));
|
||||||
|
}
|
||||||
|
if (CurrentSegment->Length == Size)
|
||||||
|
{
|
||||||
|
CurrentSegment->IsFree = false;
|
||||||
|
return (void *)((Xuint64_t)CurrentSegment + sizeof(HeapSegment));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (CurrentSegment->Next == nullptr)
|
||||||
|
break;
|
||||||
|
CurrentSegment = CurrentSegment->Next;
|
||||||
|
}
|
||||||
|
ExpandHeap(Size);
|
||||||
|
XLock.Unlock();
|
||||||
|
return this->Malloc(Size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AllocatorV1::Free(void *Address)
|
||||||
|
{
|
||||||
|
SmartSMAP;
|
||||||
|
XSL;
|
||||||
|
if (this->HeapStart == nullptr)
|
||||||
|
{
|
||||||
|
Xalloc_err("Memory allocation not initialized yet!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
HeapSegment *Segment = (HeapSegment *)Address - 1;
|
||||||
|
Segment->IsFree = true;
|
||||||
|
Segment->CombineForward(this->LastSegment);
|
||||||
|
Segment->CombineBackward(this->LastSegment);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *AllocatorV1::Calloc(Xuint64_t NumberOfBlocks, Xuint64_t Size)
|
||||||
|
{
|
||||||
|
SmartSMAP;
|
||||||
|
XSL;
|
||||||
|
if (this->HeapStart == nullptr)
|
||||||
|
{
|
||||||
|
Xalloc_err("Memory allocation not initialized yet!");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Size < 0x10)
|
||||||
|
{
|
||||||
|
// Xalloc_warn("Allocation size is too small, using 0x10 instead!");
|
||||||
|
Size = 0x10;
|
||||||
|
}
|
||||||
|
|
||||||
|
XLock.Unlock();
|
||||||
|
void *Block = this->Malloc(NumberOfBlocks * Size);
|
||||||
|
XLock.Lock(__FUNCTION__);
|
||||||
|
|
||||||
|
if (Block)
|
||||||
|
Xmemset(Block, 0, NumberOfBlocks * Size);
|
||||||
|
return Block;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *AllocatorV1::Realloc(void *Address, Xuint64_t Size)
|
||||||
|
{
|
||||||
|
SmartSMAP;
|
||||||
|
XSL;
|
||||||
|
if (this->HeapStart == nullptr)
|
||||||
|
{
|
||||||
|
Xalloc_err("Memory allocation not initialized yet!");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (!Address && Size == 0)
|
||||||
|
{
|
||||||
|
XLock.Unlock();
|
||||||
|
this->Free(Address);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
else if (!Address)
|
||||||
|
{
|
||||||
|
XLock.Unlock();
|
||||||
|
return this->Calloc(Size, sizeof(char));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Size < 0x10)
|
||||||
|
{
|
||||||
|
// Xalloc_warn("Allocation size is too small, using 0x10 instead!");
|
||||||
|
Size = 0x10;
|
||||||
|
}
|
||||||
|
|
||||||
|
XLock.Unlock();
|
||||||
|
void *newAddress = this->Calloc(Size, sizeof(char));
|
||||||
|
XLock.Lock(__FUNCTION__);
|
||||||
|
Xmemcpy(newAddress, Address, Size);
|
||||||
|
return newAddress;
|
||||||
|
}
|
||||||
|
}
|
180
Kernel/Core/Memory/HeapAllocators/Xalloc.hpp
Normal file
180
Kernel/Core/Memory/HeapAllocators/Xalloc.hpp
Normal file
@ -0,0 +1,180 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <memory.hpp>
|
||||||
|
#include <debug.h>
|
||||||
|
|
||||||
|
// Functions defines
|
||||||
|
|
||||||
|
// Page allocation functions
|
||||||
|
#define Xalloc_REQUEST_PAGE() KernelAllocator.RequestPage()
|
||||||
|
#define Xalloc_REQUEST_PAGES(Pages) KernelAllocator.RequestPages(Pages)
|
||||||
|
#define Xalloc_FREE_PAGE(Address) KernelAllocator.FreePage(Address)
|
||||||
|
#define Xalloc_FREE_PAGES(Address, Pages) KernelAllocator.FreePages(Address, Pages)
|
||||||
|
|
||||||
|
#define Xalloc_MAP_MEMORY(VirtualAddress, PhysicalAddress, Flags) Memory::Virtual(KernelPageTable).Map(VirtualAddress, PhysicalAddress, Flags)
|
||||||
|
#define Xalloc_UNMAP_MEMORY(VirtualAddress) Memory::Virtual(KernelPageTable).Unmap(VirtualAddress)
|
||||||
|
#define Xalloc_MAP_MEMORY_READ_WRITE Memory::PTFlag::RW
|
||||||
|
#define Xalloc_MAP_MEMORY_USER Memory::PTFlag::US
|
||||||
|
|
||||||
|
#define Xalloc_PAGE_SIZE PAGE_SIZE
|
||||||
|
|
||||||
|
#define Xalloc_trace(m, ...) trace(m, ##__VA_ARGS__)
|
||||||
|
#define Xalloc_warn(m, ...) warn(m, ##__VA_ARGS__)
|
||||||
|
#define Xalloc_err(m, ...) error(m, ##__VA_ARGS__)
|
||||||
|
|
||||||
|
#define XALLOC_CONCAT(x, y) x##y
|
||||||
|
|
||||||
|
typedef long unsigned Xuint64_t;
|
||||||
|
|
||||||
|
namespace Xalloc
|
||||||
|
{
|
||||||
|
class AllocatorV1
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
struct HeapSegment
|
||||||
|
{
|
||||||
|
Xuint64_t Length;
|
||||||
|
HeapSegment *Next;
|
||||||
|
HeapSegment *Last;
|
||||||
|
bool IsFree;
|
||||||
|
|
||||||
|
HeapSegment *Split(Xuint64_t SplitLength, HeapSegment *LastSegment)
|
||||||
|
{
|
||||||
|
if (SplitLength < 0x10)
|
||||||
|
return nullptr;
|
||||||
|
int64_t SplitSegmentLength = Length - SplitLength - (sizeof(HeapSegment));
|
||||||
|
if (SplitSegmentLength < 0x10)
|
||||||
|
return nullptr;
|
||||||
|
HeapSegment *NewSplitHdr = (HeapSegment *)((Xuint64_t)this + SplitLength + sizeof(HeapSegment));
|
||||||
|
Next->Last = NewSplitHdr;
|
||||||
|
NewSplitHdr->Next = Next;
|
||||||
|
Next = NewSplitHdr;
|
||||||
|
NewSplitHdr->Last = this;
|
||||||
|
NewSplitHdr->Length = SplitSegmentLength;
|
||||||
|
NewSplitHdr->IsFree = IsFree;
|
||||||
|
Length = SplitLength;
|
||||||
|
if (LastSegment == this)
|
||||||
|
LastSegment = NewSplitHdr;
|
||||||
|
return NewSplitHdr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CombineForward(HeapSegment *LastSegment)
|
||||||
|
{
|
||||||
|
if (Next == nullptr)
|
||||||
|
return;
|
||||||
|
if (Next->IsFree == false)
|
||||||
|
return;
|
||||||
|
if (Next == LastSegment)
|
||||||
|
LastSegment = this;
|
||||||
|
if (Next->Next != nullptr)
|
||||||
|
Next->Next->Last = this;
|
||||||
|
|
||||||
|
Length = Length + Next->Length + sizeof(HeapSegment);
|
||||||
|
Next = Next->Next;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CombineBackward(HeapSegment *LastSegment)
|
||||||
|
{
|
||||||
|
if (Last != nullptr && Last->IsFree)
|
||||||
|
Last->CombineForward(LastSegment);
|
||||||
|
}
|
||||||
|
} __attribute__((aligned(16)));
|
||||||
|
|
||||||
|
void *HeapStart = nullptr;
|
||||||
|
void *HeapEnd = nullptr;
|
||||||
|
HeapSegment *LastSegment = nullptr;
|
||||||
|
bool UserMapping = false;
|
||||||
|
bool SMAPUsed = false;
|
||||||
|
|
||||||
|
void ExpandHeap(Xuint64_t Length);
|
||||||
|
|
||||||
|
// TODO: Change memcpy with an optimized version
|
||||||
|
static inline void *Xmemcpy(void *__restrict__ Destination, const void *__restrict__ Source, Xuint64_t Length)
|
||||||
|
{
|
||||||
|
unsigned char *dst = (unsigned char *)Destination;
|
||||||
|
const unsigned char *src = (const unsigned char *)Source;
|
||||||
|
for (Xuint64_t i = 0; i < Length; i++)
|
||||||
|
dst[i] = src[i];
|
||||||
|
return Destination;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Change memset with an optimized version
|
||||||
|
static inline void *Xmemset(void *__restrict__ Destination, int Data, Xuint64_t Length)
|
||||||
|
{
|
||||||
|
unsigned char *Buffer = (unsigned char *)Destination;
|
||||||
|
for (Xuint64_t i = 0; i < Length; i++)
|
||||||
|
Buffer[i] = (unsigned char)Data;
|
||||||
|
return Destination;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
inline void Xstac()
|
||||||
|
{
|
||||||
|
if (this->SMAPUsed)
|
||||||
|
{
|
||||||
|
#if defined(__amd64__) || defined(__i386__)
|
||||||
|
asm volatile("stac" ::
|
||||||
|
: "cc");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void Xclac()
|
||||||
|
{
|
||||||
|
if (this->SMAPUsed)
|
||||||
|
{
|
||||||
|
#if defined(__amd64__) || defined(__i386__)
|
||||||
|
asm volatile("clac" ::
|
||||||
|
: "cc");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Construct a new Allocator V1 object
|
||||||
|
*
|
||||||
|
* @param Address Virtual address to allocate.
|
||||||
|
* @param UserMode Map the new pages with USER flag?
|
||||||
|
* @param SMAPEnabled Does the kernel has Supervisor Mode Access Prevention enabled?
|
||||||
|
*/
|
||||||
|
AllocatorV1(void *Address, bool UserMode, bool SMAPEnabled);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Destroy the Allocator V 1 object
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
~AllocatorV1();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Allocate a new memory block
|
||||||
|
*
|
||||||
|
* @param Size Size of the block to allocate.
|
||||||
|
* @return void* Pointer to the allocated block.
|
||||||
|
*/
|
||||||
|
void *Malloc(Xuint64_t Size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Free a previously allocated block
|
||||||
|
*
|
||||||
|
* @param Address Address of the block to free.
|
||||||
|
*/
|
||||||
|
void Free(void *Address);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Allocate a new memory block
|
||||||
|
*
|
||||||
|
* @param NumberOfBlocks Number of blocks to allocate.
|
||||||
|
* @param Size Size of the block to allocate.
|
||||||
|
* @return void* Pointer to the allocated block.
|
||||||
|
*/
|
||||||
|
void *Calloc(Xuint64_t NumberOfBlocks, Xuint64_t Size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Reallocate a previously allocated block
|
||||||
|
*
|
||||||
|
* @param Address Address of the block to reallocate.
|
||||||
|
* @param Size New size of the block.
|
||||||
|
* @return void* Pointer to the reallocated block.
|
||||||
|
*/
|
||||||
|
void *Realloc(void *Address, Xuint64_t Size);
|
||||||
|
};
|
||||||
|
}
|
@ -1,137 +0,0 @@
|
|||||||
# Xalloc
|
|
||||||
|
|
||||||
Xalloc is a custom memory allocator designed for hobby operating systems. It is written in C++ and provides a simple and efficient way to manage memory in your hobby OS.
|
|
||||||
|
|
||||||
#### ❗ This project is still in development and is not ready for use in production environments. ❗
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Features
|
|
||||||
|
|
||||||
- **Simple API** - Xalloc provides a simple API for allocating and freeing memory. It is designed to be easy to use and understand.
|
|
||||||
|
|
||||||
- [ ] todo complete this
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Getting Started
|
|
||||||
|
|
||||||
### Implementing missing functions
|
|
||||||
|
|
||||||
You will need to implement the following functions in your OS:
|
|
||||||
|
|
||||||
##### Wrapper.cpp
|
|
||||||
```cpp
|
|
||||||
extern "C" void *Xalloc_REQUEST_PAGES(Xsize_t Pages)
|
|
||||||
{
|
|
||||||
// ...
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" void Xalloc_FREE_PAGES(void *Address, Xsize_t Pages)
|
|
||||||
{
|
|
||||||
// ...
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" void Xalloc_MAP_MEMORY(void *VirtualAddress, void *PhysicalAddress, Xsize_t Flags)
|
|
||||||
{
|
|
||||||
// ...
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" void Xalloc_UNMAP_MEMORY(void *VirtualAddress)
|
|
||||||
{
|
|
||||||
// ...
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
##### Xalloc.hpp
|
|
||||||
```cpp
|
|
||||||
#define Xalloc_PAGE_SIZE <page size> /* <-- Replace with your page size */
|
|
||||||
#define Xalloc_trace(m, ...) <trace function>
|
|
||||||
#define Xalloc_warn(m, ...) <warning function>
|
|
||||||
#define Xalloc_err(m, ...) <error function>
|
|
||||||
#define Xalloc_def <define a lock> /* eg. std::mutex Xalloc_lock; */
|
|
||||||
#define Xalloc_lock <lock function>
|
|
||||||
#define Xalloc_unlock <unlock function>
|
|
||||||
```
|
|
||||||
|
|
||||||
### Typical usage
|
|
||||||
|
|
||||||
```cpp
|
|
||||||
#include "Xalloc.hpp"
|
|
||||||
|
|
||||||
Xalloc::V1 *XallocV1Allocator = nullptr;
|
|
||||||
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
/* Virtual Base User SMAP */
|
|
||||||
XallocV1Allocator = new Xalloc::V1((void *)0xFFFFA00000000000, false, false);
|
|
||||||
|
|
||||||
void *p = XallocV1Allocator->malloc(1234);
|
|
||||||
/* ... */
|
|
||||||
XallocV1Allocator->free(p);
|
|
||||||
delete XallocV1Allocator;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
or
|
|
||||||
|
|
||||||
```cpp
|
|
||||||
#include "Xalloc.hpp"
|
|
||||||
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
/* Virtual Base User SMAP */
|
|
||||||
Xalloc::V1 XallocV1Allocator((void *)0xFFFFA00000000000, false, false);
|
|
||||||
|
|
||||||
void *p = XallocV1Allocator.malloc(1234);
|
|
||||||
/* ... */
|
|
||||||
XallocV1Allocator.free(p);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## API
|
|
||||||
|
|
||||||
### Xalloc::V1
|
|
||||||
|
|
||||||
```cpp
|
|
||||||
void *malloc(Xsize_t Size);
|
|
||||||
```
|
|
||||||
Allocates a block of memory of size `Size` bytes.
|
|
||||||
If `Size` is 0, then `nullptr` is returned.
|
|
||||||
- `Size` - The size of the block to allocate in bytes.
|
|
||||||
|
|
||||||
<br><br>
|
|
||||||
|
|
||||||
```cpp
|
|
||||||
void free(void *Address);
|
|
||||||
```
|
|
||||||
Frees the memory block pointed to by `Address`.
|
|
||||||
If `Address` is `nullptr`, then no operation is performed.
|
|
||||||
- `Address` - The address of the memory block to free.
|
|
||||||
|
|
||||||
<br><br>
|
|
||||||
|
|
||||||
```cpp
|
|
||||||
void *calloc(Xsize_t NumberOfBlocks, Xsize_t Size);
|
|
||||||
```
|
|
||||||
Allocates a block of memory for an array of `NumberOfBlocks` elements, each of them `Size` bytes long.
|
|
||||||
If `NumberOfBlocks` or `Size` is 0, then `nullptr` is returned.
|
|
||||||
- `NumberOfBlocks` - The number of elements to allocate.
|
|
||||||
- `Size` - The size of each element in bytes.
|
|
||||||
|
|
||||||
<br><br>
|
|
||||||
|
|
||||||
```cpp
|
|
||||||
void *realloc(void *Address, Xsize_t Size);
|
|
||||||
```
|
|
||||||
Changes the size of the memory block pointed to by `Address` to `Size` bytes.
|
|
||||||
If `Address` is `nullptr`, then the call is equivalent to `malloc(Size)`.
|
|
||||||
If `Size` is equal to zero, and `Address` is not `nullptr`, then the call is equivalent to `free(Address)`.
|
|
||||||
- `Address` - The address of the memory block to resize.
|
|
||||||
- `Size` - The new size of the memory block in bytes.
|
|
||||||
|
|
||||||
---
|
|
@ -1,23 +0,0 @@
|
|||||||
#include "Xalloc.hpp"
|
|
||||||
|
|
||||||
#include <memory.hpp>
|
|
||||||
|
|
||||||
extern "C" void *Xalloc_REQUEST_PAGES(Xsize_t Pages)
|
|
||||||
{
|
|
||||||
return KernelAllocator.RequestPages(Pages);
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" void Xalloc_FREE_PAGES(void *Address, Xsize_t Pages)
|
|
||||||
{
|
|
||||||
KernelAllocator.FreePages(Address, Pages);
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" void Xalloc_MAP_MEMORY(void *VirtualAddress, void *PhysicalAddress, Xsize_t Flags)
|
|
||||||
{
|
|
||||||
Memory::Virtual(KernelPageTable).Map(VirtualAddress, PhysicalAddress, Flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" void Xalloc_UNMAP_MEMORY(void *VirtualAddress)
|
|
||||||
{
|
|
||||||
Memory::Virtual(KernelPageTable).Unmap(VirtualAddress);
|
|
||||||
}
|
|
@ -1,102 +0,0 @@
|
|||||||
#ifndef __FENNIX_KERNEL_Xalloc_H__
|
|
||||||
#define __FENNIX_KERNEL_Xalloc_H__
|
|
||||||
|
|
||||||
#include <memory.hpp>
|
|
||||||
#include <lock.hpp>
|
|
||||||
#include <debug.h>
|
|
||||||
|
|
||||||
typedef long unsigned Xuint64_t;
|
|
||||||
typedef long unsigned Xsize_t;
|
|
||||||
|
|
||||||
#define Xalloc_StopOnFail true
|
|
||||||
#define Xalloc_PAGE_SIZE PAGE_SIZE
|
|
||||||
#define Xalloc_trace(m, ...) trace(m, ##__VA_ARGS__)
|
|
||||||
#define Xalloc_warn(m, ...) warn(m, ##__VA_ARGS__)
|
|
||||||
#define Xalloc_err(m, ...) error(m, ##__VA_ARGS__)
|
|
||||||
#define Xalloc_def NewLock(XallocLock)
|
|
||||||
#define Xalloc_lock XallocLock.Lock(__FUNCTION__)
|
|
||||||
#define Xalloc_unlock XallocLock.Unlock()
|
|
||||||
|
|
||||||
namespace Xalloc
|
|
||||||
{
|
|
||||||
class V1
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
void *BaseVirtualAddress = nullptr;
|
|
||||||
void *FirstBlock = nullptr;
|
|
||||||
void *LastBlock = nullptr;
|
|
||||||
|
|
||||||
bool UserMapping = false;
|
|
||||||
bool SMAPUsed = false;
|
|
||||||
|
|
||||||
public:
|
|
||||||
/** @brief Execute "stac" instruction if the kernel has SMAP enabled */
|
|
||||||
void Xstac();
|
|
||||||
|
|
||||||
/** @brief Execute "clac" instruction if the kernel has SMAP enabled */
|
|
||||||
void Xclac();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Arrange the blocks to optimize the memory usage
|
|
||||||
* The allocator is not arranged by default
|
|
||||||
* to avoid performance issues.
|
|
||||||
* This function will defragment the memory
|
|
||||||
* and free the unused blocks.
|
|
||||||
*
|
|
||||||
* You should call this function when the
|
|
||||||
* kernel is idle or when is not using
|
|
||||||
* the allocator.
|
|
||||||
*/
|
|
||||||
void Arrange();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Allocate a new memory block
|
|
||||||
*
|
|
||||||
* @param Size Size of the block to allocate.
|
|
||||||
* @return void* Pointer to the allocated block.
|
|
||||||
*/
|
|
||||||
void *malloc(Xsize_t Size);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Free a previously allocated block
|
|
||||||
*
|
|
||||||
* @param Address Address of the block to free.
|
|
||||||
*/
|
|
||||||
void free(void *Address);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Allocate a new memory block
|
|
||||||
*
|
|
||||||
* @param NumberOfBlocks Number of blocks to allocate.
|
|
||||||
* @param Size Size of the block to allocate.
|
|
||||||
* @return void* Pointer to the allocated block.
|
|
||||||
*/
|
|
||||||
void *calloc(Xsize_t NumberOfBlocks, Xsize_t Size);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Reallocate a previously allocated block
|
|
||||||
*
|
|
||||||
* @param Address Address of the block to reallocate.
|
|
||||||
* @param Size New size of the block.
|
|
||||||
* @return void* Pointer to the reallocated block.
|
|
||||||
*/
|
|
||||||
void *realloc(void *Address, Xsize_t Size);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Construct a new Allocator object
|
|
||||||
*
|
|
||||||
* @param BaseVirtualAddress Virtual address to map the pages.
|
|
||||||
* @param UserMode Map the new pages with USER flag?
|
|
||||||
* @param SMAPEnabled Does the kernel has Supervisor Mode Access Prevention enabled?
|
|
||||||
*/
|
|
||||||
V1(void *BaseVirtualAddress, bool UserMode, bool SMAPEnabled);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Destroy the Allocator object
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
~V1();
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // !__FENNIX_KERNEL_Xalloc_H__
|
|
@ -1,271 +0,0 @@
|
|||||||
#include "Xalloc.hpp"
|
|
||||||
|
|
||||||
Xalloc_def;
|
|
||||||
|
|
||||||
#define XALLOC_CONCAT(x, y) x##y
|
|
||||||
#define XStoP(x) (x / Xalloc_PAGE_SIZE + 1)
|
|
||||||
#define XPtoS(x) (x * Xalloc_PAGE_SIZE)
|
|
||||||
#define Xalloc_BlockChecksum 0xA110C
|
|
||||||
|
|
||||||
extern "C" void *Xalloc_REQUEST_PAGES(Xsize_t Pages);
|
|
||||||
extern "C" void Xalloc_FREE_PAGES(void *Address, Xsize_t Pages);
|
|
||||||
extern "C" void Xalloc_MAP_MEMORY(void *VirtualAddress, void *PhysicalAddress, Xsize_t Flags);
|
|
||||||
extern "C" void Xalloc_UNMAP_MEMORY(void *VirtualAddress);
|
|
||||||
|
|
||||||
// TODO: Change memcpy with an optimized version
|
|
||||||
void *Xmemcpy(void *__restrict__ Destination, const void *__restrict__ Source, Xuint64_t Length)
|
|
||||||
{
|
|
||||||
unsigned char *dst = (unsigned char *)Destination;
|
|
||||||
const unsigned char *src = (const unsigned char *)Source;
|
|
||||||
for (Xuint64_t i = 0; i < Length; i++)
|
|
||||||
dst[i] = src[i];
|
|
||||||
return Destination;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Change memset with an optimized version
|
|
||||||
void *Xmemset(void *__restrict__ Destination, int Data, Xuint64_t Length)
|
|
||||||
{
|
|
||||||
unsigned char *Buffer = (unsigned char *)Destination;
|
|
||||||
for (Xuint64_t i = 0; i < Length; i++)
|
|
||||||
Buffer[i] = (unsigned char)Data;
|
|
||||||
return Destination;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace Xalloc
|
|
||||||
{
|
|
||||||
class Block
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
void *Address = nullptr;
|
|
||||||
|
|
||||||
int Checksum = Xalloc_BlockChecksum;
|
|
||||||
Xsize_t Size = 0;
|
|
||||||
Block *Next = nullptr;
|
|
||||||
Block *Last = nullptr;
|
|
||||||
bool IsFree = true;
|
|
||||||
|
|
||||||
bool Check()
|
|
||||||
{
|
|
||||||
if (this->Checksum != Xalloc_BlockChecksum)
|
|
||||||
return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
Block(Xsize_t Size)
|
|
||||||
{
|
|
||||||
this->Address = Xalloc_REQUEST_PAGES(XStoP(Size));
|
|
||||||
this->Size = Size;
|
|
||||||
Xmemset(this->Address, 0, Size);
|
|
||||||
}
|
|
||||||
|
|
||||||
~Block()
|
|
||||||
{
|
|
||||||
Xalloc_FREE_PAGES(this->Address, XStoP(this->Size));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Overload new operator to allocate memory from the heap
|
|
||||||
* @param Size Unused
|
|
||||||
* @return void* Pointer to the allocated memory
|
|
||||||
*/
|
|
||||||
void *operator new(Xsize_t Size)
|
|
||||||
{
|
|
||||||
void *ptr = Xalloc_REQUEST_PAGES(XStoP(sizeof(Block)));
|
|
||||||
return ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Overload delete operator to free memory from the heap
|
|
||||||
* @param Address Pointer to the memory to free
|
|
||||||
*/
|
|
||||||
void operator delete(void *Address)
|
|
||||||
{
|
|
||||||
Xalloc_FREE_PAGES(Address, XStoP(sizeof(Block)));
|
|
||||||
}
|
|
||||||
} __attribute__((packed, aligned((16))));
|
|
||||||
|
|
||||||
class SmartSMAPClass
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
V1 *allocator = nullptr;
|
|
||||||
|
|
||||||
public:
|
|
||||||
SmartSMAPClass(V1 *allocator)
|
|
||||||
{
|
|
||||||
this->allocator = allocator;
|
|
||||||
this->allocator->Xstac();
|
|
||||||
}
|
|
||||||
~SmartSMAPClass() { this->allocator->Xclac(); }
|
|
||||||
};
|
|
||||||
#define SmartSMAP SmartSMAPClass XALLOC_CONCAT(SmartSMAP##_, __COUNTER__)(this)
|
|
||||||
|
|
||||||
void V1::Xstac()
|
|
||||||
{
|
|
||||||
if (this->SMAPUsed)
|
|
||||||
{
|
|
||||||
#if defined(a64) || defined(a32)
|
|
||||||
asm volatile("stac" ::
|
|
||||||
: "cc");
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void V1::Xclac()
|
|
||||||
{
|
|
||||||
if (this->SMAPUsed)
|
|
||||||
{
|
|
||||||
#if defined(a64) || defined(a32)
|
|
||||||
asm volatile("clac" ::
|
|
||||||
: "cc");
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void V1::Arrange()
|
|
||||||
{
|
|
||||||
Xalloc_err("Arrange() is not implemented yet!");
|
|
||||||
}
|
|
||||||
|
|
||||||
void *V1::malloc(Xsize_t Size)
|
|
||||||
{
|
|
||||||
if (Size == 0)
|
|
||||||
{
|
|
||||||
Xalloc_warn("Attempted to allocate 0 bytes!");
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
SmartSMAP;
|
|
||||||
Xalloc_lock;
|
|
||||||
|
|
||||||
if (this->FirstBlock == nullptr)
|
|
||||||
{
|
|
||||||
this->FirstBlock = new Block(Size);
|
|
||||||
((Block *)this->FirstBlock)->IsFree = false;
|
|
||||||
Xalloc_unlock;
|
|
||||||
return ((Block *)this->FirstBlock)->Address;
|
|
||||||
}
|
|
||||||
|
|
||||||
Block *CurrentBlock = ((Block *)this->FirstBlock);
|
|
||||||
while (CurrentBlock != nullptr)
|
|
||||||
{
|
|
||||||
if (!CurrentBlock->Check())
|
|
||||||
{
|
|
||||||
Xalloc_err("Block %#lx has an invalid checksum! (%#x != %#x)",
|
|
||||||
(Xuint64_t)CurrentBlock, CurrentBlock->Checksum, Xalloc_BlockChecksum);
|
|
||||||
while (Xalloc_StopOnFail)
|
|
||||||
;
|
|
||||||
}
|
|
||||||
else if (CurrentBlock->IsFree && CurrentBlock->Size >= Size)
|
|
||||||
{
|
|
||||||
CurrentBlock->IsFree = false;
|
|
||||||
Xmemset(CurrentBlock->Address, 0, Size);
|
|
||||||
Xalloc_unlock;
|
|
||||||
return CurrentBlock->Address;
|
|
||||||
}
|
|
||||||
CurrentBlock = CurrentBlock->Next;
|
|
||||||
}
|
|
||||||
|
|
||||||
CurrentBlock = ((Block *)this->FirstBlock);
|
|
||||||
while (CurrentBlock->Next != nullptr)
|
|
||||||
CurrentBlock = CurrentBlock->Next;
|
|
||||||
|
|
||||||
CurrentBlock->Next = new Block(Size);
|
|
||||||
((Block *)CurrentBlock->Next)->Last = CurrentBlock;
|
|
||||||
((Block *)CurrentBlock->Next)->IsFree = false;
|
|
||||||
Xalloc_unlock;
|
|
||||||
return ((Block *)CurrentBlock->Next)->Address;
|
|
||||||
}
|
|
||||||
|
|
||||||
void V1::free(void *Address)
|
|
||||||
{
|
|
||||||
if (Address == nullptr)
|
|
||||||
{
|
|
||||||
Xalloc_warn("Attempted to free a null pointer!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
SmartSMAP;
|
|
||||||
Xalloc_lock;
|
|
||||||
|
|
||||||
Block *CurrentBlock = ((Block *)this->FirstBlock);
|
|
||||||
while (CurrentBlock != nullptr)
|
|
||||||
{
|
|
||||||
if (!CurrentBlock->Check())
|
|
||||||
{
|
|
||||||
Xalloc_err("Block %#lx checksum failed!", (Xuint64_t)CurrentBlock);
|
|
||||||
while (Xalloc_StopOnFail)
|
|
||||||
;
|
|
||||||
}
|
|
||||||
else if (CurrentBlock->Address == Address)
|
|
||||||
{
|
|
||||||
if (CurrentBlock->IsFree)
|
|
||||||
{
|
|
||||||
Xalloc_warn("Attempted to free an already freed pointer!");
|
|
||||||
Xalloc_unlock;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
CurrentBlock->IsFree = true;
|
|
||||||
Xalloc_unlock;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
CurrentBlock = CurrentBlock->Next;
|
|
||||||
}
|
|
||||||
|
|
||||||
Xalloc_err("Invalid address.");
|
|
||||||
Xalloc_unlock;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *V1::calloc(Xsize_t NumberOfBlocks, Xsize_t Size)
|
|
||||||
{
|
|
||||||
if (NumberOfBlocks == 0 || Size == 0)
|
|
||||||
{
|
|
||||||
Xalloc_warn("The %s%s%s is 0!",
|
|
||||||
NumberOfBlocks == 0 ? "NumberOfBlocks" : "",
|
|
||||||
NumberOfBlocks == 0 && Size == 0 ? " and " : "",
|
|
||||||
Size == 0 ? "Size" : "");
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return this->malloc(NumberOfBlocks * Size);
|
|
||||||
}
|
|
||||||
|
|
||||||
void *V1::realloc(void *Address, Xsize_t Size)
|
|
||||||
{
|
|
||||||
if (Address == nullptr)
|
|
||||||
return this->malloc(Size);
|
|
||||||
|
|
||||||
if (Size == 0)
|
|
||||||
{
|
|
||||||
this->free(Address);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// SmartSMAP;
|
|
||||||
// Xalloc_lock;
|
|
||||||
// ...
|
|
||||||
// Xalloc_unlock;
|
|
||||||
|
|
||||||
// TODO: Implement realloc
|
|
||||||
this->free(Address);
|
|
||||||
return this->malloc(Size);
|
|
||||||
}
|
|
||||||
|
|
||||||
V1::V1(void *BaseVirtualAddress, bool UserMode, bool SMAPEnabled)
|
|
||||||
{
|
|
||||||
SmartSMAP;
|
|
||||||
Xalloc_lock;
|
|
||||||
this->SMAPUsed = SMAPEnabled;
|
|
||||||
this->UserMapping = UserMode;
|
|
||||||
this->BaseVirtualAddress = BaseVirtualAddress;
|
|
||||||
Xalloc_unlock;
|
|
||||||
}
|
|
||||||
|
|
||||||
V1::~V1()
|
|
||||||
{
|
|
||||||
SmartSMAP;
|
|
||||||
Xalloc_lock;
|
|
||||||
Xalloc_trace("Destructor not implemented yet.");
|
|
||||||
Xalloc_unlock;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,88 +1,56 @@
|
|||||||
#include <memory.hpp>
|
#include <memory.hpp>
|
||||||
|
|
||||||
#include <convert.h>
|
#include <convert.h>
|
||||||
#include <lock.hpp>
|
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
#ifdef DEBUG
|
|
||||||
#include <uart.hpp>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "HeapAllocators/Xalloc/Xalloc.hpp"
|
#include "HeapAllocators/Xalloc.hpp"
|
||||||
#include "../Library/liballoc_1_1.h"
|
#include "../Library/liballoc_1_1.h"
|
||||||
#include "../../kernel.h"
|
|
||||||
|
|
||||||
// #define DEBUG_ALLOCATIONS_SL 1
|
|
||||||
// #define DEBUG_ALLOCATIONS 1
|
|
||||||
|
|
||||||
#ifdef DEBUG_ALLOCATIONS
|
|
||||||
#define memdbg(m, ...) \
|
|
||||||
debug(m, ##__VA_ARGS__); \
|
|
||||||
__sync
|
|
||||||
#else
|
|
||||||
#define memdbg(m, ...)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
using namespace Memory;
|
using namespace Memory;
|
||||||
|
|
||||||
#ifdef DEBUG_ALLOCATIONS_SL
|
|
||||||
NewLock(AllocatorLock);
|
|
||||||
NewLock(OperatorAllocatorLock);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
Physical KernelAllocator;
|
Physical KernelAllocator;
|
||||||
PageTable4 *KernelPageTable = nullptr;
|
PageTable *KernelPageTable = nullptr;
|
||||||
PageTable4 *UserspaceKernelOnlyPageTable = nullptr;
|
PageTable *UserspaceKernelOnlyPageTable = nullptr;
|
||||||
void *KPT = nullptr;
|
|
||||||
|
|
||||||
static MemoryAllocatorType AllocatorType = MemoryAllocatorType::None;
|
static MemoryAllocatorType AllocatorType = MemoryAllocatorType::None;
|
||||||
Xalloc::V1 *XallocV1Allocator = nullptr;
|
Xalloc::AllocatorV1 *XallocV1Allocator = nullptr;
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
NIF void tracepagetable(PageTable4 *pt)
|
__no_instrument_function void tracepagetable(PageTable *pt)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < 512; i++)
|
for (int i = 0; i < 512; i++)
|
||||||
{
|
{
|
||||||
#if defined(a64)
|
#if defined(__amd64__)
|
||||||
if (pt->Entries[i].Present)
|
if (pt->Entries[i].Value.Present)
|
||||||
debug("Entry %03d: %x %x %x %x %x %x %x %p-%#llx", i,
|
debug("Entry %03d: %x %x %x %x %x %x %x %x %x %x %x %p-%#llx", i,
|
||||||
pt->Entries[i].Present, pt->Entries[i].ReadWrite,
|
pt->Entries[i].Value.Present, pt->Entries[i].Value.ReadWrite,
|
||||||
pt->Entries[i].UserSupervisor, pt->Entries[i].WriteThrough,
|
pt->Entries[i].Value.UserSupervisor, pt->Entries[i].Value.WriteThrough,
|
||||||
pt->Entries[i].CacheDisable, pt->Entries[i].Accessed,
|
pt->Entries[i].Value.CacheDisable, pt->Entries[i].Value.Accessed,
|
||||||
pt->Entries[i].ExecuteDisable, pt->Entries[i].Address << 12,
|
pt->Entries[i].Value.Dirty, pt->Entries[i].Value.PageSize,
|
||||||
pt->Entries[i]);
|
pt->Entries[i].Value.Global, pt->Entries[i].Value.PageAttributeTable,
|
||||||
#elif defined(a32)
|
pt->Entries[i].Value.ExecuteDisable, pt->Entries[i].GetAddress(),
|
||||||
#elif defined(aa64)
|
pt->Entries[i].Value);
|
||||||
|
#elif defined(__i386__)
|
||||||
|
#elif defined(__aarch64__)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
NIF void MapFromZero(PageTable4 *PT, BootInfo *Info)
|
__no_instrument_function void MapFromZero(PageTable *PT, BootInfo *Info)
|
||||||
{
|
{
|
||||||
static int once = 0;
|
|
||||||
if (!once++)
|
|
||||||
{
|
|
||||||
Virtual va = Virtual(PT);
|
Virtual va = Virtual(PT);
|
||||||
void *NullAddress = KernelAllocator.RequestPage();
|
uint64_t VirtualOffsetNormalVMA = NORMAL_VMA_OFFSET;
|
||||||
memset(NullAddress, 0, PAGE_SIZE); // TODO: If the CPU instruction pointer hits this page, there should be function to handle it. (memcpy assembly code?)
|
uint64_t MemSize = Info->Memory.Size;
|
||||||
va.Map((void *)0, (void *)NullAddress, PTFlag::RW | PTFlag::US);
|
for (uint64_t t = 0; t < MemSize; t += PAGE_SIZE)
|
||||||
uintptr_t VirtualOffsetNormalVMA = NORMAL_VMA_OFFSET;
|
|
||||||
size_t MemSize = Info->Memory.Size;
|
|
||||||
for (size_t t = 0; t < MemSize; t += PAGE_SIZE)
|
|
||||||
{
|
{
|
||||||
va.Map((void *)t, (void *)t, PTFlag::RW /* | PTFlag::US */);
|
va.Map((void *)t, (void *)t, PTFlag::RW /* | PTFlag::US */);
|
||||||
// va.Map((void *)VirtualOffsetNormalVMA, (void *)t, PTFlag::RW /* | PTFlag::US */);
|
va.Map((void *)VirtualOffsetNormalVMA, (void *)t, PTFlag::RW /* | PTFlag::US */);
|
||||||
// VirtualOffsetNormalVMA += PAGE_SIZE;
|
VirtualOffsetNormalVMA += PAGE_SIZE;
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
error("MapFromZero() called more than once!");
|
|
||||||
CPU::Stop();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NIF void MapFramebuffer(PageTable4 *PT, BootInfo *Info)
|
__no_instrument_function void MapFramebuffer(PageTable *PT, BootInfo *Info)
|
||||||
{
|
{
|
||||||
Virtual va = Virtual(PT);
|
Virtual va = Virtual(PT);
|
||||||
int itrfb = 0;
|
int itrfb = 0;
|
||||||
@ -91,28 +59,28 @@ NIF void MapFramebuffer(PageTable4 *PT, BootInfo *Info)
|
|||||||
if (!Info->Framebuffer[itrfb].BaseAddress)
|
if (!Info->Framebuffer[itrfb].BaseAddress)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
for (uintptr_t fb_base = (uintptr_t)Info->Framebuffer[itrfb].BaseAddress;
|
for (uint64_t fb_base = (uint64_t)Info->Framebuffer[itrfb].BaseAddress;
|
||||||
fb_base < ((uintptr_t)Info->Framebuffer[itrfb].BaseAddress + ((Info->Framebuffer[itrfb].Pitch * Info->Framebuffer[itrfb].Height) + PAGE_SIZE));
|
fb_base < ((uint64_t)Info->Framebuffer[itrfb].BaseAddress + ((Info->Framebuffer[itrfb].Pitch * Info->Framebuffer[itrfb].Height) + PAGE_SIZE));
|
||||||
fb_base += PAGE_SIZE)
|
fb_base += PAGE_SIZE)
|
||||||
va.Map((void *)fb_base, (void *)fb_base, PTFlag::RW | PTFlag::US | PTFlag::G);
|
va.Map((void *)(fb_base + NORMAL_VMA_OFFSET), (void *)fb_base, PTFlag::RW | PTFlag::US | PTFlag::G);
|
||||||
itrfb++;
|
itrfb++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NIF void MapKernel(PageTable4 *PT, BootInfo *Info)
|
__no_instrument_function void MapKernel(PageTable *PT, BootInfo *Info)
|
||||||
{
|
{
|
||||||
/* KernelStart KernelTextEnd KernelRoDataEnd KernelEnd
|
/* KernelStart KernelTextEnd KernelRoDataEnd KernelEnd
|
||||||
Kernel Start & Text Start ------ Text End ------ Kernel Rodata End ------ Kernel Data End & Kernel End
|
Kernel Start & Text Start ------ Text End ------ Kernel Rodata End ------ Kernel Data End & Kernel End
|
||||||
*/
|
*/
|
||||||
Virtual va = Virtual(PT);
|
Virtual va = Virtual(PT);
|
||||||
uintptr_t KernelStart = (uintptr_t)&_kernel_start;
|
uint64_t KernelStart = (uint64_t)&_kernel_start;
|
||||||
uintptr_t KernelTextEnd = (uintptr_t)&_kernel_text_end;
|
uint64_t KernelTextEnd = (uint64_t)&_kernel_text_end;
|
||||||
uintptr_t KernelDataEnd = (uintptr_t)&_kernel_data_end;
|
uint64_t KernelDataEnd = (uint64_t)&_kernel_data_end;
|
||||||
uintptr_t KernelRoDataEnd = (uintptr_t)&_kernel_rodata_end;
|
uint64_t KernelRoDataEnd = (uint64_t)&_kernel_rodata_end;
|
||||||
uintptr_t KernelEnd = (uintptr_t)&_kernel_end;
|
uint64_t KernelEnd = (uint64_t)&_kernel_end;
|
||||||
|
|
||||||
uintptr_t BaseKernelMapAddress = (uintptr_t)Info->Kernel.PhysicalBase;
|
uint64_t BaseKernelMapAddress = (uint64_t)Info->Kernel.PhysicalBase;
|
||||||
uintptr_t k;
|
uint64_t k;
|
||||||
|
|
||||||
for (k = KernelStart; k < KernelTextEnd; k += PAGE_SIZE)
|
for (k = KernelStart; k < KernelTextEnd; k += PAGE_SIZE)
|
||||||
{
|
{
|
||||||
@ -146,14 +114,14 @@ NIF void MapKernel(PageTable4 *PT, BootInfo *Info)
|
|||||||
KernelStart, KernelTextEnd, KernelRoDataEnd, KernelEnd, Info->Kernel.PhysicalBase, BaseKernelMapAddress - PAGE_SIZE);
|
KernelStart, KernelTextEnd, KernelRoDataEnd, KernelEnd, Info->Kernel.PhysicalBase, BaseKernelMapAddress - PAGE_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
NIF void InitializeMemoryManagement(BootInfo *Info)
|
__no_instrument_function void InitializeMemoryManagement(BootInfo *Info)
|
||||||
{
|
{
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
for (uint64_t i = 0; i < Info->Memory.Entries; i++)
|
for (uint64_t i = 0; i < Info->Memory.Entries; i++)
|
||||||
{
|
{
|
||||||
uintptr_t Base = reinterpret_cast<uintptr_t>(Info->Memory.Entry[i].BaseAddress);
|
uint64_t Base = reinterpret_cast<uint64_t>(Info->Memory.Entry[i].BaseAddress);
|
||||||
uintptr_t Length = Info->Memory.Entry[i].Length;
|
uint64_t Length = Info->Memory.Entry[i].Length;
|
||||||
uintptr_t End = Base + Length;
|
uint64_t End = Base + Length;
|
||||||
const char *Type = "Unknown";
|
const char *Type = "Unknown";
|
||||||
|
|
||||||
switch (Info->Memory.Entry[i].Type)
|
switch (Info->Memory.Entry[i].Type)
|
||||||
@ -193,8 +161,9 @@ NIF void InitializeMemoryManagement(BootInfo *Info)
|
|||||||
Type);
|
Type);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
trace("Initializing Physical Memory Manager");
|
trace("Initializing Physical Memory Manager");
|
||||||
// KernelAllocator = Physical(); <- Already called in the constructor
|
KernelAllocator = Physical();
|
||||||
KernelAllocator.Init(Info);
|
KernelAllocator.Init(Info);
|
||||||
debug("Memory Info: %lldMB / %lldMB (%lldMB reserved)",
|
debug("Memory Info: %lldMB / %lldMB (%lldMB reserved)",
|
||||||
TO_MB(KernelAllocator.GetUsedMemory()),
|
TO_MB(KernelAllocator.GetUsedMemory()),
|
||||||
@ -204,16 +173,17 @@ NIF void InitializeMemoryManagement(BootInfo *Info)
|
|||||||
AllocatorType = MemoryAllocatorType::Pages;
|
AllocatorType = MemoryAllocatorType::Pages;
|
||||||
|
|
||||||
trace("Initializing Virtual Memory Manager");
|
trace("Initializing Virtual Memory Manager");
|
||||||
KernelPageTable = (PageTable4 *)KernelAllocator.RequestPages(TO_PAGES(PAGE_SIZE));
|
KernelPageTable = (PageTable *)KernelAllocator.RequestPages(TO_PAGES(PAGE_SIZE));
|
||||||
memset(KernelPageTable, 0, PAGE_SIZE);
|
memset(KernelPageTable, 0, PAGE_SIZE);
|
||||||
|
|
||||||
UserspaceKernelOnlyPageTable = (PageTable4 *)KernelAllocator.RequestPages(TO_PAGES(PAGE_SIZE));
|
UserspaceKernelOnlyPageTable = (PageTable *)KernelAllocator.RequestPages(TO_PAGES(PAGE_SIZE));
|
||||||
memset(UserspaceKernelOnlyPageTable, 0, PAGE_SIZE);
|
memset(UserspaceKernelOnlyPageTable, 0, PAGE_SIZE);
|
||||||
|
|
||||||
debug("Mapping from 0x0 to %#llx", Info->Memory.Size);
|
debug("Mapping from 0x0 to %#llx", Info->Memory.Size);
|
||||||
MapFromZero(KernelPageTable, Info);
|
MapFromZero(KernelPageTable, Info);
|
||||||
debug("Mapping from 0x0 %#llx for Userspace Page Table", Info->Memory.Size);
|
debug("Mapping from 0x0 %#llx for Userspace Page Table", Info->Memory.Size);
|
||||||
UserspaceKernelOnlyPageTable[0] = KernelPageTable[0];
|
UserspaceKernelOnlyPageTable[0] = KernelPageTable[0]; // TODO: This is a hack to speed up the boot process
|
||||||
|
// MapFromZero(UserspaceKernelOnlyPageTable, Info);
|
||||||
|
|
||||||
/* Mapping Framebuffer address */
|
/* Mapping Framebuffer address */
|
||||||
debug("Mapping Framebuffer");
|
debug("Mapping Framebuffer");
|
||||||
@ -234,16 +204,15 @@ NIF void InitializeMemoryManagement(BootInfo *Info)
|
|||||||
debug("Userspace:");
|
debug("Userspace:");
|
||||||
tracepagetable(UserspaceKernelOnlyPageTable);
|
tracepagetable(UserspaceKernelOnlyPageTable);
|
||||||
#endif
|
#endif
|
||||||
KPT = KernelPageTable;
|
#if defined(__amd64__) || defined(__i386__)
|
||||||
#if defined(a64) || defined(a32)
|
asmv("mov %0, %%cr3" ::"r"(KernelPageTable));
|
||||||
asmv("mov %0, %%cr3" ::"r"(KPT));
|
#elif defined(__aarch64__)
|
||||||
#elif defined(aa64)
|
asmv("msr ttbr0_el1, %0" ::"r"(KernelPageTable));
|
||||||
asmv("msr ttbr0_el1, %0" ::"r"(KPT));
|
|
||||||
#endif
|
#endif
|
||||||
debug("Page table updated.");
|
debug("Page table updated.");
|
||||||
if (strstr(Info->Kernel.CommandLine, "xallocv1"))
|
if (strstr(Info->Kernel.CommandLine, "xallocv1"))
|
||||||
{
|
{
|
||||||
XallocV1Allocator = new Xalloc::V1((void *)KERNEL_HEAP_BASE, false, false);
|
XallocV1Allocator = new Xalloc::AllocatorV1((void *)KERNEL_HEAP_BASE, false, false);
|
||||||
AllocatorType = MemoryAllocatorType::XallocV1;
|
AllocatorType = MemoryAllocatorType::XallocV1;
|
||||||
trace("XallocV1 Allocator initialized (%p)", XallocV1Allocator);
|
trace("XallocV1 Allocator initialized (%p)", XallocV1Allocator);
|
||||||
}
|
}
|
||||||
@ -253,79 +222,40 @@ NIF void InitializeMemoryManagement(BootInfo *Info)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void *HeapMalloc(size_t Size)
|
void *HeapMalloc(uint64_t Size)
|
||||||
{
|
{
|
||||||
#ifdef DEBUG_ALLOCATIONS_SL
|
|
||||||
SmartLockClass lock___COUNTER__(AllocatorLock, (KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"));
|
|
||||||
#endif
|
|
||||||
memdbg("malloc(%d)->[%s]", Size, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown");
|
|
||||||
|
|
||||||
void *ret = nullptr;
|
|
||||||
switch (AllocatorType)
|
switch (AllocatorType)
|
||||||
{
|
{
|
||||||
case MemoryAllocatorType::Pages:
|
case unlikely(MemoryAllocatorType::Pages):
|
||||||
{
|
return KernelAllocator.RequestPages(TO_PAGES(Size));
|
||||||
ret = KernelAllocator.RequestPages(TO_PAGES(Size));
|
|
||||||
memset(ret, 0, Size);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case MemoryAllocatorType::XallocV1:
|
case MemoryAllocatorType::XallocV1:
|
||||||
{
|
{
|
||||||
ret = XallocV1Allocator->malloc(Size);
|
void *ret = XallocV1Allocator->Malloc(Size);
|
||||||
break;
|
memset(ret, 0, Size);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
case MemoryAllocatorType::liballoc11:
|
case MemoryAllocatorType::liballoc11:
|
||||||
{
|
{
|
||||||
ret = PREFIX(malloc)(Size);
|
void *ret = PREFIX(malloc)(Size);
|
||||||
memset(ret, 0, Size);
|
memset(ret, 0, Size);
|
||||||
break;
|
return ret;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
#ifdef DEBUG
|
|
||||||
if (EnableExternalMemoryTracer)
|
|
||||||
{
|
|
||||||
char LockTmpStr[64];
|
|
||||||
strcpy_unsafe(LockTmpStr, __FUNCTION__);
|
|
||||||
strcat_unsafe(LockTmpStr, "_memTrk");
|
|
||||||
mExtTrkLock.TimeoutLock(LockTmpStr, 10000);
|
|
||||||
sprintf(mExtTrkLog, "malloc( %ld )=%p~%p\n\r",
|
|
||||||
Size,
|
|
||||||
ret, __builtin_return_address(0));
|
|
||||||
UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3);
|
|
||||||
for (short i = 0; i < MEM_TRK_MAX_SIZE; i++)
|
|
||||||
{
|
|
||||||
if (mExtTrkLog[i] == '\r')
|
|
||||||
break;
|
|
||||||
mTrkUART.Write(mExtTrkLog[i]);
|
|
||||||
}
|
|
||||||
mExtTrkLock.Unlock();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void *HeapCalloc(size_t n, size_t Size)
|
void *HeapCalloc(uint64_t n, uint64_t Size)
|
||||||
{
|
{
|
||||||
#ifdef DEBUG_ALLOCATIONS_SL
|
|
||||||
SmartLockClass lock___COUNTER__(AllocatorLock, (KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"));
|
|
||||||
#endif
|
|
||||||
memdbg("calloc(%d, %d)->[%s]", n, Size, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown");
|
|
||||||
|
|
||||||
void *ret = nullptr;
|
|
||||||
switch (AllocatorType)
|
switch (AllocatorType)
|
||||||
{
|
{
|
||||||
case MemoryAllocatorType::Pages:
|
case unlikely(MemoryAllocatorType::Pages):
|
||||||
{
|
return KernelAllocator.RequestPages(TO_PAGES(n * Size));
|
||||||
ret = KernelAllocator.RequestPages(TO_PAGES(n * Size));
|
|
||||||
memset(ret, 0, n * Size);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case MemoryAllocatorType::XallocV1:
|
case MemoryAllocatorType::XallocV1:
|
||||||
{
|
{
|
||||||
ret = XallocV1Allocator->calloc(n, Size);
|
void *ret = XallocV1Allocator->Calloc(n, Size);
|
||||||
break;
|
memset(ret, 0, n * Size);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
case MemoryAllocatorType::liballoc11:
|
case MemoryAllocatorType::liballoc11:
|
||||||
{
|
{
|
||||||
@ -336,49 +266,19 @@ void *HeapCalloc(size_t n, size_t Size)
|
|||||||
default:
|
default:
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
#ifdef DEBUG
|
|
||||||
if (EnableExternalMemoryTracer)
|
|
||||||
{
|
|
||||||
char LockTmpStr[64];
|
|
||||||
strcpy_unsafe(LockTmpStr, __FUNCTION__);
|
|
||||||
strcat_unsafe(LockTmpStr, "_memTrk");
|
|
||||||
mExtTrkLock.TimeoutLock(LockTmpStr, 10000);
|
|
||||||
sprintf(mExtTrkLog, "calloc( %ld %ld )=%p~%p\n\r",
|
|
||||||
n, Size,
|
|
||||||
ret, __builtin_return_address(0));
|
|
||||||
UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3);
|
|
||||||
for (short i = 0; i < MEM_TRK_MAX_SIZE; i++)
|
|
||||||
{
|
|
||||||
if (mExtTrkLog[i] == '\r')
|
|
||||||
break;
|
|
||||||
mTrkUART.Write(mExtTrkLog[i]);
|
|
||||||
}
|
|
||||||
mExtTrkLock.Unlock();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void *HeapRealloc(void *Address, size_t Size)
|
void *HeapRealloc(void *Address, uint64_t Size)
|
||||||
{
|
{
|
||||||
#ifdef DEBUG_ALLOCATIONS_SL
|
|
||||||
SmartLockClass lock___COUNTER__(AllocatorLock, (KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"));
|
|
||||||
#endif
|
|
||||||
memdbg("realloc(%#lx, %d)->[%s]", Address, Size, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown");
|
|
||||||
|
|
||||||
void *ret = nullptr;
|
|
||||||
switch (AllocatorType)
|
switch (AllocatorType)
|
||||||
{
|
{
|
||||||
case unlikely(MemoryAllocatorType::Pages):
|
case unlikely(MemoryAllocatorType::Pages):
|
||||||
{
|
return KernelAllocator.RequestPages(TO_PAGES(Size)); // WARNING: Potential memory leak
|
||||||
ret = KernelAllocator.RequestPages(TO_PAGES(Size)); // WARNING: Potential memory leak
|
|
||||||
memset(ret, 0, Size);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case MemoryAllocatorType::XallocV1:
|
case MemoryAllocatorType::XallocV1:
|
||||||
{
|
{
|
||||||
ret = XallocV1Allocator->realloc(Address, Size);
|
void *ret = XallocV1Allocator->Realloc(Address, Size);
|
||||||
break;
|
memset(ret, 0, Size);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
case MemoryAllocatorType::liballoc11:
|
case MemoryAllocatorType::liballoc11:
|
||||||
{
|
{
|
||||||
@ -389,291 +289,54 @@ void *HeapRealloc(void *Address, size_t Size)
|
|||||||
default:
|
default:
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
#ifdef DEBUG
|
|
||||||
if (EnableExternalMemoryTracer)
|
|
||||||
{
|
|
||||||
char LockTmpStr[64];
|
|
||||||
strcpy_unsafe(LockTmpStr, __FUNCTION__);
|
|
||||||
strcat_unsafe(LockTmpStr, "_memTrk");
|
|
||||||
mExtTrkLock.TimeoutLock(LockTmpStr, 10000);
|
|
||||||
sprintf(mExtTrkLog, "realloc( %p %ld )=%p~%p\n\r",
|
|
||||||
Address, Size,
|
|
||||||
ret, __builtin_return_address(0));
|
|
||||||
UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3);
|
|
||||||
for (short i = 0; i < MEM_TRK_MAX_SIZE; i++)
|
|
||||||
{
|
|
||||||
if (mExtTrkLog[i] == '\r')
|
|
||||||
break;
|
|
||||||
mTrkUART.Write(mExtTrkLog[i]);
|
|
||||||
}
|
|
||||||
mExtTrkLock.Unlock();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void HeapFree(void *Address)
|
void HeapFree(void *Address)
|
||||||
{
|
{
|
||||||
#ifdef DEBUG_ALLOCATIONS_SL
|
|
||||||
SmartLockClass lock___COUNTER__(AllocatorLock, (KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"));
|
|
||||||
#endif
|
|
||||||
memdbg("free(%#lx)->[%s]", Address, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown");
|
|
||||||
|
|
||||||
switch (AllocatorType)
|
switch (AllocatorType)
|
||||||
{
|
{
|
||||||
case unlikely(MemoryAllocatorType::Pages):
|
case unlikely(MemoryAllocatorType::Pages):
|
||||||
{
|
|
||||||
KernelAllocator.FreePage(Address); // WARNING: Potential memory leak
|
KernelAllocator.FreePage(Address); // WARNING: Potential memory leak
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
case MemoryAllocatorType::XallocV1:
|
case MemoryAllocatorType::XallocV1:
|
||||||
{
|
if (XallocV1Allocator)
|
||||||
XallocV1Allocator->free(Address);
|
XallocV1Allocator->Free(Address);
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
case MemoryAllocatorType::liballoc11:
|
case MemoryAllocatorType::liballoc11:
|
||||||
{
|
|
||||||
PREFIX(free)
|
PREFIX(free)
|
||||||
(Address);
|
(Address);
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
#ifdef DEBUG
|
|
||||||
if (EnableExternalMemoryTracer)
|
|
||||||
{
|
|
||||||
char LockTmpStr[64];
|
|
||||||
strcpy_unsafe(LockTmpStr, __FUNCTION__);
|
|
||||||
strcat_unsafe(LockTmpStr, "_memTrk");
|
|
||||||
mExtTrkLock.TimeoutLock(LockTmpStr, 10000);
|
|
||||||
sprintf(mExtTrkLog, "free( %p )~%p\n\r",
|
|
||||||
Address,
|
|
||||||
__builtin_return_address(0));
|
|
||||||
UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3);
|
|
||||||
for (short i = 0; i < MEM_TRK_MAX_SIZE; i++)
|
|
||||||
{
|
|
||||||
if (mExtTrkLog[i] == '\r')
|
|
||||||
break;
|
|
||||||
mTrkUART.Write(mExtTrkLog[i]);
|
|
||||||
}
|
|
||||||
mExtTrkLock.Unlock();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void *operator new(size_t Size)
|
void *operator new(size_t Size)
|
||||||
{
|
{
|
||||||
#ifdef DEBUG_ALLOCATIONS_SL
|
return HeapMalloc(Size);
|
||||||
SmartLockClass lock___COUNTER__(OperatorAllocatorLock, (KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"));
|
|
||||||
#endif
|
|
||||||
memdbg("new(%d)->[%s]", Size, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown");
|
|
||||||
|
|
||||||
void *ret = HeapMalloc(Size);
|
|
||||||
#ifdef DEBUG
|
|
||||||
if (EnableExternalMemoryTracer)
|
|
||||||
{
|
|
||||||
char LockTmpStr[64];
|
|
||||||
strcpy_unsafe(LockTmpStr, __FUNCTION__);
|
|
||||||
strcat_unsafe(LockTmpStr, "_memTrk");
|
|
||||||
mExtTrkLock.TimeoutLock(LockTmpStr, 10000);
|
|
||||||
sprintf(mExtTrkLog, "new( %ld )=%p~%p\n\r",
|
|
||||||
Size,
|
|
||||||
ret, __builtin_return_address(0));
|
|
||||||
UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3);
|
|
||||||
for (short i = 0; i < MEM_TRK_MAX_SIZE; i++)
|
|
||||||
{
|
|
||||||
if (mExtTrkLog[i] == '\r')
|
|
||||||
break;
|
|
||||||
mTrkUART.Write(mExtTrkLog[i]);
|
|
||||||
}
|
|
||||||
mExtTrkLock.Unlock();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void *operator new[](size_t Size)
|
void *operator new[](size_t Size)
|
||||||
{
|
{
|
||||||
#ifdef DEBUG_ALLOCATIONS_SL
|
return HeapMalloc(Size);
|
||||||
SmartLockClass lock___COUNTER__(OperatorAllocatorLock, (KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"));
|
|
||||||
#endif
|
|
||||||
memdbg("new[](%d)->[%s]", Size, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown");
|
|
||||||
|
|
||||||
void *ret = HeapMalloc(Size);
|
|
||||||
#ifdef DEBUG
|
|
||||||
if (EnableExternalMemoryTracer)
|
|
||||||
{
|
|
||||||
char LockTmpStr[64];
|
|
||||||
strcpy_unsafe(LockTmpStr, __FUNCTION__);
|
|
||||||
strcat_unsafe(LockTmpStr, "_memTrk");
|
|
||||||
mExtTrkLock.TimeoutLock(LockTmpStr, 10000);
|
|
||||||
sprintf(mExtTrkLog, "new[]( %ld )=%p~%p\n\r",
|
|
||||||
Size,
|
|
||||||
ret, __builtin_return_address(0));
|
|
||||||
UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3);
|
|
||||||
for (short i = 0; i < MEM_TRK_MAX_SIZE; i++)
|
|
||||||
{
|
|
||||||
if (mExtTrkLog[i] == '\r')
|
|
||||||
break;
|
|
||||||
mTrkUART.Write(mExtTrkLog[i]);
|
|
||||||
}
|
|
||||||
mExtTrkLock.Unlock();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void *operator new(unsigned long Size, std::align_val_t Alignment)
|
void *operator new(unsigned long Size, std::align_val_t Alignment)
|
||||||
{
|
{
|
||||||
#ifdef DEBUG_ALLOCATIONS_SL
|
|
||||||
SmartLockClass lock___COUNTER__(OperatorAllocatorLock, (KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"));
|
|
||||||
#endif
|
|
||||||
memdbg("new(%d, %d)->[%s]", Size, Alignment, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown");
|
|
||||||
fixme("operator new with alignment(%#lx) is not implemented", Alignment);
|
fixme("operator new with alignment(%#lx) is not implemented", Alignment);
|
||||||
|
return HeapMalloc(Size);
|
||||||
void *ret = HeapMalloc(Size);
|
|
||||||
#ifdef DEBUG
|
|
||||||
if (EnableExternalMemoryTracer)
|
|
||||||
{
|
|
||||||
char LockTmpStr[64];
|
|
||||||
strcpy_unsafe(LockTmpStr, __FUNCTION__);
|
|
||||||
strcat_unsafe(LockTmpStr, "_memTrk");
|
|
||||||
mExtTrkLock.TimeoutLock(LockTmpStr, 10000);
|
|
||||||
sprintf(mExtTrkLog, "new( %ld %#lx )=%p~%p\n\r",
|
|
||||||
Size, (uintptr_t)Alignment,
|
|
||||||
ret, __builtin_return_address(0));
|
|
||||||
UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3);
|
|
||||||
for (short i = 0; i < MEM_TRK_MAX_SIZE; i++)
|
|
||||||
{
|
|
||||||
if (mExtTrkLog[i] == '\r')
|
|
||||||
break;
|
|
||||||
mTrkUART.Write(mExtTrkLog[i]);
|
|
||||||
}
|
|
||||||
mExtTrkLock.Unlock();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator delete(void *Pointer)
|
void operator delete(void *Pointer)
|
||||||
{
|
{
|
||||||
#ifdef DEBUG_ALLOCATIONS_SL
|
|
||||||
SmartLockClass lock___COUNTER__(OperatorAllocatorLock, (KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"));
|
|
||||||
#endif
|
|
||||||
memdbg("delete(%#lx)->[%s]", Pointer, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown");
|
|
||||||
|
|
||||||
HeapFree(Pointer);
|
HeapFree(Pointer);
|
||||||
#ifdef DEBUG
|
|
||||||
if (EnableExternalMemoryTracer)
|
|
||||||
{
|
|
||||||
char LockTmpStr[64];
|
|
||||||
strcpy_unsafe(LockTmpStr, __FUNCTION__);
|
|
||||||
strcat_unsafe(LockTmpStr, "_memTrk");
|
|
||||||
mExtTrkLock.TimeoutLock(LockTmpStr, 10000);
|
|
||||||
sprintf(mExtTrkLog, "delete( %p )~%p\n\r",
|
|
||||||
Pointer,
|
|
||||||
__builtin_return_address(0));
|
|
||||||
UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3);
|
|
||||||
for (short i = 0; i < MEM_TRK_MAX_SIZE; i++)
|
|
||||||
{
|
|
||||||
if (mExtTrkLog[i] == '\r')
|
|
||||||
break;
|
|
||||||
mTrkUART.Write(mExtTrkLog[i]);
|
|
||||||
}
|
|
||||||
mExtTrkLock.Unlock();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator delete[](void *Pointer)
|
void operator delete[](void *Pointer)
|
||||||
{
|
{
|
||||||
#ifdef DEBUG_ALLOCATIONS_SL
|
|
||||||
SmartLockClass lock___COUNTER__(OperatorAllocatorLock, (KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"));
|
|
||||||
#endif
|
|
||||||
memdbg("delete[](%#lx)->[%s]", Pointer, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown");
|
|
||||||
|
|
||||||
HeapFree(Pointer);
|
HeapFree(Pointer);
|
||||||
#ifdef DEBUG
|
|
||||||
if (EnableExternalMemoryTracer)
|
|
||||||
{
|
|
||||||
char LockTmpStr[64];
|
|
||||||
strcpy_unsafe(LockTmpStr, __FUNCTION__);
|
|
||||||
strcat_unsafe(LockTmpStr, "_memTrk");
|
|
||||||
mExtTrkLock.TimeoutLock(LockTmpStr, 10000);
|
|
||||||
sprintf(mExtTrkLog, "delete[]( %p )~%p\n\r",
|
|
||||||
Pointer,
|
|
||||||
__builtin_return_address(0));
|
|
||||||
UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3);
|
|
||||||
for (short i = 0; i < MEM_TRK_MAX_SIZE; i++)
|
|
||||||
{
|
|
||||||
if (mExtTrkLog[i] == '\r')
|
|
||||||
break;
|
|
||||||
mTrkUART.Write(mExtTrkLog[i]);
|
|
||||||
}
|
|
||||||
mExtTrkLock.Unlock();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator delete(void *Pointer, long unsigned int Size)
|
void operator delete(void *Pointer, long unsigned int Size)
|
||||||
{
|
{
|
||||||
UNUSED(Size);
|
|
||||||
#ifdef DEBUG_ALLOCATIONS_SL
|
|
||||||
SmartLockClass lock___COUNTER__(OperatorAllocatorLock, (KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"));
|
|
||||||
#endif
|
|
||||||
memdbg("delete(%#lx, %d)->[%s]", Pointer, Size, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown");
|
|
||||||
|
|
||||||
HeapFree(Pointer);
|
HeapFree(Pointer);
|
||||||
#ifdef DEBUG
|
|
||||||
if (EnableExternalMemoryTracer)
|
|
||||||
{
|
|
||||||
char LockTmpStr[64];
|
|
||||||
strcpy_unsafe(LockTmpStr, __FUNCTION__);
|
|
||||||
strcat_unsafe(LockTmpStr, "_memTrk");
|
|
||||||
mExtTrkLock.TimeoutLock(LockTmpStr, 10000);
|
|
||||||
sprintf(mExtTrkLog, "delete( %p %ld )~%p\n\r",
|
|
||||||
Pointer, Size,
|
|
||||||
__builtin_return_address(0));
|
|
||||||
UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3);
|
|
||||||
for (short i = 0; i < MEM_TRK_MAX_SIZE; i++)
|
|
||||||
{
|
|
||||||
if (mExtTrkLog[i] == '\r')
|
|
||||||
break;
|
|
||||||
mTrkUART.Write(mExtTrkLog[i]);
|
|
||||||
}
|
|
||||||
mExtTrkLock.Unlock();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator delete[](void *Pointer, long unsigned int Size)
|
void operator delete[](void *Pointer, long unsigned int Size)
|
||||||
{
|
{
|
||||||
UNUSED(Size);
|
|
||||||
#ifdef DEBUG_ALLOCATIONS_SL
|
|
||||||
SmartLockClass lock___COUNTER__(OperatorAllocatorLock, (KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"));
|
|
||||||
#endif
|
|
||||||
memdbg("delete[](%#lx, %d)->[%s]", Pointer, Size, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown");
|
|
||||||
|
|
||||||
HeapFree(Pointer);
|
HeapFree(Pointer);
|
||||||
#ifdef DEBUG
|
|
||||||
if (EnableExternalMemoryTracer)
|
|
||||||
{
|
|
||||||
char LockTmpStr[64];
|
|
||||||
strcpy_unsafe(LockTmpStr, __FUNCTION__);
|
|
||||||
strcat_unsafe(LockTmpStr, "_memTrk");
|
|
||||||
mExtTrkLock.TimeoutLock(LockTmpStr, 10000);
|
|
||||||
sprintf(mExtTrkLog, "delete[]( %p %ld )~%p\n\r",
|
|
||||||
Pointer, Size,
|
|
||||||
__builtin_return_address(0));
|
|
||||||
UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3);
|
|
||||||
for (short i = 0; i < MEM_TRK_MAX_SIZE; i++)
|
|
||||||
{
|
|
||||||
if (mExtTrkLog[i] == '\r')
|
|
||||||
break;
|
|
||||||
mTrkUART.Write(mExtTrkLog[i]);
|
|
||||||
}
|
|
||||||
mExtTrkLock.Unlock();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
@ -1,220 +0,0 @@
|
|||||||
#include <memory.hpp>
|
|
||||||
#include <debug.h>
|
|
||||||
|
|
||||||
#include "../../kernel.h"
|
|
||||||
|
|
||||||
namespace Memory
|
|
||||||
{
|
|
||||||
ReadFSFunction(MEM_Read)
|
|
||||||
{
|
|
||||||
if (!Size)
|
|
||||||
Size = node->Length;
|
|
||||||
if (Offset > node->Length)
|
|
||||||
return 0;
|
|
||||||
if (Offset + Size > node->Length)
|
|
||||||
Size = node->Length - Offset;
|
|
||||||
memcpy(Buffer, (uint8_t *)(node->Address + Offset), Size);
|
|
||||||
return Size;
|
|
||||||
}
|
|
||||||
|
|
||||||
WriteFSFunction(MEM_Write)
|
|
||||||
{
|
|
||||||
if (!Size)
|
|
||||||
Size = node->Length;
|
|
||||||
if (Offset > node->Length)
|
|
||||||
return 0;
|
|
||||||
if (Offset + Size > node->Length)
|
|
||||||
Size = node->Length - Offset;
|
|
||||||
memcpy((uint8_t *)(node->Address + Offset), Buffer, Size);
|
|
||||||
return Size;
|
|
||||||
}
|
|
||||||
|
|
||||||
VirtualFileSystem::FileSystemOperations mem_op = {
|
|
||||||
.Name = "mem",
|
|
||||||
.Read = MEM_Read,
|
|
||||||
.Write = MEM_Write,
|
|
||||||
};
|
|
||||||
|
|
||||||
uint64_t MemMgr::GetAllocatedMemorySize()
|
|
||||||
{
|
|
||||||
uint64_t Size = 0;
|
|
||||||
foreach (auto ap in AllocatedPagesList)
|
|
||||||
Size += ap.PageCount;
|
|
||||||
return FROM_PAGES(Size);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MemMgr::Add(void *Address, size_t Count)
|
|
||||||
{
|
|
||||||
if (Address == nullptr)
|
|
||||||
{
|
|
||||||
error("Address is null!");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Count == 0)
|
|
||||||
{
|
|
||||||
error("Count is 0!");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = 0; i < AllocatedPagesList.size(); i++)
|
|
||||||
{
|
|
||||||
if (AllocatedPagesList[i].Address == Address)
|
|
||||||
{
|
|
||||||
error("Address already exists!");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else if ((uintptr_t)Address < (uintptr_t)AllocatedPagesList[i].Address)
|
|
||||||
{
|
|
||||||
if ((uintptr_t)Address + (Count * PAGE_SIZE) > (uintptr_t)AllocatedPagesList[i].Address)
|
|
||||||
{
|
|
||||||
error("Address intersects with an allocated page!");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if ((uintptr_t)AllocatedPagesList[i].Address + (AllocatedPagesList[i].PageCount * PAGE_SIZE) > (uintptr_t)Address)
|
|
||||||
{
|
|
||||||
error("Address intersects with an allocated page!");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this->Directory)
|
|
||||||
{
|
|
||||||
char FileName[64];
|
|
||||||
sprintf(FileName, "%lx-%ld", (uintptr_t)Address, Count);
|
|
||||||
VirtualFileSystem::Node *n = vfs->Create(FileName, VirtualFileSystem::NodeFlags::FILE, this->Directory);
|
|
||||||
if (n)
|
|
||||||
{
|
|
||||||
n->Address = (uintptr_t)Address;
|
|
||||||
n->Length = Count * PAGE_SIZE;
|
|
||||||
n->Operator = &mem_op;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
AllocatedPagesList.push_back({Address, Count});
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *MemMgr::RequestPages(size_t Count, bool User)
|
|
||||||
{
|
|
||||||
void *Address = KernelAllocator.RequestPages(Count);
|
|
||||||
for (size_t i = 0; i < Count; i++)
|
|
||||||
{
|
|
||||||
int Flags = Memory::PTFlag::RW;
|
|
||||||
if (User)
|
|
||||||
Flags |= Memory::PTFlag::US;
|
|
||||||
Memory::Virtual(this->PageTable).Remap((void *)((uintptr_t)Address + (i * PAGE_SIZE)), (void *)((uint64_t)Address + (i * PAGE_SIZE)), Flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this->Directory)
|
|
||||||
{
|
|
||||||
char FileName[64];
|
|
||||||
sprintf(FileName, "%lx-%ld", (uintptr_t)Address, Count);
|
|
||||||
VirtualFileSystem::Node *n = vfs->Create(FileName, VirtualFileSystem::NodeFlags::FILE, this->Directory);
|
|
||||||
if (n) // If null, error or file already exists
|
|
||||||
{
|
|
||||||
n->Address = (uintptr_t)Address;
|
|
||||||
n->Length = Count * PAGE_SIZE;
|
|
||||||
n->Operator = &mem_op;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
AllocatedPagesList.push_back({Address, Count});
|
|
||||||
|
|
||||||
/* For security reasons, we clear the memory
|
|
||||||
if the page is user accessible. */
|
|
||||||
if (User)
|
|
||||||
memset(Address, 0, Count * PAGE_SIZE);
|
|
||||||
return Address;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MemMgr::FreePages(void *Address, size_t Count)
|
|
||||||
{
|
|
||||||
for (size_t i = 0; i < AllocatedPagesList.size(); i++)
|
|
||||||
if (AllocatedPagesList[i].Address == Address)
|
|
||||||
{
|
|
||||||
/** TODO: Advanced checks. Allow if the page count is less than the requested one.
|
|
||||||
* This will allow the user to free only a part of the allocated pages.
|
|
||||||
*
|
|
||||||
* But this will be in a separate function because we need to specify if we
|
|
||||||
* want to free from the start or from the end and return the new address.
|
|
||||||
*/
|
|
||||||
if (AllocatedPagesList[i].PageCount != Count)
|
|
||||||
{
|
|
||||||
error("Page count mismatch! (Allocated: %lld, Requested: %lld)", AllocatedPagesList[i].PageCount, Count);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
KernelAllocator.FreePages(Address, Count);
|
|
||||||
for (size_t i = 0; i < Count; i++)
|
|
||||||
Memory::Virtual(this->PageTable).Remap((void *)((uintptr_t)Address + (i * PAGE_SIZE)), (void *)((uint64_t)Address + (i * PAGE_SIZE)), Memory::PTFlag::RW);
|
|
||||||
// Memory::Virtual(this->PageTable).Unmap((void *)((uintptr_t)Address + (i * PAGE_SIZE)));
|
|
||||||
|
|
||||||
if (this->Directory)
|
|
||||||
{
|
|
||||||
char FileName[64];
|
|
||||||
sprintf(FileName, "%lx-%ld", (uintptr_t)Address, Count);
|
|
||||||
VirtualFileSystem::FileStatus s = vfs->Delete(FileName, false, this->Directory);
|
|
||||||
if (s != VirtualFileSystem::FileStatus::OK)
|
|
||||||
error("Failed to delete file %s", FileName);
|
|
||||||
}
|
|
||||||
|
|
||||||
AllocatedPagesList.remove(i);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MemMgr::DetachAddress(void *Address)
|
|
||||||
{
|
|
||||||
for (size_t i = 0; i < AllocatedPagesList.size(); i++)
|
|
||||||
if (AllocatedPagesList[i].Address == Address)
|
|
||||||
{
|
|
||||||
if (this->Directory)
|
|
||||||
{
|
|
||||||
char FileName[64];
|
|
||||||
sprintf(FileName, "%lx-%ld", (uintptr_t)Address, AllocatedPagesList[i].PageCount);
|
|
||||||
VirtualFileSystem::FileStatus s = vfs->Delete(FileName, false, this->Directory);
|
|
||||||
if (s != VirtualFileSystem::FileStatus::OK)
|
|
||||||
error("Failed to delete file %s", FileName);
|
|
||||||
}
|
|
||||||
|
|
||||||
AllocatedPagesList.remove(i);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MemMgr::MemMgr(PageTable4 *PageTable, VirtualFileSystem::Node *Directory)
|
|
||||||
{
|
|
||||||
if (PageTable)
|
|
||||||
this->PageTable = PageTable;
|
|
||||||
else
|
|
||||||
#if defined(a64)
|
|
||||||
this->PageTable = (PageTable4 *)CPU::x64::readcr3().raw;
|
|
||||||
#elif defined(a32)
|
|
||||||
this->PageTable = (PageTable4 *)CPU::x32::readcr3().raw;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
this->Directory = Directory;
|
|
||||||
debug("+ %#lx", this);
|
|
||||||
}
|
|
||||||
|
|
||||||
MemMgr::~MemMgr()
|
|
||||||
{
|
|
||||||
foreach (auto ap in AllocatedPagesList)
|
|
||||||
{
|
|
||||||
KernelAllocator.FreePages(ap.Address, ap.PageCount);
|
|
||||||
for (size_t i = 0; i < ap.PageCount; i++)
|
|
||||||
Memory::Virtual(this->PageTable).Remap((void *)((uintptr_t)ap.Address + (i * PAGE_SIZE)), (void *)((uintptr_t)ap.Address + (i * PAGE_SIZE)), Memory::PTFlag::RW);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this->Directory)
|
|
||||||
foreach (auto Child in this->Directory->Children)
|
|
||||||
vfs->Delete(Child, true);
|
|
||||||
|
|
||||||
debug("- %#lx", this);
|
|
||||||
}
|
|
||||||
}
|
|
42
Kernel/Core/Memory/PageDirectoryEntry.cpp
Normal file
42
Kernel/Core/Memory/PageDirectoryEntry.cpp
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
#include <memory.hpp>
|
||||||
|
|
||||||
|
namespace Memory
|
||||||
|
{
|
||||||
|
void PageDirectoryEntry::AddFlag(uint64_t Flag) { this->Value.raw |= Flag; }
|
||||||
|
void PageDirectoryEntry::RemoveFlags(uint64_t Flag) { this->Value.raw &= ~Flag; }
|
||||||
|
void PageDirectoryEntry::ClearFlags() { this->Value.raw = 0; }
|
||||||
|
void PageDirectoryEntry::SetFlag(uint64_t Flag, bool Enabled)
|
||||||
|
{
|
||||||
|
this->Value.raw = 0;
|
||||||
|
if (Enabled)
|
||||||
|
this->Value.raw |= Flag;
|
||||||
|
}
|
||||||
|
bool PageDirectoryEntry::GetFlag(uint64_t Flag) { return (this->Value.raw & Flag) > 0 ? true : false; }
|
||||||
|
uint64_t PageDirectoryEntry::GetFlag() { return this->Value.raw; }
|
||||||
|
void PageDirectoryEntry::SetAddress(uint64_t Address)
|
||||||
|
{
|
||||||
|
#if defined(__amd64__)
|
||||||
|
Address &= 0x000000FFFFFFFFFF;
|
||||||
|
this->Value.raw &= 0xFFF0000000000FFF;
|
||||||
|
this->Value.raw |= (Address << 12);
|
||||||
|
#elif defined(__i386__)
|
||||||
|
Address &= 0x000FFFFF;
|
||||||
|
this->Value.raw &= 0xFFC00003;
|
||||||
|
this->Value.raw |= (Address << 12);
|
||||||
|
#elif defined(__aarch64__)
|
||||||
|
Address &= 0x000000FFFFFFFFFF;
|
||||||
|
this->Value.raw &= 0xFFF0000000000FFF;
|
||||||
|
this->Value.raw |= (Address << 12);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
uint64_t PageDirectoryEntry::GetAddress()
|
||||||
|
{
|
||||||
|
#if defined(__amd64__)
|
||||||
|
return (this->Value.raw & 0x000FFFFFFFFFF000) >> 12;
|
||||||
|
#elif defined(__i386__)
|
||||||
|
return (this->Value.raw & 0x003FFFFF000) >> 12;
|
||||||
|
#elif defined(__aarch64__)
|
||||||
|
return (this->Value.raw & 0x000FFFFFFFFFF000) >> 12;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
@ -2,27 +2,27 @@
|
|||||||
|
|
||||||
namespace Memory
|
namespace Memory
|
||||||
{
|
{
|
||||||
Virtual::PageMapIndexer::PageMapIndexer(uintptr_t VirtualAddress)
|
Virtual::PageMapIndexer::PageMapIndexer(uint64_t VirtualAddress)
|
||||||
{
|
{
|
||||||
#if defined(a64)
|
#if defined(__amd64__)
|
||||||
uintptr_t Address = VirtualAddress;
|
uint64_t Address = VirtualAddress;
|
||||||
Address >>= 12;
|
Address >>= 12;
|
||||||
this->PTEIndex = Address & 0x1FF;
|
this->PIndex = Address & 0x1FF;
|
||||||
Address >>= 9;
|
Address >>= 9;
|
||||||
this->PDEIndex = Address & 0x1FF;
|
this->PTIndex = Address & 0x1FF;
|
||||||
Address >>= 9;
|
Address >>= 9;
|
||||||
this->PDPTEIndex = Address & 0x1FF;
|
this->PDIndex = Address & 0x1FF;
|
||||||
Address >>= 9;
|
Address >>= 9;
|
||||||
this->PMLIndex = Address & 0x1FF;
|
this->PDPIndex = Address & 0x1FF;
|
||||||
#elif defined(a32)
|
#elif defined(__i386__)
|
||||||
uintptr_t Address = VirtualAddress;
|
uint64_t Address = VirtualAddress;
|
||||||
Address >>= 12;
|
Address >>= 12;
|
||||||
this->PTEIndex = Address & 0x3FF;
|
this->PIndex = Address & 0x3FF;
|
||||||
Address >>= 10;
|
Address >>= 10;
|
||||||
this->PDEIndex = Address & 0x3FF;
|
this->PTIndex = Address & 0x3FF;
|
||||||
Address >>= 10;
|
Address >>= 10;
|
||||||
this->PDPTEIndex = Address & 0x3FF;
|
this->PDIndex = Address & 0x3FF;
|
||||||
#elif defined(aa64)
|
#elif defined(__aarch64__)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,6 @@
|
|||||||
#include <memory.hpp>
|
#include <memory.hpp>
|
||||||
|
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
#ifdef DEBUG
|
|
||||||
#include <uart.hpp>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "../../kernel.h"
|
|
||||||
|
|
||||||
extern "C" char BootPageTable[]; // 0x10000 in length
|
|
||||||
|
|
||||||
namespace Memory
|
namespace Memory
|
||||||
{
|
{
|
||||||
@ -41,10 +34,10 @@ namespace Memory
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Physical::SwapPages(void *Address, size_t PageCount)
|
bool Physical::SwapPages(void *Address, uint64_t PageCount)
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < PageCount; i++)
|
for (uint64_t i = 0; i < PageCount; i++)
|
||||||
if (!this->SwapPage((void *)((uintptr_t)Address + (i * PAGE_SIZE))))
|
if (!this->SwapPage((void *)((uint64_t)Address + (i * PAGE_SIZE))))
|
||||||
return false;
|
return false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -55,10 +48,10 @@ namespace Memory
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Physical::UnswapPages(void *Address, size_t PageCount)
|
bool Physical::UnswapPages(void *Address, uint64_t PageCount)
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < PageCount; i++)
|
for (uint64_t i = 0; i < PageCount; i++)
|
||||||
if (!this->UnswapPage((void *)((uintptr_t)Address + (i * PAGE_SIZE))))
|
if (!this->UnswapPage((void *)((uint64_t)Address + (i * PAGE_SIZE))))
|
||||||
return false;
|
return false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -77,34 +70,15 @@ namespace Memory
|
|||||||
if (this->SwapPage((void *)(PageBitmapIndex * PAGE_SIZE)))
|
if (this->SwapPage((void *)(PageBitmapIndex * PAGE_SIZE)))
|
||||||
{
|
{
|
||||||
this->LockPage((void *)(PageBitmapIndex * PAGE_SIZE));
|
this->LockPage((void *)(PageBitmapIndex * PAGE_SIZE));
|
||||||
#ifdef DEBUG
|
|
||||||
if (EnableExternalMemoryTracer)
|
|
||||||
{
|
|
||||||
char LockTmpStr[64];
|
|
||||||
strcpy_unsafe(LockTmpStr, __FUNCTION__);
|
|
||||||
strcat_unsafe(LockTmpStr, "_memTrk");
|
|
||||||
mExtTrkLock.TimeoutLock(LockTmpStr, 10000);
|
|
||||||
sprintf(mExtTrkLog, "RequestPage( )=%p~%p\n\r",
|
|
||||||
(void *)(PageBitmapIndex * PAGE_SIZE), __builtin_return_address(0));
|
|
||||||
UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3);
|
|
||||||
for (short i = 0; i < MEM_TRK_MAX_SIZE; i++)
|
|
||||||
{
|
|
||||||
if (mExtTrkLog[i] == '\r')
|
|
||||||
break;
|
|
||||||
mTrkUART.Write(mExtTrkLog[i]);
|
|
||||||
}
|
|
||||||
mExtTrkLock.Unlock();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return (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));
|
error("Out of memory! (Free: %ldMB; Used: %ldMB; Reserved: %ldMB)", TO_MB(FreeMemory), TO_MB(UsedMemory), TO_MB(ReservedMemory));
|
||||||
CPU::Stop();
|
CPU::Halt(true);
|
||||||
__builtin_unreachable();
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *Physical::RequestPages(size_t Count)
|
void *Physical::RequestPages(uint64_t Count)
|
||||||
{
|
{
|
||||||
SmartLock(this->MemoryLock);
|
SmartLock(this->MemoryLock);
|
||||||
for (; PageBitmapIndex < PageBitmap.Size * 8; PageBitmapIndex++)
|
for (; PageBitmapIndex < PageBitmap.Size * 8; PageBitmapIndex++)
|
||||||
@ -117,31 +91,11 @@ namespace Memory
|
|||||||
if (PageBitmap[Index] == true)
|
if (PageBitmap[Index] == true)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
for (size_t i = 0; i < Count; i++)
|
for (uint64_t i = 0; i < Count; i++)
|
||||||
if (PageBitmap[Index + i] == true)
|
if (PageBitmap[Index + i] == true)
|
||||||
goto NextPage;
|
goto NextPage;
|
||||||
|
|
||||||
this->LockPages((void *)(Index * PAGE_SIZE), Count);
|
this->LockPages((void *)(Index * PAGE_SIZE), Count);
|
||||||
#ifdef DEBUG
|
|
||||||
if (EnableExternalMemoryTracer)
|
|
||||||
{
|
|
||||||
char LockTmpStr[64];
|
|
||||||
strcpy_unsafe(LockTmpStr, __FUNCTION__);
|
|
||||||
strcat_unsafe(LockTmpStr, "_memTrk");
|
|
||||||
mExtTrkLock.TimeoutLock(LockTmpStr, 10000);
|
|
||||||
sprintf(mExtTrkLog, "RequestPages( %ld )=%p~%p\n\r",
|
|
||||||
Count,
|
|
||||||
(void *)(Index * PAGE_SIZE), __builtin_return_address(0));
|
|
||||||
UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3);
|
|
||||||
for (short i = 0; i < MEM_TRK_MAX_SIZE; i++)
|
|
||||||
{
|
|
||||||
if (mExtTrkLog[i] == '\r')
|
|
||||||
break;
|
|
||||||
mTrkUART.Write(mExtTrkLog[i]);
|
|
||||||
}
|
|
||||||
mExtTrkLock.Unlock();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return (void *)(Index * PAGE_SIZE);
|
return (void *)(Index * PAGE_SIZE);
|
||||||
|
|
||||||
NextPage:
|
NextPage:
|
||||||
@ -153,32 +107,12 @@ namespace Memory
|
|||||||
if (this->SwapPages((void *)(PageBitmapIndex * PAGE_SIZE), Count))
|
if (this->SwapPages((void *)(PageBitmapIndex * PAGE_SIZE), Count))
|
||||||
{
|
{
|
||||||
this->LockPages((void *)(PageBitmapIndex * PAGE_SIZE), Count);
|
this->LockPages((void *)(PageBitmapIndex * PAGE_SIZE), Count);
|
||||||
#ifdef DEBUG
|
|
||||||
if (EnableExternalMemoryTracer)
|
|
||||||
{
|
|
||||||
char LockTmpStr[64];
|
|
||||||
strcpy_unsafe(LockTmpStr, __FUNCTION__);
|
|
||||||
strcat_unsafe(LockTmpStr, "_memTrk");
|
|
||||||
mExtTrkLock.TimeoutLock(LockTmpStr, 10000);
|
|
||||||
sprintf(mExtTrkLog, "RequestPages( %ld )=%p~%p\n\r",
|
|
||||||
Count,
|
|
||||||
(void *)(PageBitmapIndex * PAGE_SIZE), __builtin_return_address(0));
|
|
||||||
UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3);
|
|
||||||
for (short i = 0; i < MEM_TRK_MAX_SIZE; i++)
|
|
||||||
{
|
|
||||||
if (mExtTrkLog[i] == '\r')
|
|
||||||
break;
|
|
||||||
mTrkUART.Write(mExtTrkLog[i]);
|
|
||||||
}
|
|
||||||
mExtTrkLock.Unlock();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return (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));
|
error("Out of memory! (Free: %ldMB; Used: %ldMB; Reserved: %ldMB)", TO_MB(FreeMemory), TO_MB(UsedMemory), TO_MB(ReservedMemory));
|
||||||
CPU::Halt(true);
|
CPU::Halt(true);
|
||||||
__builtin_unreachable();
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Physical::FreePage(void *Address)
|
void Physical::FreePage(void *Address)
|
||||||
@ -189,7 +123,7 @@ namespace Memory
|
|||||||
warn("Null pointer passed to FreePage.");
|
warn("Null pointer passed to FreePage.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
size_t Index = (size_t)Address / PAGE_SIZE;
|
uint64_t Index = (uint64_t)Address / PAGE_SIZE;
|
||||||
if (unlikely(PageBitmap[Index] == false))
|
if (unlikely(PageBitmap[Index] == false))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -200,58 +134,18 @@ namespace Memory
|
|||||||
if (PageBitmapIndex > Index)
|
if (PageBitmapIndex > Index)
|
||||||
PageBitmapIndex = Index;
|
PageBitmapIndex = Index;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
if (EnableExternalMemoryTracer)
|
|
||||||
{
|
|
||||||
char LockTmpStr[64];
|
|
||||||
strcpy_unsafe(LockTmpStr, __FUNCTION__);
|
|
||||||
strcat_unsafe(LockTmpStr, "_memTrk");
|
|
||||||
mExtTrkLock.TimeoutLock(LockTmpStr, 10000);
|
|
||||||
sprintf(mExtTrkLog, "FreePage( %p )~%p\n\r",
|
|
||||||
Address,
|
|
||||||
__builtin_return_address(0));
|
|
||||||
UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3);
|
|
||||||
for (short i = 0; i < MEM_TRK_MAX_SIZE; i++)
|
|
||||||
{
|
|
||||||
if (mExtTrkLog[i] == '\r')
|
|
||||||
break;
|
|
||||||
mTrkUART.Write(mExtTrkLog[i]);
|
|
||||||
}
|
|
||||||
mExtTrkLock.Unlock();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Physical::FreePages(void *Address, size_t Count)
|
void Physical::FreePages(void *Address, uint64_t Count)
|
||||||
{
|
{
|
||||||
if (unlikely(Address == nullptr || Count == 0))
|
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" : "");
|
warn("%s%s passed to FreePages.", Address == nullptr ? "Null pointer" : "", Count == 0 ? "Zero count" : "");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#ifdef DEBUG
|
|
||||||
if (EnableExternalMemoryTracer)
|
for (uint64_t t = 0; t < Count; t++)
|
||||||
{
|
this->FreePage((void *)((uint64_t)Address + (t * PAGE_SIZE)));
|
||||||
char LockTmpStr[64];
|
|
||||||
strcpy_unsafe(LockTmpStr, __FUNCTION__);
|
|
||||||
strcat_unsafe(LockTmpStr, "_memTrk");
|
|
||||||
mExtTrkLock.TimeoutLock(LockTmpStr, 10000);
|
|
||||||
sprintf(mExtTrkLog, "!FreePages( %p %ld )~%p\n\r",
|
|
||||||
Address, Count,
|
|
||||||
__builtin_return_address(0));
|
|
||||||
UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3);
|
|
||||||
for (short i = 0; i < MEM_TRK_MAX_SIZE; i++)
|
|
||||||
{
|
|
||||||
if (mExtTrkLog[i] == '\r')
|
|
||||||
break;
|
|
||||||
mTrkUART.Write(mExtTrkLog[i]);
|
|
||||||
}
|
|
||||||
mExtTrkLock.Unlock();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
for (size_t t = 0; t < Count; t++)
|
|
||||||
this->FreePage((void *)((uintptr_t)Address + (t * PAGE_SIZE)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Physical::LockPage(void *Address)
|
void Physical::LockPage(void *Address)
|
||||||
@ -259,7 +153,7 @@ namespace Memory
|
|||||||
if (unlikely(Address == nullptr))
|
if (unlikely(Address == nullptr))
|
||||||
warn("Trying to lock null address.");
|
warn("Trying to lock null address.");
|
||||||
|
|
||||||
uintptr_t Index = (uintptr_t)Address / PAGE_SIZE;
|
uint64_t Index = (uint64_t)Address / PAGE_SIZE;
|
||||||
if (unlikely(PageBitmap[Index] == true))
|
if (unlikely(PageBitmap[Index] == true))
|
||||||
return;
|
return;
|
||||||
if (PageBitmap.Set(Index, true))
|
if (PageBitmap.Set(Index, true))
|
||||||
@ -269,13 +163,13 @@ namespace Memory
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Physical::LockPages(void *Address, size_t PageCount)
|
void Physical::LockPages(void *Address, uint64_t PageCount)
|
||||||
{
|
{
|
||||||
if (unlikely(Address == nullptr || PageCount == 0))
|
if (unlikely(Address == nullptr || PageCount == 0))
|
||||||
warn("Trying to lock %s%s.", Address ? "null address" : "", PageCount ? "0 pages" : "");
|
warn("Trying to lock %s%s.", Address ? "null address" : "", PageCount ? "0 pages" : "");
|
||||||
|
|
||||||
for (size_t i = 0; i < PageCount; i++)
|
for (uint64_t i = 0; i < PageCount; i++)
|
||||||
this->LockPage((void *)((uintptr_t)Address + (i * PAGE_SIZE)));
|
this->LockPage((void *)((uint64_t)Address + (i * PAGE_SIZE)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Physical::ReservePage(void *Address)
|
void Physical::ReservePage(void *Address)
|
||||||
@ -283,7 +177,7 @@ namespace Memory
|
|||||||
if (unlikely(Address == nullptr))
|
if (unlikely(Address == nullptr))
|
||||||
warn("Trying to reserve null address.");
|
warn("Trying to reserve null address.");
|
||||||
|
|
||||||
uintptr_t Index = (uintptr_t)Address / PAGE_SIZE;
|
uint64_t Index = (uint64_t)Address / PAGE_SIZE;
|
||||||
if (unlikely(PageBitmap[Index] == true))
|
if (unlikely(PageBitmap[Index] == true))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -294,13 +188,13 @@ namespace Memory
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Physical::ReservePages(void *Address, size_t PageCount)
|
void Physical::ReservePages(void *Address, uint64_t PageCount)
|
||||||
{
|
{
|
||||||
if (unlikely(Address == nullptr || PageCount == 0))
|
if (unlikely(Address == nullptr || PageCount == 0))
|
||||||
warn("Trying to reserve %s%s.", Address ? "null address" : "", PageCount ? "0 pages" : "");
|
warn("Trying to reserve %s%s.", Address ? "null address" : "", PageCount ? "0 pages" : "");
|
||||||
|
|
||||||
for (size_t t = 0; t < PageCount; t++)
|
for (uint64_t t = 0; t < PageCount; t++)
|
||||||
this->ReservePage((void *)((uintptr_t)Address + (t * PAGE_SIZE)));
|
this->ReservePage((void *)((uint64_t)Address + (t * PAGE_SIZE)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Physical::UnreservePage(void *Address)
|
void Physical::UnreservePage(void *Address)
|
||||||
@ -308,7 +202,7 @@ namespace Memory
|
|||||||
if (unlikely(Address == nullptr))
|
if (unlikely(Address == nullptr))
|
||||||
warn("Trying to unreserve null address.");
|
warn("Trying to unreserve null address.");
|
||||||
|
|
||||||
uintptr_t Index = (uintptr_t)Address / PAGE_SIZE;
|
uint64_t Index = (uint64_t)Address / PAGE_SIZE;
|
||||||
if (unlikely(PageBitmap[Index] == false))
|
if (unlikely(PageBitmap[Index] == false))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -321,13 +215,13 @@ namespace Memory
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Physical::UnreservePages(void *Address, size_t PageCount)
|
void Physical::UnreservePages(void *Address, uint64_t PageCount)
|
||||||
{
|
{
|
||||||
if (unlikely(Address == nullptr || PageCount == 0))
|
if (unlikely(Address == nullptr || PageCount == 0))
|
||||||
warn("Trying to unreserve %s%s.", Address ? "null address" : "", PageCount ? "0 pages" : "");
|
warn("Trying to unreserve %s%s.", Address ? "null address" : "", PageCount ? "0 pages" : "");
|
||||||
|
|
||||||
for (size_t t = 0; t < PageCount; t++)
|
for (uint64_t t = 0; t < PageCount; t++)
|
||||||
this->UnreservePage((void *)((uintptr_t)Address + (t * PAGE_SIZE)));
|
this->UnreservePage((void *)((uint64_t)Address + (t * PAGE_SIZE)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Physical::Init(BootInfo *Info)
|
void Physical::Init(BootInfo *Info)
|
||||||
@ -359,24 +253,22 @@ namespace Memory
|
|||||||
CPU::Stop();
|
CPU::Stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t BitmapSize = (MemorySize / PAGE_SIZE) / 8 + 1;
|
uint64_t BitmapSize = (MemorySize / PAGE_SIZE) / 8 + 1;
|
||||||
trace("Initializing Bitmap at %llp-%llp (%lld Bytes)",
|
trace("Initializing Bitmap at %llp-%llp (%lld Bytes)",
|
||||||
LargestFreeMemorySegment,
|
LargestFreeMemorySegment,
|
||||||
(void *)((uintptr_t)LargestFreeMemorySegment + BitmapSize),
|
(void *)((uint64_t)LargestFreeMemorySegment + BitmapSize),
|
||||||
BitmapSize);
|
BitmapSize);
|
||||||
PageBitmap.Size = BitmapSize;
|
PageBitmap.Size = BitmapSize;
|
||||||
PageBitmap.Buffer = (uint8_t *)LargestFreeMemorySegment;
|
PageBitmap.Buffer = (uint8_t *)LargestFreeMemorySegment;
|
||||||
for (size_t i = 0; i < BitmapSize; i++)
|
for (uint64_t i = 0; i < BitmapSize; i++)
|
||||||
*(uint8_t *)(PageBitmap.Buffer + i) = 0;
|
*(uint8_t *)(PageBitmap.Buffer + i) = 0;
|
||||||
|
|
||||||
trace("Reserving pages...");
|
trace("Reserving pages...");
|
||||||
for (uint64_t i = 0; i < Info->Memory.Entries; i++)
|
for (uint64_t i = 0; i < Info->Memory.Entries; i++)
|
||||||
if (Info->Memory.Entry[i].Type != Usable)
|
if (Info->Memory.Entry[i].Type != Usable)
|
||||||
this->ReservePages((void *)Info->Memory.Entry[i].BaseAddress, Info->Memory.Entry[i].Length / PAGE_SIZE + 1);
|
this->ReservePages((void *)Info->Memory.Entry[i].BaseAddress, Info->Memory.Entry[i].Length / PAGE_SIZE + 1);
|
||||||
|
|
||||||
this->ReservePages(0, 0x100);
|
|
||||||
this->ReservePages(BootPageTable, TO_PAGES(0x10000));
|
|
||||||
trace("Locking bitmap pages...");
|
trace("Locking bitmap pages...");
|
||||||
|
this->ReservePages(0, 0x100);
|
||||||
this->LockPages(PageBitmap.Buffer, PageBitmap.Size / PAGE_SIZE + 1);
|
this->LockPages(PageBitmap.Buffer, PageBitmap.Size / PAGE_SIZE + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
namespace Memory
|
namespace Memory
|
||||||
{
|
{
|
||||||
StackGuard::StackGuard(bool User, PageTable4 *Table)
|
StackGuard::StackGuard(bool User, PageTable *Table)
|
||||||
{
|
{
|
||||||
this->UserMode = User;
|
this->UserMode = User;
|
||||||
this->Table = Table;
|
this->Table = Table;
|
||||||
@ -13,28 +13,22 @@ namespace Memory
|
|||||||
void *AllocatedStack = KernelAllocator.RequestPages(TO_PAGES(USER_STACK_SIZE));
|
void *AllocatedStack = KernelAllocator.RequestPages(TO_PAGES(USER_STACK_SIZE));
|
||||||
debug("AllocatedStack: %p", AllocatedStack);
|
debug("AllocatedStack: %p", AllocatedStack);
|
||||||
memset(AllocatedStack, 0, USER_STACK_SIZE);
|
memset(AllocatedStack, 0, USER_STACK_SIZE);
|
||||||
for (size_t i = 0; i < TO_PAGES(USER_STACK_SIZE); i++)
|
for (uint64_t i = 0; i < TO_PAGES(USER_STACK_SIZE); i++)
|
||||||
{
|
{
|
||||||
Virtual(Table).Map((void *)(USER_STACK_BASE + (i * PAGE_SIZE)),
|
Virtual(Table).Map((void *)((uint64_t)AllocatedStack + (i * PAGE_SIZE)),
|
||||||
(void *)((uintptr_t)AllocatedStack + (i * PAGE_SIZE)),
|
(void *)(USER_STACK_BASE + (i * PAGE_SIZE)),
|
||||||
PTFlag::RW | PTFlag::US);
|
PTFlag::RW | PTFlag::US);
|
||||||
debug("Mapped %p to %p", (void *)(USER_STACK_BASE + (i * PAGE_SIZE)),
|
|
||||||
(void *)((uintptr_t)AllocatedStack + (i * PAGE_SIZE)));
|
|
||||||
}
|
}
|
||||||
this->StackBottom = (void *)USER_STACK_BASE;
|
this->StackBottom = (void *)USER_STACK_BASE;
|
||||||
this->StackTop = (void *)(USER_STACK_BASE + USER_STACK_SIZE);
|
this->StackTop = (void *)(USER_STACK_BASE + USER_STACK_SIZE);
|
||||||
this->StackPhyiscalBottom = AllocatedStack;
|
|
||||||
this->StackPhyiscalTop = (void *)((uintptr_t)AllocatedStack + USER_STACK_SIZE);
|
|
||||||
this->Size = USER_STACK_SIZE;
|
this->Size = USER_STACK_SIZE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
this->StackBottom = KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE));
|
this->StackBottom = KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE));
|
||||||
this->StackPhyiscalBottom = this->StackBottom;
|
|
||||||
debug("StackBottom: %p", this->StackBottom);
|
debug("StackBottom: %p", this->StackBottom);
|
||||||
memset(this->StackBottom, 0, STACK_SIZE);
|
memset(this->StackBottom, 0, STACK_SIZE);
|
||||||
this->StackTop = (void *)((uintptr_t)this->StackBottom + STACK_SIZE);
|
this->StackTop = (void *)((uint64_t)this->StackBottom + STACK_SIZE);
|
||||||
this->StackPhyiscalTop = this->StackTop;
|
|
||||||
this->Size = STACK_SIZE;
|
this->Size = STACK_SIZE;
|
||||||
}
|
}
|
||||||
trace("Allocated stack at %p", this->StackBottom);
|
trace("Allocated stack at %p", this->StackBottom);
|
||||||
@ -47,12 +41,12 @@ namespace Memory
|
|||||||
// debug("Freed stack at %p", this->StackBottom);
|
// debug("Freed stack at %p", this->StackBottom);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool StackGuard::Expand(uintptr_t FaultAddress)
|
bool StackGuard::Expand(uint64_t FaultAddress)
|
||||||
{
|
{
|
||||||
if (this->UserMode)
|
if (this->UserMode)
|
||||||
{
|
{
|
||||||
if (FaultAddress < (uintptr_t)this->StackBottom - USER_STACK_SIZE ||
|
if (FaultAddress < (uint64_t)this->StackBottom - USER_STACK_SIZE ||
|
||||||
FaultAddress > (uintptr_t)this->StackTop)
|
FaultAddress > (uint64_t)this->StackTop)
|
||||||
{
|
{
|
||||||
return false; // It's not about the stack.
|
return false; // It's not about the stack.
|
||||||
}
|
}
|
||||||
@ -61,12 +55,9 @@ namespace Memory
|
|||||||
void *AllocatedStack = KernelAllocator.RequestPages(TO_PAGES(USER_STACK_SIZE));
|
void *AllocatedStack = KernelAllocator.RequestPages(TO_PAGES(USER_STACK_SIZE));
|
||||||
debug("AllocatedStack: %p", AllocatedStack);
|
debug("AllocatedStack: %p", AllocatedStack);
|
||||||
memset(AllocatedStack, 0, USER_STACK_SIZE);
|
memset(AllocatedStack, 0, USER_STACK_SIZE);
|
||||||
for (uintptr_t i = 0; i < TO_PAGES(USER_STACK_SIZE); i++)
|
for (uint64_t i = 0; i < TO_PAGES(USER_STACK_SIZE); i++)
|
||||||
{
|
Virtual(this->Table).Map((void *)((uint64_t)AllocatedStack + (i * PAGE_SIZE)), (void *)((uint64_t)this->StackBottom - (i * PAGE_SIZE)), PTFlag::RW | PTFlag::US);
|
||||||
Virtual(this->Table).Map((void *)((uintptr_t)this->StackBottom - (i * PAGE_SIZE)), (void *)((uintptr_t)AllocatedStack + (i * PAGE_SIZE)), PTFlag::RW | PTFlag::US);
|
this->StackBottom = (void *)((uint64_t)this->StackBottom - USER_STACK_SIZE);
|
||||||
debug("Mapped %p to %p", (void *)((uintptr_t)this->StackBottom - (i * PAGE_SIZE)), (void *)((uintptr_t)AllocatedStack + (i * PAGE_SIZE)));
|
|
||||||
}
|
|
||||||
this->StackBottom = (void *)((uintptr_t)this->StackBottom - USER_STACK_SIZE);
|
|
||||||
this->Size += USER_STACK_SIZE;
|
this->Size += USER_STACK_SIZE;
|
||||||
info("Stack expanded to %p", this->StackBottom);
|
info("Stack expanded to %p", this->StackBottom);
|
||||||
return true;
|
return true;
|
||||||
|
@ -8,35 +8,37 @@ namespace Memory
|
|||||||
bool Virtual::Check(void *VirtualAddress, PTFlag Flag)
|
bool Virtual::Check(void *VirtualAddress, PTFlag Flag)
|
||||||
{
|
{
|
||||||
// 0x1000 aligned
|
// 0x1000 aligned
|
||||||
uintptr_t Address = (uintptr_t)VirtualAddress;
|
uint64_t Address = (uint64_t)VirtualAddress;
|
||||||
Address &= 0xFFFFFFFFFFFFF000;
|
Address &= 0xFFFFFFFFFFFFF000;
|
||||||
|
|
||||||
PageMapIndexer Index = PageMapIndexer(Address);
|
PageMapIndexer Index = PageMapIndexer((uint64_t)Address);
|
||||||
PageMapLevel4 PML4 = this->Table->Entries[Index.PMLIndex];
|
PageDirectoryEntry PDE = this->Table->Entries[Index.PDPIndex];
|
||||||
|
PageTable *PDP = nullptr;
|
||||||
|
PageTable *PD = nullptr;
|
||||||
|
PageTable *PT = nullptr;
|
||||||
|
if (PDE.GetFlag(Flag))
|
||||||
|
PDP = (PageTable *)((uint64_t)PDE.GetAddress() << 12);
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
|
||||||
PageDirectoryPointerTableEntryPtr *PDPTE = nullptr;
|
PDE = PDP->Entries[Index.PDIndex];
|
||||||
PageDirectoryEntryPtr *PDE = nullptr;
|
if (PDE.GetFlag(Flag))
|
||||||
PageTableEntryPtr *PTE = nullptr;
|
PD = (PageTable *)((uint64_t)PDE.GetAddress() << 12);
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
|
||||||
if ((PML4.raw & Flag) > 0)
|
PDE = PD->Entries[Index.PTIndex];
|
||||||
{
|
if (PDE.GetFlag(Flag))
|
||||||
PDPTE = (PageDirectoryPointerTableEntryPtr *)((uintptr_t)PML4.GetAddress() << 12);
|
PT = (PageTable *)((uint64_t)PDE.GetAddress() << 12);
|
||||||
if (PDPTE)
|
else
|
||||||
if ((PDPTE->Entries[Index.PDPTEIndex].Present))
|
return false;
|
||||||
{
|
|
||||||
PDE = (PageDirectoryEntryPtr *)((uintptr_t)PDPTE->Entries[Index.PDPTEIndex].GetAddress() << 12);
|
PDE = PT->Entries[Index.PIndex];
|
||||||
if (PDE)
|
if (PDE.GetFlag(Flag))
|
||||||
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 true;
|
||||||
}
|
else
|
||||||
}
|
return false;
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -48,64 +50,60 @@ namespace Memory
|
|||||||
error("No page table");
|
error("No page table");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
PageMapIndexer Index = PageMapIndexer((uint64_t)VirtualAddress);
|
||||||
PageMapIndexer Index = PageMapIndexer((uintptr_t)VirtualAddress);
|
PageDirectoryEntry PDE = this->Table->Entries[Index.PDPIndex];
|
||||||
// Clear any flags that are not 1 << 0 (Present) - 1 << 5 (Accessed) because rest are for page table entries only
|
PageTable *PDP = nullptr;
|
||||||
uint64_t DirectoryFlags = Flags & 0x3F;
|
if (!PDE.GetFlag(PTFlag::P))
|
||||||
|
|
||||||
PageMapLevel4 PML4 = this->Table->Entries[Index.PMLIndex];
|
|
||||||
PageDirectoryPointerTableEntryPtr *PDPTEPtr = nullptr;
|
|
||||||
if (!PML4.Present)
|
|
||||||
{
|
{
|
||||||
PDPTEPtr = (PageDirectoryPointerTableEntryPtr *)KernelAllocator.RequestPage();
|
PDP = (PageTable *)KernelAllocator.RequestPage();
|
||||||
memset(PDPTEPtr, 0, PAGE_SIZE);
|
memset(PDP, 0, PAGE_SIZE);
|
||||||
PML4.Present = true;
|
PDE.SetFlag(PTFlag::P, true);
|
||||||
PML4.SetAddress((uintptr_t)PDPTEPtr >> 12);
|
PDE.AddFlag(Flags);
|
||||||
|
PDE.SetAddress((uint64_t)PDP >> 12);
|
||||||
|
this->Table->Entries[Index.PDPIndex] = PDE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
PDPTEPtr = (PageDirectoryPointerTableEntryPtr *)((uintptr_t)PML4.GetAddress() << 12);
|
PDP = (PageTable *)((uint64_t)PDE.GetAddress() << 12);
|
||||||
PML4.raw |= DirectoryFlags;
|
|
||||||
this->Table->Entries[Index.PMLIndex] = PML4;
|
|
||||||
|
|
||||||
PageDirectoryPointerTableEntry PDPTE = PDPTEPtr->Entries[Index.PDPTEIndex];
|
PDE = PDP->Entries[Index.PDIndex];
|
||||||
PageDirectoryEntryPtr *PDEPtr = nullptr;
|
PageTable *PD = nullptr;
|
||||||
if (!PDPTE.Present)
|
if (!PDE.GetFlag(PTFlag::P))
|
||||||
{
|
{
|
||||||
PDEPtr = (PageDirectoryEntryPtr *)KernelAllocator.RequestPage();
|
PD = (PageTable *)KernelAllocator.RequestPage();
|
||||||
memset(PDEPtr, 0, PAGE_SIZE);
|
memset(PD, 0, PAGE_SIZE);
|
||||||
PDPTE.Present = true;
|
PDE.SetFlag(PTFlag::P, true);
|
||||||
PDPTE.SetAddress((uintptr_t)PDEPtr >> 12);
|
PDE.AddFlag(Flags);
|
||||||
|
PDE.SetAddress((uint64_t)PD >> 12);
|
||||||
|
PDP->Entries[Index.PDIndex] = PDE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
PDEPtr = (PageDirectoryEntryPtr *)((uintptr_t)PDPTE.GetAddress() << 12);
|
PD = (PageTable *)((uint64_t)PDE.GetAddress() << 12);
|
||||||
PDPTE.raw |= DirectoryFlags;
|
|
||||||
PDPTEPtr->Entries[Index.PDPTEIndex] = PDPTE;
|
|
||||||
|
|
||||||
PageDirectoryEntry PDE = PDEPtr->Entries[Index.PDEIndex];
|
PDE = PD->Entries[Index.PTIndex];
|
||||||
PageTableEntryPtr *PTEPtr = nullptr;
|
PageTable *PT = nullptr;
|
||||||
if (!PDE.Present)
|
if (!PDE.GetFlag(PTFlag::P))
|
||||||
{
|
{
|
||||||
PTEPtr = (PageTableEntryPtr *)KernelAllocator.RequestPage();
|
PT = (PageTable *)KernelAllocator.RequestPage();
|
||||||
memset(PTEPtr, 0, PAGE_SIZE);
|
memset(PT, 0, PAGE_SIZE);
|
||||||
PDE.Present = true;
|
PDE.SetFlag(PTFlag::P, true);
|
||||||
PDE.SetAddress((uintptr_t)PTEPtr >> 12);
|
PDE.AddFlag(Flags);
|
||||||
|
PDE.SetAddress((uint64_t)PT >> 12);
|
||||||
|
PD->Entries[Index.PTIndex] = PDE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
PTEPtr = (PageTableEntryPtr *)((uintptr_t)PDE.GetAddress() << 12);
|
PT = (PageTable *)((uint64_t)PDE.GetAddress() << 12);
|
||||||
PDE.raw |= DirectoryFlags;
|
|
||||||
PDEPtr->Entries[Index.PDEIndex] = PDE;
|
|
||||||
|
|
||||||
PageTableEntry PTE = PTEPtr->Entries[Index.PTEIndex];
|
PDE = PT->Entries[Index.PIndex];
|
||||||
PTE.Present = true;
|
PDE.SetFlag(PTFlag::P, true);
|
||||||
PTE.raw |= Flags;
|
PDE.AddFlag(Flags);
|
||||||
PTE.SetAddress((uintptr_t)PhysicalAddress >> 12);
|
PDE.SetAddress((uint64_t)PhysicalAddress >> 12);
|
||||||
PTEPtr->Entries[Index.PTEIndex] = PTE;
|
PT->Entries[Index.PIndex] = PDE;
|
||||||
|
|
||||||
#if defined(a64)
|
#if defined(__amd64__)
|
||||||
CPU::x64::invlpg(VirtualAddress);
|
CPU::x64::invlpg(VirtualAddress);
|
||||||
#elif defined(a32)
|
#elif defined(__i386__)
|
||||||
CPU::x32::invlpg(VirtualAddress);
|
CPU::x32::invlpg(VirtualAddress);
|
||||||
#elif defined(aa64)
|
#elif defined(__aarch64__)
|
||||||
asmv("dsb sy");
|
asmv("dsb sy");
|
||||||
asmv("tlbi vae1is, %0"
|
asmv("tlbi vae1is, %0"
|
||||||
:
|
:
|
||||||
@ -129,14 +127,14 @@ namespace Memory
|
|||||||
(byte & 0x01 ? '1' : '0')
|
(byte & 0x01 ? '1' : '0')
|
||||||
|
|
||||||
if (!this->Check(VirtualAddress, (PTFlag)Flags)) // quick workaround just to see where it fails
|
if (!this->Check(VirtualAddress, (PTFlag)Flags)) // quick workaround just to see where it fails
|
||||||
warn("Failed to map %#lx - %#lx with flags: " BYTE_TO_BINARY_PATTERN, VirtualAddress, PhysicalAddress, BYTE_TO_BINARY(Flags));
|
warn("Failed to map %#lx with flags: " BYTE_TO_BINARY_PATTERN, VirtualAddress, BYTE_TO_BINARY(Flags));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void Virtual::Map(void *VirtualAddress, void *PhysicalAddress, size_t PageCount, uint64_t Flags)
|
void Virtual::Map(void *VirtualAddress, void *PhysicalAddress, uint64_t PageCount, uint64_t Flags)
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < PageCount; i++)
|
for (uint64_t i = 0; i < PageCount; i++)
|
||||||
this->Map((void *)((uintptr_t)VirtualAddress + (i * PAGE_SIZE)), (void *)((uintptr_t)PhysicalAddress + (i * PAGE_SIZE)), Flags);
|
this->Map((void *)((uint64_t)VirtualAddress + (i * PAGE_SIZE)), (void *)((uint64_t)PhysicalAddress + (i * PAGE_SIZE)), Flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Virtual::Unmap(void *VirtualAddress)
|
void Virtual::Unmap(void *VirtualAddress)
|
||||||
@ -148,43 +146,38 @@ namespace Memory
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
PageMapIndexer Index = PageMapIndexer((uintptr_t)VirtualAddress);
|
PageMapIndexer Index = PageMapIndexer((uint64_t)VirtualAddress);
|
||||||
PageMapLevel4 PML4 = this->Table->Entries[Index.PMLIndex];
|
PageDirectoryEntry PDE = this->Table->Entries[Index.PDPIndex];
|
||||||
if (!PML4.Present)
|
|
||||||
|
if (PDE.GetFlag(PTFlag::P))
|
||||||
{
|
{
|
||||||
error("Page not present");
|
PageTable *PDP = (PageTable *)((uint64_t)PDE.GetAddress() << 12);
|
||||||
return;
|
|
||||||
|
PDE = PDP->Entries[Index.PDIndex];
|
||||||
|
if (PDE.GetFlag(PTFlag::P))
|
||||||
|
{
|
||||||
|
PageTable *PD = (PageTable *)((uint64_t)PDE.GetAddress() << 12);
|
||||||
|
|
||||||
|
PDE = PD->Entries[Index.PTIndex];
|
||||||
|
if (PDE.GetFlag(PTFlag::P))
|
||||||
|
{
|
||||||
|
PageTable *PT = (PageTable *)((uint64_t)PDE.GetAddress() << 12);
|
||||||
|
|
||||||
|
PDE = PT->Entries[Index.PIndex];
|
||||||
|
if (PDE.GetFlag(PTFlag::P))
|
||||||
|
{
|
||||||
|
PDE.ClearFlags();
|
||||||
|
// debug("Unmapped %#lx", VirtualAddress);
|
||||||
}
|
}
|
||||||
PageDirectoryPointerTableEntryPtr *PDPTEPtr = (PageDirectoryPointerTableEntryPtr *)((uintptr_t)PML4.Address << 12);
|
|
||||||
PageDirectoryPointerTableEntry PDPTE = PDPTEPtr->Entries[Index.PDPTEIndex];
|
|
||||||
if (!PDPTE.Present)
|
|
||||||
{
|
|
||||||
error("Page not present");
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
PageDirectoryEntryPtr *PDEPtr = (PageDirectoryEntryPtr *)((uintptr_t)PDPTE.Address << 12);
|
|
||||||
PageDirectoryEntry PDE = PDEPtr->Entries[Index.PDEIndex];
|
|
||||||
if (!PDE.Present)
|
|
||||||
{
|
|
||||||
error("Page not present");
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
PageTableEntryPtr *PTEPtr = (PageTableEntryPtr *)((uintptr_t)PDE.Address << 12);
|
|
||||||
PageTableEntry PTE = PTEPtr->Entries[Index.PTEIndex];
|
|
||||||
if (!PTE.Present)
|
|
||||||
{
|
|
||||||
error("Page not present");
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PTE.Present = false;
|
#if defined(__amd64__)
|
||||||
PTEPtr->Entries[Index.PTEIndex] = PTE;
|
|
||||||
|
|
||||||
#if defined(a64)
|
|
||||||
CPU::x64::invlpg(VirtualAddress);
|
CPU::x64::invlpg(VirtualAddress);
|
||||||
#elif defined(a32)
|
#elif defined(__i386__)
|
||||||
CPU::x32::invlpg(VirtualAddress);
|
CPU::x32::invlpg(VirtualAddress);
|
||||||
#elif defined(aa64)
|
#elif defined(__aarch64__)
|
||||||
asmv("dsb sy");
|
asmv("dsb sy");
|
||||||
asmv("tlbi vae1is, %0"
|
asmv("tlbi vae1is, %0"
|
||||||
:
|
:
|
||||||
@ -195,10 +188,10 @@ namespace Memory
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void Virtual::Unmap(void *VirtualAddress, size_t PageCount)
|
void Virtual::Unmap(void *VirtualAddress, uint64_t PageCount)
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < PageCount; i++)
|
for (uint64_t i = 0; i < PageCount; i++)
|
||||||
this->Unmap((void *)((uintptr_t)VirtualAddress + (i * PAGE_SIZE)));
|
this->Unmap((void *)((uint64_t)VirtualAddress + (i * PAGE_SIZE)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Virtual::Remap(void *VirtualAddress, void *PhysicalAddress, uint64_t Flags)
|
void Virtual::Remap(void *VirtualAddress, void *PhysicalAddress, uint64_t Flags)
|
||||||
@ -207,12 +200,12 @@ namespace Memory
|
|||||||
this->Map(VirtualAddress, PhysicalAddress, Flags);
|
this->Map(VirtualAddress, PhysicalAddress, Flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
Virtual::Virtual(PageTable4 *Table)
|
Virtual::Virtual(PageTable *Table)
|
||||||
{
|
{
|
||||||
if (Table)
|
if (Table)
|
||||||
this->Table = Table;
|
this->Table = Table;
|
||||||
else
|
else
|
||||||
this->Table = (PageTable4 *)CPU::PageTable();
|
this->Table = (PageTable *)CPU::PageTable();
|
||||||
}
|
}
|
||||||
|
|
||||||
Virtual::~Virtual() {}
|
Virtual::~Virtual() {}
|
||||||
|
@ -2,10 +2,10 @@
|
|||||||
|
|
||||||
#include <memory.hpp>
|
#include <memory.hpp>
|
||||||
#include <power.hpp>
|
#include <power.hpp>
|
||||||
#if defined(a64)
|
#if defined(__amd64__)
|
||||||
#include "../Architecture/amd64/acpi.hpp"
|
#include "../Architecture/amd64/acpi.hpp"
|
||||||
#elif defined(a32)
|
#elif defined(__i386__)
|
||||||
#elif defined(aa64)
|
#elif defined(__aarch64__)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "../kernel.h"
|
#include "../kernel.h"
|
||||||
@ -14,34 +14,42 @@ namespace PCI
|
|||||||
{
|
{
|
||||||
namespace Descriptors
|
namespace Descriptors
|
||||||
{
|
{
|
||||||
|
char HexToStringOutput8[128];
|
||||||
const char *u8ToHexString(uint8_t Value)
|
const char *u8ToHexString(uint8_t Value)
|
||||||
{
|
{
|
||||||
static char Buffer[3];
|
uint8_t *ValuePtr = &Value;
|
||||||
memset(Buffer, 0, 3);
|
uint8_t *Ptr;
|
||||||
for (size_t i = 0; i < 2; i++)
|
uint8_t Temp;
|
||||||
|
uint8_t Size = 1 * 2 - 1;
|
||||||
|
for (uint8_t i = 0; i < Size; i++)
|
||||||
{
|
{
|
||||||
uint8_t Digit = (Value >> (4 - (i * 4))) & 0xF;
|
Ptr = ((uint8_t *)ValuePtr + i);
|
||||||
if (Digit < 10)
|
Temp = ((*Ptr & 0xF0) >> 4);
|
||||||
Buffer[i] = '0' + Digit;
|
HexToStringOutput8[Size - (i * 2 + 1)] = Temp + (Temp > 9 ? 55 : '0');
|
||||||
else
|
Temp = ((*Ptr & 0x0F));
|
||||||
Buffer[i] = 'A' + (Digit - 10);
|
HexToStringOutput8[Size - (i * 2)] = Temp + (Temp > 9 ? 55 : '0');
|
||||||
}
|
}
|
||||||
return Buffer;
|
HexToStringOutput8[Size + 1] = 0;
|
||||||
|
return HexToStringOutput8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char HexToStringOutput32[128];
|
||||||
const char *u32ToHexString(uint32_t Value)
|
const char *u32ToHexString(uint32_t Value)
|
||||||
{
|
{
|
||||||
static char Buffer[9];
|
uint32_t *ValuePtr = &Value;
|
||||||
memset(Buffer, 0, 9);
|
uint8_t *Ptr;
|
||||||
for (size_t i = 0; i < 8; i++)
|
uint8_t Temp;
|
||||||
|
uint8_t Size = 4 * 2 - 1;
|
||||||
|
for (uint8_t i = 0; i < Size; i++)
|
||||||
{
|
{
|
||||||
uint8_t Digit = (Value >> (28 - (i * 4))) & 0xF;
|
Ptr = ((uint8_t *)ValuePtr + i);
|
||||||
if (Digit < 10)
|
Temp = ((*Ptr & 0xF0) >> 4);
|
||||||
Buffer[i] = '0' + Digit;
|
HexToStringOutput32[Size - (i * 2 + 1)] = Temp + (Temp > 9 ? 55 : '0');
|
||||||
else
|
Temp = ((*Ptr & 0x0F));
|
||||||
Buffer[i] = 'A' + (Digit - 10);
|
HexToStringOutput32[Size - (i * 2)] = Temp + (Temp > 9 ? 55 : '0');
|
||||||
}
|
}
|
||||||
return Buffer;
|
HexToStringOutput32[Size + 1] = 0;
|
||||||
|
return HexToStringOutput32;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *MassStorageControllerSubclassName(uint8_t SubclassCode)
|
const char *MassStorageControllerSubclassName(uint8_t SubclassCode)
|
||||||
@ -386,13 +394,13 @@ namespace PCI
|
|||||||
case 0x000B:
|
case 0x000B:
|
||||||
return "QEMU PCIe Expander bridge";
|
return "QEMU PCIe Expander bridge";
|
||||||
case 0x000C:
|
case 0x000C:
|
||||||
return "QEMU PCIe Root Port";
|
return "QEMU PCIe Root port";
|
||||||
case 0x000D:
|
case 0x000D:
|
||||||
return "QEMU XHCI Host Controller";
|
return "QEMU XHCI Host Controller";
|
||||||
case 0x0010:
|
case 0x0010:
|
||||||
return "QEMU NVM Express Controller";
|
return "QEMU NVM Express Controller";
|
||||||
case 0x0100:
|
case 0x0100:
|
||||||
return "QXL Paravirtual Graphic Card";
|
return "QXL paravirtual graphic card";
|
||||||
case 0x1AF41100:
|
case 0x1AF41100:
|
||||||
return "QEMU Virtual Machine";
|
return "QEMU Virtual Machine";
|
||||||
default:
|
default:
|
||||||
@ -755,8 +763,7 @@ namespace PCI
|
|||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
void e(PCIDeviceHeader *hdr)
|
void e(PCIDeviceHeader *hdr)
|
||||||
{
|
{
|
||||||
debug("%#x:%#x\t\t%s / %s / %s / %s / %s",
|
debug("%s / %s / %s / %s / %s",
|
||||||
hdr->VendorID, hdr->DeviceID,
|
|
||||||
Descriptors::GetVendorName(hdr->VendorID),
|
Descriptors::GetVendorName(hdr->VendorID),
|
||||||
Descriptors::GetDeviceName(hdr->VendorID, hdr->DeviceID),
|
Descriptors::GetDeviceName(hdr->VendorID, hdr->DeviceID),
|
||||||
Descriptors::DeviceClasses[hdr->Class],
|
Descriptors::DeviceClasses[hdr->Class],
|
||||||
@ -765,10 +772,10 @@ namespace PCI
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void PCI::EnumerateFunction(uintptr_t DeviceAddress, uint64_t Function)
|
void PCI::EnumerateFunction(uint64_t DeviceAddress, uint64_t Function)
|
||||||
{
|
{
|
||||||
uintptr_t Offset = Function << 12;
|
uint64_t Offset = Function << 12;
|
||||||
uintptr_t FunctionAddress = DeviceAddress + Offset;
|
uint64_t FunctionAddress = DeviceAddress + Offset;
|
||||||
Memory::Virtual().Map((void *)FunctionAddress, (void *)FunctionAddress, Memory::PTFlag::RW);
|
Memory::Virtual().Map((void *)FunctionAddress, (void *)FunctionAddress, Memory::PTFlag::RW);
|
||||||
PCIDeviceHeader *PCIDeviceHdr = (PCIDeviceHeader *)FunctionAddress;
|
PCIDeviceHeader *PCIDeviceHdr = (PCIDeviceHeader *)FunctionAddress;
|
||||||
if (PCIDeviceHdr->DeviceID == 0)
|
if (PCIDeviceHdr->DeviceID == 0)
|
||||||
@ -781,24 +788,24 @@ namespace PCI
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void PCI::EnumerateDevice(uintptr_t BusAddress, uint64_t Device)
|
void PCI::EnumerateDevice(uint64_t BusAddress, uint64_t Device)
|
||||||
{
|
{
|
||||||
uintptr_t Offset = Device << 15;
|
uint64_t Offset = Device << 15;
|
||||||
uintptr_t DeviceAddress = BusAddress + Offset;
|
uint64_t DeviceAddress = BusAddress + Offset;
|
||||||
Memory::Virtual().Map((void *)DeviceAddress, (void *)DeviceAddress, Memory::PTFlag::RW);
|
Memory::Virtual().Map((void *)DeviceAddress, (void *)DeviceAddress, Memory::PTFlag::RW);
|
||||||
PCIDeviceHeader *PCIDeviceHdr = (PCIDeviceHeader *)DeviceAddress;
|
PCIDeviceHeader *PCIDeviceHdr = (PCIDeviceHeader *)DeviceAddress;
|
||||||
if (PCIDeviceHdr->DeviceID == 0)
|
if (PCIDeviceHdr->DeviceID == 0)
|
||||||
return;
|
return;
|
||||||
if (PCIDeviceHdr->DeviceID == 0xFFFF)
|
if (PCIDeviceHdr->DeviceID == 0xFFFF)
|
||||||
return;
|
return;
|
||||||
for (uintptr_t Function = 0; Function < 8; Function++)
|
for (uint64_t Function = 0; Function < 8; Function++)
|
||||||
EnumerateFunction(DeviceAddress, Function);
|
EnumerateFunction(DeviceAddress, Function);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PCI::EnumerateBus(uintptr_t BaseAddress, uint64_t Bus)
|
void PCI::EnumerateBus(uint64_t BaseAddress, uint64_t Bus)
|
||||||
{
|
{
|
||||||
uintptr_t Offset = Bus << 20;
|
uint64_t Offset = Bus << 20;
|
||||||
uintptr_t BusAddress = BaseAddress + Offset;
|
uint64_t BusAddress = BaseAddress + Offset;
|
||||||
Memory::Virtual().Map((void *)BusAddress, (void *)BusAddress, Memory::PTFlag::RW);
|
Memory::Virtual().Map((void *)BusAddress, (void *)BusAddress, Memory::PTFlag::RW);
|
||||||
PCIDeviceHeader *PCIDeviceHdr = (PCIDeviceHeader *)BusAddress;
|
PCIDeviceHeader *PCIDeviceHdr = (PCIDeviceHeader *)BusAddress;
|
||||||
if (Bus != 0) // TODO: VirtualBox workaround (UNTESTED ON REAL HARDWARE!)
|
if (Bus != 0) // TODO: VirtualBox workaround (UNTESTED ON REAL HARDWARE!)
|
||||||
@ -808,12 +815,12 @@ namespace PCI
|
|||||||
if (PCIDeviceHdr->DeviceID == 0xFFFF)
|
if (PCIDeviceHdr->DeviceID == 0xFFFF)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
debug("PCI Bus DeviceID:%#llx VendorID:%#llx BIST:%#llx Cache:%#llx Class:%#llx Cmd:%#llx HdrType:%#llx LatencyTimer:%#llx ProgIF:%#llx RevID:%#llx Status:%#llx SubClass:%#llx ",
|
trace("PCI Bus DeviceID:%#llx VendorID:%#llx BIST:%#llx Cache:%#llx Class:%#llx Cmd:%#llx HdrType:%#llx LatencyTimer:%#llx ProgIF:%#llx RevID:%#llx Status:%#llx SubClass:%#llx ",
|
||||||
PCIDeviceHdr->DeviceID, PCIDeviceHdr->VendorID, PCIDeviceHdr->BIST,
|
PCIDeviceHdr->DeviceID, PCIDeviceHdr->VendorID, PCIDeviceHdr->BIST,
|
||||||
PCIDeviceHdr->CacheLineSize, PCIDeviceHdr->Class, PCIDeviceHdr->Command,
|
PCIDeviceHdr->CacheLineSize, PCIDeviceHdr->Class, PCIDeviceHdr->Command,
|
||||||
PCIDeviceHdr->HeaderType, PCIDeviceHdr->LatencyTimer, PCIDeviceHdr->ProgIF,
|
PCIDeviceHdr->HeaderType, PCIDeviceHdr->LatencyTimer, PCIDeviceHdr->ProgIF,
|
||||||
PCIDeviceHdr->RevisionID, PCIDeviceHdr->Status, PCIDeviceHdr->Subclass);
|
PCIDeviceHdr->RevisionID, PCIDeviceHdr->Status, PCIDeviceHdr->Subclass);
|
||||||
for (uintptr_t Device = 0; Device < 32; Device++)
|
for (uint64_t Device = 0; Device < 32; Device++)
|
||||||
EnumerateDevice(BusAddress, Device);
|
EnumerateDevice(BusAddress, Device);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -837,20 +844,20 @@ namespace PCI
|
|||||||
|
|
||||||
PCI::PCI()
|
PCI::PCI()
|
||||||
{
|
{
|
||||||
#if defined(a64)
|
#if defined(__amd64__)
|
||||||
int Entries = ((((ACPI::ACPI *)PowerManager->GetACPI())->MCFG->Header.Length) - sizeof(ACPI::ACPI::MCFGHeader)) / sizeof(DeviceConfig);
|
int Entries = ((((ACPI::ACPI *)PowerManager->GetACPI())->MCFG->Header.Length) - sizeof(ACPI::ACPI::MCFGHeader)) / sizeof(DeviceConfig);
|
||||||
for (int t = 0; t < Entries; t++)
|
for (int t = 0; t < Entries; t++)
|
||||||
{
|
{
|
||||||
DeviceConfig *NewDeviceConfig = (DeviceConfig *)((uintptr_t)((ACPI::ACPI *)PowerManager->GetACPI())->MCFG + sizeof(ACPI::ACPI::MCFGHeader) + (sizeof(DeviceConfig) * t));
|
DeviceConfig *NewDeviceConfig = (DeviceConfig *)((uint64_t)((ACPI::ACPI *)PowerManager->GetACPI())->MCFG + sizeof(ACPI::ACPI::MCFGHeader) + (sizeof(DeviceConfig) * t));
|
||||||
Memory::Virtual().Map((void *)NewDeviceConfig->BaseAddress, (void *)NewDeviceConfig->BaseAddress, Memory::PTFlag::RW);
|
Memory::Virtual().Map((void *)NewDeviceConfig->BaseAddress, (void *)NewDeviceConfig->BaseAddress, Memory::PTFlag::RW);
|
||||||
debug("PCI Entry %d Address:%#llx BUS:%#llx-%#llx", t, NewDeviceConfig->BaseAddress,
|
trace("PCI Entry %d Address:%#llx BUS:%#llx-%#llx", t, NewDeviceConfig->BaseAddress,
|
||||||
NewDeviceConfig->StartBus, NewDeviceConfig->EndBus);
|
NewDeviceConfig->StartBus, NewDeviceConfig->EndBus);
|
||||||
for (uintptr_t Bus = NewDeviceConfig->StartBus; Bus < NewDeviceConfig->EndBus; Bus++)
|
for (uint64_t Bus = NewDeviceConfig->StartBus; Bus < NewDeviceConfig->EndBus; Bus++)
|
||||||
EnumerateBus(NewDeviceConfig->BaseAddress, Bus);
|
EnumerateBus(NewDeviceConfig->BaseAddress, Bus);
|
||||||
}
|
}
|
||||||
#elif defined(a32)
|
#elif defined(__i386__)
|
||||||
error("PCI not implemented on i386");
|
error("PCI not implemented on i386");
|
||||||
#elif defined(aa64)
|
#elif defined(__aarch64__)
|
||||||
error("PCI not implemented on aarch64");
|
error("PCI not implemented on aarch64");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
#include "../kernel.h"
|
#include "../kernel.h"
|
||||||
|
|
||||||
#if defined(a64)
|
#if defined(__amd64__)
|
||||||
#include <io.h>
|
#include <io.h>
|
||||||
|
|
||||||
#include "../Architecture/amd64/acpi.hpp"
|
#include "../Architecture/amd64/acpi.hpp"
|
||||||
@ -71,11 +71,10 @@ namespace Power
|
|||||||
|
|
||||||
Power::~Power()
|
Power::~Power()
|
||||||
{
|
{
|
||||||
debug("Destructor called");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#elif defined(a32)
|
#elif defined(__i386__)
|
||||||
|
|
||||||
namespace Power
|
namespace Power
|
||||||
{
|
{
|
||||||
@ -99,7 +98,7 @@ namespace Power
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#elif defined(aa64)
|
#elif defined(__aarch64__)
|
||||||
|
|
||||||
namespace Power
|
namespace Power
|
||||||
{
|
{
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
#include <rand.hpp>
|
#include <rand.hpp>
|
||||||
#include <cpu.hpp>
|
|
||||||
|
|
||||||
namespace Random
|
namespace Random
|
||||||
{
|
{
|
||||||
@ -7,150 +6,22 @@ namespace Random
|
|||||||
|
|
||||||
uint16_t rand16()
|
uint16_t rand16()
|
||||||
{
|
{
|
||||||
int RDRANDFlag = 0;
|
|
||||||
if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_AMD) == 0)
|
|
||||||
{
|
|
||||||
#if defined(a64)
|
|
||||||
CPU::x64::AMD::CPUID0x1 cpuid1amd;
|
|
||||||
#elif defined(a32)
|
|
||||||
CPU::x32::AMD::CPUID0x1 cpuid1amd;
|
|
||||||
#endif
|
|
||||||
#if defined(a64) || defined(a32)
|
|
||||||
asmv("cpuid"
|
|
||||||
: "=a"(cpuid1amd.EAX.raw), "=b"(cpuid1amd.EBX.raw), "=c"(cpuid1amd.ECX.raw), "=d"(cpuid1amd.EDX.raw)
|
|
||||||
: "a"(0x1));
|
|
||||||
#endif
|
|
||||||
RDRANDFlag = cpuid1amd.ECX.RDRAND;
|
|
||||||
}
|
|
||||||
else if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_INTEL) == 0)
|
|
||||||
{
|
|
||||||
#if defined(a64)
|
|
||||||
CPU::x64::Intel::CPUID0x1 cpuid1intel;
|
|
||||||
#elif defined(a32)
|
|
||||||
CPU::x32::Intel::CPUID0x1 cpuid1intel;
|
|
||||||
#endif
|
|
||||||
#if defined(a64) || defined(a32)
|
|
||||||
asmv("cpuid"
|
|
||||||
: "=a"(cpuid1intel.EAX.raw), "=b"(cpuid1intel.EBX.raw), "=c"(cpuid1intel.ECX.raw), "=d"(cpuid1intel.EDX.raw)
|
|
||||||
: "a"(0x1));
|
|
||||||
#endif
|
|
||||||
RDRANDFlag = cpuid1intel.ECX.RDRAND;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strcmp(CPU::Hypervisor(), x86_CPUID_VENDOR_TCG) == 0)
|
|
||||||
RDRANDFlag = 0;
|
|
||||||
|
|
||||||
#if defined(a64) || defined(a32)
|
|
||||||
if (RDRANDFlag)
|
|
||||||
{
|
|
||||||
uint16_t RDRANDValue = 0;
|
|
||||||
asmv("1: rdrand %0; jnc 1b"
|
|
||||||
: "=r"(RDRANDValue));
|
|
||||||
return RDRANDValue;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
Seed = Seed * 1103515245 + 12345;
|
Seed = Seed * 1103515245 + 12345;
|
||||||
return (uint16_t)(Seed / 65536) % __UINT16_MAX__;
|
return (uint16_t)(Seed / 65536) % __UINT16_MAX__;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t rand32()
|
uint32_t rand32()
|
||||||
{
|
{
|
||||||
int RDRANDFlag = 0;
|
|
||||||
if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_AMD) == 0)
|
|
||||||
{
|
|
||||||
#if defined(a64)
|
|
||||||
CPU::x64::AMD::CPUID0x1 cpuid1amd;
|
|
||||||
#elif defined(a32)
|
|
||||||
CPU::x32::AMD::CPUID0x1 cpuid1amd;
|
|
||||||
#endif
|
|
||||||
#if defined(a64) || defined(a32)
|
|
||||||
asmv("cpuid"
|
|
||||||
: "=a"(cpuid1amd.EAX.raw), "=b"(cpuid1amd.EBX.raw), "=c"(cpuid1amd.ECX.raw), "=d"(cpuid1amd.EDX.raw)
|
|
||||||
: "a"(0x1));
|
|
||||||
#endif
|
|
||||||
RDRANDFlag = cpuid1amd.ECX.RDRAND;
|
|
||||||
}
|
|
||||||
else if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_INTEL) == 0)
|
|
||||||
{
|
|
||||||
#if defined(a64)
|
|
||||||
CPU::x64::Intel::CPUID0x1 cpuid1intel;
|
|
||||||
#elif defined(a32)
|
|
||||||
CPU::x32::Intel::CPUID0x1 cpuid1intel;
|
|
||||||
#endif
|
|
||||||
#if defined(a64) || defined(a32)
|
|
||||||
asmv("cpuid"
|
|
||||||
: "=a"(cpuid1intel.EAX.raw), "=b"(cpuid1intel.EBX.raw), "=c"(cpuid1intel.ECX.raw), "=d"(cpuid1intel.EDX.raw)
|
|
||||||
: "a"(0x1));
|
|
||||||
#endif
|
|
||||||
RDRANDFlag = cpuid1intel.ECX.RDRAND;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strcmp(CPU::Hypervisor(), x86_CPUID_VENDOR_TCG) == 0)
|
|
||||||
RDRANDFlag = 0;
|
|
||||||
|
|
||||||
#if defined(a64) || defined(a32)
|
|
||||||
if (RDRANDFlag)
|
|
||||||
{
|
|
||||||
uint32_t RDRANDValue = 0;
|
|
||||||
asmv("1: rdrand %0; jnc 1b"
|
|
||||||
: "=r"(RDRANDValue));
|
|
||||||
return RDRANDValue;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
Seed = Seed * 1103515245 + 12345;
|
Seed = Seed * 1103515245 + 12345;
|
||||||
return (uint32_t)(Seed / 65536) % __UINT16_MAX__;
|
return (uint32_t)(Seed / 65536) % __UINT32_MAX__;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t rand64()
|
uint64_t rand64()
|
||||||
{
|
{
|
||||||
int RDRANDFlag = 0;
|
|
||||||
if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_AMD) == 0)
|
|
||||||
{
|
|
||||||
#if defined(a64)
|
|
||||||
CPU::x64::AMD::CPUID0x1 cpuid1amd;
|
|
||||||
#elif defined(a32)
|
|
||||||
CPU::x32::AMD::CPUID0x1 cpuid1amd;
|
|
||||||
#endif
|
|
||||||
#if defined(a64) || defined(a32)
|
|
||||||
asmv("cpuid"
|
|
||||||
: "=a"(cpuid1amd.EAX.raw), "=b"(cpuid1amd.EBX.raw), "=c"(cpuid1amd.ECX.raw), "=d"(cpuid1amd.EDX.raw)
|
|
||||||
: "a"(0x1));
|
|
||||||
#endif
|
|
||||||
RDRANDFlag = cpuid1amd.ECX.RDRAND;
|
|
||||||
}
|
|
||||||
else if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_INTEL) == 0)
|
|
||||||
{
|
|
||||||
#if defined(a64)
|
|
||||||
CPU::x64::Intel::CPUID0x1 cpuid1intel;
|
|
||||||
#elif defined(a32)
|
|
||||||
CPU::x32::Intel::CPUID0x1 cpuid1intel;
|
|
||||||
#endif
|
|
||||||
#if defined(a64) || defined(a32)
|
|
||||||
asmv("cpuid"
|
|
||||||
: "=a"(cpuid1intel.EAX.raw), "=b"(cpuid1intel.EBX.raw), "=c"(cpuid1intel.ECX.raw), "=d"(cpuid1intel.EDX.raw)
|
|
||||||
: "a"(0x1));
|
|
||||||
#endif
|
|
||||||
RDRANDFlag = cpuid1intel.ECX.RDRAND;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strcmp(CPU::Hypervisor(), x86_CPUID_VENDOR_TCG) == 0)
|
|
||||||
RDRANDFlag = 0;
|
|
||||||
|
|
||||||
#if defined(a64) || defined(a32)
|
|
||||||
if (RDRANDFlag)
|
|
||||||
{
|
|
||||||
uint64_t RDRANDValue = 0;
|
|
||||||
asmv("1: rdrand %0; jnc 1b"
|
|
||||||
: "=r"(RDRANDValue));
|
|
||||||
return RDRANDValue;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
Seed = Seed * 1103515245 + 12345;
|
Seed = Seed * 1103515245 + 12345;
|
||||||
return (uint64_t)(Seed / 65536) % __UINT16_MAX__;
|
return (uint64_t)(Seed / 65536) % __UINT64_MAX__;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChangeSeed(uint64_t CustomSeed) { Seed = CustomSeed; }
|
void changeseed(uint64_t CustomSeed) { Seed = CustomSeed; }
|
||||||
|
|
||||||
}
|
}
|
56
Kernel/Core/StackGuard.c
Normal file
56
Kernel/Core/StackGuard.c
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
#include <types.h>
|
||||||
|
#include <debug.h>
|
||||||
|
|
||||||
|
#include "../kernel.h"
|
||||||
|
|
||||||
|
#ifndef STACK_CHK_GUARD_VALUE
|
||||||
|
#if UINTPTR_MAX == UINT32_MAX
|
||||||
|
#define STACK_CHK_GUARD_VALUE 0xDEAD57AC
|
||||||
|
#else
|
||||||
|
#define STACK_CHK_GUARD_VALUE 0xDEAD57AC00000000
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
__attribute__((weak)) uintptr_t __stack_chk_guard = 0;
|
||||||
|
|
||||||
|
__attribute__((weak, no_stack_protector)) uintptr_t __stack_chk_guard_init(void)
|
||||||
|
{
|
||||||
|
return STACK_CHK_GUARD_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern __attribute__((constructor, no_stack_protector)) void __guard_setup(void)
|
||||||
|
{
|
||||||
|
debug("StackGuard: __guard_setup");
|
||||||
|
if (__stack_chk_guard == 0)
|
||||||
|
__stack_chk_guard = __stack_chk_guard_init();
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((weak, noreturn, no_stack_protector)) void __stack_chk_fail(void)
|
||||||
|
{
|
||||||
|
TaskingPanic();
|
||||||
|
for (short i = 0; i < 10; i++)
|
||||||
|
error("Stack smashing detected!");
|
||||||
|
debug("%#lx", __stack_chk_guard);
|
||||||
|
KPrint("\eFF0000Stack smashing detected!");
|
||||||
|
#if defined(__amd64__) || defined(__i386__)
|
||||||
|
while (1)
|
||||||
|
asmv("cli; hlt");
|
||||||
|
#elif defined(__aarch64__)
|
||||||
|
asmv("wfe");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://github.com/gcc-mirror/gcc/blob/master/libssp/ssp.c
|
||||||
|
__attribute__((weak, noreturn, no_stack_protector)) void __chk_fail(void)
|
||||||
|
{
|
||||||
|
TaskingPanic();
|
||||||
|
for (short i = 0; i < 10; i++)
|
||||||
|
error("Buffer overflow detected!");
|
||||||
|
KPrint("\eFF0000Buffer overflow detected!");
|
||||||
|
#if defined(__amd64__) || defined(__i386__)
|
||||||
|
while (1)
|
||||||
|
asmv("cli; hlt");
|
||||||
|
#elif defined(__aarch64__)
|
||||||
|
asmv("wfe");
|
||||||
|
#endif
|
||||||
|
}
|
@ -1,79 +0,0 @@
|
|||||||
#include <types.h>
|
|
||||||
#include <debug.h>
|
|
||||||
#include <rand.hpp>
|
|
||||||
|
|
||||||
#include "../kernel.h"
|
|
||||||
|
|
||||||
/* EXTERNC */ __attribute__((weak)) uintptr_t __stack_chk_guard = 0;
|
|
||||||
|
|
||||||
EXTERNC __attribute__((weak, no_stack_protector)) uintptr_t __stack_chk_guard_init(void)
|
|
||||||
{
|
|
||||||
int MaxRetries = 0;
|
|
||||||
#if UINTPTR_MAX == UINT32_MAX
|
|
||||||
uint32_t num;
|
|
||||||
Retry:
|
|
||||||
num = Random::rand32();
|
|
||||||
if (num < 0x1000 && MaxRetries++ < 10)
|
|
||||||
goto Retry;
|
|
||||||
return num;
|
|
||||||
|
|
||||||
#else
|
|
||||||
uint64_t num;
|
|
||||||
Retry:
|
|
||||||
num = Random::rand64();
|
|
||||||
if (num < 0x100000 && MaxRetries++ < 10)
|
|
||||||
goto Retry;
|
|
||||||
return num;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
EXTERNC __attribute__((constructor, no_stack_protector)) void __guard_setup(void)
|
|
||||||
{
|
|
||||||
debug("StackGuard: __guard_setup");
|
|
||||||
if (__stack_chk_guard == 0)
|
|
||||||
__stack_chk_guard = __stack_chk_guard_init();
|
|
||||||
debug("Stack guard value: %ld", __stack_chk_guard);
|
|
||||||
}
|
|
||||||
|
|
||||||
EXTERNC __attribute__((weak, noreturn, no_stack_protector)) void __stack_chk_fail(void)
|
|
||||||
{
|
|
||||||
TaskingPanic();
|
|
||||||
for (short i = 0; i < 10; i++)
|
|
||||||
error("Stack smashing detected!");
|
|
||||||
debug("Current stack check guard value: %#lx", __stack_chk_guard);
|
|
||||||
KPrint("\eFF0000Stack smashing detected!");
|
|
||||||
|
|
||||||
#if defined(a64) || defined(a32)
|
|
||||||
void *Stack = nullptr;
|
|
||||||
#if defined(a64)
|
|
||||||
asmv("movq %%rsp, %0"
|
|
||||||
: "=r"(Stack));
|
|
||||||
#elif defined(a32)
|
|
||||||
asmv("movl %%esp, %0"
|
|
||||||
: "=r"(Stack));
|
|
||||||
#endif
|
|
||||||
error("Stack address: %#lx", Stack);
|
|
||||||
|
|
||||||
while (1)
|
|
||||||
asmv("cli; hlt");
|
|
||||||
#elif defined(aa64)
|
|
||||||
asmv("wfe");
|
|
||||||
#endif
|
|
||||||
CPU::Stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://github.com/gcc-mirror/gcc/blob/master/libssp/ssp.c
|
|
||||||
EXTERNC __attribute__((weak, noreturn, no_stack_protector)) void __chk_fail(void)
|
|
||||||
{
|
|
||||||
TaskingPanic();
|
|
||||||
for (short i = 0; i < 10; i++)
|
|
||||||
error("Buffer overflow detected!");
|
|
||||||
KPrint("\eFF0000Buffer overflow detected!");
|
|
||||||
|
|
||||||
#if defined(a64) || defined(a32)
|
|
||||||
while (1)
|
|
||||||
asmv("cli; hlt");
|
|
||||||
#elif defined(aa64)
|
|
||||||
asmv("wfe");
|
|
||||||
#endif
|
|
||||||
}
|
|
@ -2,16 +2,63 @@
|
|||||||
#include <memory.hpp>
|
#include <memory.hpp>
|
||||||
#include <convert.h>
|
#include <convert.h>
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
#include <elf.h>
|
|
||||||
|
|
||||||
// #pragma GCC diagnostic ignored "-Wignored-qualifiers"
|
// #pragma GCC diagnostic ignored "-Wignored-qualifiers"
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
unsigned char e_ident[16];
|
||||||
|
uint16_t e_type;
|
||||||
|
uint16_t e_machine;
|
||||||
|
uint32_t e_version;
|
||||||
|
uint64_t e_entry;
|
||||||
|
uint64_t e_phoff;
|
||||||
|
uint64_t e_shoff;
|
||||||
|
uint32_t e_flags;
|
||||||
|
uint16_t e_ehsize;
|
||||||
|
uint16_t e_phentsize;
|
||||||
|
uint16_t e_phnum;
|
||||||
|
uint16_t e_shentsize;
|
||||||
|
uint16_t e_shnum;
|
||||||
|
uint16_t e_shstrndx;
|
||||||
|
} Elf64_Ehdr;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint32_t sh_name;
|
||||||
|
uint32_t sh_type;
|
||||||
|
uint64_t sh_flags;
|
||||||
|
uint64_t sh_addr;
|
||||||
|
uint64_t sh_offset;
|
||||||
|
uint64_t sh_size;
|
||||||
|
uint32_t sh_link;
|
||||||
|
uint32_t sh_info;
|
||||||
|
uint64_t sh_addralign;
|
||||||
|
uint64_t sh_entsize;
|
||||||
|
} Elf64_Shdr;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint32_t st_name;
|
||||||
|
unsigned char st_info;
|
||||||
|
unsigned char st_other;
|
||||||
|
uint16_t st_shndx;
|
||||||
|
uint64_t st_value;
|
||||||
|
uint64_t st_size;
|
||||||
|
} Elf64_Sym;
|
||||||
|
|
||||||
|
#define SHT_SYMTAB 2
|
||||||
|
#define SHT_STRTAB 3
|
||||||
|
|
||||||
namespace SymbolResolver
|
namespace SymbolResolver
|
||||||
{
|
{
|
||||||
Symbols::Symbols(uintptr_t ImageAddress)
|
Symbols::SymbolTable SymTable[0x10000];
|
||||||
|
uint64_t TotalEntries = 0;
|
||||||
|
|
||||||
|
Symbols::Symbols(uint64_t Address)
|
||||||
{
|
{
|
||||||
debug("Solving symbols for address: %#llx", ImageAddress);
|
debug("Solving symbols for address: %#llx", Address);
|
||||||
Elf64_Ehdr *Header = (Elf64_Ehdr *)ImageAddress;
|
Elf64_Ehdr *Header = (Elf64_Ehdr *)Address;
|
||||||
if (Header->e_ident[0] != 0x7F &&
|
if (Header->e_ident[0] != 0x7F &&
|
||||||
Header->e_ident[1] != 'E' &&
|
Header->e_ident[1] != 'E' &&
|
||||||
Header->e_ident[2] != 'L' &&
|
Header->e_ident[2] != 'L' &&
|
||||||
@ -20,20 +67,17 @@ namespace SymbolResolver
|
|||||||
error("Invalid ELF header");
|
error("Invalid ELF header");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Elf64_Shdr *ElfSections = (Elf64_Shdr *)(ImageAddress + Header->e_shoff);
|
Elf64_Shdr *ElfSections = (Elf64_Shdr *)(Address + Header->e_shoff);
|
||||||
Elf64_Sym *ElfSymbols = nullptr;
|
Elf64_Sym *ElfSymbols = nullptr;
|
||||||
char *strtab = nullptr;
|
char *strtab = nullptr;
|
||||||
|
|
||||||
for (uint16_t i = 0; i < Header->e_shnum; i++)
|
for (uint64_t i = 0; i < Header->e_shnum; i++)
|
||||||
switch (ElfSections[i].sh_type)
|
switch (ElfSections[i].sh_type)
|
||||||
{
|
{
|
||||||
case SHT_SYMTAB:
|
case SHT_SYMTAB:
|
||||||
ElfSymbols = (Elf64_Sym *)(ImageAddress + ElfSections[i].sh_offset);
|
ElfSymbols = (Elf64_Sym *)(Address + ElfSections[i].sh_offset);
|
||||||
this->TotalEntries = ElfSections[i].sh_size / sizeof(Elf64_Sym);
|
TotalEntries = ElfSections[i].sh_size / sizeof(Elf64_Sym);
|
||||||
if (this->TotalEntries >= 0x10000)
|
debug("Symbol table found, %d entries", TotalEntries);
|
||||||
this->TotalEntries = 0x10000 - 1;
|
|
||||||
|
|
||||||
debug("Symbol table found, %d entries", this->TotalEntries);
|
|
||||||
break;
|
break;
|
||||||
case SHT_STRTAB:
|
case SHT_STRTAB:
|
||||||
if (Header->e_shstrndx == i)
|
if (Header->e_shstrndx == i)
|
||||||
@ -42,7 +86,7 @@ namespace SymbolResolver
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
strtab = (char *)(ImageAddress + ElfSections[i].sh_offset);
|
strtab = (char *)Address + ElfSections[i].sh_offset;
|
||||||
debug("String table found, %d entries", ElfSections[i].sh_size);
|
debug("String table found, %d entries", ElfSections[i].sh_size);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -50,11 +94,11 @@ namespace SymbolResolver
|
|||||||
|
|
||||||
if (ElfSymbols != nullptr && strtab != nullptr)
|
if (ElfSymbols != nullptr && strtab != nullptr)
|
||||||
{
|
{
|
||||||
uintptr_t Index, MinimumIndex;
|
size_t Index, MinimumIndex;
|
||||||
for (uintptr_t i = 0; i < this->TotalEntries - 1; i++)
|
for (size_t i = 0; i < TotalEntries - 1; i++)
|
||||||
{
|
{
|
||||||
MinimumIndex = i;
|
MinimumIndex = i;
|
||||||
for (Index = i + 1; Index < this->TotalEntries; Index++)
|
for (Index = i + 1; Index < TotalEntries; Index++)
|
||||||
if (ElfSymbols[Index].st_value < ElfSymbols[MinimumIndex].st_value)
|
if (ElfSymbols[Index].st_value < ElfSymbols[MinimumIndex].st_value)
|
||||||
MinimumIndex = Index;
|
MinimumIndex = Index;
|
||||||
Elf64_Sym tmp = ElfSymbols[MinimumIndex];
|
Elf64_Sym tmp = ElfSymbols[MinimumIndex];
|
||||||
@ -65,52 +109,26 @@ namespace SymbolResolver
|
|||||||
while (ElfSymbols[0].st_value == 0)
|
while (ElfSymbols[0].st_value == 0)
|
||||||
{
|
{
|
||||||
ElfSymbols++;
|
ElfSymbols++;
|
||||||
this->TotalEntries--;
|
TotalEntries--;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG
|
trace("Symbol table loaded, %d entries (%ldKB)", TotalEntries, TO_KB(TotalEntries * sizeof(SymbolTable)));
|
||||||
static int once = 0;
|
for (size_t i = 0, g = TotalEntries; i < g; i++)
|
||||||
#endif
|
|
||||||
|
|
||||||
trace("Symbol table loaded, %d entries (%ldKB)", this->TotalEntries, TO_KB(this->TotalEntries * sizeof(SymbolTable)));
|
|
||||||
for (uintptr_t i = 0, g = this->TotalEntries; i < g; i++)
|
|
||||||
{
|
{
|
||||||
this->SymTable[i].Address = ElfSymbols[i].st_value;
|
SymTable[i].Address = ElfSymbols[i].st_value;
|
||||||
this->SymTable[i].FunctionName = &strtab[ElfSymbols[i].st_name];
|
SymTable[i].FunctionName = &strtab[ElfSymbols[i].st_name];
|
||||||
#ifdef DEBUG
|
|
||||||
if (once)
|
|
||||||
debug("Symbol %d: %#llx %s", i, this->SymTable[i].Address, this->SymTable[i].FunctionName);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
if (!once)
|
|
||||||
once++;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Symbols::~Symbols() {}
|
Symbols::~Symbols() {}
|
||||||
|
|
||||||
const NIF char *Symbols::GetSymbolFromAddress(uintptr_t Address)
|
const __no_instrument_function char *Symbols::GetSymbolFromAddress(uint64_t Address)
|
||||||
{
|
{
|
||||||
Symbols::SymbolTable Result{0, (char *)"<unknown>"};
|
Symbols::SymbolTable Result{0, (char *)"<unknown>"};
|
||||||
for (uintptr_t i = 0; i < this->TotalEntries; i++)
|
for (size_t i = 0; i < TotalEntries; i++)
|
||||||
if (this->SymTable[i].Address <= Address && this->SymTable[i].Address > Result.Address)
|
if (SymTable[i].Address <= Address && SymTable[i].Address > Result.Address)
|
||||||
Result = this->SymTable[i];
|
Result = SymTable[i];
|
||||||
return Result.FunctionName;
|
return Result.FunctionName;
|
||||||
}
|
}
|
||||||
|
|
||||||
NIF void Symbols::AddSymbol(uintptr_t Address, const char *Name)
|
|
||||||
{
|
|
||||||
if (this->TotalEntries >= 0x10000)
|
|
||||||
{
|
|
||||||
error("Symbol table is full");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this->SymTable[this->TotalEntries].Address = Address;
|
|
||||||
strcpy(this->SymTable[this->TotalEntries].FunctionName, Name);
|
|
||||||
this->TotalEntries++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -38,16 +38,16 @@ namespace SMBIOS
|
|||||||
SMBIOSEntryPoint *Header = (SMBIOSEntryPoint *)bInfo->SMBIOSPtr;
|
SMBIOSEntryPoint *Header = (SMBIOSEntryPoint *)bInfo->SMBIOSPtr;
|
||||||
debug("Getting SMBIOS header for type %d", Type);
|
debug("Getting SMBIOS header for type %d", Type);
|
||||||
|
|
||||||
struct SMBIOSHeader *hdr = (SMBIOSHeader *)(uintptr_t)Header->TableAddress;
|
struct SMBIOSHeader *hdr = (SMBIOSHeader *)(uint64_t)Header->TableAddress;
|
||||||
for (int i = 0; i <= 11; i++)
|
for (int i = 0; i <= 11; i++)
|
||||||
{
|
{
|
||||||
if (hdr < (void *)(uintptr_t)(Header->TableAddress + Header->TableLength))
|
if (hdr < (void *)(uint64_t)(Header->TableAddress + Header->TableLength))
|
||||||
if (hdr->Type == Type)
|
if (hdr->Type == Type)
|
||||||
{
|
{
|
||||||
debug("Found SMBIOS header for type %d at %#lx", Type, hdr);
|
debug("Found SMBIOS header for type %d at %#lx", Type, hdr);
|
||||||
return hdr;
|
return hdr;
|
||||||
}
|
}
|
||||||
hdr = (struct SMBIOSHeader *)((uintptr_t)hdr + SMBIOSTableLength(hdr));
|
hdr = (struct SMBIOSHeader *)((uint64_t)hdr + SMBIOSTableLength(hdr));
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
#include <time.hpp>
|
#include <time.hpp>
|
||||||
#include <debug.h>
|
|
||||||
#include <io.h>
|
#include <io.h>
|
||||||
|
|
||||||
namespace Time
|
namespace Time
|
||||||
@ -7,7 +6,7 @@ namespace Time
|
|||||||
Clock ReadClock()
|
Clock ReadClock()
|
||||||
{
|
{
|
||||||
Clock tm;
|
Clock tm;
|
||||||
#if defined(a64) || defined(a32)
|
#if defined(__amd64__) || defined(__i386__)
|
||||||
uint32_t t = 0;
|
uint32_t t = 0;
|
||||||
outb(0x70, 0x00);
|
outb(0x70, 0x00);
|
||||||
t = inb(0x71);
|
t = inb(0x71);
|
||||||
@ -28,7 +27,7 @@ namespace Time
|
|||||||
t = inb(0x71);
|
t = inb(0x71);
|
||||||
tm.Year = ((t & 0x0F) + ((t >> 4) * 10));
|
tm.Year = ((t & 0x0F) + ((t >> 4) * 10));
|
||||||
tm.Counter = 0;
|
tm.Counter = 0;
|
||||||
#elif defined(aa64)
|
#elif defined(__aarch64__)
|
||||||
tm.Year = 0;
|
tm.Year = 0;
|
||||||
tm.Month = 0;
|
tm.Month = 0;
|
||||||
tm.Day = 0;
|
tm.Day = 0;
|
||||||
@ -39,50 +38,4 @@ namespace Time
|
|||||||
#endif
|
#endif
|
||||||
return tm;
|
return tm;
|
||||||
}
|
}
|
||||||
|
|
||||||
Clock ConvertFromUnix(int Timestamp)
|
|
||||||
{
|
|
||||||
Clock result;
|
|
||||||
|
|
||||||
uint64_t Seconds = Timestamp;
|
|
||||||
uint64_t Minutes = Seconds / 60;
|
|
||||||
uint64_t Hours = Minutes / 60;
|
|
||||||
uint64_t Days = Hours / 24;
|
|
||||||
|
|
||||||
result.Year = 1970;
|
|
||||||
while (Days >= 365)
|
|
||||||
{
|
|
||||||
if (result.Year % 4 == 0 && (result.Year % 100 != 0 || result.Year % 400 == 0))
|
|
||||||
{
|
|
||||||
if (Days >= 366)
|
|
||||||
{
|
|
||||||
Days -= 366;
|
|
||||||
result.Year++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Days -= 365;
|
|
||||||
result.Year++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int DaysInMonth[] = {31, result.Year % 4 == 0 ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
|
|
||||||
for (result.Month = 0; result.Month < 12; result.Month++)
|
|
||||||
{
|
|
||||||
if (Days < static_cast<uint64_t>(DaysInMonth[result.Month]))
|
|
||||||
break;
|
|
||||||
Days -= DaysInMonth[result.Month];
|
|
||||||
}
|
|
||||||
result.Month++;
|
|
||||||
|
|
||||||
result.Day = static_cast<int>(Days) + 1;
|
|
||||||
result.Hour = static_cast<int>(Hours % 24);
|
|
||||||
result.Minute = static_cast<int>(Minutes % 60);
|
|
||||||
result.Second = static_cast<int>(Seconds % 60);
|
|
||||||
result.Counter = static_cast<uint64_t>(Timestamp);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -4,48 +4,21 @@
|
|||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
#include <io.h>
|
#include <io.h>
|
||||||
|
|
||||||
#if defined(a64)
|
#if defined(__amd64__)
|
||||||
#include "../Architecture/amd64/acpi.hpp"
|
#include "../Architecture/amd64/acpi.hpp"
|
||||||
#elif defined(a32)
|
#elif defined(__i386__)
|
||||||
#elif defined(aa64)
|
#elif defined(__aarch64__)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "../kernel.h"
|
|
||||||
|
|
||||||
namespace Time
|
namespace Time
|
||||||
{
|
{
|
||||||
void time::Sleep(uint64_t Milliseconds)
|
void time::Sleep(uint64_t Milliseconds)
|
||||||
{
|
{
|
||||||
#if defined(a64) || defined(a32)
|
#if defined(__amd64__) || defined(__i386__)
|
||||||
uint64_t Target = mminq(&((HPET *)hpet)->MainCounterValue) + (Milliseconds * 1000000000000) / clk;
|
uint64_t Target = mminq(&((HPET *)hpet)->MainCounterValue) + (Milliseconds * 1000000000) / clk;
|
||||||
#ifdef DEBUG
|
|
||||||
uint64_t Counter = mminq(&((HPET *)hpet)->MainCounterValue);
|
|
||||||
while (Counter < Target)
|
|
||||||
{
|
|
||||||
Counter = mminq(&((HPET *)hpet)->MainCounterValue);
|
|
||||||
CPU::Pause();
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
while (mminq(&((HPET *)hpet)->MainCounterValue) < Target)
|
while (mminq(&((HPET *)hpet)->MainCounterValue) < Target)
|
||||||
CPU::Pause();
|
CPU::Pause();
|
||||||
#endif
|
#elif defined(__aarch64__)
|
||||||
#elif defined(aa64)
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t time::GetCounter()
|
|
||||||
{
|
|
||||||
#if defined(a64) || defined(a32)
|
|
||||||
return mminq(&((HPET *)hpet)->MainCounterValue);
|
|
||||||
#elif defined(aa64)
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t time::CalculateTarget(uint64_t Milliseconds)
|
|
||||||
{
|
|
||||||
#if defined(a64) || defined(a32)
|
|
||||||
return mminq(&((HPET *)hpet)->MainCounterValue) + (Milliseconds * 1000000000000) / clk;
|
|
||||||
#elif defined(aa64)
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,7 +26,7 @@ namespace Time
|
|||||||
{
|
{
|
||||||
if (_acpi)
|
if (_acpi)
|
||||||
{
|
{
|
||||||
#if defined(a64)
|
#if defined(__amd64__)
|
||||||
this->acpi = _acpi;
|
this->acpi = _acpi;
|
||||||
ACPI::ACPI *acpi = (ACPI::ACPI *)this->acpi;
|
ACPI::ACPI *acpi = (ACPI::ACPI *)this->acpi;
|
||||||
if (acpi->HPET)
|
if (acpi->HPET)
|
||||||
@ -71,19 +44,15 @@ namespace Time
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// For now, we need HPET.
|
trace("HPET not found");
|
||||||
error("HPET not found");
|
|
||||||
KPrint("\eFF2200HPET not found");
|
|
||||||
CPU::Stop();
|
|
||||||
}
|
}
|
||||||
#elif defined(a32)
|
#elif defined(__i386__)
|
||||||
#elif defined(aa64)
|
#elif defined(__aarch64__)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
time::~time()
|
time::~time()
|
||||||
{
|
{
|
||||||
debug("Destructor called");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,313 +30,63 @@ __ubsan_handle_pointer_overflow_abort
|
|||||||
__ubsan_handle_cfi_check_fail
|
__ubsan_handle_cfi_check_fail
|
||||||
*/
|
*/
|
||||||
|
|
||||||
extern void __asan_report_load1(void *unknown)
|
extern void __asan_report_load1(void *unknown) { ubsan("load1"); }
|
||||||
{
|
extern void __asan_report_load2(void *unknown) { ubsan("load2"); }
|
||||||
ubsan("load1");
|
extern void __asan_report_load4(void *unknown) { ubsan("load4"); }
|
||||||
UNUSED(unknown);
|
extern void __asan_report_load8(void *unknown) { ubsan("load8"); }
|
||||||
}
|
extern void __asan_report_load16(void *unknown) { ubsan("load16"); }
|
||||||
|
extern void __asan_report_load_n(void *unknown, uintptr_t size) { ubsan("loadn"); }
|
||||||
|
|
||||||
extern void __asan_report_load2(void *unknown)
|
extern void __asan_report_store1(void *unknown) { ubsan("store1"); }
|
||||||
{
|
extern void __asan_report_store2(void *unknown) { ubsan("store2"); }
|
||||||
ubsan("load2");
|
extern void __asan_report_store4(void *unknown) { ubsan("store4"); }
|
||||||
UNUSED(unknown);
|
extern void __asan_report_store8(void *unknown) { ubsan("store8"); }
|
||||||
}
|
extern void __asan_report_store16(void *unknown) { ubsan("store16"); }
|
||||||
|
extern void __asan_report_store_n(void *unknown, uintptr_t size) { ubsan("storen"); }
|
||||||
|
|
||||||
extern void __asan_report_load4(void *unknown)
|
extern void __asan_report_load1_noabort(void *unknown) { ubsan("load1"); }
|
||||||
{
|
extern void __asan_report_load2_noabort(void *unknown) { ubsan("load2"); }
|
||||||
ubsan("load4");
|
extern void __asan_report_load4_noabort(void *unknown) { ubsan("load4"); }
|
||||||
UNUSED(unknown);
|
extern void __asan_report_load8_noabort(void *unknown) { ubsan("load8"); }
|
||||||
}
|
extern void __asan_report_load16_noabort(void *unknown) { ubsan("load16"); }
|
||||||
|
extern void __asan_report_load_n_noabort(void *unknown, uintptr_t size) { ubsan("loadn"); }
|
||||||
|
|
||||||
extern void __asan_report_load8(void *unknown)
|
extern void __asan_report_store1_noabort(void *unknown) { ubsan("store1"); }
|
||||||
{
|
extern void __asan_report_store2_noabort(void *unknown) { ubsan("store2"); }
|
||||||
ubsan("load8");
|
extern void __asan_report_store4_noabort(void *unknown) { ubsan("store4"); }
|
||||||
UNUSED(unknown);
|
extern void __asan_report_store8_noabort(void *unknown) { ubsan("store8"); }
|
||||||
}
|
extern void __asan_report_store16_noabort(void *unknown) { ubsan("store16"); }
|
||||||
|
extern void __asan_report_store_n_noabort(void *unknown, uintptr_t size) { ubsan("storen"); }
|
||||||
|
|
||||||
extern void __asan_report_load16(void *unknown)
|
extern void __asan_stack_malloc_0(uintptr_t size) { ubsan("stack malloc 0"); }
|
||||||
{
|
extern void __asan_stack_malloc_1(uintptr_t size) { ubsan("stack malloc 1"); }
|
||||||
ubsan("load16");
|
extern void __asan_stack_malloc_2(uintptr_t size) { ubsan("stack malloc 2"); }
|
||||||
UNUSED(unknown);
|
extern void __asan_stack_malloc_3(uintptr_t size) { ubsan("stack malloc 3"); }
|
||||||
}
|
extern void __asan_stack_malloc_4(uintptr_t size) { ubsan("stack malloc 4"); }
|
||||||
|
extern void __asan_stack_malloc_5(uintptr_t size) { ubsan("stack malloc 5"); }
|
||||||
|
extern void __asan_stack_malloc_6(uintptr_t size) { ubsan("stack malloc 6"); }
|
||||||
|
extern void __asan_stack_malloc_7(uintptr_t size) { ubsan("stack malloc 7"); }
|
||||||
|
extern void __asan_stack_malloc_8(uintptr_t size) { ubsan("stack malloc 8"); }
|
||||||
|
extern void __asan_stack_malloc_9(uintptr_t size) { ubsan("stack malloc 9"); }
|
||||||
|
|
||||||
extern void __asan_report_load_n(void *unknown, uintptr_t size)
|
extern void __asan_stack_free_0(void *ptr, uintptr_t size) { ubsan("stack free 0"); }
|
||||||
{
|
extern void __asan_stack_free_1(void *ptr, uintptr_t size) { ubsan("stack free 1"); }
|
||||||
ubsan("loadn");
|
extern void __asan_stack_free_2(void *ptr, uintptr_t size) { ubsan("stack free 2"); }
|
||||||
UNUSED(unknown);
|
extern void __asan_stack_free_3(void *ptr, uintptr_t size) { ubsan("stack free 3"); }
|
||||||
UNUSED(size);
|
extern void __asan_stack_free_4(void *ptr, uintptr_t size) { ubsan("stack free 4"); }
|
||||||
}
|
extern void __asan_stack_free_5(void *ptr, uintptr_t size) { ubsan("stack free 5"); }
|
||||||
|
extern void __asan_stack_free_6(void *ptr, uintptr_t size) { ubsan("stack free 6"); }
|
||||||
|
extern void __asan_stack_free_7(void *ptr, uintptr_t size) { ubsan("stack free 7"); }
|
||||||
|
extern void __asan_stack_free_8(void *ptr, uintptr_t size) { ubsan("stack free 8"); }
|
||||||
|
extern void __asan_stack_free_9(void *ptr, uintptr_t size) { ubsan("stack free 9"); }
|
||||||
|
|
||||||
extern void __asan_report_store1(void *unknown)
|
extern void __asan_poison_stack_memory(void *addr, uintptr_t size) { ubsan("poison stack memory"); }
|
||||||
{
|
extern void __asan_unpoison_stack_memory(void *addr, uintptr_t size) { ubsan("unpoison stack memory"); }
|
||||||
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_before_dynamic_init(const char *module_name) { ubsan("before dynamic init"); }
|
||||||
extern void __asan_after_dynamic_init(void) { ubsan("after dynamic init"); }
|
extern void __asan_after_dynamic_init(void) { ubsan("after dynamic init"); }
|
||||||
|
|
||||||
extern void __asan_register_globals(void *unknown, size_t size)
|
extern void __asan_register_globals(void *unknown, size_t size) { ubsan("register_globals"); }
|
||||||
{
|
|
||||||
ubsan("register_globals");
|
|
||||||
UNUSED(unknown);
|
|
||||||
UNUSED(size);
|
|
||||||
}
|
|
||||||
|
|
||||||
extern void __asan_unregister_globals(void) { ubsan("unregister_globals"); }
|
extern void __asan_unregister_globals(void) { ubsan("unregister_globals"); }
|
||||||
|
|
||||||
extern void __asan_init(void) { ubsan("init"); }
|
extern void __asan_init(void) { ubsan("init"); }
|
||||||
@ -370,11 +120,11 @@ bool UBSANMsg(const char *file, uint32_t line, uint32_t column)
|
|||||||
// blacklist
|
// blacklist
|
||||||
// if (strstr(file, "liballoc") ||
|
// if (strstr(file, "liballoc") ||
|
||||||
// strstr(file, "cwalk") ||
|
// strstr(file, "cwalk") ||
|
||||||
// strstr(file, "AdvancedConfigurationAndPowerInterface") ||
|
// strstr(file, "AdvancedConfigurationandPowerInterface") ||
|
||||||
// strstr(file, "SystemManagementBIOS"))
|
// strstr(file, "SystemManagementBIOS"))
|
||||||
// return false;
|
// return false;
|
||||||
|
|
||||||
if (strstr(file, "AdvancedConfigurationAndPowerInterface.cpp") &&
|
if (strstr(file, "AdvancedConfigurationandPowerInterface.cpp") &&
|
||||||
(line == 17 && column == 47))
|
(line == 17 && column == 47))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -399,9 +149,6 @@ bool UBSANMsg(const char *file, uint32_t line, uint32_t column)
|
|||||||
(line == 48 && column == 28))
|
(line == 48 && column == 28))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (strstr(file, "Task.cpp") && line > 500)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
ubsan("\t\tIn File: %s:%i:%i", file, line, column);
|
ubsan("\t\tIn File: %s:%i:%i", file, line, column);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -533,5 +280,4 @@ void __ubsan_handle_dynamic_type_cache_miss(struct dynamic_type_cache_miss_data
|
|||||||
{
|
{
|
||||||
if (UBSANMsg(data->location.file, data->location.line, data->location.column))
|
if (UBSANMsg(data->location.file, data->location.line, data->location.column))
|
||||||
ubsan("Dynamic type cache miss.");
|
ubsan("Dynamic type cache miss.");
|
||||||
UNUSED(ptr);
|
|
||||||
}
|
}
|
@ -6,8 +6,8 @@
|
|||||||
volatile bool serialports[8] = {false, false, false, false, false, false, false, false};
|
volatile bool serialports[8] = {false, false, false, false, false, false, false, false};
|
||||||
Vector<UniversalAsynchronousReceiverTransmitter::Events *> RegisteredEvents;
|
Vector<UniversalAsynchronousReceiverTransmitter::Events *> RegisteredEvents;
|
||||||
|
|
||||||
#if defined(a64) || defined(a32)
|
#if defined(__amd64__) || defined(__i386__)
|
||||||
NIF __always_inline inline uint8_t NoProfiler_inportb(uint16_t Port)
|
__no_instrument_function uint8_t NoProfiler_inportb(uint16_t Port)
|
||||||
{
|
{
|
||||||
uint8_t Result;
|
uint8_t Result;
|
||||||
asm("in %%dx, %%al"
|
asm("in %%dx, %%al"
|
||||||
@ -16,7 +16,7 @@ NIF __always_inline inline uint8_t NoProfiler_inportb(uint16_t Port)
|
|||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
NIF __always_inline inline void NoProfiler_outportb(uint16_t Port, uint8_t Data)
|
__no_instrument_function void NoProfiler_outportb(uint16_t Port, uint8_t Data)
|
||||||
{
|
{
|
||||||
asmv("out %%al, %%dx"
|
asmv("out %%al, %%dx"
|
||||||
:
|
:
|
||||||
@ -27,19 +27,13 @@ NIF __always_inline inline void NoProfiler_outportb(uint16_t Port, uint8_t Data)
|
|||||||
namespace UniversalAsynchronousReceiverTransmitter
|
namespace UniversalAsynchronousReceiverTransmitter
|
||||||
{
|
{
|
||||||
#define SERIAL_ENABLE_DLAB 0x80
|
#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_LO 0x03
|
||||||
#define SERIAL_RATE_38400_HI 0x00
|
#define SERIAL_RATE_38400_HI 0x00
|
||||||
#define SERIAL_BUFFER_EMPTY 0x20
|
#define SERIAL_BUFFER_EMPTY 0x20
|
||||||
|
|
||||||
/* TODO: Serial Port implementation needs reword. https://wiki.osdev.org/Serial_Ports */
|
SafeFunction __no_instrument_function UART::UART(SerialPorts Port)
|
||||||
|
|
||||||
SafeFunction NIF UART::UART(SerialPorts Port)
|
|
||||||
{
|
{
|
||||||
#if defined(a64) || defined(a32)
|
#if defined(__amd64__) || defined(__i386__)
|
||||||
if (Port == COMNULL)
|
if (Port == COMNULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -82,8 +76,8 @@ namespace UniversalAsynchronousReceiverTransmitter
|
|||||||
// Initialize the serial port
|
// Initialize the serial port
|
||||||
NoProfiler_outportb(Port + 1, 0x00); // Disable all interrupts
|
NoProfiler_outportb(Port + 1, 0x00); // Disable all interrupts
|
||||||
NoProfiler_outportb(Port + 3, SERIAL_ENABLE_DLAB); // Enable DLAB (set baud rate divisor)
|
NoProfiler_outportb(Port + 3, SERIAL_ENABLE_DLAB); // Enable DLAB (set baud rate divisor)
|
||||||
NoProfiler_outportb(Port + 0, SERIAL_RATE_115200_LO); // Set divisor to 1 (lo byte) 115200 baud
|
NoProfiler_outportb(Port + 0, SERIAL_RATE_38400_LO); // Set divisor to 3 (lo byte) 38400 baud
|
||||||
NoProfiler_outportb(Port + 1, SERIAL_RATE_115200_HI); // (hi byte)
|
NoProfiler_outportb(Port + 1, SERIAL_RATE_38400_HI); // (hi byte)
|
||||||
NoProfiler_outportb(Port + 3, 0x03); // 8 bits, no parity, one stop bit
|
NoProfiler_outportb(Port + 3, 0x03); // 8 bits, no parity, one stop bit
|
||||||
NoProfiler_outportb(Port + 2, 0xC7); // Enable FIFO, clear them, with 14-byte threshold
|
NoProfiler_outportb(Port + 2, 0xC7); // Enable FIFO, clear them, with 14-byte threshold
|
||||||
NoProfiler_outportb(Port + 4, 0x0B); // IRQs enabled, RTS/DSR set
|
NoProfiler_outportb(Port + 4, 0x0B); // IRQs enabled, RTS/DSR set
|
||||||
@ -104,11 +98,11 @@ namespace UniversalAsynchronousReceiverTransmitter
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
SafeFunction NIF UART::~UART() {}
|
SafeFunction __no_instrument_function UART::~UART() {}
|
||||||
|
|
||||||
SafeFunction NIF void UART::Write(uint8_t Char)
|
SafeFunction __no_instrument_function void UART::Write(uint8_t Char)
|
||||||
{
|
{
|
||||||
#if defined(a64) || defined(a32)
|
#if defined(__amd64__) || defined(__i386__)
|
||||||
while ((NoProfiler_inportb(Port + 5) & SERIAL_BUFFER_EMPTY) == 0)
|
while ((NoProfiler_inportb(Port + 5) & SERIAL_BUFFER_EMPTY) == 0)
|
||||||
;
|
;
|
||||||
NoProfiler_outportb(Port, Char);
|
NoProfiler_outportb(Port, Char);
|
||||||
@ -118,9 +112,9 @@ namespace UniversalAsynchronousReceiverTransmitter
|
|||||||
e->OnSent(Char);
|
e->OnSent(Char);
|
||||||
}
|
}
|
||||||
|
|
||||||
SafeFunction NIF uint8_t UART::Read()
|
SafeFunction __no_instrument_function uint8_t UART::Read()
|
||||||
{
|
{
|
||||||
#if defined(a64) || defined(a32)
|
#if defined(__amd64__) || defined(__i386__)
|
||||||
while ((NoProfiler_inportb(Port + 5) & 1) == 0)
|
while ((NoProfiler_inportb(Port + 5) & 1) == 0)
|
||||||
;
|
;
|
||||||
return NoProfiler_inportb(Port);
|
return NoProfiler_inportb(Port);
|
||||||
@ -129,22 +123,22 @@ namespace UniversalAsynchronousReceiverTransmitter
|
|||||||
{
|
{
|
||||||
if (e->GetRegisteredPort() == Port || e->GetRegisteredPort() == COMNULL)
|
if (e->GetRegisteredPort() == Port || e->GetRegisteredPort() == COMNULL)
|
||||||
{
|
{
|
||||||
#if defined(a64) || defined(a32)
|
#if defined(__amd64__) || defined(__i386__)
|
||||||
e->OnReceived(NoProfiler_inportb(Port));
|
e->OnReceived(NoProfiler_inportb(Port));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SafeFunction NIF Events::Events(SerialPorts Port)
|
SafeFunction __no_instrument_function Events::Events(SerialPorts Port)
|
||||||
{
|
{
|
||||||
this->Port = Port;
|
this->Port = Port;
|
||||||
RegisteredEvents.push_back(this);
|
RegisteredEvents.push_back(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
SafeFunction NIF Events::~Events()
|
SafeFunction __no_instrument_function Events::~Events()
|
||||||
{
|
{
|
||||||
for (uintptr_t i = 0; i < RegisteredEvents.size(); i++)
|
for (uint64_t i = 0; i < RegisteredEvents.size(); i++)
|
||||||
if (RegisteredEvents[i] == this)
|
if (RegisteredEvents[i] == this)
|
||||||
{
|
{
|
||||||
RegisteredEvents.remove(i);
|
RegisteredEvents.remove(i);
|
||||||
|
@ -3,177 +3,14 @@
|
|||||||
#include <uart.hpp>
|
#include <uart.hpp>
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
|
||||||
extern uintptr_t _binary_Files_tamsyn_font_1_11_Tamsyn7x14r_psf_start;
|
extern uint64_t _binary_Files_ter_powerline_v12n_psf_start;
|
||||||
extern uintptr_t _binary_Files_tamsyn_font_1_11_Tamsyn7x14r_psf_end;
|
extern uint64_t _binary_Files_ter_powerline_v12n_psf_end;
|
||||||
extern uintptr_t _binary_Files_tamsyn_font_1_11_Tamsyn7x14r_psf_size;
|
extern uint64_t _binary_Files_ter_powerline_v12n_psf_size;
|
||||||
|
|
||||||
NewLock(PrintLock);
|
NewLock(PrintLock);
|
||||||
|
|
||||||
namespace Video
|
namespace Video
|
||||||
{
|
{
|
||||||
Font *Display::GetCurrentFont()
|
|
||||||
{
|
|
||||||
return CurrentFont;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Display::SetCurrentFont(Font *Font)
|
|
||||||
{
|
|
||||||
CurrentFont = Font;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Display::CreateBuffer(uint32_t Width, uint32_t Height, int Index)
|
|
||||||
{
|
|
||||||
if (Width == 0 && Height == 0)
|
|
||||||
{
|
|
||||||
Width = this->framebuffer.Width;
|
|
||||||
Height = this->framebuffer.Height;
|
|
||||||
debug("No width and height specified, using %ldx%lld", Width, Height);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t Size = this->framebuffer.Pitch * Height;
|
|
||||||
if (this->Buffers[Index])
|
|
||||||
{
|
|
||||||
if (this->Buffers[Index]->Checksum == 0xDEAD)
|
|
||||||
{
|
|
||||||
warn("Buffer %d already exists, skipping creation", Index);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ScreenBuffer *buffer = new ScreenBuffer;
|
|
||||||
buffer->Buffer = KernelAllocator.RequestPages(TO_PAGES(Size));
|
|
||||||
buffer->Width = Width;
|
|
||||||
buffer->Height = Height;
|
|
||||||
buffer->Size = Size;
|
|
||||||
buffer->Color = 0xFFFFFF;
|
|
||||||
buffer->CursorX = 0;
|
|
||||||
buffer->CursorY = 0;
|
|
||||||
buffer->Brightness = 100;
|
|
||||||
this->Buffers[Index] = buffer;
|
|
||||||
memset(this->Buffers[Index]->Buffer, 0, Size);
|
|
||||||
this->Buffers[Index]->Checksum = 0xDEAD;
|
|
||||||
debug("Created buffer %d, address %#lx", Index, buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Display::SetBuffer(int Index)
|
|
||||||
{
|
|
||||||
if (this->Buffers[Index]->Brightness != 100)
|
|
||||||
this->SetBrightness(this->Buffers[Index]->Brightness, Index);
|
|
||||||
|
|
||||||
if (this->Buffers[Index]->Brightness == 0) /* Just clear the buffer */
|
|
||||||
memset(this->Buffers[Index]->Buffer, 0, this->Buffers[Index]->Size);
|
|
||||||
|
|
||||||
memcpy(this->framebuffer.BaseAddress, this->Buffers[Index]->Buffer, this->Buffers[Index]->Size);
|
|
||||||
}
|
|
||||||
|
|
||||||
ScreenBuffer *Display::GetBuffer(int Index)
|
|
||||||
{
|
|
||||||
return this->Buffers[Index];
|
|
||||||
}
|
|
||||||
|
|
||||||
void Display::ClearBuffer(int Index)
|
|
||||||
{
|
|
||||||
memset(this->Buffers[Index]->Buffer, 0, this->Buffers[Index]->Size);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Display::DeleteBuffer(int Index)
|
|
||||||
{
|
|
||||||
if (this->Buffers[Index] == nullptr)
|
|
||||||
return;
|
|
||||||
KernelAllocator.FreePages(this->Buffers[Index]->Buffer, TO_PAGES(this->Buffers[Index]->Size));
|
|
||||||
this->Buffers[Index]->Buffer = nullptr;
|
|
||||||
this->Buffers[Index]->Checksum = 0; // Making sure that the buffer is not used anymore
|
|
||||||
delete this->Buffers[Index], this->Buffers[Index] = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Display::SetBrightness(int Value, int Index)
|
|
||||||
{
|
|
||||||
if (this->Buffers[Index] == nullptr)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (Value > 100)
|
|
||||||
Value = 100;
|
|
||||||
else if (Value < 0)
|
|
||||||
Value = 0;
|
|
||||||
|
|
||||||
ScreenBuffer *buffer = this->Buffers[Index];
|
|
||||||
uint32_t *pixel = (uint32_t *)buffer->Buffer;
|
|
||||||
|
|
||||||
for (uint32_t y = 0; y < buffer->Height; y++)
|
|
||||||
{
|
|
||||||
for (uint32_t x = 0; x < buffer->Width; x++)
|
|
||||||
{
|
|
||||||
uint32_t color = pixel[y * buffer->Width + x];
|
|
||||||
|
|
||||||
uint8_t r = color & 0xff;
|
|
||||||
uint8_t g = (color >> 8) & 0xff;
|
|
||||||
uint8_t b = (color >> 16) & 0xff;
|
|
||||||
|
|
||||||
r = (r * Value) / 100;
|
|
||||||
g = (g * Value) / 100;
|
|
||||||
b = (b * Value) / 100;
|
|
||||||
|
|
||||||
pixel[y * buffer->Width + x] = (b << 16) | (g << 8) | r;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
buffer->Brightness = Value;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Display::SetBufferCursor(int Index, uint32_t X, uint32_t Y)
|
|
||||||
{
|
|
||||||
this->Buffers[Index]->CursorX = X;
|
|
||||||
this->Buffers[Index]->CursorY = Y;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Display::GetBufferCursor(int Index, uint32_t *X, uint32_t *Y)
|
|
||||||
{
|
|
||||||
*X = this->Buffers[Index]->CursorX;
|
|
||||||
*Y = this->Buffers[Index]->CursorY;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Display::SetPixel(uint32_t X, uint32_t Y, uint32_t Color, int Index)
|
|
||||||
{
|
|
||||||
if (unlikely(X >= this->Buffers[Index]->Width))
|
|
||||||
X = this->Buffers[Index]->Width - 1;
|
|
||||||
if (unlikely(Y >= this->Buffers[Index]->Height))
|
|
||||||
Y = this->Buffers[Index]->Height - 1;
|
|
||||||
uint32_t *Pixel = (uint32_t *)((uintptr_t)this->Buffers[Index]->Buffer + (Y * this->Buffers[Index]->Width + X) * (this->framebuffer.BitsPerPixel / 8));
|
|
||||||
*Pixel = Color;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t Display::GetPixel(uint32_t X, uint32_t Y, int Index)
|
|
||||||
{
|
|
||||||
if (unlikely(X >= this->Buffers[Index]->Width || Y >= this->Buffers[Index]->Height))
|
|
||||||
return 0;
|
|
||||||
uint32_t *Pixel = (uint32_t *)((uintptr_t)this->Buffers[Index]->Buffer + (Y * this->Buffers[Index]->Width + X) * (this->framebuffer.BitsPerPixel / 8));
|
|
||||||
return *Pixel;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t Display::GetBitsPerPixel()
|
|
||||||
{
|
|
||||||
return this->framebuffer.BitsPerPixel;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t Display::GetPitch()
|
|
||||||
{
|
|
||||||
return this->framebuffer.Pitch;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Display::Scroll(int Index, int Lines)
|
|
||||||
{
|
|
||||||
if (Lines == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (Lines > 0)
|
|
||||||
{
|
|
||||||
uint32_t LineSize = this->Buffers[Index]->Width * (this->framebuffer.BitsPerPixel / 8);
|
|
||||||
uint32_t BytesToMove = LineSize * Lines * this->CurrentFont->GetInfo().Height;
|
|
||||||
uint32_t BytesToClear = this->Buffers[Index]->Size - BytesToMove;
|
|
||||||
memmove(this->Buffers[Index]->Buffer, (uint8_t *)this->Buffers[Index]->Buffer + BytesToMove, BytesToClear);
|
|
||||||
memset((uint8_t *)this->Buffers[Index]->Buffer + BytesToClear, 0, BytesToMove);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
char Display::Print(char Char, int Index, bool WriteToUART)
|
char Display::Print(char Char, int Index, bool WriteToUART)
|
||||||
{
|
{
|
||||||
// SmartLock(PrintLock);
|
// SmartLock(PrintLock);
|
||||||
@ -230,7 +67,7 @@ namespace Video
|
|||||||
|
|
||||||
for (unsigned long Y = this->Buffers[Index]->CursorY; Y < this->Buffers[Index]->CursorY + fonthdrHeight; Y++)
|
for (unsigned long Y = this->Buffers[Index]->CursorY; Y < this->Buffers[Index]->CursorY + fonthdrHeight; Y++)
|
||||||
for (unsigned long X = this->Buffers[Index]->CursorX - fonthdrWidth; X < this->Buffers[Index]->CursorX; X++)
|
for (unsigned long X = this->Buffers[Index]->CursorX - fonthdrWidth; X < this->Buffers[Index]->CursorX; X++)
|
||||||
*(uint32_t *)((uintptr_t)this->Buffers[Index]->Buffer +
|
*(uint32_t *)((uint64_t)this->Buffers[Index]->Buffer +
|
||||||
(Y * this->Buffers[Index]->Width + X) * (this->framebuffer.BitsPerPixel / 8)) = 0;
|
(Y * this->Buffers[Index]->Width + X) * (this->framebuffer.BitsPerPixel / 8)) = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -262,18 +99,16 @@ namespace Video
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t FontHeight = this->GetCurrentFont()->GetInfo().Height;
|
if (this->Buffers[Index]->CursorY + this->GetCurrentFont()->GetInfo().Height >= this->Buffers[Index]->Height)
|
||||||
|
{
|
||||||
|
this->Buffers[Index]->CursorY -= this->GetCurrentFont()->GetInfo().Height;
|
||||||
|
this->Scroll(Index, 1);
|
||||||
|
}
|
||||||
|
|
||||||
if (this->Buffers[Index]->CursorX + this->GetCurrentFont()->GetInfo().Width >= this->Buffers[Index]->Width)
|
if (this->Buffers[Index]->CursorX + this->GetCurrentFont()->GetInfo().Width >= this->Buffers[Index]->Width)
|
||||||
{
|
{
|
||||||
this->Buffers[Index]->CursorX = 0;
|
this->Buffers[Index]->CursorX = 0;
|
||||||
this->Buffers[Index]->CursorY += FontHeight;
|
this->Buffers[Index]->CursorY += this->GetCurrentFont()->GetInfo().Height;
|
||||||
}
|
|
||||||
|
|
||||||
if (this->Buffers[Index]->CursorY + FontHeight >= this->Buffers[Index]->Height)
|
|
||||||
{
|
|
||||||
this->Buffers[Index]->CursorY -= FontHeight;
|
|
||||||
this->Scroll(Index, 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (this->CurrentFont->GetInfo().Type)
|
switch (this->CurrentFont->GetInfo().Type)
|
||||||
@ -298,30 +133,24 @@ namespace Video
|
|||||||
// if (this->CurrentFont->PSF2Font->GlyphBuffer == (uint16_t *)0x01) // HAS UNICODE TABLE
|
// if (this->CurrentFont->PSF2Font->GlyphBuffer == (uint16_t *)0x01) // HAS UNICODE TABLE
|
||||||
// Char = this->CurrentFont->PSF2Font->GlyphBuffer[Char];
|
// Char = this->CurrentFont->PSF2Font->GlyphBuffer[Char];
|
||||||
int BytesPerLine = (this->CurrentFont->GetInfo().PSF2Font->Header->width + 7) / 8;
|
int BytesPerLine = (this->CurrentFont->GetInfo().PSF2Font->Header->width + 7) / 8;
|
||||||
char *FontAddress = (char *)this->CurrentFont->GetInfo().StartAddress;
|
char *FontPtr = (char *)this->CurrentFont->GetInfo().StartAddress +
|
||||||
uint32_t FontHeaderSize = this->CurrentFont->GetInfo().PSF2Font->Header->headersize;
|
this->CurrentFont->GetInfo().PSF2Font->Header->headersize +
|
||||||
uint32_t FontCharSize = this->CurrentFont->GetInfo().PSF2Font->Header->charsize;
|
(Char > 0 && (unsigned char)Char < this->CurrentFont->GetInfo().PSF2Font->Header->length ? Char : 0) *
|
||||||
uint32_t FontLength = this->CurrentFont->GetInfo().PSF2Font->Header->length;
|
this->CurrentFont->GetInfo().PSF2Font->Header->charsize;
|
||||||
char *FontPtr = FontAddress + FontHeaderSize + (Char > 0 && (uint32_t)Char < FontLength ? Char : 0) * FontCharSize;
|
|
||||||
|
|
||||||
uint32_t FontHdrWidth = this->CurrentFont->GetInfo().PSF2Font->Header->width;
|
uint32_t fonthdrWidth = this->CurrentFont->GetInfo().PSF2Font->Header->width;
|
||||||
uint32_t FontHdrHeight = this->CurrentFont->GetInfo().PSF2Font->Header->height;
|
uint32_t fonthdrHeight = this->CurrentFont->GetInfo().PSF2Font->Header->height;
|
||||||
|
|
||||||
for (size_t Y = this->Buffers[Index]->CursorY; Y < this->Buffers[Index]->CursorY + FontHdrHeight; Y++)
|
for (uint64_t Y = this->Buffers[Index]->CursorY; Y < this->Buffers[Index]->CursorY + fonthdrHeight; Y++)
|
||||||
{
|
|
||||||
for (size_t X = this->Buffers[Index]->CursorX; X < this->Buffers[Index]->CursorX + FontHdrWidth; X++)
|
|
||||||
{
|
{
|
||||||
|
for (uint64_t X = this->Buffers[Index]->CursorX; X < this->Buffers[Index]->CursorX + fonthdrWidth; X++)
|
||||||
if ((*FontPtr & (0b10000000 >> (X - this->Buffers[Index]->CursorX))) > 0)
|
if ((*FontPtr & (0b10000000 >> (X - this->Buffers[Index]->CursorX))) > 0)
|
||||||
{
|
*(uint32_t *)((uint64_t)this->Buffers[Index]->Buffer +
|
||||||
void *FramebufferAddress = (void *)((uintptr_t)this->Buffers[Index]->Buffer +
|
(Y * this->Buffers[Index]->Width + X) * (this->framebuffer.BitsPerPixel / 8)) = this->Buffers[Index]->Color;
|
||||||
(Y * this->Buffers[Index]->Width + X) *
|
|
||||||
(this->framebuffer.BitsPerPixel / 8));
|
|
||||||
*(uint32_t *)FramebufferAddress = this->Buffers[Index]->Color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
FontPtr += BytesPerLine;
|
FontPtr += BytesPerLine;
|
||||||
}
|
}
|
||||||
this->Buffers[Index]->CursorX += FontHdrWidth;
|
this->Buffers[Index]->CursorX += fonthdrWidth;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@ -331,21 +160,12 @@ namespace Video
|
|||||||
return Char;
|
return Char;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Display::DrawString(const char *String, uint32_t X, uint32_t Y, int Index, bool WriteToUART)
|
|
||||||
{
|
|
||||||
this->Buffers[Index]->CursorX = X;
|
|
||||||
this->Buffers[Index]->CursorY = Y;
|
|
||||||
|
|
||||||
for (int i = 0; String[i] != '\0'; i++)
|
|
||||||
this->Print(String[i], Index, WriteToUART);
|
|
||||||
}
|
|
||||||
|
|
||||||
Display::Display(BootInfo::FramebufferInfo Info, bool LoadDefaultFont)
|
Display::Display(BootInfo::FramebufferInfo Info, bool LoadDefaultFont)
|
||||||
{
|
{
|
||||||
this->framebuffer = Info;
|
this->framebuffer = Info;
|
||||||
if (LoadDefaultFont)
|
if (LoadDefaultFont)
|
||||||
{
|
{
|
||||||
this->CurrentFont = new Font(&_binary_Files_tamsyn_font_1_11_Tamsyn7x14r_psf_start, &_binary_Files_tamsyn_font_1_11_Tamsyn7x14r_psf_end, FontType::PCScreenFont2);
|
this->CurrentFont = new Font(&_binary_Files_ter_powerline_v12n_psf_start, &_binary_Files_ter_powerline_v12n_psf_end, FontType::PCScreenFont2);
|
||||||
FontInfo Info = this->CurrentFont->GetInfo();
|
FontInfo Info = this->CurrentFont->GetInfo();
|
||||||
debug("Font loaded: %dx%d %s",
|
debug("Font loaded: %dx%d %s",
|
||||||
Info.Width, Info.Height, Info.Type == FontType::PCScreenFont1 ? "PSF1" : "PSF2");
|
Info.Width, Info.Height, Info.Type == FontType::PCScreenFont1 ? "PSF1" : "PSF2");
|
||||||
@ -355,11 +175,7 @@ namespace Video
|
|||||||
|
|
||||||
Display::~Display()
|
Display::~Display()
|
||||||
{
|
{
|
||||||
debug("Destructor called");
|
for (int i = 0; i < 16; i++)
|
||||||
this->ClearBuffer(0);
|
DeleteBuffer(i);
|
||||||
this->SetBuffer(0);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < sizeof(this->Buffers) / sizeof(this->Buffers[0]); i++)
|
|
||||||
this->DeleteBuffer(i);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
namespace Video
|
namespace Video
|
||||||
{
|
{
|
||||||
Font::Font(uintptr_t *Start, uintptr_t *End, FontType Type)
|
Font::Font(uint64_t *Start, uint64_t *End, FontType Type)
|
||||||
{
|
{
|
||||||
trace("Initializing font with start %#llx and end %#llx Type: %d", Start, End, Type);
|
trace("Initializing font with start %#llx and end %#llx Type: %d", Start, End, Type);
|
||||||
this->Info.StartAddress = Start;
|
this->Info.StartAddress = Start;
|
||||||
@ -14,9 +14,9 @@ namespace Video
|
|||||||
{
|
{
|
||||||
this->Info.PSF2Font = new PSF2_FONT;
|
this->Info.PSF2Font = new PSF2_FONT;
|
||||||
|
|
||||||
uintptr_t FontDataLength = End - Start;
|
uint64_t FontDataLength = End - Start;
|
||||||
PSF2_HEADER *font2 = (PSF2_HEADER *)KernelAllocator.RequestPages(FontDataLength / PAGE_SIZE + 1);
|
PSF2_HEADER *font2 = (PSF2_HEADER *)KernelAllocator.RequestPages(FontDataLength / PAGE_SIZE + 1);
|
||||||
for (uintptr_t i = 0; i < FontDataLength / PAGE_SIZE + 1; i++)
|
for (uint64_t i = 0; i < FontDataLength / PAGE_SIZE + 1; i++)
|
||||||
Memory::Virtual().Map((void *)(font2 + (i * PAGE_SIZE)), (void *)(font2 + (i * PAGE_SIZE)), Memory::PTFlag::RW);
|
Memory::Virtual().Map((void *)(font2 + (i * PAGE_SIZE)), (void *)(font2 + (i * PAGE_SIZE)), Memory::PTFlag::RW);
|
||||||
memcpy((void *)font2, Start, FontDataLength);
|
memcpy((void *)font2, Start, FontDataLength);
|
||||||
|
|
||||||
@ -26,7 +26,7 @@ namespace Video
|
|||||||
error("Font2 magic mismatch.");
|
error("Font2 magic mismatch.");
|
||||||
|
|
||||||
this->Info.PSF2Font->Header = font2;
|
this->Info.PSF2Font->Header = font2;
|
||||||
this->Info.PSF2Font->GlyphBuffer = reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(Start) + sizeof(PSF2_HEADER));
|
this->Info.PSF2Font->GlyphBuffer = reinterpret_cast<void *>(reinterpret_cast<uint64_t>(Start) + sizeof(PSF2_HEADER));
|
||||||
}
|
}
|
||||||
else if (Type == FontType::PCScreenFont1)
|
else if (Type == FontType::PCScreenFont1)
|
||||||
{
|
{
|
||||||
@ -37,7 +37,7 @@ namespace Video
|
|||||||
uint32_t glyphBufferSize = font1->charsize * 256;
|
uint32_t glyphBufferSize = font1->charsize * 256;
|
||||||
if (font1->mode == 1) // 512 glyph mode
|
if (font1->mode == 1) // 512 glyph mode
|
||||||
glyphBufferSize = font1->charsize * 512;
|
glyphBufferSize = font1->charsize * 512;
|
||||||
void *glyphBuffer = reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(Start) + sizeof(PSF1_HEADER));
|
void *glyphBuffer = reinterpret_cast<void *>(reinterpret_cast<uint64_t>(Start) + sizeof(PSF1_HEADER));
|
||||||
this->Info.PSF1Font->Header = font1;
|
this->Info.PSF1Font->Header = font1;
|
||||||
this->Info.PSF1Font->GlyphBuffer = glyphBuffer;
|
this->Info.PSF1Font->GlyphBuffer = glyphBuffer;
|
||||||
UNUSED(glyphBufferSize); // TODO: Use this in the future?
|
UNUSED(glyphBufferSize); // TODO: Use this in the future?
|
||||||
|
@ -1,18 +1,17 @@
|
|||||||
#ifndef __FENNIX_KERNEL_CRASH_HANDLER_H__
|
#ifndef __FENNIX_KERNEL_CRASH_HANDELR_H__
|
||||||
#define __FENNIX_KERNEL_CRASH_HANDLER_H__
|
#define __FENNIX_KERNEL_CRASH_HANDELR_H__
|
||||||
|
|
||||||
#include <types.h>
|
#include <types.h>
|
||||||
|
|
||||||
#include <ints.hpp>
|
#include <interrupts.hpp>
|
||||||
#include <cpu.hpp>
|
#include <cpu.hpp>
|
||||||
|
|
||||||
namespace CrashHandler
|
namespace CrashHandler
|
||||||
{
|
{
|
||||||
extern uintptr_t PageFaultAddress;
|
|
||||||
extern void *EHIntFrames[INT_FRAMES_MAX];
|
extern void *EHIntFrames[INT_FRAMES_MAX];
|
||||||
|
|
||||||
void EHPrint(const char *Format, ...);
|
void EHPrint(const char *Format, ...);
|
||||||
void Handle(void *Data);
|
void Handle(void *Data);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // !__FENNIX_KERNEL_CRASH_HANDLER_H__
|
#endif // !__FENNIX_KERNEL_CRASH_HANDELR_H__
|
||||||
|
209
Kernel/DAPI.hpp
209
Kernel/DAPI.hpp
@ -1,17 +1,6 @@
|
|||||||
#ifndef __FENNIX_DRIVER_API_H__
|
#ifndef __FENNIX_DRIVER_API_H__
|
||||||
#define __FENNIX_DRIVER_API_H__
|
#define __FENNIX_DRIVER_API_H__
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief The driver API is a set of functions that the kernel provides to the drivers.
|
|
||||||
*
|
|
||||||
* - The driver is responsible for the memory management.
|
|
||||||
* - The kernel will NOT free any memory allocated by the driver. On @see StopReason the driver must free all the memory it allocated and disable the hardware it uses.
|
|
||||||
* - The driver image will be freed after the driver is unloaded.
|
|
||||||
* - The kernel will unbind the interrupt handlers and the process handlers.
|
|
||||||
* - Kernel API will be freed after the driver is unloaded.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
enum DriverReturnCode
|
enum DriverReturnCode
|
||||||
{
|
{
|
||||||
ERROR,
|
ERROR,
|
||||||
@ -23,13 +12,10 @@ enum DriverReturnCode
|
|||||||
NOT_AUTHORIZED,
|
NOT_AUTHORIZED,
|
||||||
NOT_VALID,
|
NOT_VALID,
|
||||||
NOT_ACCEPTED,
|
NOT_ACCEPTED,
|
||||||
INVALID_PCI_BAR,
|
|
||||||
INVALID_KERNEL_API,
|
INVALID_KERNEL_API,
|
||||||
INVALID_MEMORY_ALLOCATION,
|
|
||||||
INVALID_DATA,
|
|
||||||
DEVICE_NOT_SUPPORTED,
|
DEVICE_NOT_SUPPORTED,
|
||||||
SYSTEM_NOT_SUPPORTED,
|
SYSTEM_NOT_SUPPORTED,
|
||||||
KERNEL_API_VERSION_NOT_SUPPORTED,
|
KERNEL_API_VERSION_NOT_SUPPORTED
|
||||||
};
|
};
|
||||||
|
|
||||||
enum DriverBindType
|
enum DriverBindType
|
||||||
@ -76,8 +62,6 @@ struct KernelAPI
|
|||||||
void (*DisplayPrint)(char *Value);
|
void (*DisplayPrint)(char *Value);
|
||||||
void *(*memcpy)(void *Destination, void *Source, unsigned long Size);
|
void *(*memcpy)(void *Destination, void *Source, unsigned long Size);
|
||||||
void *(*memset)(void *Destination, int Value, unsigned long Size);
|
void *(*memset)(void *Destination, int Value, unsigned long Size);
|
||||||
void (*Sleep)(unsigned long Milliseconds);
|
|
||||||
int (*sprintf)(char *Buffer, const char *Format, ...);
|
|
||||||
} Util;
|
} Util;
|
||||||
|
|
||||||
struct KAPIDriverTalk
|
struct KAPIDriverTalk
|
||||||
@ -100,94 +84,25 @@ struct KernelAPI
|
|||||||
} Disk;
|
} Disk;
|
||||||
} Command;
|
} Command;
|
||||||
|
|
||||||
struct KAPIDisplay
|
|
||||||
{
|
|
||||||
unsigned int (*GetWidth)(void);
|
|
||||||
unsigned int (*GetHeight)(void);
|
|
||||||
/* TODO: Add more */
|
|
||||||
} Display;
|
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
enum CallbackReason
|
enum CallbackReason
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* @brief This is used to detect memory corruption, not used.
|
|
||||||
*/
|
|
||||||
UnknownReason,
|
UnknownReason,
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief This is called once the kernel is ready to use the driver and call @see ConfigurationReason .
|
|
||||||
*/
|
|
||||||
AcknowledgeReason,
|
AcknowledgeReason,
|
||||||
|
SendReason,
|
||||||
/**
|
ReceiveReason,
|
||||||
* @brief This is used after the driver is loaded and the kernel is ready to use the driver.
|
|
||||||
*
|
|
||||||
* For PCI drivers, @see RawPtr will be the PCI device address.
|
|
||||||
*/
|
|
||||||
ConfigurationReason,
|
ConfigurationReason,
|
||||||
|
FetchReason,
|
||||||
/**
|
BindReason,
|
||||||
* @brief This will be called when the registered interrupt is triggered.
|
UnbindReason,
|
||||||
*/
|
|
||||||
InterruptReason,
|
InterruptReason,
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief This is used when the kernel wants to stop the driver.
|
|
||||||
*
|
|
||||||
* The memory allocated by the driver will be freed automatically.
|
|
||||||
*/
|
|
||||||
StopReason,
|
|
||||||
|
|
||||||
ProcessReason,
|
ProcessReason,
|
||||||
InputReason,
|
InputReason,
|
||||||
|
|
||||||
/* Kernel reserved callbacks. */
|
|
||||||
/* ------------------------------------------------------- */
|
|
||||||
/* Driver callbacks for basic usage. */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief This is used when the kernel sends data.
|
|
||||||
*
|
|
||||||
* - Network
|
|
||||||
* - Packet
|
|
||||||
* - Audio
|
|
||||||
* - PCM Data
|
|
||||||
*/
|
|
||||||
SendReason,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief This is used when the kernel wants to receive data.
|
|
||||||
* Currently not used.
|
|
||||||
*/
|
|
||||||
ReceiveReason,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief This is used to adjust driver settings.
|
|
||||||
*
|
|
||||||
* - Audio
|
|
||||||
* - Volume
|
|
||||||
* - PCM Encoding
|
|
||||||
*/
|
|
||||||
AdjustReason,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief This is used when the kernel wants to fetch information about the driver.
|
|
||||||
*
|
|
||||||
* - Input
|
|
||||||
* - Mouse
|
|
||||||
* - Position
|
|
||||||
* - Buttons
|
|
||||||
* - Keyboard
|
|
||||||
* - Key
|
|
||||||
*/
|
|
||||||
FetchReason,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
union KernelCallback
|
struct KernelCallback
|
||||||
{
|
{
|
||||||
struct
|
|
||||||
{
|
|
||||||
CallbackReason Reason;
|
CallbackReason Reason;
|
||||||
void *RawPtr;
|
void *RawPtr;
|
||||||
unsigned long RawData;
|
unsigned long RawData;
|
||||||
@ -195,17 +110,8 @@ union KernelCallback
|
|||||||
/** @brief When the kernel wants to send a packet. */
|
/** @brief When the kernel wants to send a packet. */
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
struct
|
void *Data;
|
||||||
{
|
|
||||||
unsigned char *Data;
|
|
||||||
unsigned long Length;
|
unsigned long Length;
|
||||||
} Send;
|
|
||||||
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
char Name[128];
|
|
||||||
unsigned long MAC;
|
|
||||||
} Fetch;
|
|
||||||
} NetworkCallback;
|
} NetworkCallback;
|
||||||
|
|
||||||
/** @brief When the kernel wants to write to disk. */
|
/** @brief When the kernel wants to write to disk. */
|
||||||
@ -227,7 +133,6 @@ union KernelCallback
|
|||||||
} Fetch;
|
} Fetch;
|
||||||
} DiskCallback;
|
} DiskCallback;
|
||||||
|
|
||||||
/** @brief When the kernel wants to get mouse position / keyboard key */
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
struct
|
struct
|
||||||
@ -244,108 +149,10 @@ union KernelCallback
|
|||||||
} Mouse;
|
} Mouse;
|
||||||
} InputCallback;
|
} InputCallback;
|
||||||
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
bool _Volume;
|
|
||||||
bool _Encoding;
|
|
||||||
bool _SampleRate;
|
|
||||||
bool _Channels;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Adjust the volume.
|
|
||||||
*
|
|
||||||
* 0 - 100
|
|
||||||
*/
|
|
||||||
unsigned char Volume;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Adjust the encoding.
|
|
||||||
*
|
|
||||||
* 0 - None, use default
|
|
||||||
*
|
|
||||||
* 1 - Signed PCM 8-bit
|
|
||||||
* 2 - Unsigned PCM 8-bit
|
|
||||||
*
|
|
||||||
* 3 - Signed PCM 16-bit Little Endian
|
|
||||||
* 4 - Signed PCM 20-bit Little Endian
|
|
||||||
* 5 - Signed PCM 24-bit Little Endian
|
|
||||||
* 6 - Signed PCM 32-bit Little Endian
|
|
||||||
*
|
|
||||||
* 7 - Unsigned PCM 16-bit Little Endian
|
|
||||||
* 8 - Unsigned PCM 20-bit Little Endian
|
|
||||||
* 9 - Unsigned PCM 24-bit Little Endian
|
|
||||||
* 10 - Unsigned PCM 32-bit Little Endian
|
|
||||||
*
|
|
||||||
* 11 - Signed PCM 16-bit Big Endian
|
|
||||||
* 12 - Signed PCM 20-bit Big Endian
|
|
||||||
* 13 - Signed PCM 24-bit Big Endian
|
|
||||||
* 14 - Signed PCM 32-bit Big Endian
|
|
||||||
*
|
|
||||||
* 15 - Unsigned PCM 16-bit Big Endian
|
|
||||||
* 16 - Unsigned PCM 20-bit Big Endian
|
|
||||||
* 17 - Unsigned PCM 24-bit Big Endian
|
|
||||||
* 18 - Unsigned PCM 32-bit Big Endian
|
|
||||||
*
|
|
||||||
* 19 - Float PCM 32-bit Little Endian
|
|
||||||
* 20 - Float PCM 64-bit Little Endian
|
|
||||||
*
|
|
||||||
* 21 - Float PCM 32-bit Big Endian
|
|
||||||
* 22 - Float PCM 64-bit Big Endian
|
|
||||||
*
|
|
||||||
* 23 - PCM A-law
|
|
||||||
* 24 - PCM Mu-law
|
|
||||||
*
|
|
||||||
* ... - More
|
|
||||||
*/
|
|
||||||
unsigned short Encoding;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Adjust the sample rate.
|
|
||||||
*
|
|
||||||
* 0 - 8000 Hz
|
|
||||||
* 1 - 11025 Hz
|
|
||||||
* 2 - 16000 Hz
|
|
||||||
* 3 - 22050 Hz
|
|
||||||
* 4 - 32000 Hz
|
|
||||||
* 5 - 44100 Hz
|
|
||||||
* 6 - 48000 Hz
|
|
||||||
* 7 - 88200 Hz
|
|
||||||
* 8 - 96000 Hz
|
|
||||||
*/
|
|
||||||
unsigned char SampleRate;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Adjust the channels.
|
|
||||||
*
|
|
||||||
* 0 - Mono
|
|
||||||
* 1 - Stereo
|
|
||||||
*/
|
|
||||||
unsigned char Channels;
|
|
||||||
} Adjust;
|
|
||||||
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
unsigned char *Data;
|
|
||||||
unsigned long Length;
|
|
||||||
} Send;
|
|
||||||
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
unsigned char Volume;
|
|
||||||
unsigned short Encoding;
|
|
||||||
unsigned char SampleRate;
|
|
||||||
unsigned char Channels;
|
|
||||||
} Fetch;
|
|
||||||
} AudioCallback;
|
|
||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
unsigned char Vector;
|
unsigned char Vector;
|
||||||
} InterruptInfo;
|
} InterruptInfo;
|
||||||
};
|
|
||||||
unsigned long raw;
|
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
#endif // !__FENNIX_DRIVER_API_H__
|
#endif // !__FENNIX_DRIVER_API_H__
|
||||||
|
@ -1,217 +0,0 @@
|
|||||||
#include <exec.hpp>
|
|
||||||
|
|
||||||
#include <memory.hpp>
|
|
||||||
#include <lock.hpp>
|
|
||||||
#include <msexec.h>
|
|
||||||
#include <cwalk.h>
|
|
||||||
#include <elf.h>
|
|
||||||
#include <abi.h>
|
|
||||||
|
|
||||||
#include "../../kernel.h"
|
|
||||||
#include "../../Fex.hpp"
|
|
||||||
|
|
||||||
using namespace Tasking;
|
|
||||||
using VirtualFileSystem::File;
|
|
||||||
using VirtualFileSystem::FileStatus;
|
|
||||||
using VirtualFileSystem::NodeFlags;
|
|
||||||
|
|
||||||
namespace Execute
|
|
||||||
{
|
|
||||||
/* Passing arguments as a sanity check and debugging. */
|
|
||||||
void ELFInterpreterIPCThread(PCB *Process, char *Path, void *MemoryImage, Vector<String> NeededLibraries)
|
|
||||||
{
|
|
||||||
debug("Interpreter thread started for %s", Path);
|
|
||||||
// Interpreter will create an IPC with token "LOAD".
|
|
||||||
char UniqueToken[16] = {'L', 'O', 'A', 'D', '\0'};
|
|
||||||
InterProcessCommunication::IPCHandle *Handle = nullptr;
|
|
||||||
while (Handle == nullptr)
|
|
||||||
{
|
|
||||||
debug("Searching for IPC with token %s", UniqueToken);
|
|
||||||
Handle = Process->IPC->SearchByToken(UniqueToken);
|
|
||||||
if (Handle == nullptr)
|
|
||||||
debug("Failed");
|
|
||||||
TaskManager->Sleep(100);
|
|
||||||
if (Handle == nullptr)
|
|
||||||
debug("Retrying...");
|
|
||||||
}
|
|
||||||
debug("IPC found, sending data...");
|
|
||||||
RetryIPCWrite:
|
|
||||||
uintptr_t *TmpBuffer = new uintptr_t[0x1000];
|
|
||||||
*(int *)TmpBuffer = 2545;
|
|
||||||
InterProcessCommunication::IPCErrorCode ret = Process->IPC->Write(Handle->ID, TmpBuffer, 0x1000);
|
|
||||||
delete[] TmpBuffer, TmpBuffer = nullptr;
|
|
||||||
debug("Write returned %d", ret);
|
|
||||||
if (ret == InterProcessCommunication::IPCErrorCode::IPCNotListening)
|
|
||||||
{
|
|
||||||
debug("IPC not listening, retrying...");
|
|
||||||
TaskManager->Sleep(100);
|
|
||||||
goto RetryIPCWrite;
|
|
||||||
}
|
|
||||||
CPU::Halt(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
PCB *InterpreterTargetProcess;
|
|
||||||
String *InterpreterTargetPath; /* We can't have String as a constructor :( */
|
|
||||||
void *InterpreterMemoryImage;
|
|
||||||
Vector<String> InterpreterNeededLibraries;
|
|
||||||
void ELFInterpreterThreadWrapper()
|
|
||||||
{
|
|
||||||
ELFInterpreterIPCThread(InterpreterTargetProcess, (char *)InterpreterTargetPath->c_str(), InterpreterMemoryImage, InterpreterNeededLibraries);
|
|
||||||
delete InterpreterTargetPath, InterpreterTargetPath = nullptr;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ELFBaseLoad ELFLoad(char *Path, const char **argv, const char **envp, Tasking::TaskCompatibility Compatibility)
|
|
||||||
{
|
|
||||||
/* We get the base name ("app.elf") */
|
|
||||||
const char *BaseName;
|
|
||||||
cwk_path_get_basename(Path, &BaseName, nullptr);
|
|
||||||
TaskArchitecture Arch = TaskArchitecture::UnknownArchitecture;
|
|
||||||
|
|
||||||
shared_ptr<File> ExFile = vfs->Open(Path);
|
|
||||||
|
|
||||||
if (ExFile->Status != FileStatus::OK)
|
|
||||||
{
|
|
||||||
vfs->Close(ExFile);
|
|
||||||
error("Failed to open file: %s", Path);
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (ExFile->node->Flags != NodeFlags::FILE)
|
|
||||||
{
|
|
||||||
vfs->Close(ExFile);
|
|
||||||
error("Invalid file path: %s", Path);
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
else if (GetBinaryType(Path) != BinaryType::BinTypeELF)
|
|
||||||
{
|
|
||||||
vfs->Close(ExFile);
|
|
||||||
error("Invalid file type: %s", Path);
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t ExFileSize = ExFile->node->Length;
|
|
||||||
|
|
||||||
/* Allocate elf in memory */
|
|
||||||
void *ElfFile = KernelAllocator.RequestPages(TO_PAGES(ExFileSize));
|
|
||||||
/* Copy the file to the allocated memory */
|
|
||||||
memcpy(ElfFile, (void *)ExFile->node->Address, ExFileSize);
|
|
||||||
debug("Image Size: %#lx - %#lx (length: %ld)", ElfFile, (uintptr_t)ElfFile + ExFileSize, ExFileSize);
|
|
||||||
|
|
||||||
Elf64_Ehdr *ELFHeader = (Elf64_Ehdr *)ElfFile;
|
|
||||||
|
|
||||||
switch (ELFHeader->e_machine)
|
|
||||||
{
|
|
||||||
case EM_386:
|
|
||||||
Arch = TaskArchitecture::x32;
|
|
||||||
break;
|
|
||||||
case EM_X86_64:
|
|
||||||
Arch = TaskArchitecture::x64;
|
|
||||||
break;
|
|
||||||
case EM_ARM:
|
|
||||||
Arch = TaskArchitecture::ARM32;
|
|
||||||
break;
|
|
||||||
case EM_AARCH64:
|
|
||||||
Arch = TaskArchitecture::ARM64;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: This shouldn't be ignored
|
|
||||||
if (ELFHeader->e_ident[EI_CLASS] == ELFCLASS32)
|
|
||||||
{
|
|
||||||
if (ELFHeader->e_ident[EI_DATA] == ELFDATA2LSB)
|
|
||||||
fixme("ELF32 LSB");
|
|
||||||
else if (ELFHeader->e_ident[EI_DATA] == ELFDATA2MSB)
|
|
||||||
fixme("ELF32 MSB");
|
|
||||||
else
|
|
||||||
fixme("ELF32 Unknown");
|
|
||||||
}
|
|
||||||
else if (ELFHeader->e_ident[EI_CLASS] == ELFCLASS64)
|
|
||||||
{
|
|
||||||
if (ELFHeader->e_ident[EI_DATA] == ELFDATA2LSB)
|
|
||||||
fixme("ELF64 LSB");
|
|
||||||
else if (ELFHeader->e_ident[EI_DATA] == ELFDATA2MSB)
|
|
||||||
fixme("ELF64 MSB");
|
|
||||||
else
|
|
||||||
fixme("ELF64 Unknown");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
fixme("Unknown ELF");
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------------------------------------------------------------ */
|
|
||||||
|
|
||||||
PCB *Process = TaskManager->CreateProcess(TaskManager->GetCurrentProcess(), BaseName, TaskTrustLevel::User, ElfFile);
|
|
||||||
Memory::Virtual pV = Memory::Virtual(Process->PageTable);
|
|
||||||
for (size_t i = 0; i < TO_PAGES(ExFileSize); i++)
|
|
||||||
pV.Remap((void *)((uintptr_t)ElfFile + (i * PAGE_SIZE)), (void *)((uintptr_t)ElfFile + (i * PAGE_SIZE)), Memory::PTFlag::RW | Memory::PTFlag::US);
|
|
||||||
|
|
||||||
// for (size_t i = 0; i < TO_PAGES(ElfLazyResolverSize); i++)
|
|
||||||
// pV.Remap((void *)((uintptr_t)ElfLazyResolver + (i * PAGE_SIZE)), (void *)((uintptr_t)ElfLazyResolver + (i * PAGE_SIZE)), Memory::PTFlag::RW | Memory::PTFlag::US);
|
|
||||||
|
|
||||||
ELFBaseLoad bl;
|
|
||||||
|
|
||||||
switch (ELFHeader->e_type)
|
|
||||||
{
|
|
||||||
case ET_REL:
|
|
||||||
bl = ELFLoadRel(ElfFile, ExFile.Get(), Process);
|
|
||||||
break;
|
|
||||||
case ET_EXEC:
|
|
||||||
bl = ELFLoadExec(ElfFile, ExFile.Get(), Process);
|
|
||||||
break;
|
|
||||||
case ET_DYN:
|
|
||||||
bl = ELFLoadDyn(ElfFile, ExFile.Get(), Process);
|
|
||||||
break;
|
|
||||||
case ET_CORE:
|
|
||||||
{
|
|
||||||
fixme("ET_CORE not implemented");
|
|
||||||
TaskManager->RevertProcessCreation(Process);
|
|
||||||
vfs->Close(ExFile);
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
case ET_NONE:
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
error("Unknown ELF Type: %d", ELFHeader->e_type);
|
|
||||||
vfs->Close(ExFile);
|
|
||||||
TaskManager->RevertProcessCreation(Process);
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bl.Interpreter)
|
|
||||||
{
|
|
||||||
InterpreterTargetProcess = Process;
|
|
||||||
InterpreterTargetPath = new String(Path); /* We store in a String because Path may get changed while outside ELFLoad(). */
|
|
||||||
InterpreterMemoryImage = bl.MemoryImage;
|
|
||||||
InterpreterNeededLibraries = bl.NeededLibraries;
|
|
||||||
__sync;
|
|
||||||
TCB *InterpreterIPCThread = TaskManager->CreateThread(TaskManager->GetCurrentProcess(), (IP)ELFInterpreterThreadWrapper);
|
|
||||||
InterpreterIPCThread->Rename("ELF Interpreter IPC Thread");
|
|
||||||
InterpreterIPCThread->SetPriority(TaskPriority::Low);
|
|
||||||
}
|
|
||||||
|
|
||||||
TCB *Thread = TaskManager->CreateThread(Process,
|
|
||||||
bl.InstructionPointer,
|
|
||||||
argv, envp, bl.auxv,
|
|
||||||
(IPOffset)0 /* ProgramHeader->p_offset */, // I guess I don't need this
|
|
||||||
Arch,
|
|
||||||
Compatibility);
|
|
||||||
|
|
||||||
foreach (Memory::MemMgr::AllocatedPages p in bl.TmpMem->GetAllocatedPagesList())
|
|
||||||
{
|
|
||||||
Thread->Memory->Add(p.Address, p.PageCount);
|
|
||||||
bl.TmpMem->DetachAddress(p.Address);
|
|
||||||
}
|
|
||||||
delete bl.TmpMem, bl.TmpMem = nullptr;
|
|
||||||
|
|
||||||
bl.sd.Process = Process;
|
|
||||||
bl.sd.Thread = Thread;
|
|
||||||
bl.sd.Status = ExStatus::OK;
|
|
||||||
vfs->Close(ExFile);
|
|
||||||
return bl;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,24 +0,0 @@
|
|||||||
#include <exec.hpp>
|
|
||||||
|
|
||||||
#include <memory.hpp>
|
|
||||||
#include <lock.hpp>
|
|
||||||
#include <msexec.h>
|
|
||||||
#include <cwalk.h>
|
|
||||||
#include <elf.h>
|
|
||||||
#include <abi.h>
|
|
||||||
|
|
||||||
#include "../../kernel.h"
|
|
||||||
#include "../../Fex.hpp"
|
|
||||||
|
|
||||||
using namespace Tasking;
|
|
||||||
|
|
||||||
namespace Execute
|
|
||||||
{
|
|
||||||
ELFBaseLoad ELFLoadDyn(void *BaseImage,
|
|
||||||
VirtualFileSystem::File *ExFile,
|
|
||||||
Tasking::PCB *Process)
|
|
||||||
{
|
|
||||||
fixme("Not implemented");
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,206 +0,0 @@
|
|||||||
#include <exec.hpp>
|
|
||||||
|
|
||||||
#include <memory.hpp>
|
|
||||||
#include <lock.hpp>
|
|
||||||
#include <msexec.h>
|
|
||||||
#include <cwalk.h>
|
|
||||||
#include <elf.h>
|
|
||||||
#include <abi.h>
|
|
||||||
|
|
||||||
#include "../../kernel.h"
|
|
||||||
#include "../../Fex.hpp"
|
|
||||||
|
|
||||||
using namespace Tasking;
|
|
||||||
|
|
||||||
namespace Execute
|
|
||||||
{
|
|
||||||
ELFBaseLoad ELFLoadExec(void *ElfFile,
|
|
||||||
VirtualFileSystem::File *ExFile,
|
|
||||||
Tasking::PCB *Process)
|
|
||||||
{
|
|
||||||
debug("Executable");
|
|
||||||
ELFBaseLoad ELFBase = {};
|
|
||||||
/* This should be deleted inside BaseLoad.cpp */
|
|
||||||
ELFBase.TmpMem = new Memory::MemMgr(Process->PageTable);
|
|
||||||
|
|
||||||
Elf64_Ehdr *ELFHeader = (Elf64_Ehdr *)ElfFile;
|
|
||||||
Memory::Virtual pV(Process->PageTable);
|
|
||||||
|
|
||||||
uintptr_t BaseAddress = UINTPTR_MAX;
|
|
||||||
uint64_t ElfAppSize = 0;
|
|
||||||
uintptr_t EntryPoint = ELFHeader->e_entry;
|
|
||||||
|
|
||||||
Elf64_Phdr ItrPhdr;
|
|
||||||
|
|
||||||
/* Get base address */
|
|
||||||
for (Elf64_Half i = 0; i < ELFHeader->e_phnum; i++)
|
|
||||||
{
|
|
||||||
memcpy(&ItrPhdr,
|
|
||||||
(uint8_t *)ElfFile + ELFHeader->e_phoff + ELFHeader->e_phentsize * i,
|
|
||||||
sizeof(Elf64_Phdr));
|
|
||||||
|
|
||||||
BaseAddress = MIN(BaseAddress, ItrPhdr.p_vaddr);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get size */
|
|
||||||
for (Elf64_Half i = 0; i < ELFHeader->e_phnum; i++)
|
|
||||||
{
|
|
||||||
memcpy(&ItrPhdr,
|
|
||||||
(uint8_t *)ElfFile + ELFHeader->e_phoff + ELFHeader->e_phentsize * i,
|
|
||||||
sizeof(Elf64_Phdr));
|
|
||||||
|
|
||||||
uintptr_t SegmentEnd;
|
|
||||||
SegmentEnd = ItrPhdr.p_vaddr - BaseAddress + ItrPhdr.p_memsz;
|
|
||||||
ElfAppSize = MAX(ElfAppSize, SegmentEnd);
|
|
||||||
}
|
|
||||||
debug("BaseAddress: %#lx | ElfAppSize: %#lx (%ld, %ld KB)", BaseAddress, ElfAppSize, ElfAppSize, TO_KB(ElfAppSize));
|
|
||||||
|
|
||||||
/* If required, MemoryImage will be at virtual address. (unless has PIE)
|
|
||||||
*
|
|
||||||
* tl;dr this is where the code is stored. */
|
|
||||||
void *MemoryImage = ELFCreateMemoryImage(ELFBase.TmpMem, pV, ElfFile, ElfAppSize);
|
|
||||||
|
|
||||||
debug("Solving symbols for address: %#llx", (uintptr_t)ElfFile);
|
|
||||||
Elf64_Shdr *ElfSections = (Elf64_Shdr *)((uintptr_t)ElfFile + ELFHeader->e_shoff);
|
|
||||||
Elf64_Shdr *DynamicString = nullptr;
|
|
||||||
Elf64_Shdr *StringTable = nullptr;
|
|
||||||
|
|
||||||
for (Elf64_Half i = 0; i < ELFHeader->e_shnum; i++)
|
|
||||||
{
|
|
||||||
char *DynamicStringTable = (char *)((uintptr_t)ElfFile + ElfSections[ELFHeader->e_shstrndx].sh_offset + ElfSections[i].sh_name);
|
|
||||||
|
|
||||||
if (strcmp(DynamicStringTable, ".dynstr") == 0)
|
|
||||||
{
|
|
||||||
DynamicString = &ElfSections[i];
|
|
||||||
debug("Found .dynstr");
|
|
||||||
}
|
|
||||||
else if (strcmp(DynamicStringTable, ".strtab") == 0)
|
|
||||||
{
|
|
||||||
StringTable = &ElfSections[i];
|
|
||||||
debug("Found .strtab");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!DynamicString)
|
|
||||||
DynamicString = StringTable;
|
|
||||||
|
|
||||||
/* Calculate entry point */
|
|
||||||
memcpy(&ItrPhdr, (uint8_t *)ElfFile + ELFHeader->e_phoff, sizeof(Elf64_Phdr));
|
|
||||||
if (ItrPhdr.p_vaddr == 0)
|
|
||||||
EntryPoint += (uintptr_t)MemoryImage;
|
|
||||||
|
|
||||||
char InterpreterPath[256];
|
|
||||||
|
|
||||||
for (Elf64_Half i = 0; i < ELFHeader->e_phnum; i++)
|
|
||||||
{
|
|
||||||
memcpy(&ItrPhdr,
|
|
||||||
(uint8_t *)ElfFile + ELFHeader->e_phoff + ELFHeader->e_phentsize * i,
|
|
||||||
sizeof(Elf64_Phdr));
|
|
||||||
|
|
||||||
switch (ItrPhdr.p_type)
|
|
||||||
{
|
|
||||||
case PT_NULL:
|
|
||||||
fixme("PT_NULL");
|
|
||||||
break;
|
|
||||||
case PT_LOAD:
|
|
||||||
{
|
|
||||||
debug("PT_LOAD - Offset: %#lx, VirtAddr: %#lx, FileSiz: %ld, MemSiz: %ld, Align: %#lx",
|
|
||||||
ItrPhdr.p_offset, ItrPhdr.p_vaddr,
|
|
||||||
ItrPhdr.p_filesz, ItrPhdr.p_memsz, ItrPhdr.p_align);
|
|
||||||
uintptr_t MAddr = (ItrPhdr.p_vaddr - BaseAddress) + (uintptr_t)MemoryImage;
|
|
||||||
fixme("Address: %#lx %s%s%s", MAddr,
|
|
||||||
(ItrPhdr.p_flags & PF_R) ? "R" : "",
|
|
||||||
(ItrPhdr.p_flags & PF_W) ? "W" : "",
|
|
||||||
(ItrPhdr.p_flags & PF_X) ? "X" : "");
|
|
||||||
|
|
||||||
memcpy((void *)MAddr, (uint8_t *)ElfFile + ItrPhdr.p_offset, ItrPhdr.p_filesz);
|
|
||||||
debug("memcpy: %#lx => %#lx (%ld bytes)", (uint8_t *)ElfFile + ItrPhdr.p_offset, MAddr, ItrPhdr.p_filesz);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case PT_DYNAMIC:
|
|
||||||
{
|
|
||||||
debug("PT_DYNAMIC - Offset: %#lx VirtAddr: %#lx FileSiz: %ld MemSiz: %ld Align: %#lx",
|
|
||||||
ItrPhdr.p_offset, ItrPhdr.p_vaddr,
|
|
||||||
ItrPhdr.p_filesz, ItrPhdr.p_memsz, ItrPhdr.p_align);
|
|
||||||
|
|
||||||
Elf64_Dyn *Dynamic = (Elf64_Dyn *)((uint8_t *)ElfFile + ItrPhdr.p_offset);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < ItrPhdr.p_filesz / sizeof(Elf64_Dyn); i++)
|
|
||||||
{
|
|
||||||
if (Dynamic[i].d_tag == DT_NEEDED)
|
|
||||||
{
|
|
||||||
if (!DynamicString)
|
|
||||||
{
|
|
||||||
error("DynamicString is null");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
String ReqLib = (char *)((uintptr_t)ElfFile + DynamicString->sh_offset + Dynamic[i].d_un.d_val);
|
|
||||||
debug("DT_NEEDED - Name[%ld]: %s", i, ReqLib.c_str());
|
|
||||||
ELFBase.NeededLibraries.push_back(ReqLib);
|
|
||||||
}
|
|
||||||
else if (Dynamic[i].d_tag == DT_NULL)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case PT_INTERP:
|
|
||||||
{
|
|
||||||
debug("PT_INTERP - Offset: %#lx VirtAddr: %#lx FileSiz: %ld MemSiz: %ld Align: %#lx",
|
|
||||||
ItrPhdr.p_offset, ItrPhdr.p_vaddr,
|
|
||||||
ItrPhdr.p_filesz, ItrPhdr.p_memsz, ItrPhdr.p_align);
|
|
||||||
|
|
||||||
memcpy((void *)InterpreterPath, (uint8_t *)ElfFile + ItrPhdr.p_offset, 256);
|
|
||||||
debug("Interpreter: %s", InterpreterPath);
|
|
||||||
|
|
||||||
shared_ptr<VirtualFileSystem::File> InterpreterFile = vfs->Open(InterpreterPath);
|
|
||||||
if (InterpreterFile->Status != VirtualFileSystem::FileStatus::OK)
|
|
||||||
warn("Failed to open interpreter file: %s", InterpreterPath);
|
|
||||||
|
|
||||||
vfs->Close(InterpreterFile);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
/* ... */
|
|
||||||
case PT_PHDR:
|
|
||||||
{
|
|
||||||
debug("PT_PHDR - Offset: %#lx VirtAddr: %#lx FileSiz: %ld MemSiz: %ld Align: %#lx",
|
|
||||||
ItrPhdr.p_offset, ItrPhdr.p_vaddr,
|
|
||||||
ItrPhdr.p_filesz, ItrPhdr.p_memsz, ItrPhdr.p_align);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
warn("Unknown or unsupported program header type: %d", ItrPhdr.p_type);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strlen(InterpreterPath) > 1)
|
|
||||||
{
|
|
||||||
EntryPoint = LoadELFInterpreter(ELFBase.TmpMem, pV, InterpreterPath);
|
|
||||||
ELFBase.Interpreter = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
debug("Entry Point: %#lx", EntryPoint);
|
|
||||||
|
|
||||||
char *aux_platform = (char *)ELFBase.TmpMem->RequestPages(1, true);
|
|
||||||
strcpy(aux_platform, "x86_64");
|
|
||||||
|
|
||||||
ELFBase.auxv.push_back({.archaux = {.a_type = AT_NULL, .a_un = {.a_val = 0}}});
|
|
||||||
ELFBase.auxv.push_back({.archaux = {.a_type = AT_EXECFN, .a_un = {.a_val = (uint64_t)vfs->GetPathFromNode(ExFile->node).Get()}}});
|
|
||||||
ELFBase.auxv.push_back({.archaux = {.a_type = AT_PLATFORM, .a_un = {.a_val = (uint64_t)aux_platform}}});
|
|
||||||
ELFBase.auxv.push_back({.archaux = {.a_type = AT_ENTRY, .a_un = {.a_val = (uint64_t)EntryPoint}}});
|
|
||||||
ELFBase.auxv.push_back({.archaux = {.a_type = AT_BASE, .a_un = {.a_val = (uint64_t)MemoryImage}}});
|
|
||||||
ELFBase.auxv.push_back({.archaux = {.a_type = AT_PAGESZ, .a_un = {.a_val = (uint64_t)PAGE_SIZE}}});
|
|
||||||
ELFBase.auxv.push_back({.archaux = {.a_type = AT_PHNUM, .a_un = {.a_val = (uint64_t)ELFHeader->e_phnum}}});
|
|
||||||
ELFBase.auxv.push_back({.archaux = {.a_type = AT_PHENT, .a_un = {.a_val = (uint64_t)ELFHeader->e_phentsize}}});
|
|
||||||
ELFBase.auxv.push_back({.archaux = {.a_type = AT_PHDR, .a_un = {.a_val = (uint64_t)ELFHeader->e_phoff}}});
|
|
||||||
|
|
||||||
ELFBase.InstructionPointer = EntryPoint;
|
|
||||||
ELFBase.MemoryImage = MemoryImage;
|
|
||||||
|
|
||||||
ELFBase.Success = true;
|
|
||||||
return ELFBase;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,284 +0,0 @@
|
|||||||
#include <exec.hpp>
|
|
||||||
|
|
||||||
#include <msexec.h>
|
|
||||||
|
|
||||||
#include "../../kernel.h"
|
|
||||||
#include "../../Fex.hpp"
|
|
||||||
|
|
||||||
namespace Execute
|
|
||||||
{
|
|
||||||
/* Originally from https://wiki.osdev.org/ELF_Tutorial */
|
|
||||||
|
|
||||||
Elf64_Shdr *GetELFSheader(Elf64_Ehdr *Header)
|
|
||||||
{
|
|
||||||
return (Elf64_Shdr *)((uintptr_t)Header + Header->e_shoff);
|
|
||||||
}
|
|
||||||
|
|
||||||
Elf64_Shdr *GetELFSection(Elf64_Ehdr *Header, uint64_t Index)
|
|
||||||
{
|
|
||||||
return &GetELFSheader(Header)[Index];
|
|
||||||
}
|
|
||||||
|
|
||||||
char *GetELFStringTable(Elf64_Ehdr *Header)
|
|
||||||
{
|
|
||||||
if (Header->e_shstrndx == SHN_UNDEF)
|
|
||||||
return nullptr;
|
|
||||||
return (char *)Header + GetELFSection(Header, Header->e_shstrndx)->sh_offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *ELFLookupString(Elf64_Ehdr *Header, uintptr_t Offset)
|
|
||||||
{
|
|
||||||
char *StringTable = GetELFStringTable(Header);
|
|
||||||
if (StringTable == nullptr)
|
|
||||||
return nullptr;
|
|
||||||
return StringTable + Offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *ELFLookupSymbol(Elf64_Ehdr *Header, const char *Name)
|
|
||||||
{
|
|
||||||
Elf64_Shdr *SymbolTable = nullptr;
|
|
||||||
Elf64_Shdr *StringTable = nullptr;
|
|
||||||
Elf64_Sym *Symbol = nullptr;
|
|
||||||
char *String = nullptr;
|
|
||||||
|
|
||||||
for (Elf64_Half i = 0; i < Header->e_shnum; i++)
|
|
||||||
{
|
|
||||||
Elf64_Shdr *shdr = GetELFSection(Header, i);
|
|
||||||
switch (shdr->sh_type)
|
|
||||||
{
|
|
||||||
case SHT_SYMTAB:
|
|
||||||
SymbolTable = shdr;
|
|
||||||
StringTable = GetELFSection(Header, shdr->sh_link);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SymbolTable == nullptr || StringTable == nullptr)
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < (SymbolTable->sh_size / sizeof(Elf64_Sym)); i++)
|
|
||||||
{
|
|
||||||
Symbol = (Elf64_Sym *)((uintptr_t)Header + SymbolTable->sh_offset + (i * sizeof(Elf64_Sym)));
|
|
||||||
String = (char *)((uintptr_t)Header + StringTable->sh_offset + Symbol->st_name);
|
|
||||||
if (strcmp(String, Name) == 0)
|
|
||||||
return (void *)Symbol->st_value;
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
uintptr_t ELFGetSymbolValue(Elf64_Ehdr *Header, uint64_t Table, uint64_t Index)
|
|
||||||
{
|
|
||||||
if (Table == SHN_UNDEF || Index == SHN_UNDEF)
|
|
||||||
return 0;
|
|
||||||
Elf64_Shdr *SymbolTable = GetELFSection(Header, Table);
|
|
||||||
|
|
||||||
uint64_t STEntries = SymbolTable->sh_size / SymbolTable->sh_entsize;
|
|
||||||
if (Index >= STEntries)
|
|
||||||
{
|
|
||||||
error("Symbol index out of range %d-%u.", Table, Index);
|
|
||||||
return 0xdead;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t SymbolAddress = (uint64_t)Header + SymbolTable->sh_offset;
|
|
||||||
Elf64_Sym *Symbol = &((Elf64_Sym *)SymbolAddress)[Index];
|
|
||||||
|
|
||||||
if (Symbol->st_shndx == SHN_UNDEF)
|
|
||||||
{
|
|
||||||
Elf64_Shdr *StringTable = GetELFSection(Header, SymbolTable->sh_link);
|
|
||||||
const char *Name = (const char *)Header + StringTable->sh_offset + Symbol->st_name;
|
|
||||||
|
|
||||||
void *Target = ELFLookupSymbol(Header, Name);
|
|
||||||
if (Target == nullptr)
|
|
||||||
{
|
|
||||||
if (ELF64_ST_BIND(Symbol->st_info) & STB_WEAK)
|
|
||||||
return 0;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
error("Undefined external symbol \"%s\".", Name);
|
|
||||||
return 0xdead;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return (uintptr_t)Target;
|
|
||||||
}
|
|
||||||
else if (Symbol->st_shndx == SHN_ABS)
|
|
||||||
return Symbol->st_value;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Elf64_Shdr *Target = GetELFSection(Header, Symbol->st_shndx);
|
|
||||||
return (uintptr_t)Header + Symbol->st_value + Target->sh_offset;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Elf64_Dyn *ELFGetDynamicTag(void *ElfFile, enum DynamicArrayTags Tag)
|
|
||||||
{
|
|
||||||
Elf64_Ehdr *ELFHeader = (Elf64_Ehdr *)ElfFile;
|
|
||||||
|
|
||||||
Elf64_Phdr ItrPhdr;
|
|
||||||
for (Elf64_Half i = 0; i < ELFHeader->e_phnum; i++)
|
|
||||||
{
|
|
||||||
memcpy(&ItrPhdr, (uint8_t *)ElfFile + ELFHeader->e_phoff + ELFHeader->e_phentsize * i, sizeof(Elf64_Phdr));
|
|
||||||
if (ItrPhdr.p_type == PT_DYNAMIC)
|
|
||||||
{
|
|
||||||
Elf64_Dyn *Dynamic = (Elf64_Dyn *)((uint8_t *)ElfFile + ItrPhdr.p_offset);
|
|
||||||
for (size_t i = 0; i < ItrPhdr.p_filesz / sizeof(Elf64_Dyn); i++)
|
|
||||||
{
|
|
||||||
if (Dynamic[i].d_tag == Tag)
|
|
||||||
{
|
|
||||||
debug("Found dynamic tag %d at %#lx [d_val: %#lx].", Tag, &Dynamic[i], Dynamic[i].d_un.d_val);
|
|
||||||
return &Dynamic[i];
|
|
||||||
}
|
|
||||||
if (Dynamic[i].d_tag == DT_NULL)
|
|
||||||
{
|
|
||||||
debug("Reached end of dynamic tag list for tag %d.", Tag);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
debug("Dynamic tag %d not found.", Tag);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *ELFCreateMemoryImage(Memory::MemMgr *mem, Memory::Virtual &pV, void *ElfFile, size_t Length)
|
|
||||||
{
|
|
||||||
void *MemoryImage = nullptr;
|
|
||||||
Elf64_Ehdr *ELFHeader = (Elf64_Ehdr *)ElfFile;
|
|
||||||
|
|
||||||
/* TODO: Not sure what I am supposed to do with this.
|
|
||||||
* It is supposed to detect if it's PIC or not but I
|
|
||||||
* don't know if it's right. */
|
|
||||||
if (ELFGetDynamicTag(ElfFile, DT_TEXTREL))
|
|
||||||
{
|
|
||||||
fixme("Text relocation is not(?) tested yet!");
|
|
||||||
MemoryImage = (uint8_t *)mem->RequestPages(TO_PAGES(Length), true);
|
|
||||||
memset(MemoryImage, 0, Length);
|
|
||||||
return MemoryImage;
|
|
||||||
}
|
|
||||||
|
|
||||||
Elf64_Phdr ItrPhdr;
|
|
||||||
uintptr_t FirstProgramHeaderVirtualAddress = 0x0;
|
|
||||||
|
|
||||||
bool FirstProgramHeader = false;
|
|
||||||
for (Elf64_Half i = 0; i < ELFHeader->e_phnum; i++)
|
|
||||||
{
|
|
||||||
memcpy(&ItrPhdr,
|
|
||||||
(uint8_t *)ElfFile + ELFHeader->e_phoff + ELFHeader->e_phentsize * i,
|
|
||||||
sizeof(Elf64_Phdr));
|
|
||||||
|
|
||||||
if (ItrPhdr.p_type == PT_LOAD && !FirstProgramHeader)
|
|
||||||
{
|
|
||||||
FirstProgramHeaderVirtualAddress = ItrPhdr.p_vaddr;
|
|
||||||
FirstProgramHeader = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ItrPhdr.p_type == PT_LOAD && ItrPhdr.p_vaddr == 0)
|
|
||||||
{
|
|
||||||
debug("p_vaddr is 0, allocating %ld pages for image", TO_PAGES(Length));
|
|
||||||
MemoryImage = mem->RequestPages(TO_PAGES(Length), true);
|
|
||||||
memset(MemoryImage, 0, Length);
|
|
||||||
return MemoryImage;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
debug("Allocating %ld pages for image", TO_PAGES(Length));
|
|
||||||
MemoryImage = mem->RequestPages(TO_PAGES(Length));
|
|
||||||
memset(MemoryImage, 0, Length);
|
|
||||||
|
|
||||||
if (FirstProgramHeaderVirtualAddress != 0)
|
|
||||||
FirstProgramHeaderVirtualAddress &= 0xFFFFFFFFFFFFF000;
|
|
||||||
else
|
|
||||||
FirstProgramHeaderVirtualAddress = (uintptr_t)MemoryImage;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < TO_PAGES(Length); i++)
|
|
||||||
{
|
|
||||||
pV.Remap((void *)((uintptr_t)FirstProgramHeaderVirtualAddress + (i * PAGE_SIZE)), (void *)((uintptr_t)MemoryImage + (i * PAGE_SIZE)), Memory::PTFlag::RW | Memory::PTFlag::US);
|
|
||||||
debug("Remapped: %#lx -> %#lx", (uintptr_t)FirstProgramHeaderVirtualAddress + (i * PAGE_SIZE), (uintptr_t)MemoryImage + (i * PAGE_SIZE));
|
|
||||||
}
|
|
||||||
return MemoryImage;
|
|
||||||
}
|
|
||||||
|
|
||||||
uintptr_t LoadELFInterpreter(Memory::MemMgr *mem, Memory::Virtual &pV, const char *Interpreter)
|
|
||||||
{
|
|
||||||
if (GetBinaryType((char *)Interpreter) != BinaryType::BinTypeELF)
|
|
||||||
{
|
|
||||||
error("Interpreter \"%s\" is not an ELF file.", Interpreter);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* No need to check if it's valid, the GetBinaryType() call above does that. */
|
|
||||||
shared_ptr<VirtualFileSystem::File> File = vfs->Open(Interpreter);
|
|
||||||
|
|
||||||
Elf64_Ehdr *ELFHeader = (Elf64_Ehdr *)File->node->Address;
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
const char *InterpreterType[6] = {
|
|
||||||
"ET_NONE",
|
|
||||||
"ET_REL",
|
|
||||||
"ET_EXEC",
|
|
||||||
"ET_DYN",
|
|
||||||
"ET_CORE",
|
|
||||||
"ET_LOPROC - ET_HIPROC"};
|
|
||||||
Elf64_Half IntType = ELFHeader->e_type;
|
|
||||||
if (IntType > 5)
|
|
||||||
IntType = 5;
|
|
||||||
debug("Interpreter type: %s - %#x", InterpreterType[IntType], ELFHeader->e_type);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
uintptr_t BaseAddress = UINTPTR_MAX;
|
|
||||||
uint64_t ElfAppSize = 0;
|
|
||||||
|
|
||||||
Elf64_Phdr ItrPhdr;
|
|
||||||
|
|
||||||
/* Get base address */
|
|
||||||
for (Elf64_Half i = 0; i < ELFHeader->e_phnum; i++)
|
|
||||||
{
|
|
||||||
memcpy(&ItrPhdr,
|
|
||||||
(uint8_t *)File->node->Address + ELFHeader->e_phoff + ELFHeader->e_phentsize * i,
|
|
||||||
sizeof(Elf64_Phdr));
|
|
||||||
|
|
||||||
BaseAddress = MIN(BaseAddress, ItrPhdr.p_vaddr);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get size */
|
|
||||||
for (Elf64_Half i = 0; i < ELFHeader->e_phnum; i++)
|
|
||||||
{
|
|
||||||
memcpy(&ItrPhdr,
|
|
||||||
(uint8_t *)File->node->Address + ELFHeader->e_phoff + ELFHeader->e_phentsize * i,
|
|
||||||
sizeof(Elf64_Phdr));
|
|
||||||
|
|
||||||
uintptr_t SegmentEnd;
|
|
||||||
SegmentEnd = ItrPhdr.p_vaddr - BaseAddress + ItrPhdr.p_memsz;
|
|
||||||
ElfAppSize = MAX(ElfAppSize, SegmentEnd);
|
|
||||||
}
|
|
||||||
|
|
||||||
void *MemoryImage = ELFCreateMemoryImage(mem, pV, (void *)File->node->Address, ElfAppSize);
|
|
||||||
|
|
||||||
for (Elf64_Half i = 0; i < ELFHeader->e_phnum; i++)
|
|
||||||
{
|
|
||||||
memcpy(&ItrPhdr,
|
|
||||||
(uint8_t *)File->node->Address + ELFHeader->e_phoff + ELFHeader->e_phentsize * i,
|
|
||||||
sizeof(Elf64_Phdr));
|
|
||||||
|
|
||||||
if (ItrPhdr.p_type == PT_LOAD)
|
|
||||||
{
|
|
||||||
debug("PT_LOAD - Offset: %#lx, VirtAddr: %#lx, FileSiz: %ld, MemSiz: %ld, Align: %#lx",
|
|
||||||
ItrPhdr.p_offset, ItrPhdr.p_vaddr,
|
|
||||||
ItrPhdr.p_filesz, ItrPhdr.p_memsz, ItrPhdr.p_align);
|
|
||||||
uintptr_t MAddr = (ItrPhdr.p_vaddr - BaseAddress) + (uintptr_t)MemoryImage;
|
|
||||||
fixme("Address: %#lx %s%s%s", MAddr,
|
|
||||||
(ItrPhdr.p_flags & PF_R) ? "R" : "",
|
|
||||||
(ItrPhdr.p_flags & PF_W) ? "W" : "",
|
|
||||||
(ItrPhdr.p_flags & PF_X) ? "X" : "");
|
|
||||||
|
|
||||||
memcpy((void *)MAddr, (uint8_t *)File->node->Address + ItrPhdr.p_offset, ItrPhdr.p_filesz);
|
|
||||||
debug("memcpy: %#lx => %#lx (%ld bytes)", (uint8_t *)File->node->Address + ItrPhdr.p_offset, MAddr, ItrPhdr.p_filesz);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
vfs->Close(File);
|
|
||||||
debug("Interpreter entry point: %#lx (%#lx + %#lx)", (uintptr_t)MemoryImage + ELFHeader->e_entry,
|
|
||||||
(uintptr_t)MemoryImage, ELFHeader->e_entry);
|
|
||||||
return (uintptr_t)MemoryImage + ELFHeader->e_entry;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,93 +0,0 @@
|
|||||||
#include <exec.hpp>
|
|
||||||
|
|
||||||
#include <msexec.h>
|
|
||||||
|
|
||||||
#include "../../kernel.h"
|
|
||||||
#include "../../Fex.hpp"
|
|
||||||
|
|
||||||
namespace Execute
|
|
||||||
{
|
|
||||||
/* Originally from https://wiki.osdev.org/ELF_Tutorial */
|
|
||||||
|
|
||||||
ELFBaseLoad ELFLoadRel(void *BaseImage,
|
|
||||||
VirtualFileSystem::File *ExFile,
|
|
||||||
Tasking::PCB *Process)
|
|
||||||
{
|
|
||||||
debug("Relocatable");
|
|
||||||
/* TODO: I have to fully implement this, but for now I will leave it as it is now. */
|
|
||||||
warn("Relocatable ELF is not fully supported yet");
|
|
||||||
/* This should be deleted after with kfree */
|
|
||||||
ELFBaseLoad ELFBase = {};
|
|
||||||
/* This should be deleted inside BaseLoad.cpp */
|
|
||||||
ELFBase.TmpMem = new Memory::MemMgr(Process->PageTable);
|
|
||||||
|
|
||||||
Elf64_Shdr *shdr = GetELFSheader(((Elf64_Ehdr *)BaseImage));
|
|
||||||
for (Elf64_Half i = 0; i < ((Elf64_Ehdr *)BaseImage)->e_shnum; i++)
|
|
||||||
{
|
|
||||||
Elf64_Shdr *Section = &shdr[i];
|
|
||||||
if (Section->sh_type == SHT_NOBITS)
|
|
||||||
{
|
|
||||||
if (!Section->sh_size)
|
|
||||||
continue;
|
|
||||||
if (Section->sh_flags & SHF_ALLOC)
|
|
||||||
{
|
|
||||||
void *Buffer = KernelAllocator.RequestPages(TO_PAGES(Section->sh_size));
|
|
||||||
memset(Buffer, 0, Section->sh_size);
|
|
||||||
|
|
||||||
Memory::Virtual pva = Memory::Virtual(Process->PageTable);
|
|
||||||
for (size_t i = 0; i < TO_PAGES(Section->sh_size); i++)
|
|
||||||
pva.Map((void *)((uintptr_t)Buffer + (i * PAGE_SIZE)), (void *)((uintptr_t)Buffer + (i * PAGE_SIZE)), Memory::PTFlag::RW | Memory::PTFlag::US);
|
|
||||||
|
|
||||||
Section->sh_offset = (uintptr_t)Buffer - (uintptr_t)BaseImage;
|
|
||||||
debug("Section %ld", Section->sh_size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (Elf64_Half i = 0; i < ((Elf64_Ehdr *)BaseImage)->e_shnum; i++)
|
|
||||||
{
|
|
||||||
Elf64_Shdr *Section = &shdr[i];
|
|
||||||
if (Section->sh_type == SHT_REL)
|
|
||||||
{
|
|
||||||
for (size_t Index = 0; Index < Section->sh_size / Section->sh_entsize; Index++)
|
|
||||||
{
|
|
||||||
Elf64_Rel *RelTable = &((Elf64_Rel *)((uintptr_t)BaseImage + Section->sh_offset))[Index];
|
|
||||||
Elf64_Shdr *Target = GetELFSection(((Elf64_Ehdr *)BaseImage), Section->sh_info);
|
|
||||||
|
|
||||||
uintptr_t *RelAddress = (uintptr_t *)(((uintptr_t)BaseImage + Target->sh_offset) + RelTable->r_offset);
|
|
||||||
uint64_t SymbolValue = 0;
|
|
||||||
|
|
||||||
if (ELF64_R_SYM(RelTable->r_info) != SHN_UNDEF)
|
|
||||||
{
|
|
||||||
SymbolValue = ELFGetSymbolValue(((Elf64_Ehdr *)BaseImage), Section->sh_link, ELF64_R_SYM(RelTable->r_info));
|
|
||||||
if (SymbolValue == 0xdead)
|
|
||||||
{
|
|
||||||
delete ELFBase.TmpMem, ELFBase.TmpMem = nullptr;
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (ELF64_R_TYPE(RelTable->r_info))
|
|
||||||
{
|
|
||||||
case R_386_NONE:
|
|
||||||
break;
|
|
||||||
case R_386_32:
|
|
||||||
*RelAddress = DO_64_64(SymbolValue, *RelAddress);
|
|
||||||
break;
|
|
||||||
case R_386_PC32:
|
|
||||||
*RelAddress = DO_64_PC32(SymbolValue, *RelAddress, (uintptr_t)RelAddress);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
error("Unsupported relocation type: %d", ELF64_R_TYPE(RelTable->r_info));
|
|
||||||
delete ELFBase.TmpMem, ELFBase.TmpMem = nullptr;
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
debug("Symbol value: %#lx", SymbolValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ELFBase;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,115 +0,0 @@
|
|||||||
#include <exec.hpp>
|
|
||||||
|
|
||||||
#include <memory.hpp>
|
|
||||||
#include <lock.hpp>
|
|
||||||
#include <msexec.h>
|
|
||||||
#include <cwalk.h>
|
|
||||||
#include <elf.h>
|
|
||||||
#include <abi.h>
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
#include <dumper.hpp>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "../../kernel.h"
|
|
||||||
#include "../../Fex.hpp"
|
|
||||||
|
|
||||||
using namespace Tasking;
|
|
||||||
|
|
||||||
NewLock(ExecuteServiceLock);
|
|
||||||
|
|
||||||
namespace Execute
|
|
||||||
{
|
|
||||||
Memory::MemMgr *mem = nullptr;
|
|
||||||
Vector<SharedLibraries> Libs;
|
|
||||||
|
|
||||||
void StartExecuteService()
|
|
||||||
{
|
|
||||||
mem = new Memory::MemMgr;
|
|
||||||
// return;
|
|
||||||
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
ExecuteServiceLock.Lock(__FUNCTION__);
|
|
||||||
foreach (auto &Lib in Libs)
|
|
||||||
{
|
|
||||||
if (Lib.RefCount > 0)
|
|
||||||
{
|
|
||||||
Lib.Timeout = TimeManager->CalculateTarget(600000);
|
|
||||||
debug("Reset timeout for %s", Lib.Identifier);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (Lib.Timeout < TimeManager->GetCounter())
|
|
||||||
{
|
|
||||||
// TODO: Remove
|
|
||||||
fixme("Removed library %s because of timeout", Lib.Identifier);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
debug("Timeout for %s is %ld", Lib.Identifier, Lib.Timeout);
|
|
||||||
}
|
|
||||||
debug("Waiting 10 seconds...");
|
|
||||||
ExecuteServiceLock.Unlock();
|
|
||||||
TaskManager->Sleep(10000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SharedLibraries *AddLibrary(char *Identifier, void *ElfImage, size_t Length, const Memory::Virtual &pV)
|
|
||||||
{
|
|
||||||
SmartLock(ExecuteServiceLock);
|
|
||||||
SharedLibraries sl;
|
|
||||||
|
|
||||||
strcpy(sl.Identifier, Identifier);
|
|
||||||
sl.Timeout = TimeManager->CalculateTarget(600000); /* 10 minutes */
|
|
||||||
sl.RefCount = 0;
|
|
||||||
|
|
||||||
void *LibFile = mem->RequestPages(TO_PAGES(Length), true);
|
|
||||||
memcpy(LibFile, (void *)ElfImage, Length);
|
|
||||||
|
|
||||||
Memory::Virtual ncpV = pV;
|
|
||||||
sl.MemoryImage = ELFCreateMemoryImage(mem, ncpV, LibFile, Length);
|
|
||||||
|
|
||||||
{
|
|
||||||
uintptr_t BaseAddress = UINTPTR_MAX;
|
|
||||||
Elf64_Phdr ItrProgramHeader;
|
|
||||||
|
|
||||||
for (Elf64_Half i = 0; i < ((Elf64_Ehdr *)LibFile)->e_phnum; i++)
|
|
||||||
{
|
|
||||||
memcpy(&ItrProgramHeader, (uint8_t *)LibFile + ((Elf64_Ehdr *)LibFile)->e_phoff + ((Elf64_Ehdr *)LibFile)->e_phentsize * i, sizeof(Elf64_Phdr));
|
|
||||||
BaseAddress = MIN(BaseAddress, ItrProgramHeader.p_vaddr);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (Elf64_Half i = 0; i < ((Elf64_Ehdr *)LibFile)->e_phnum; i++)
|
|
||||||
{
|
|
||||||
memcpy(&ItrProgramHeader, (uint8_t *)LibFile + ((Elf64_Ehdr *)LibFile)->e_phoff + ((Elf64_Ehdr *)LibFile)->e_phentsize * i, sizeof(Elf64_Phdr));
|
|
||||||
if (ItrProgramHeader.p_type != PT_LOAD)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
debug("PT_LOAD - Offset: %#lx, VirtAddr: %#lx, FileSiz: %ld, MemSiz: %ld, Align: %#lx",
|
|
||||||
ItrProgramHeader.p_offset, ItrProgramHeader.p_vaddr,
|
|
||||||
ItrProgramHeader.p_filesz, ItrProgramHeader.p_memsz, ItrProgramHeader.p_align);
|
|
||||||
uintptr_t MAddr = (ItrProgramHeader.p_vaddr - BaseAddress) + (uintptr_t)sl.MemoryImage;
|
|
||||||
fixme("Address: %#lx %s%s%s", MAddr,
|
|
||||||
(ItrProgramHeader.p_flags & PF_R) ? "R" : "",
|
|
||||||
(ItrProgramHeader.p_flags & PF_W) ? "W" : "",
|
|
||||||
(ItrProgramHeader.p_flags & PF_X) ? "X" : "");
|
|
||||||
|
|
||||||
memcpy((void *)MAddr, (uint8_t *)LibFile + ItrProgramHeader.p_offset, ItrProgramHeader.p_filesz);
|
|
||||||
debug("memcpy: %#lx => %#lx (%ld bytes)", (uint8_t *)LibFile + ItrProgramHeader.p_offset, (uintptr_t)MAddr, ItrProgramHeader.p_filesz);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sl.Address = LibFile;
|
|
||||||
sl.Length = Length;
|
|
||||||
|
|
||||||
debug("Library %s loaded at %#lx (full file: %#lx)", Identifier, sl.MemoryImage, LibFile);
|
|
||||||
|
|
||||||
Libs.push_back(sl);
|
|
||||||
return &Libs[Libs.size() - 1];
|
|
||||||
}
|
|
||||||
|
|
||||||
void SearchLibrary(char *Identifier)
|
|
||||||
{
|
|
||||||
SmartLock(ExecuteServiceLock);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,21 +0,0 @@
|
|||||||
#include <exec.hpp>
|
|
||||||
|
|
||||||
#include <memory.hpp>
|
|
||||||
#include <lock.hpp>
|
|
||||||
#include <msexec.h>
|
|
||||||
#include <cwalk.h>
|
|
||||||
#include <elf.h>
|
|
||||||
#include <abi.h>
|
|
||||||
|
|
||||||
#include "../../kernel.h"
|
|
||||||
#include "../../Fex.hpp"
|
|
||||||
|
|
||||||
using namespace Tasking;
|
|
||||||
|
|
||||||
namespace Execute
|
|
||||||
{
|
|
||||||
void FEXLoad()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
@ -7,77 +7,227 @@
|
|||||||
|
|
||||||
namespace Execute
|
namespace Execute
|
||||||
{
|
{
|
||||||
BinaryType GetBinaryType(void *Image)
|
BinaryType GetBinaryType(char *Path)
|
||||||
{
|
{
|
||||||
Fex *FexHdr = (Fex *)Image;
|
BinaryType Type = BinaryType::BinTypeInvalid;
|
||||||
|
FileSystem::FILE *ExFile = vfs->Open(Path);
|
||||||
|
|
||||||
/* Elf64_Ehdr and Elf32_Ehdr are very similar (Elf64_Half and
|
if (ExFile->Status == FileSystem::FileStatus::OK)
|
||||||
Elf32_Half are the same size type) so we can use directly Elf64_Ehdr. */
|
{
|
||||||
Elf64_Ehdr *ELFHeader = (Elf64_Ehdr *)Image;
|
if (ExFile->Node->Flags == FileSystem::NodeFlags::FS_FILE)
|
||||||
|
{
|
||||||
IMAGE_DOS_HEADER *MZHeader = (IMAGE_DOS_HEADER *)Image;
|
Fex *FexHdr = (Fex *)ExFile->Node->Address;
|
||||||
|
Elf64_Ehdr *ELFHeader = (Elf64_Ehdr *)ExFile->Node->Address;
|
||||||
/* Check Fex magic */
|
IMAGE_DOS_HEADER *MZHeader = (IMAGE_DOS_HEADER *)ExFile->Node->Address;
|
||||||
if (FexHdr->Magic[0] == 'F' && FexHdr->Magic[1] == 'E' && FexHdr->Magic[2] == 'X' && FexHdr->Magic[3] == '\0')
|
if (FexHdr->Magic[0] == 'F' && FexHdr->Magic[1] == 'E' && FexHdr->Magic[2] == 'X' && FexHdr->Magic[3] == '\0')
|
||||||
{
|
{
|
||||||
/* If the fex type is driver, we shouldn't return as Fex. */
|
|
||||||
if (FexHdr->Type == FexFormatType::FexFormatType_Executable)
|
if (FexHdr->Type == FexFormatType::FexFormatType_Executable)
|
||||||
{
|
{
|
||||||
debug("Image - Fex");
|
trace("%s - Fex", Path);
|
||||||
return BinaryType::BinTypeFex;
|
Type = BinaryType::BinTypeFex;
|
||||||
|
goto Exit;
|
||||||
}
|
}
|
||||||
else if (FexHdr->Type == FexFormatType::FexFormatType_Driver)
|
|
||||||
debug("Fex Driver is not supposed to be executed.");
|
|
||||||
}
|
}
|
||||||
/* Check ELF magic. */
|
|
||||||
else if (ELFHeader->e_ident[EI_MAG0] == ELFMAG0 &&
|
else if (ELFHeader->e_ident[EI_MAG0] == ELFMAG0 &&
|
||||||
ELFHeader->e_ident[EI_MAG1] == ELFMAG1 &&
|
ELFHeader->e_ident[EI_MAG1] == ELFMAG1 &&
|
||||||
ELFHeader->e_ident[EI_MAG2] == ELFMAG2 &&
|
ELFHeader->e_ident[EI_MAG2] == ELFMAG2 &&
|
||||||
ELFHeader->e_ident[EI_MAG3] == ELFMAG3)
|
ELFHeader->e_ident[EI_MAG3] == ELFMAG3)
|
||||||
{
|
{
|
||||||
debug("Image - ELF");
|
trace("%s - ELF", Path);
|
||||||
return BinaryType::BinTypeELF;
|
Type = BinaryType::BinTypeELF;
|
||||||
|
goto Exit;
|
||||||
}
|
}
|
||||||
/* Every Windows executable starts with MZ header. */
|
|
||||||
else if (MZHeader->e_magic == IMAGE_DOS_SIGNATURE)
|
else if (MZHeader->e_magic == IMAGE_DOS_SIGNATURE)
|
||||||
{
|
{
|
||||||
IMAGE_NT_HEADERS *PEHeader = (IMAGE_NT_HEADERS *)(((char *)Image) + MZHeader->e_lfanew);
|
IMAGE_NT_HEADERS *PEHeader = (IMAGE_NT_HEADERS *)(((char *)ExFile->Node->Address) + MZHeader->e_lfanew);
|
||||||
IMAGE_OS2_HEADER *NEHeader = (IMAGE_OS2_HEADER *)(((char *)Image) + MZHeader->e_lfanew);
|
IMAGE_OS2_HEADER *NEHeader = (IMAGE_OS2_HEADER *)(((char *)ExFile->Node->Address) + MZHeader->e_lfanew);
|
||||||
|
if (NEHeader->ne_magic == IMAGE_OS2_SIGNATURE)
|
||||||
/* TODO: LE, EDOS */
|
|
||||||
if (PEHeader->Signature == IMAGE_NT_SIGNATURE)
|
|
||||||
{
|
{
|
||||||
debug("Image - PE");
|
trace("%s - NE", Path);
|
||||||
return BinaryType::BinTypePE;
|
Type = BinaryType::BinTypeNE;
|
||||||
}
|
}
|
||||||
else if (NEHeader->ne_magic == IMAGE_OS2_SIGNATURE)
|
else if (PEHeader->Signature == IMAGE_NT_SIGNATURE)
|
||||||
{
|
{
|
||||||
debug("Image - NE");
|
trace("%s - PE", Path);
|
||||||
return BinaryType::BinTypeNE;
|
Type = BinaryType::BinTypePE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
debug("Image - MZ");
|
trace("%s - MZ", Path);
|
||||||
return BinaryType::BinTypeMZ;
|
Type = BinaryType::BinTypeMZ;
|
||||||
}
|
}
|
||||||
|
goto Exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ... */
|
/* ... */
|
||||||
return BinaryType::BinTypeUnknown;
|
|
||||||
|
Type = BinaryType::BinTypeUnknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
BinaryType GetBinaryType(char *Path)
|
|
||||||
{
|
|
||||||
BinaryType Type = BinaryType::BinTypeInvalid;
|
|
||||||
shared_ptr<VirtualFileSystem::File> ExFile = vfs->Open(Path);
|
|
||||||
|
|
||||||
if (ExFile->Status == VirtualFileSystem::FileStatus::OK)
|
|
||||||
{
|
|
||||||
debug("File opened: %s", Path);
|
|
||||||
Type = GetBinaryType((void *)ExFile->node->Address);
|
|
||||||
}
|
}
|
||||||
|
Exit:
|
||||||
vfs->Close(ExFile);
|
vfs->Close(ExFile);
|
||||||
return Type;
|
return Type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Originally from https://wiki.osdev.org/ELF_Tutorial */
|
||||||
|
|
||||||
|
static inline Elf64_Shdr *GetElfSheader(Elf64_Ehdr *Header) { return (Elf64_Shdr *)((uint64_t)Header + Header->e_shoff); }
|
||||||
|
static inline Elf64_Shdr *GetElfSection(Elf64_Ehdr *Header, uint64_t Index) { return &GetElfSheader(Header)[Index]; }
|
||||||
|
|
||||||
|
static inline char *GetElfStringTable(Elf64_Ehdr *Header)
|
||||||
|
{
|
||||||
|
if (Header->e_shstrndx == SHN_UNDEF)
|
||||||
|
return nullptr;
|
||||||
|
return (char *)Header + GetElfSection(Header, Header->e_shstrndx)->sh_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline char *elf_lookup_string(Elf64_Ehdr *Header, uint64_t Offset)
|
||||||
|
{
|
||||||
|
char *StringTable = GetElfStringTable(Header);
|
||||||
|
if (StringTable == nullptr)
|
||||||
|
return nullptr;
|
||||||
|
return StringTable + Offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *ElfLookupSymbol(Elf64_Ehdr *Header, const char *Name)
|
||||||
|
{
|
||||||
|
Elf64_Shdr *SymbolTable = nullptr;
|
||||||
|
Elf64_Shdr *StringTable = nullptr;
|
||||||
|
Elf64_Sym *Symbol = nullptr;
|
||||||
|
char *String = nullptr;
|
||||||
|
|
||||||
|
for (Elf64_Half i = 0; i < Header->e_shnum; i++)
|
||||||
|
{
|
||||||
|
Elf64_Shdr *shdr = GetElfSection(Header, i);
|
||||||
|
switch (shdr->sh_type)
|
||||||
|
{
|
||||||
|
case SHT_SYMTAB:
|
||||||
|
SymbolTable = shdr;
|
||||||
|
StringTable = GetElfSection(Header, shdr->sh_link);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SymbolTable == nullptr || StringTable == nullptr)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
for (uint64_t i = 0; i < (SymbolTable->sh_size / sizeof(Elf64_Sym)); i++)
|
||||||
|
{
|
||||||
|
Symbol = (Elf64_Sym *)((uint64_t)Header + SymbolTable->sh_offset + (i * sizeof(Elf64_Sym)));
|
||||||
|
String = (char *)((uint64_t)Header + StringTable->sh_offset + Symbol->st_name);
|
||||||
|
if (strcmp(String, Name) == 0)
|
||||||
|
return (void *)Symbol->st_value;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint64_t ELFGetSymbolValue(Elf64_Ehdr *Header, uint64_t Table, uint32_t Index)
|
||||||
|
{
|
||||||
|
if (Table == SHN_UNDEF || Index == SHN_UNDEF)
|
||||||
|
return 0;
|
||||||
|
Elf64_Shdr *SymbolTable = GetElfSection(Header, Table);
|
||||||
|
|
||||||
|
uint32_t STEntries = SymbolTable->sh_size / SymbolTable->sh_entsize;
|
||||||
|
if (Index >= STEntries)
|
||||||
|
{
|
||||||
|
error("Symbol index out of range %d-%u.", Table, Index);
|
||||||
|
return 0xdead;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t SymbolAddress = (uint64_t)Header + SymbolTable->sh_offset;
|
||||||
|
Elf32_Sym *Symbol = &((Elf32_Sym *)SymbolAddress)[Index];
|
||||||
|
|
||||||
|
if (Symbol->st_shndx == SHN_UNDEF)
|
||||||
|
{
|
||||||
|
Elf64_Shdr *StringTable = GetElfSection(Header, SymbolTable->sh_link);
|
||||||
|
const char *Name = (const char *)Header + StringTable->sh_offset + Symbol->st_name;
|
||||||
|
|
||||||
|
void *Target = ElfLookupSymbol(Header, Name);
|
||||||
|
if (Target == nullptr)
|
||||||
|
{
|
||||||
|
if (ELF32_ST_BIND(Symbol->st_info) & STB_WEAK)
|
||||||
|
return 0;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
error("Undefined external symbol \"%s\".", Name);
|
||||||
|
return 0xdead;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return (uint64_t)Target;
|
||||||
|
}
|
||||||
|
else if (Symbol->st_shndx == SHN_ABS)
|
||||||
|
return Symbol->st_value;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Elf64_Shdr *Target = GetElfSection(Header, Symbol->st_shndx);
|
||||||
|
return (uint64_t)Header + Symbol->st_value + Target->sh_offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void *ELFLoadRel(Elf64_Ehdr *Header)
|
||||||
|
{
|
||||||
|
Elf64_Shdr *shdr = GetElfSheader(Header);
|
||||||
|
for (uint64_t i = 0; i < Header->e_shnum; i++)
|
||||||
|
{
|
||||||
|
Elf64_Shdr *Section = &shdr[i];
|
||||||
|
if (Section->sh_type == SHT_NOBITS)
|
||||||
|
{
|
||||||
|
if (!Section->sh_size)
|
||||||
|
continue;
|
||||||
|
if (Section->sh_flags & SHF_ALLOC)
|
||||||
|
{
|
||||||
|
void *Buffer = KernelAllocator.RequestPages(TO_PAGES(Section->sh_size));
|
||||||
|
memset(Buffer, 0, Section->sh_size);
|
||||||
|
|
||||||
|
Memory::Virtual pva = Memory::Virtual(/* TODO TODO TODO TODO TODO TODO */);
|
||||||
|
for (uint64_t i = 0; i < TO_PAGES(Section->sh_size); i++)
|
||||||
|
pva.Map((void *)((uint64_t)Buffer + (i * PAGE_SIZE)), (void *)((uint64_t)Buffer + (i * PAGE_SIZE)), Memory::PTFlag::RW | Memory::PTFlag::US);
|
||||||
|
|
||||||
|
Section->sh_offset = (uint64_t)Buffer - (uint64_t)Header;
|
||||||
|
debug("Section %ld", Section->sh_size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint64_t i = 0; i < Header->e_shnum; i++)
|
||||||
|
{
|
||||||
|
Elf64_Shdr *Section = &shdr[i];
|
||||||
|
if (Section->sh_type == SHT_REL)
|
||||||
|
{
|
||||||
|
for (uint64_t Index = 0; Index < Section->sh_size / Section->sh_entsize; Index++)
|
||||||
|
{
|
||||||
|
Elf64_Rel *RelTable = &((Elf64_Rel *)((uint64_t)Header + Section->sh_offset))[Index];
|
||||||
|
Elf64_Shdr *Target = GetElfSection(Header, Section->sh_info);
|
||||||
|
|
||||||
|
uint64_t *RelAddress = (uint64_t *)(((uint64_t)Header + Target->sh_offset) + RelTable->r_offset);
|
||||||
|
uint64_t SymbolValue = 0;
|
||||||
|
|
||||||
|
if (ELF64_R_SYM(RelTable->r_info) != SHN_UNDEF)
|
||||||
|
{
|
||||||
|
SymbolValue = ELFGetSymbolValue(Header, Section->sh_link, ELF64_R_SYM(RelTable->r_info));
|
||||||
|
if (SymbolValue == 0xdead)
|
||||||
|
return (void *)0xdeadbeef;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (ELF64_R_TYPE(RelTable->r_info))
|
||||||
|
{
|
||||||
|
case R_386_NONE:
|
||||||
|
break;
|
||||||
|
case R_386_32:
|
||||||
|
*RelAddress = DO_64_64(SymbolValue, *RelAddress);
|
||||||
|
break;
|
||||||
|
case R_386_PC32:
|
||||||
|
*RelAddress = DO_64_PC32(SymbolValue, *RelAddress, (uint64_t)RelAddress);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
error("Unsupported relocation type: %d", ELF64_R_TYPE(RelTable->r_info));
|
||||||
|
return (void *)0xdeadbeef;
|
||||||
|
}
|
||||||
|
debug("Symbol value: %#lx", SymbolValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (void *)Header->e_entry;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,39 +19,36 @@ namespace Execute
|
|||||||
SpawnData ret = {.Status = ExStatus::Unknown,
|
SpawnData ret = {.Status = ExStatus::Unknown,
|
||||||
.Process = nullptr,
|
.Process = nullptr,
|
||||||
.Thread = nullptr};
|
.Thread = nullptr};
|
||||||
|
FileSystem::FILE *ExFile = vfs->Open(Path);
|
||||||
shared_ptr<VirtualFileSystem::File> ExFile = vfs->Open(Path);
|
if (ExFile->Status == FileSystem::FileStatus::OK)
|
||||||
|
|
||||||
if (ExFile->Status == VirtualFileSystem::FileStatus::OK)
|
|
||||||
{
|
{
|
||||||
if (ExFile->node->Flags != VirtualFileSystem::NodeFlags::FILE)
|
if (ExFile->Node->Flags == FileSystem::NodeFlags::FS_FILE)
|
||||||
{
|
{
|
||||||
ret.Status = ExStatus::InvalidFilePath;
|
BinaryType Type = GetBinaryType(Path);
|
||||||
goto Exit;
|
switch (Type)
|
||||||
}
|
|
||||||
|
|
||||||
switch (GetBinaryType(Path))
|
|
||||||
{
|
{
|
||||||
case BinaryType::BinTypeFex:
|
case BinaryType::BinTypeFex:
|
||||||
{
|
{
|
||||||
Fex *FexHdr = (Fex *)ExFile->node->Address;
|
#if defined(__amd64__)
|
||||||
|
|
||||||
|
Fex *FexHdr = (Fex *)ExFile->Node->Address;
|
||||||
if (FexHdr->Type == FexFormatType::FexFormatType_Executable)
|
if (FexHdr->Type == FexFormatType::FexFormatType_Executable)
|
||||||
{
|
{
|
||||||
const char *BaseName;
|
const char *BaseName;
|
||||||
cwk_path_get_basename(Path, &BaseName, nullptr);
|
cwk_path_get_basename(Path, &BaseName, nullptr);
|
||||||
PCB *Process = TaskManager->CreateProcess(TaskManager->GetCurrentProcess(), BaseName, TaskTrustLevel::User);
|
PCB *Process = TaskManager->CreateProcess(TaskManager->GetCurrentProcess(), BaseName, TaskTrustLevel::User);
|
||||||
|
|
||||||
void *BaseImage = KernelAllocator.RequestPages(TO_PAGES(ExFile->node->Length));
|
void *BaseImage = KernelAllocator.RequestPages(TO_PAGES(ExFile->Node->Length));
|
||||||
memcpy(BaseImage, (void *)ExFile->node->Address, ExFile->node->Length);
|
memcpy(BaseImage, (void *)ExFile->Node->Address, ExFile->Node->Length);
|
||||||
|
|
||||||
Memory::Virtual pva = Memory::Virtual(Process->PageTable);
|
Memory::Virtual pva = Memory::Virtual(Process->PageTable);
|
||||||
for (size_t i = 0; i < TO_PAGES(ExFile->node->Length); i++)
|
for (uint64_t i = 0; i < TO_PAGES(ExFile->Node->Length); i++)
|
||||||
pva.Map((void *)((uintptr_t)BaseImage + (i * PAGE_SIZE)), (void *)((uintptr_t)BaseImage + (i * PAGE_SIZE)), Memory::PTFlag::RW | Memory::PTFlag::US);
|
pva.Map((void *)((uint64_t)BaseImage + (i * PAGE_SIZE)), (void *)((uint64_t)BaseImage + (i * PAGE_SIZE)), Memory::PTFlag::RW | Memory::PTFlag::US);
|
||||||
|
|
||||||
Vector<AuxiliaryVector> auxv; // TODO!
|
Vector<AuxiliaryVector> auxv; // TODO!
|
||||||
|
|
||||||
TCB *Thread = TaskManager->CreateThread(Process,
|
TCB *Thread = TaskManager->CreateThread(Process,
|
||||||
(IP)FexHdr->EntryPoint,
|
(IP)FexHdr->Pointer,
|
||||||
argv, envp, auxv,
|
argv, envp, auxv,
|
||||||
(IPOffset)BaseImage,
|
(IPOffset)BaseImage,
|
||||||
TaskArchitecture::x64,
|
TaskArchitecture::x64,
|
||||||
@ -59,35 +56,189 @@ namespace Execute
|
|||||||
ret.Process = Process;
|
ret.Process = Process;
|
||||||
ret.Thread = Thread;
|
ret.Thread = Thread;
|
||||||
ret.Status = ExStatus::OK;
|
ret.Status = ExStatus::OK;
|
||||||
|
#elif defined(__i386__)
|
||||||
|
if (1)
|
||||||
|
{
|
||||||
|
#elif defined(__aarch64__)
|
||||||
|
if (1)
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
goto Exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret.Status = ExStatus::InvalidFileHeader;
|
ret.Status = ExStatus::InvalidFileHeader;
|
||||||
goto Exit;
|
goto Exit;
|
||||||
}
|
}
|
||||||
case BinaryType::BinTypeELF:
|
case BinaryType::BinTypeELF:
|
||||||
{
|
{
|
||||||
ELFBaseLoad bl = ELFLoad(Path, argv, envp);
|
#if defined(__amd64__)
|
||||||
if (!bl.Success)
|
const char *BaseName;
|
||||||
|
cwk_path_get_basename(Path, &BaseName, nullptr);
|
||||||
|
PCB *Process = TaskManager->CreateProcess(TaskManager->GetCurrentProcess(), BaseName, TaskTrustLevel::User);
|
||||||
|
|
||||||
|
void *BaseImage = KernelAllocator.RequestPages(TO_PAGES(ExFile->Node->Length));
|
||||||
|
memcpy(BaseImage, (void *)ExFile->Node->Address, ExFile->Node->Length);
|
||||||
|
debug("Image Size: %#lx - %#lx (length: %ld)", BaseImage, (uint64_t)BaseImage + ExFile->Node->Length, ExFile->Node->Length);
|
||||||
|
|
||||||
|
Memory::Virtual pva = Memory::Virtual(Process->PageTable);
|
||||||
|
for (uint64_t i = 0; i < TO_PAGES(ExFile->Node->Length); i++)
|
||||||
|
pva.Remap((void *)((uint64_t)BaseImage + (i * PAGE_SIZE)), (void *)((uint64_t)BaseImage + (i * PAGE_SIZE)), Memory::PTFlag::RW | Memory::PTFlag::US);
|
||||||
|
|
||||||
|
Elf64_Ehdr *ELFHeader = (Elf64_Ehdr *)BaseImage;
|
||||||
|
|
||||||
|
TaskArchitecture Arch = TaskArchitecture::x64;
|
||||||
|
TaskCompatibility Comp = TaskCompatibility::Native;
|
||||||
|
if (ELFHeader->e_machine == EM_386)
|
||||||
|
Arch = TaskArchitecture::x32;
|
||||||
|
else if (ELFHeader->e_machine == EM_AMD64)
|
||||||
|
Arch = TaskArchitecture::x64;
|
||||||
|
else if (ELFHeader->e_machine == EM_AARCH64)
|
||||||
|
Arch = TaskArchitecture::ARM64;
|
||||||
|
else
|
||||||
|
Arch = TaskArchitecture::UnknownArchitecture;
|
||||||
|
|
||||||
|
// TODO: Should I care about this?
|
||||||
|
if (ELFHeader->e_ident[EI_CLASS] == ELFCLASS32)
|
||||||
{
|
{
|
||||||
ret.Status = ExStatus::GenericError;
|
if (ELFHeader->e_ident[EI_DATA] == ELFDATA2LSB)
|
||||||
|
fixme("ELF32 LSB");
|
||||||
|
else if (ELFHeader->e_ident[EI_DATA] == ELFDATA2MSB)
|
||||||
|
fixme("ELF32 MSB");
|
||||||
|
else
|
||||||
|
fixme("ELF32 Unknown");
|
||||||
|
}
|
||||||
|
else if (ELFHeader->e_ident[EI_CLASS] == ELFCLASS64)
|
||||||
|
{
|
||||||
|
if (ELFHeader->e_ident[EI_DATA] == ELFDATA2LSB)
|
||||||
|
fixme("ELF64 LSB");
|
||||||
|
else if (ELFHeader->e_ident[EI_DATA] == ELFDATA2MSB)
|
||||||
|
fixme("ELF64 MSB");
|
||||||
|
else
|
||||||
|
fixme("ELF64 Unknown");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
fixme("Unknown ELF");
|
||||||
|
|
||||||
|
if (ELFHeader->e_type == ET_EXEC)
|
||||||
|
{
|
||||||
|
trace("Executable");
|
||||||
|
Elf64_Phdr *pheader = (Elf64_Phdr *)(((char *)BaseImage) + ELFHeader->e_phoff);
|
||||||
|
debug("p_paddr: %#lx | p_vaddr: %#lx | p_filesz: %#lx | p_memsz: %#lx | p_offset: %#lx", pheader->p_paddr, pheader->p_vaddr, pheader->p_filesz, pheader->p_memsz, pheader->p_offset);
|
||||||
|
|
||||||
|
void *Address = nullptr;
|
||||||
|
for (int i = 0; i < ELFHeader->e_phnum; i++, pheader++)
|
||||||
|
{
|
||||||
|
if (pheader->p_type != PT_LOAD)
|
||||||
|
continue;
|
||||||
|
Address = (void *)((uint64_t)pheader->p_vaddr + pheader->p_memsz);
|
||||||
|
}
|
||||||
|
void *Offset = KernelAllocator.RequestPages(TO_PAGES((uint64_t)Address));
|
||||||
|
|
||||||
|
pheader = (Elf64_Phdr *)(((char *)BaseImage) + ELFHeader->e_phoff);
|
||||||
|
for (uint64_t i = 0; i < TO_PAGES((uint64_t)Address); i++)
|
||||||
|
{
|
||||||
|
pva.Remap((void *)((uint64_t)pheader->p_vaddr + (i * PAGE_SIZE)), (void *)((uint64_t)Offset + (i * PAGE_SIZE)), Memory::PTFlag::RW | Memory::PTFlag::US);
|
||||||
|
// debug("Mapping: %#lx -> %#lx", (uint64_t)pheader->p_vaddr + (i * PAGE_SIZE), (uint64_t)Offset + (i * PAGE_SIZE));
|
||||||
|
}
|
||||||
|
|
||||||
|
pheader = (Elf64_Phdr *)(((char *)BaseImage) + ELFHeader->e_phoff);
|
||||||
|
for (int i = 0; i < ELFHeader->e_phnum; i++, pheader++)
|
||||||
|
{
|
||||||
|
if (pheader->p_type != PT_LOAD)
|
||||||
|
continue;
|
||||||
|
void *dst = (void *)((uint64_t)pheader->p_vaddr + (uint64_t)Offset);
|
||||||
|
memset(dst, 0, pheader->p_memsz);
|
||||||
|
memcpy(dst, ((char *)BaseImage) + pheader->p_offset, pheader->p_filesz);
|
||||||
|
}
|
||||||
|
|
||||||
|
debug("Entry Point: %#lx", ELFHeader->e_entry);
|
||||||
|
|
||||||
|
Vector<AuxiliaryVector> auxv;
|
||||||
|
|
||||||
|
pheader = (Elf64_Phdr *)(((char *)BaseImage) + ELFHeader->e_phoff);
|
||||||
|
auxv.push_back({.archaux = {.a_type = AT_PHDR, .a_un = {.a_val = (uint64_t)ELFHeader->e_phoff}}});
|
||||||
|
auxv.push_back({.archaux = {.a_type = AT_PHENT, .a_un = {.a_val = (uint64_t)ELFHeader->e_phentsize}}});
|
||||||
|
auxv.push_back({.archaux = {.a_type = AT_PHNUM, .a_un = {.a_val = (uint64_t)ELFHeader->e_phnum}}});
|
||||||
|
auxv.push_back({.archaux = {.a_type = AT_PAGESZ, .a_un = {.a_val = (uint64_t)PAGE_SIZE}}});
|
||||||
|
auxv.push_back({.archaux = {.a_type = AT_BASE, .a_un = {.a_val = (uint64_t)Offset}}});
|
||||||
|
auxv.push_back({.archaux = {.a_type = AT_ENTRY, .a_un = {.a_val = (uint64_t)ELFHeader->e_entry + (uint64_t)pheader->p_offset}}});
|
||||||
|
auxv.push_back({.archaux = {.a_type = AT_PLATFORM, .a_un = {.a_val = (uint64_t) "x86_64"}}});
|
||||||
|
auxv.push_back({.archaux = {.a_type = AT_EXECFN, .a_un = {.a_val = (uint64_t)Path}}});
|
||||||
|
|
||||||
|
TCB *Thread = TaskManager->CreateThread(Process,
|
||||||
|
(IP)ELFHeader->e_entry,
|
||||||
|
argv, envp, auxv,
|
||||||
|
(IPOffset)pheader->p_offset,
|
||||||
|
Arch,
|
||||||
|
Comp);
|
||||||
|
ret.Process = Process;
|
||||||
|
ret.Thread = Thread;
|
||||||
|
ret.Status = ExStatus::OK;
|
||||||
goto Exit;
|
goto Exit;
|
||||||
}
|
}
|
||||||
ret = bl.sd;
|
else if (ELFHeader->e_type == ET_DYN)
|
||||||
|
{
|
||||||
|
fixme("Shared Object");
|
||||||
|
}
|
||||||
|
else if (ELFHeader->e_type == ET_REL)
|
||||||
|
{
|
||||||
|
trace("Relocatable");
|
||||||
|
void *EP = ELFLoadRel(ELFHeader);
|
||||||
|
if (EP == (void *)0xdeadbeef || EP == 0x0)
|
||||||
|
{
|
||||||
|
ret.Status = ExStatus::InvalidFileEntryPoint;
|
||||||
|
goto Exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector<AuxiliaryVector> auxv;
|
||||||
|
fixme("auxv");
|
||||||
|
|
||||||
|
TCB *Thread = TaskManager->CreateThread(Process,
|
||||||
|
(IP)EP,
|
||||||
|
argv, envp, auxv,
|
||||||
|
(IPOffset)BaseImage,
|
||||||
|
Arch,
|
||||||
|
Comp);
|
||||||
|
ret.Process = Process;
|
||||||
|
ret.Thread = Thread;
|
||||||
|
ret.Status = ExStatus::OK;
|
||||||
|
goto Exit;
|
||||||
|
}
|
||||||
|
else if (ELFHeader->e_type == ET_CORE)
|
||||||
|
{
|
||||||
|
fixme("Core");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fixme("Unknown");
|
||||||
|
}
|
||||||
|
ret.Status = ExStatus::InvalidFileHeader;
|
||||||
|
#elif defined(__i386__)
|
||||||
|
#elif defined(__aarch64__)
|
||||||
|
#endif
|
||||||
goto Exit;
|
goto Exit;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
{
|
|
||||||
ret.Status = ExStatus::Unsupported;
|
ret.Status = ExStatus::Unsupported;
|
||||||
goto Exit;
|
goto Exit;
|
||||||
}
|
}
|
||||||
|
goto Exit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (ExFile->Status == VirtualFileSystem::FileStatus::NotFound)
|
else if (ExFile->Status == FileSystem::FileStatus::NOT_FOUND)
|
||||||
|
{
|
||||||
ret.Status = ExStatus::InvalidFilePath;
|
ret.Status = ExStatus::InvalidFilePath;
|
||||||
|
goto Exit;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
ret.Status = ExStatus::InvalidFile;
|
ret.Status = ExStatus::InvalidFile;
|
||||||
|
goto Exit;
|
||||||
|
}
|
||||||
|
|
||||||
Exit:
|
Exit:
|
||||||
|
if (ret.Status != ExStatus::OK)
|
||||||
|
if (ret.Process)
|
||||||
|
ret.Process->Status = TaskStatus::Terminated;
|
||||||
vfs->Close(ExFile);
|
vfs->Close(ExFile);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -43,23 +43,15 @@ enum FexDriverType
|
|||||||
/* ... */
|
/* ... */
|
||||||
};
|
};
|
||||||
|
|
||||||
enum FexDriverInputTypes
|
|
||||||
{
|
|
||||||
FexDriverInputTypes_None = 0b00000000,
|
|
||||||
FexDriverInputTypes_Mouse = 0b00000001,
|
|
||||||
FexDriverInputTypes_Keyboard = 0b00000010,
|
|
||||||
/* ... */
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Fex
|
struct Fex
|
||||||
{
|
{
|
||||||
char Magic[4];
|
char Magic[4];
|
||||||
enum FexFormatType Type : 4;
|
enum FexFormatType Type : 4;
|
||||||
enum FexOSType OS : 4;
|
enum FexOSType OS : 4;
|
||||||
int (*EntryPoint)(void *);
|
int (*Pointer)(void *);
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
union KernelCallback;
|
struct KernelCallback;
|
||||||
|
|
||||||
struct FexExtended
|
struct FexExtended
|
||||||
{
|
{
|
||||||
@ -72,9 +64,7 @@ struct FexExtended
|
|||||||
{
|
{
|
||||||
char Name[64];
|
char Name[64];
|
||||||
enum FexDriverType Type : 4;
|
enum FexDriverType Type : 4;
|
||||||
enum FexDriverInputTypes TypeFlags : 4;
|
int (*Callback)(struct KernelCallback *);
|
||||||
bool OverrideOnConflict : 1;
|
|
||||||
int (*Callback)(union KernelCallback *);
|
|
||||||
|
|
||||||
struct DriverBind
|
struct DriverBind
|
||||||
{
|
{
|
||||||
@ -100,8 +90,8 @@ struct FexExtended
|
|||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
char AttachToMouse;
|
bool AttachToMouse;
|
||||||
char AttachToKeyboard;
|
bool AttachToKeyboard;
|
||||||
} Input;
|
} Input;
|
||||||
} Bind;
|
} Bind;
|
||||||
} Driver;
|
} Driver;
|
||||||
@ -112,7 +102,7 @@ struct FexExtended
|
|||||||
*
|
*
|
||||||
* @param FormatType FexFormatType
|
* @param FormatType FexFormatType
|
||||||
* @param OperatingSystem FexOSType
|
* @param OperatingSystem FexOSType
|
||||||
* @param Address EntryPoint to the start function
|
* @param Address Pointer to the start function
|
||||||
*
|
*
|
||||||
* @note Must include ".header : { *(.header .header.*) }" in linker script
|
* @note Must include ".header : { *(.header .header.*) }" in linker script
|
||||||
*/
|
*/
|
||||||
@ -121,6 +111,6 @@ struct FexExtended
|
|||||||
.Magic = {'F', 'E', 'X', '\0'}, \
|
.Magic = {'F', 'E', 'X', '\0'}, \
|
||||||
.Type = FormatType, \
|
.Type = FormatType, \
|
||||||
.OS = OperatingSystem, \
|
.OS = OperatingSystem, \
|
||||||
.EntryPoint = Address}
|
.Pointer = Address}
|
||||||
|
|
||||||
#endif // !__FENNIX_FILE_FEX_H__
|
#endif // !__FENNIX_FILE_FEX_H__
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user