14 Commits

342 changed files with 10501 additions and 32796 deletions

61
Kernel/.github/workflows/codacy.yml vendored Normal file
View File

@ -0,0 +1,61 @@
# 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

View File

@ -4,23 +4,6 @@
"head",
],
"body": [
"/*",
" This file is part of Fennix Kernel.",
"",
" Fennix Kernel is free software: you can redistribute it and/or",
" modify it under the terms of the GNU General Public License as",
" published by the Free Software Foundation, either version 3 of",
" the License, or (at your option) any later version.",
"",
" Fennix Kernel is distributed in the hope that it will be useful,",
" but WITHOUT ANY WARRANTY; without even the implied warranty of",
" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the",
" GNU General Public License for more details.",
"",
" You should have received a copy of the GNU General Public License",
" along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.",
"*/",
"",
"#ifndef __FENNIX_KERNEL_${2:header}_H__",
"#define __FENNIX_KERNEL_${2:header}_H__",
"",
@ -41,29 +24,5 @@
"/** @brief $0 */"
],
"description": "Create kernel documentation brief."
},
"License": {
"prefix": [
"license",
],
"body": [
"/*",
" This file is part of Fennix Kernel.",
"",
" Fennix Kernel is free software: you can redistribute it and/or",
" modify it under the terms of the GNU General Public License as",
" published by the Free Software Foundation, either version 3 of",
" the License, or (at your option) any later version.",
"",
" Fennix Kernel is distributed in the hope that it will be useful,",
" but WITHOUT ANY WARRANTY; without even the implied warranty of",
" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the",
" GNU General Public License for more details.",
"",
" You should have received a copy of the GNU General Public License",
" along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.",
"*/"
],
"description": "Create kernel license."
}
}
}

View File

@ -4,9 +4,7 @@
"name": "Fennix x64 (Linux, GCC, debug)",
"includePath": [
"${workspaceFolder}/include",
"${workspaceFolder}/include/**",
"${workspaceFolder}/include_std",
"${workspaceFolder}/include_std/**"
"${workspaceFolder}/include/**"
],
"defines": [
"__debug_vscode__",
@ -15,7 +13,6 @@
"GIT_COMMIT=\"0000000000000000000000000000000000000000\"",
"GIT_COMMIT_SHORT=\"0000000\"",
"a64",
"a86",
"DEBUG=\"1\""
],
"compilerPath": "${workspaceFolder}/../tools/cross/bin/amd64-elf-gcc",
@ -33,18 +30,6 @@
"-mcmodel=kernel",
"-fno-builtin",
// Warnings
"-Wall",
"-Wextra",
"-Wfloat-equal",
"-Wpointer-arith",
"-Wcast-align",
"-Wredundant-decls",
"-Winit-self",
"-Wswitch-default",
"-Wstrict-overflow=5",
"-Wconversion",
// C++ flags
"-fno-rtti",
"-fexceptions",
@ -76,10 +61,7 @@
{
"name": "Fennix x32 (Linux, GCC, debug)",
"includePath": [
"${workspaceFolder}/include",
"${workspaceFolder}/include/**",
"${workspaceFolder}/include_std",
"${workspaceFolder}/include_std/**"
"${workspaceFolder}/include/**"
],
"defines": [
"__debug_vscode__",
@ -88,10 +70,9 @@
"GIT_COMMIT=\"0000000000000000000000000000000000000000\"",
"GIT_COMMIT_SHORT=\"0000000\"",
"a32",
"a86",
"DEBUG=\"1\""
],
"compilerPath": "${workspaceFolder}/../tools/cross/bin/i386-elf-gcc",
"compilerPath": "${workspaceFolder}/../tools/cross/bin/i686-elf-gcc",
"cStandard": "c17",
"cppStandard": "c++20",
"intelliSenseMode": "gcc-x86",
@ -109,24 +90,12 @@
"-msoft-float",
"-fno-builtin",
// Warnings
"-Wall",
"-Wextra",
"-Wfloat-equal",
"-Wpointer-arith",
"-Wcast-align",
"-Wredundant-decls",
"-Winit-self",
"-Wswitch-default",
"-Wstrict-overflow=5",
"-Wconversion",
// C++ flags
"-fno-rtti",
"-fexceptions",
// Linker flags
"-T${workspaceFolder}/Architecture/i386/linker.ld",
"-T${workspaceFolder}/Architecture/i686/linker.ld",
"-Wl,-static,--no-dynamic-linker,-ztext",
"-nostdlib",
"-nodefaultlibs",
@ -143,71 +112,6 @@
"-fstack-check",
"-fsanitize=undefined",
// VSCode flags
"-ffreestanding",
"-nostdinc",
"-nostdinc++"
]
},
{
"name": "Fennix Aarch64 (Linux, GCC, debug)",
"includePath": [
"${workspaceFolder}/include",
"${workspaceFolder}/include/**",
"${workspaceFolder}/include_std",
"${workspaceFolder}/include_std/**"
],
"defines": [
"__debug_vscode__",
"KERNEL_NAME=\"Fennix\"",
"KERNEL_VERSION=\"1.0\"",
"GIT_COMMIT=\"0000000000000000000000000000000000000000\"",
"GIT_COMMIT_SHORT=\"0000000\"",
"aa64",
"DEBUG=\"1\""
],
"compilerPath": "${workspaceFolder}/../tools/cross/bin/aarch64-elf-gcc",
"cStandard": "c17",
"cppStandard": "c++20",
"intelliSenseMode": "linux-gcc-arm64",
"configurationProvider": "ms-vscode.makefile-tools",
"compilerArgs": [
// Compiler flags
"-pipe",
"-fno-builtin",
"-msoft-float",
"-fPIC",
"-Wstack-protector",
// Warnings
"-Wall",
"-Wextra",
"-Wfloat-equal",
"-Wpointer-arith",
"-Wcast-align",
"-Wredundant-decls",
"-Winit-self",
"-Wswitch-default",
"-Wstrict-overflow=5",
"-Wconversion",
// C++ flags
"-fno-rtti",
"-fexceptions",
// Linker flags
"-T${workspaceFolder}/Architecture/aarch64/linker.ld",
"-fPIC",
// Debug flags
"-ggdb3",
"-O0",
"-fdiagnostics-color=always",
"-fverbose-asm",
"-fstack-usage",
"-fstack-check",
"-fsanitize=undefined",
// VSCode flags
"-ffreestanding",
"-nostdinc",

View File

@ -2,7 +2,7 @@
"version": "0.2.0",
"configurations": [
{
"name": "Attach to a running VM instance",
"name": "Attach to a running QEMU instance",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceRoot}/kernel.fsys",

View File

@ -1,36 +0,0 @@
/* Based on this tutorial:
https://github.com/s-matyukevich/raspberry-pi-os */
.section ".text.boot"
.extern _bss_start
.extern _bss_end
.extern arm64Entry
memzero:
str xzr, [x0], #8
subs x1, x1, #8
b.gt memzero
ret
.global _start
_start:
mrs x0, mpidr_el1
and x0, x0, #0xFF
cbz x0, _start2
b CPU_Loop
_start2:
adr x0, _bss_start
adr x1, _bss_end
sub x1, x1, x0
bl memzero
mov sp, #0x200000
bl arm64Entry
Halt:
wfe
b Halt
CPU_Loop:
b CPU_Loop

View File

@ -1,20 +1,3 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include <types.h>
#include <debug.h>

View File

@ -1,25 +1,8 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include <syscalls.hpp>
#include <cpu.hpp>
extern "C" __naked __used __no_stack_protector void SystemCallHandlerStub()
extern "C" __attribute__((naked, used, no_stack_protector)) void SystemCallHandlerStub()
{
}

View File

@ -1,20 +1,3 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include <smp.hpp>
#include <ints.hpp>
@ -26,7 +9,7 @@
volatile bool CPUEnabled = false;
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
static __aligned(0x1000) CPUData CPUs[MAX_CPU] = {0};
static __attribute__((aligned(PAGE_SIZE))) CPUData CPUs[MAX_CPU] = {0};
CPUData *GetCPU(uint64_t id) { return &CPUs[id]; }
@ -50,8 +33,6 @@ CPUData *GetCurrentCPU()
namespace SMP
{
int CPUCores = 0;
void Initialize(void *madt)
{
fixme("SMP::Initialize() is not implemented!");

View File

@ -1,33 +1,8 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
ENTRY(_start)
SECTIONS
{
.text.boot :
{
*(.text.boot)
. += CONSTANT(MAXPAGESIZE);
_bss_start = .;
*(.text.bss)
_bss_end = .;
}
. = 0x80000;
_kernel_start = .;
.text :
{
@ -51,22 +26,6 @@ SECTIONS
. = ALIGN(4096);
_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 = .);
}
.bss :
{
*(.bss .bss.*)

View File

@ -1,17 +1,17 @@
// .section ".text.boot"
.section ".text.boot"
// .global _start
// .org 0x80000
// _start:
// ldr x5, =_start
// mov sp, x5
// ldr x5, =_kernel_rodata_end
// ldr w6, =_bss_size
// 1: cbz w6, 2f
// str xzr, [x5], #8
// sub w6, w6, #1
// cbnz w6, 1b
// 2: bl arm64Entry
// Halt:
// wfe
// b Halt
.global _start
.org 0x80000
_start:
ldr x5, =_start
mov sp, x5
ldr x5, =_kernel_rodata_end
ldr w6, =_bss_size
1: cbz w6, 2f
str xzr, [x5], #8
sub w6, w6, #1
cbnz w6, 1b
2: bl arm64Entry
Halt:
wfe
b Halt

View File

@ -1,13 +1,13 @@
// .section .init
// .global _init
// .type _init, @function
// _init:
.section .init
.global _init
.type _init, @function
_init:
// push %rbp
// movq %rsp, %rbp
// .section .fini
// .global _fini
// .type _fini, @function
// _fini:
.section .fini
.global _fini
.type _fini, @function
_fini:
// push %rbp
// movq %rsp, %rbp

View File

@ -1,27 +1,8 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "acpi.hpp"
#include <debug.h>
#include <io.h>
#include "../../kernel.h"
#pragma GCC diagnostic ignored "-Wint-to-pointer-cast"
namespace ACPI
@ -30,20 +11,20 @@ namespace ACPI
{
for (uint64_t t = 0; t < ((ACPIHeader->Length - sizeof(ACPI::ACPIHeader)) / (XSDTSupported ? 8 : 4)); t++)
{
// TODO: Should I be concerned about unaligned memory access?
// Should I be concerned about unaligned memory access?
ACPI::ACPIHeader *SDTHdr = nullptr;
if (XSDTSupported)
SDTHdr = (ACPI::ACPIHeader *)(*(uint64_t *)((uint64_t)ACPIHeader + sizeof(ACPI::ACPIHeader) + (t * 8)));
else
SDTHdr = (ACPI::ACPIHeader *)(*(uint32_t *)((uint64_t)ACPIHeader + sizeof(ACPI::ACPIHeader) + (t * 4)));
for (int i = 0; i < 4; i++)
for (uint64_t i = 0; i < 4; i++)
{
if (SDTHdr->Signature[i] != Signature[i])
break;
if (i == 3)
{
trace("%s found at address %p", Signature, (uintptr_t)SDTHdr);
trace("%s found!", Signature);
return SDTHdr;
}
}
@ -57,94 +38,88 @@ namespace ACPI
if (!Header)
return;
HPET = (HPETHeader *)FindTable(Header, (char *)"HPET");
FADT = (FADTHeader *)FindTable(Header, (char *)"FACP");
MCFG = (MCFGHeader *)FindTable(Header, (char *)"MCFG");
BGRT = (BGRTHeader *)FindTable(Header, (char *)"BGRT");
SRAT = (SRATHeader *)FindTable(Header, (char *)"SRAT");
TPM2 = (TPM2Header *)FindTable(Header, (char *)"TPM2");
TCPA = (TCPAHeader *)FindTable(Header, (char *)"TCPA");
WAET = (WAETHeader *)FindTable(Header, (char *)"WAET");
MADT = (MADTHeader *)FindTable(Header, (char *)"APIC");
HEST = (HESTHeader *)FindTable(Header, (char *)"HEST");
FindTable(Header, (char *)"BERT");
FindTable(Header, (char *)"CPEP");
FindTable(Header, (char *)"DSDT");
FindTable(Header, (char *)"ECDT");
FindTable(Header, (char *)"EINJ");
FindTable(Header, (char *)"ERST");
FindTable(Header, (char *)"FACS");
FindTable(Header, (char *)"MSCT");
FindTable(Header, (char *)"MPST");
FindTable(Header, (char *)"OEMx");
FindTable(Header, (char *)"PMTT");
FindTable(Header, (char *)"PSDT");
FindTable(Header, (char *)"RASF");
FindTable(Header, (char *)"RSDT");
FindTable(Header, (char *)"SBST");
FindTable(Header, (char *)"SLIT");
FindTable(Header, (char *)"SSDT");
FindTable(Header, (char *)"XSDT");
FindTable(Header, (char *)"DRTM");
FindTable(Header, (char *)"FPDT");
FindTable(Header, (char *)"GTDT");
FindTable(Header, (char *)"PCCT");
FindTable(Header, (char *)"S3PT");
FindTable(Header, (char *)"MATR");
FindTable(Header, (char *)"MSDM");
FindTable(Header, (char *)"WPBT");
FindTable(Header, (char *)"OSDT");
FindTable(Header, (char *)"RSDP");
FindTable(Header, (char *)"NFIT");
FindTable(Header, (char *)"ASF!");
FindTable(Header, (char *)"BOOT");
FindTable(Header, (char *)"CSRT");
FindTable(Header, (char *)"DBG2");
FindTable(Header, (char *)"DBGP");
FindTable(Header, (char *)"DMAR");
FindTable(Header, (char *)"IBFT");
FindTable(Header, (char *)"IORT");
FindTable(Header, (char *)"IVRS");
FindTable(Header, (char *)"LPIT");
FindTable(Header, (char *)"MCHI");
FindTable(Header, (char *)"MTMR");
FindTable(Header, (char *)"SLIC");
FindTable(Header, (char *)"SPCR");
FindTable(Header, (char *)"SPMI");
FindTable(Header, (char *)"UEFI");
FindTable(Header, (char *)"VRTC");
FindTable(Header, (char *)"WDAT");
FindTable(Header, (char *)"WDDT");
FindTable(Header, (char *)"WDRT");
FindTable(Header, (char *)"ATKG");
FindTable(Header, (char *)"GSCI");
FindTable(Header, (char *)"IEIT");
FindTable(Header, (char *)"HMAT");
FindTable(Header, (char *)"CEDT");
FindTable(Header, (char *)"AEST");
HPET = (HPETHeader *)FindTable(XSDT, (char *)"HPET");
FADT = (FADTHeader *)FindTable(XSDT, (char *)"FACP");
MCFG = (MCFGHeader *)FindTable(XSDT, (char *)"MCFG");
BGRT = (BGRTHeader *)FindTable(XSDT, (char *)"BGRT");
SRAT = (SRATHeader *)FindTable(XSDT, (char *)"SRAT");
TPM2 = (TPM2Header *)FindTable(XSDT, (char *)"TPM2");
TCPA = (TCPAHeader *)FindTable(XSDT, (char *)"TCPA");
WAET = (WAETHeader *)FindTable(XSDT, (char *)"WAET");
MADT = (MADTHeader *)FindTable(XSDT, (char *)"APIC");
HEST = (HESTHeader *)FindTable(XSDT, (char *)"HEST");
FindTable(XSDT, (char *)"BERT");
FindTable(XSDT, (char *)"CPEP");
FindTable(XSDT, (char *)"DSDT");
FindTable(XSDT, (char *)"ECDT");
FindTable(XSDT, (char *)"EINJ");
FindTable(XSDT, (char *)"ERST");
FindTable(XSDT, (char *)"FACS");
FindTable(XSDT, (char *)"MSCT");
FindTable(XSDT, (char *)"MPST");
FindTable(XSDT, (char *)"OEMx");
FindTable(XSDT, (char *)"PMTT");
FindTable(XSDT, (char *)"PSDT");
FindTable(XSDT, (char *)"RASF");
FindTable(XSDT, (char *)"RSDT");
FindTable(XSDT, (char *)"SBST");
FindTable(XSDT, (char *)"SLIT");
FindTable(XSDT, (char *)"SSDT");
FindTable(XSDT, (char *)"XSDT");
FindTable(XSDT, (char *)"DRTM");
FindTable(XSDT, (char *)"FPDT");
FindTable(XSDT, (char *)"GTDT");
FindTable(XSDT, (char *)"PCCT");
FindTable(XSDT, (char *)"S3PT");
FindTable(XSDT, (char *)"MATR");
FindTable(XSDT, (char *)"MSDM");
FindTable(XSDT, (char *)"WPBT");
FindTable(XSDT, (char *)"OSDT");
FindTable(XSDT, (char *)"RSDP");
FindTable(XSDT, (char *)"NFIT");
FindTable(XSDT, (char *)"ASF!");
FindTable(XSDT, (char *)"BOOT");
FindTable(XSDT, (char *)"CSRT");
FindTable(XSDT, (char *)"DBG2");
FindTable(XSDT, (char *)"DBGP");
FindTable(XSDT, (char *)"DMAR");
FindTable(XSDT, (char *)"IBFT");
FindTable(XSDT, (char *)"IORT");
FindTable(XSDT, (char *)"IVRS");
FindTable(XSDT, (char *)"LPIT");
FindTable(XSDT, (char *)"MCHI");
FindTable(XSDT, (char *)"MTMR");
FindTable(XSDT, (char *)"SLIC");
FindTable(XSDT, (char *)"SPCR");
FindTable(XSDT, (char *)"SPMI");
FindTable(XSDT, (char *)"UEFI");
FindTable(XSDT, (char *)"VRTC");
FindTable(XSDT, (char *)"WDAT");
FindTable(XSDT, (char *)"WDDT");
FindTable(XSDT, (char *)"WDRT");
}
ACPI::ACPI()
ACPI::ACPI(BootInfo *Info)
{
trace("Initializing ACPI");
if (bInfo.RSDP->Revision >= 2 && bInfo.RSDP->XSDTAddress)
if (Info->RSDP->Revision >= 2 && Info->RSDP->XSDTAddress)
{
debug("XSDT supported");
XSDTSupported = true;
XSDT = (ACPIHeader *)(bInfo.RSDP->XSDTAddress);
XSDT = (ACPIHeader *)(Info->RSDP->XSDTAddress);
}
else
{
debug("RSDT supported");
XSDT = (ACPIHeader *)(uintptr_t)bInfo.RSDP->RSDTAddress;
XSDT = (ACPIHeader *)(uintptr_t)Info->RSDP->RSDTAddress;
}
this->SearchTables(XSDT);
if (FADT)
{
outb(s_cst(uint16_t, FADT->SMI_CommandPort), FADT->AcpiEnable);
while (!(inw(s_cst(uint16_t, FADT->PM1aControlBlock)) & 1))
outb(FADT->SMI_CommandPort, FADT->AcpiEnable);
while (!(inw(FADT->PM1aControlBlock) & 1))
;
}
}

View File

@ -1,5 +0,0 @@
section .multiboot
align 4
dd 0x1BADB002
dd 1 << 0 | 1 << 1
dd -(0x1BADB002 + (1 << 0 | 1 << 1))

View File

@ -1,20 +1,3 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include <boot/binfo.h>
#include <types.h>
#include <debug.h>
@ -23,13 +6,13 @@
#include "../../../../tools/limine/limine.h"
#include "../../../kernel.h"
void InitLimine();
void init_limine();
static volatile struct limine_entry_point_request EntryPointRequest = {
.id = LIMINE_ENTRY_POINT_REQUEST,
.revision = 0,
.response = NULL,
.entry = InitLimine};
.entry = init_limine};
static volatile struct limine_bootloader_info_request BootloaderInfoRequest = {
.id = LIMINE_BOOTLOADER_INFO_REQUEST,
.revision = 0};
@ -54,42 +37,14 @@ static volatile struct limine_kernel_file_request KernelFileRequest = {
static volatile struct limine_module_request ModuleRequest = {
.id = LIMINE_MODULE_REQUEST,
.revision = 0};
static volatile struct limine_smbios_request SmbiosRequest = {
.id = LIMINE_SMBIOS_REQUEST,
.revision = 0};
void *TempStackPtr = NULL;
__naked __used __no_stack_protector void InitLimine()
SafeFunction NIF void init_limine()
{
asmv("mov %%rsp, %0"
: "=r"(TempStackPtr));
asmv("mov %0, %%rsp"
:
: "r"((uintptr_t)TempStackPtr - 0xFFFF800000000000));
asmv("mov $0, %rax\n"
"mov $0, %rbx\n"
"mov $0, %rcx\n"
"mov $0, %rdx\n"
"mov $0, %rsi\n"
"mov $0, %rdi\n"
"mov $0, %rbp\n"
"mov $0, %r8\n"
"mov $0, %r9\n"
"mov $0, %r10\n"
"mov $0, %r11\n"
"mov $0, %r12\n"
"mov $0, %r13\n"
"mov $0, %r14\n"
"mov $0, %r15");
asmv("jmp InitLimineAfterStack");
}
SafeFunction NIF void InitLimineAfterStack()
{
struct BootInfo binfo = {};
struct BootInfo binfo;
struct limine_bootloader_info_response *BootloaderInfoResponse = BootloaderInfoRequest.response;
info("Bootloader: %s %s", BootloaderInfoResponse->name, BootloaderInfoResponse->version);
@ -98,7 +53,8 @@ SafeFunction NIF void InitLimineAfterStack()
if (TerminalResponse == NULL || TerminalResponse->terminal_count < 1)
{
warn("No terminal available.");
inf_loop asmv("hlt");
while (1)
asmv("hlt");
}
TerminalResponse->write(TerminalResponse->terminals[0], "\033[37mPlease wait... ", 20);
@ -112,79 +68,66 @@ SafeFunction NIF void InitLimineAfterStack()
if (FrameBufferResponse == NULL || FrameBufferResponse->framebuffer_count < 1)
{
error("No framebuffer available [%#lx;%ld]", FrameBufferResponse,
error("No framebuffer available [%p;%ld]", FrameBufferResponse,
(FrameBufferResponse == NULL) ? 0 : FrameBufferResponse->framebuffer_count);
TerminalResponse->write(TerminalResponse->terminals[0], "No framebuffer available", 24);
inf_loop asmv("hlt");
while (1)
asmv("hlt");
}
if (MemmapResponse == NULL || MemmapResponse->entry_count < 1)
{
error("No memory map available [%#lx;%ld]", MemmapResponse,
error("No memory map available [%p;%ld]", MemmapResponse,
(MemmapResponse == NULL) ? 0 : MemmapResponse->entry_count);
TerminalResponse->write(TerminalResponse->terminals[0], "No memory map available", 23);
inf_loop asmv("hlt");
while (1)
asmv("hlt");
}
if (KernelAddressResponse == NULL)
{
error("No kernel address available [%#lx]", KernelAddressResponse);
error("No kernel address available [%p]", KernelAddressResponse);
TerminalResponse->write(TerminalResponse->terminals[0], "No kernel address available", 27);
inf_loop asmv("hlt");
while (1)
asmv("hlt");
}
if (RsdpResponse == NULL || RsdpResponse->address == 0)
{
error("No RSDP address available [%#lx;%#lx]", RsdpResponse,
error("No RSDP address available [%p;%p]", RsdpResponse,
(RsdpResponse == NULL) ? 0 : RsdpResponse->address);
TerminalResponse->write(TerminalResponse->terminals[0], "No RSDP address available", 25);
inf_loop asmv("hlt");
while (1)
asmv("hlt");
}
if (KernelFileResponse == NULL || KernelFileResponse->kernel_file == NULL)
{
error("No kernel file available [%#lx;%#lx]", KernelFileResponse,
error("No kernel file available [%p;%p]", KernelFileResponse,
(KernelFileResponse == NULL) ? 0 : KernelFileResponse->kernel_file);
TerminalResponse->write(TerminalResponse->terminals[0], "No kernel file available", 24);
inf_loop asmv("hlt");
while (1)
asmv("hlt");
}
if (ModuleResponse == NULL || ModuleResponse->module_count < 1)
{
error("No module information available [%#lx;%ld]", ModuleResponse,
error("No module information available [%p;%ld]", ModuleResponse,
(ModuleResponse == NULL) ? 0 : ModuleResponse->module_count);
TerminalResponse->write(TerminalResponse->terminals[0], "No module information available", 31);
inf_loop asmv("hlt");
while (1)
asmv("hlt");
}
/* Actual parsing starts here */
for (uint64_t i = 0; i < FrameBufferResponse->framebuffer_count; i++)
{
struct limine_framebuffer *framebuffer = FrameBufferResponse->framebuffers[i];
switch (framebuffer->memory_model)
{
case LIMINE_FRAMEBUFFER_RGB:
binfo.Framebuffer[i].Type = RGB;
break;
default:
{
error("Unsupported framebuffer memory model %d", framebuffer->memory_model);
TerminalResponse->write(TerminalResponse->terminals[0], "Unsupported framebuffer memory model", 37);
inf_loop asmv("hlt");
}
}
binfo.Framebuffer[i].BaseAddress = (void *)((uintptr_t)framebuffer->address - 0xFFFF800000000000);
binfo.Framebuffer[i].Width = (uint32_t)framebuffer->width;
binfo.Framebuffer[i].Height = (uint32_t)framebuffer->height;
binfo.Framebuffer[i].Pitch = (uint32_t)framebuffer->pitch;
binfo.Framebuffer[i].BaseAddress = (void *)((uint64_t)framebuffer->address - 0xffff800000000000);
binfo.Framebuffer[i].Width = framebuffer->width;
binfo.Framebuffer[i].Height = framebuffer->height;
binfo.Framebuffer[i].Pitch = framebuffer->pitch;
binfo.Framebuffer[i].BitsPerPixel = framebuffer->bpp;
binfo.Framebuffer[i].MemoryModel = framebuffer->memory_model;
binfo.Framebuffer[i].RedMaskSize = framebuffer->red_mask_size;
binfo.Framebuffer[i].RedMaskShift = framebuffer->red_mask_shift;
binfo.Framebuffer[i].GreenMaskSize = framebuffer->green_mask_size;
@ -193,24 +136,9 @@ SafeFunction NIF void InitLimineAfterStack()
binfo.Framebuffer[i].BlueMaskShift = framebuffer->blue_mask_shift;
binfo.Framebuffer[i].ExtendedDisplayIdentificationData = framebuffer->edid;
binfo.Framebuffer[i].EDIDSize = framebuffer->edid_size;
debug("Framebuffer %d: %dx%d %d bpp", i,
binfo.Framebuffer[i].Width,
binfo.Framebuffer[i].Height,
binfo.Framebuffer[i].BitsPerPixel);
debug("More info:\nAddress: %#lx\nPitch: %ld\nType: %d\nRedMaskSize: %d\nRedMaskShift: %d\nGreenMaskSize: %d\nGreenMaskShift: %d\nBlueMaskSize: %d\nBlueMaskShift: %d\nEDID: %#lx\nEDIDSize: %d",
binfo.Framebuffer[i].BaseAddress,
binfo.Framebuffer[i].Pitch,
binfo.Framebuffer[i].Type,
binfo.Framebuffer[i].RedMaskSize,
binfo.Framebuffer[i].RedMaskShift,
binfo.Framebuffer[i].GreenMaskSize,
binfo.Framebuffer[i].GreenMaskShift,
binfo.Framebuffer[i].BlueMaskSize,
binfo.Framebuffer[i].BlueMaskShift,
binfo.Framebuffer[i].ExtendedDisplayIdentificationData,
binfo.Framebuffer[i].EDIDSize);
debug("Framebuffer %d: %dx%d %d bpp", i, framebuffer->width, framebuffer->height, framebuffer->bpp);
debug("More info:\nAddress: %p\nPitch: %ld\nMemoryModel: %d\nRedMaskSize: %d\nRedMaskShift: %d\nGreenMaskSize: %d\nGreenMaskShift: %d\nBlueMaskSize: %d\nBlueMaskShift: %d\nEDID: %p\nEDIDSize: %d",
(uint64_t)framebuffer->address - 0xffff800000000000, framebuffer->pitch, framebuffer->memory_model, framebuffer->red_mask_size, framebuffer->red_mask_shift, framebuffer->green_mask_size, framebuffer->green_mask_shift, framebuffer->blue_mask_size, framebuffer->blue_mask_shift, framebuffer->edid, framebuffer->edid_size);
}
binfo.Memory.Entries = MemmapResponse->entry_count;
@ -223,12 +151,6 @@ SafeFunction NIF void InitLimineAfterStack()
}
struct limine_memmap_entry *entry = MemmapResponse->entries[i];
if (!entry)
{
warn("Null memory entry %ld (%#lx), skipping...", i, entry);
continue;
}
binfo.Memory.Size += entry->length;
switch (entry->type)
{
@ -288,59 +210,48 @@ SafeFunction NIF void InitLimineAfterStack()
break;
}
binfo.Modules[i].Address = (void *)((uint64_t)ModuleResponse->modules[i]->address - 0xFFFF800000000000);
binfo.Modules[i].Size = ModuleResponse->modules[i]->size;
binfo.Modules[i].Address = (void *)((uint64_t)ModuleResponse->modules[i]->address - 0xffff800000000000);
strncpy(binfo.Modules[i].Path,
ModuleResponse->modules[i]->path,
strlen(ModuleResponse->modules[i]->path) + 1);
strncpy(binfo.Modules[i].CommandLine,
ModuleResponse->modules[i]->cmdline,
strlen(ModuleResponse->modules[i]->cmdline) + 1);
debug("Module %d:\nAddress: %#lx\nPath: \"%s\"\nCommand Line: \"%s\"\nSize: %ld",
i,
binfo.Modules[i].Address,
binfo.Modules[i].Path,
binfo.Modules[i].CommandLine,
binfo.Modules[i].Size);
binfo.Modules[i].Size = ModuleResponse->modules[i]->size;
debug("Module %d:\nAddress: %p\nPath: %s\nCommand Line: %s\nSize: %ld", i,
(uint64_t)ModuleResponse->modules[i]->address - 0xffff800000000000, ModuleResponse->modules[i]->path,
ModuleResponse->modules[i]->cmdline, ModuleResponse->modules[i]->size);
}
binfo.RSDP = (struct RSDPInfo *)((uintptr_t)RsdpResponse->address - 0xFFFF800000000000);
debug("RSDP: %#lx [Signature: \"%.8s\"] [OEM: \"%.6s\"]",
binfo.RSDP, binfo.RSDP->Signature, binfo.RSDP->OEMID);
binfo.RSDP = (struct RSDPInfo *)((uint64_t)RsdpResponse->address - 0xffff800000000000);
trace("RSDP: %p(%p) [Signature: %.8s] [OEM: %.6s]",
RsdpResponse->address, binfo.RSDP, binfo.RSDP->Signature, binfo.RSDP->OEMID);
if (SmbiosResponse->entry_64 != NULL)
binfo.SMBIOSPtr = (void *)((uintptr_t)SmbiosResponse->entry_64 - 0xFFFF800000000000);
else if (SmbiosResponse->entry_32 != NULL)
binfo.SMBIOSPtr = (void *)((uintptr_t)SmbiosResponse->entry_32 - 0xFFFF800000000000);
debug("SMBIOS: %p %p", SmbiosResponse->entry_32, SmbiosResponse->entry_64);
if (SmbiosResponse->entry_32 != NULL)
binfo.SMBIOSPtr = (void *)((uint64_t)SmbiosResponse->entry_32 - 0xffff800000000000);
else if (SmbiosResponse->entry_64 != NULL)
binfo.SMBIOSPtr = (void *)((uint64_t)SmbiosResponse->entry_64 - 0xffff800000000000);
else
binfo.SMBIOSPtr = NULL;
debug("SMBIOS: %#lx %#lx (binfo: %#lx)",
SmbiosResponse->entry_32,
SmbiosResponse->entry_64,
binfo.SMBIOSPtr);
binfo.Kernel.PhysicalBase = (void *)KernelAddressResponse->physical_base;
binfo.Kernel.VirtualBase = (void *)KernelAddressResponse->virtual_base;
binfo.Kernel.FileBase = (void *)((uintptr_t)KernelFileResponse->kernel_file->address - 0xFFFF800000000000);
binfo.Kernel.Size = KernelFileResponse->kernel_file->size;
binfo.Kernel.FileBase = KernelFileResponse->kernel_file->address;
strncpy(binfo.Kernel.CommandLine,
KernelFileResponse->kernel_file->cmdline,
strlen(KernelFileResponse->kernel_file->cmdline) + 1);
debug("Kernel physical address: %#lx", binfo.Kernel.PhysicalBase);
debug("Kernel virtual address: %#lx", binfo.Kernel.VirtualBase);
binfo.Kernel.Size = KernelFileResponse->kernel_file->size;
trace("Kernel physical address: %p", KernelAddressResponse->physical_base);
trace("Kernel virtual address: %p", KernelAddressResponse->virtual_base);
strncpy(binfo.Bootloader.Name,
BootloaderInfoResponse->name,
strlen(BootloaderInfoResponse->name) + 1);
strncpy(binfo.Bootloader.Version,
BootloaderInfoResponse->version,
strlen(BootloaderInfoResponse->version) + 1);
// Call kernel entry point
Entry(&binfo);
}

View File

@ -1,299 +0,0 @@
#include <types.h>
#include <boot/protocols/multiboot2.h>
#include <memory.hpp>
#include <io.h>
#include "../../../kernel.h"
EXTERNC void multiboot_main(uint64_t Magic, uint64_t Info)
{
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();
}
BootInfo mb2binfo{};
// Clear the BSS
// memset_unsafe(&_kernel_rodata_end, 0, &_kernel_end - &_kernel_rodata_end);
{
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);
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)))
{
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);
module_count++;
break;
}
case MULTIBOOT_TAG_TYPE_BASIC_MEMINFO:
{
multiboot_tag_basic_meminfo *meminfo = (multiboot_tag_basic_meminfo *)Tag;
fixme("basic_meminfo->[mem_lower: %#x, mem_upper: %#x]",
meminfo->mem_lower, meminfo->mem_upper);
break;
}
case MULTIBOOT_TAG_TYPE_BOOTDEV:
{
multiboot_tag_bootdev *bootdev = (multiboot_tag_bootdev *)Tag;
fixme("bootdev->[biosdev: %#x, slice: %#x, part: %#x]",
bootdev->biosdev, bootdev->slice, bootdev->part);
break;
}
case MULTIBOOT_TAG_TYPE_MMAP:
{
multiboot_tag_mmap *mmap = (multiboot_tag_mmap *)Tag;
size_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;
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;
}
default:
{
mb2binfo.Framebuffer[fb_count].Type = Unknown_Framebuffer_Type;
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->[num=%d, size=%d, entsize=%d, shndx=%d]",
elf->num, elf->size, elf->entsize, elf->shndx);
break;
}
case MULTIBOOT_TAG_TYPE_APM:
{
multiboot_tag_apm *apm = (multiboot_tag_apm *)Tag;
fixme("apm->[version: %d, cseg: %d, offset: %d, cseg_16: %d, dseg: %d, flags: %d, cseg_len: %d, cseg_16_len: %d, dseg_len: %d]",
apm->version, apm->cseg, apm->offset, apm->cseg_16, apm->dseg, apm->flags, apm->cseg_len, apm->cseg_16_len, apm->dseg_len);
break;
}
case MULTIBOOT_TAG_TYPE_EFI32:
{
multiboot_tag_efi32 *efi32 = (multiboot_tag_efi32 *)Tag;
fixme("efi32->[pointer: %p, size: %d]", efi32->pointer, efi32->size);
break;
}
case MULTIBOOT_TAG_TYPE_EFI64:
{
multiboot_tag_efi64 *efi64 = (multiboot_tag_efi64 *)Tag;
fixme("efi64->[pointer: %p, size: %d]", efi64->pointer, efi64->size);
break;
}
case MULTIBOOT_TAG_TYPE_SMBIOS:
{
multiboot_tag_smbios *smbios = (multiboot_tag_smbios *)Tag;
fixme("smbios->[major: %d, minor: %d]", smbios->major, smbios->minor);
break;
}
case MULTIBOOT_TAG_TYPE_ACPI_OLD:
{
mb2binfo.RSDP = (BootInfo::RSDPInfo *)((multiboot_tag_old_acpi *)Tag)->rsdp;
debug("OLD ACPI RSDP: %p", mb2binfo.RSDP);
break;
}
case MULTIBOOT_TAG_TYPE_ACPI_NEW:
{
mb2binfo.RSDP = (BootInfo::RSDPInfo *)((multiboot_tag_new_acpi *)Tag)->rsdp;
debug("NEW ACPI RSDP: %p", mb2binfo.RSDP);
break;
}
case MULTIBOOT_TAG_TYPE_NETWORK:
{
multiboot_tag_network *net = (multiboot_tag_network *)Tag;
fixme("network->[dhcpack: %p]", net->dhcpack);
break;
}
case MULTIBOOT_TAG_TYPE_EFI_MMAP:
{
multiboot_tag_efi_mmap *efi_mmap = (multiboot_tag_efi_mmap *)Tag;
fixme("efi_mmap->[descr_size: %d, descr_vers: %d, efi_mmap: %p]",
efi_mmap->descr_size, efi_mmap->descr_vers, efi_mmap->efi_mmap);
break;
}
case MULTIBOOT_TAG_TYPE_EFI_BS:
{
fixme("efi_bs->[%p] (unknown structure)", Tag);
break;
}
case MULTIBOOT_TAG_TYPE_EFI32_IH:
{
multiboot_tag_efi32_ih *efi32_ih = (multiboot_tag_efi32_ih *)Tag;
fixme("efi32_ih->[pointer: %p]", efi32_ih->pointer);
break;
}
case MULTIBOOT_TAG_TYPE_EFI64_IH:
{
multiboot_tag_efi64_ih *efi64_ih = (multiboot_tag_efi64_ih *)Tag;
fixme("efi64_ih->[pointer: %p]", efi64_ih->pointer);
break;
}
case MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR:
{
multiboot_tag_load_base_addr *load_base_addr = (multiboot_tag_load_base_addr *)Tag;
mb2binfo.Kernel.PhysicalBase = (void *)(uint64_t)load_base_addr->load_base_addr;
mb2binfo.Kernel.VirtualBase = (void *)(uint64_t)(load_base_addr->load_base_addr + 0xFFFFFFFF80000000);
mb2binfo.Kernel.Size = ((uint64_t)&_kernel_end - (uint64_t)&_kernel_start) + ((uint64_t)&_bootstrap_end - (uint64_t)&_bootstrap_start);
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);
}

View File

@ -0,0 +1,41 @@
[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

View File

@ -0,0 +1,152 @@
; 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

View File

@ -1,4 +1,6 @@
; https://www.gnu.org/software/grub/manual/multiboot2/multiboot.html
extern MB2_start
[bits 32]
section .multiboot2
align 4096
HEADER_START:
@ -34,28 +36,22 @@ MB2_INFO_REQUEST_TAG_START:
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 0
dd 0
dd 32
dd 1280 ; Width
dd 720 ; Height
dd 32 ; Depth
MB2_FRAMEBUFFER_TAG_END:
align 8
MB2_EGA_SUPPORT_TAG_START:
dw 4
dw 0
dd MB2_EGA_SUPPORT_TAG_END - MB2_EGA_SUPPORT_TAG_START
dd 1 ; https://www.gnu.org/software/grub/manual/multiboot2/html_node/Console-header-tags.html
MB2_EGA_SUPPORT_TAG_END:
align 8
MB2_MODULE_ALIGN_TAG_START:
dw 6
dw 0
dd MB2_MODULE_ALIGN_TAG_END - MB2_MODULE_ALIGN_TAG_START
MB2_MODULE_ALIGN_TAG_END:
align 8
MB2_TAG_START:
dw 0
dw 0

View File

@ -33,7 +33,7 @@ union __attribute__((packed)) PageTableEntry
struct __attribute__((packed)) PageTableEntryPtr
{
PageTableEntry Entries[512];
PageTableEntry Entries[511];
};
union __attribute__((packed)) PageDirectoryEntry
@ -67,7 +67,7 @@ union __attribute__((packed)) PageDirectoryEntry
struct __attribute__((packed)) PageDirectoryEntryPtr
{
PageDirectoryEntry Entries[512];
PageDirectoryEntry Entries[511];
};
union __attribute__((packed)) PageDirectoryPointerTableEntry
@ -101,7 +101,7 @@ union __attribute__((packed)) PageDirectoryPointerTableEntry
struct __attribute__((packed)) PageDirectoryPointerTableEntryPtr
{
PageDirectoryPointerTableEntry Entries[512];
PageDirectoryPointerTableEntry Entries[511];
};
union __attribute__((packed)) PageMapLevel4
@ -135,7 +135,7 @@ union __attribute__((packed)) PageMapLevel4
struct PageTable4
{
PageMapLevel4 Entries[512];
PageMapLevel4 Entries[511];
} __attribute__((aligned(0x1000)));
extern "C" char BootPageTable[];
@ -177,7 +177,7 @@ public:
}
};
__attribute__((section(".bootstrap.text"))) SafeFunction NIF void MB2_64_Map(void *VirtualAddress, void *PhysicalAddress, uint64_t Flags)
__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
@ -188,11 +188,9 @@ __attribute__((section(".bootstrap.text"))) SafeFunction NIF void MB2_64_Map(voi
if (!PML4.Present)
{
PDPTEPtr = (PageDirectoryPointerTableEntryPtr *)RequestPage();
if (PDPTEPtr == nullptr)
return;
{
void *ptr = PDPTEPtr;
uint8_t value = 0;
int value = 0;
size_t num = 0x1000;
uint8_t *p = (uint8_t *)ptr;
for (size_t i = 0; i < num; i++)
@ -211,11 +209,9 @@ __attribute__((section(".bootstrap.text"))) SafeFunction NIF void MB2_64_Map(voi
if (!PDPTE.Present)
{
PDEPtr = (PageDirectoryEntryPtr *)RequestPage();
if (PDEPtr == nullptr)
return;
{
void *ptr = PDEPtr;
uint8_t value = 0;
int value = 0;
size_t num = 0x1000;
uint8_t *p = (uint8_t *)ptr;
for (size_t i = 0; i < num; i++)
@ -234,11 +230,9 @@ __attribute__((section(".bootstrap.text"))) SafeFunction NIF void MB2_64_Map(voi
if (!PDE.Present)
{
PTEPtr = (PageTableEntryPtr *)RequestPage();
if (PTEPtr == nullptr)
return;
{
void *ptr = PTEPtr;
uint8_t value = 0;
int value = 0;
size_t num = 0x1000;
uint8_t *p = (uint8_t *)ptr;
for (size_t i = 0; i < num; i++)
@ -265,17 +259,21 @@ __attribute__((section(".bootstrap.text"))) SafeFunction NIF void MB2_64_Map(voi
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)
// MB2_64_Map((void *)i, (void *)i, 0x3);
// 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)
{
MB2_64_Map((void *)i, (void *)PhysicalStart, 0x3);
Map((void *)i, (void *)PhysicalStart, 0x3);
PhysicalStart += 0x1000;
}

View File

@ -4,10 +4,57 @@
#include <memory.hpp>
#include <io.h>
#include "../../../kernel.h"
#include "../../../../kernel.h"
EXTERNC void multiboot_main(uint32_t Magic, uint32_t Info)
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)
@ -31,12 +78,16 @@ EXTERNC void multiboot_main(uint32_t Magic, uint32_t Info)
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");
@ -157,6 +208,7 @@ EXTERNC void multiboot_main(uint32_t Magic, uint32_t Info)
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:
@ -192,8 +244,8 @@ EXTERNC void multiboot_main(uint32_t Magic, uint32_t Info)
case MULTIBOOT_TAG_TYPE_ELF_SECTIONS:
{
multiboot_tag_elf_sections *elf = (multiboot_tag_elf_sections *)Tag;
fixme("elf_sections->[num=%d, size=%d, entsize=%d, shndx=%d]",
elf->num, elf->size, elf->entsize, elf->shndx);
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:

View File

@ -1,7 +1,7 @@
PAGE_TABLE_SIZE equ 0x4 ; 1GB
PAGE_TABLE_SIZE equ 0x8 ; 2GB
[bits 32]
section .bootstrap.data
section .bootstrap.bss
align 0x1000
global BootPageTable
BootPageTable:
@ -30,7 +30,7 @@ UpdatePageTable:
loop .FillPageTableLevel3 ; Loop until rcx is 0
mov edi, (BootPageTable + 0x2000) ; First PDE
mov eax, 10000011b ; Present, Write, Large Page
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

View File

@ -1,114 +0,0 @@
[bits 32]
KERNEL_STACK_SIZE equ 0x4000 ; 16KB
extern multiboot_main
extern LoadGDT32
extern BootPageTable
extern UpdatePageTable
section .bootstrap.data
MB_HeaderMagic:
dq 0
MB_HeaderInfo:
dq 0
section .bootstrap.text
global _start
_start:
cli
mov [MB_HeaderMagic], eax
mov [MB_HeaderInfo], ebx
mov ecx, cr4
or ecx, 0x00000010 ; Set PSE in CR4
or ecx, 0x00000020 ; Set PAE in CR4
mov cr4, ecx
call LoadGDT32
call UpdatePageTable
mov ecx, BootPageTable
mov cr3, ecx
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 in CR0
mov cr0, ecx
lgdt [GDT64.Ptr]
jmp GDT64.code:HigherHalfStart
extern UpdatePageTable64
[bits 64]
HigherHalfStart:
mov ax, GDT64.data
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
call UpdatePageTable64
mov rsp, KernelStack + KERNEL_STACK_SIZE
mov rdi, [MB_HeaderMagic]
mov rsi, [MB_HeaderInfo]
push rsi
push rdi
call multiboot_main
.Hang:
hlt
jmp .Hang
; 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
section .bootstrap.bss
align 16
KernelStack:
resb KERNEL_STACK_SIZE

View File

@ -1,20 +1,3 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "acpi.hpp"
#include <time.hpp>
@ -36,7 +19,7 @@
namespace ACPI
{
__always_inline inline bool IsCanonical(uint64_t Address)
__attribute__((always_inline)) inline bool IsCanonical(uint64_t Address)
{
return ((Address <= 0x00007FFFFFFFFFFF) || ((Address >= 0xFFFF800000000000) && (Address <= 0xFFFFFFFFFFFFFFFF)));
}
@ -56,13 +39,13 @@ namespace ACPI
uint16_t a = 0, b = 0;
if (acpi->FADT->PM1aEventBlock)
{
a = inw(s_cst(uint16_t, acpi->FADT->PM1aEventBlock));
outw(s_cst(uint16_t, acpi->FADT->PM1aEventBlock), a);
a = inw(acpi->FADT->PM1aEventBlock);
outw(acpi->FADT->PM1aEventBlock, a);
}
if (acpi->FADT->PM1bEventBlock)
{
b = inw(s_cst(uint16_t, acpi->FADT->PM1bEventBlock));
outw(s_cst(uint16_t, acpi->FADT->PM1bEventBlock), b);
b = inw(acpi->FADT->PM1bEventBlock);
outw(acpi->FADT->PM1bEventBlock, b);
}
Event = a | b;
}
@ -78,15 +61,15 @@ namespace ACPI
}
else if (Event & ACPI_POWER_BUTTON)
{
if (TaskManager)
{
TaskManager->CreateThread(TaskManager->CreateProcess(nullptr,
"Shutdown",
Tasking::TaskTrustLevel::Kernel),
(Tasking::IP)KST_Shutdown);
}
else
KernelShutdownThread(false);
BeforeShutdown();
this->Shutdown();
Time::Clock tm = Time::ReadClock();
while (tm.Second == Time::ReadClock().Second)
;
outw(0xB004, 0x2000);
outw(0x604, 0x2000);
outw(0x4004, 0x3400);
CPU::Stop();
}
else if (Event & ACPI_SLEEP_BUTTON)
{
@ -121,24 +104,12 @@ namespace ACPI
trace("Shutting down...");
if (SCI_EN == 1)
{
outw(s_cst(uint16_t, acpi->FADT->PM1aControlBlock),
s_cst(uint16_t,
(inw(s_cst(uint16_t,
acpi->FADT->PM1aControlBlock)) &
0xE3FF) |
((SLP_TYPa << 10) | ACPI_SLEEP)));
outw(acpi->FADT->PM1aControlBlock, (inw(acpi->FADT->PM1aControlBlock) & 0xE3FF) | ((SLP_TYPa << 10) | ACPI_SLEEP));
if (acpi->FADT->PM1bControlBlock)
outw(s_cst(uint16_t, acpi->FADT->PM1bControlBlock),
s_cst(uint16_t,
(inw(
s_cst(uint16_t, acpi->FADT->PM1bControlBlock)) &
0xE3FF) |
((SLP_TYPb << 10) | ACPI_SLEEP)));
outw(s_cst(uint16_t, PM1a_CNT), SLP_TYPa | SLP_EN);
outw(acpi->FADT->PM1bControlBlock, (inw(acpi->FADT->PM1bControlBlock) & 0xE3FF) | ((SLP_TYPb << 10) | ACPI_SLEEP));
outw(PM1a_CNT, SLP_TYPa | SLP_EN);
if (PM1b_CNT)
outw(s_cst(uint16_t, PM1b_CNT), SLP_TYPb | SLP_EN);
outw(PM1b_CNT, SLP_TYPb | SLP_EN);
}
}
@ -148,17 +119,12 @@ namespace ACPI
switch (acpi->FADT->ResetReg.AddressSpace)
{
case ACPI_GAS_MMIO:
{
*(uint8_t *)(acpi->FADT->ResetReg.Address) = acpi->FADT->ResetValue;
break;
}
case ACPI_GAS_IO:
{
outb(s_cst(uint16_t, acpi->FADT->ResetReg.Address), acpi->FADT->ResetValue);
outb(acpi->FADT->ResetReg.Address, acpi->FADT->ResetValue);
break;
}
case ACPI_GAS_PCI:
{
fixme("ACPI_GAS_PCI not supported.");
/*
seg - 0
@ -170,15 +136,9 @@ namespace ACPI
*/
break;
}
default:
{
error("Unknown reset register address space: %d", acpi->FADT->ResetReg.AddressSpace);
break;
}
}
}
DSDT::DSDT(ACPI *acpi) : Interrupts::Handler(acpi->FADT->SCI_Interrupt)
DSDT::DSDT(ACPI *acpi) : Interrupts::Handler(acpi->FADT->SCI_Interrupt + CPU::x86::IRQ0)
{
this->acpi = acpi;
uint64_t Address = ((IsCanonical(acpi->FADT->X_Dsdt) && acpi->XSDTSupported) ? acpi->FADT->X_Dsdt : acpi->FADT->Dsdt);
@ -202,11 +162,11 @@ namespace ACPI
S5Address += ((*S5Address & 0xC0) >> 6) + 2;
if (*S5Address == 0x0A)
S5Address++;
SLP_TYPa = s_cst(uint16_t, *(S5Address) << 10);
SLP_TYPa = *(S5Address) << 10;
S5Address++;
if (*S5Address == 0x0A)
S5Address++;
SLP_TYPb = s_cst(uint16_t, *(S5Address) << 10);
SLP_TYPb = *(S5Address) << 10;
SMI_CMD = acpi->FADT->SMI_CommandPort;
ACPI_ENABLE = acpi->FADT->AcpiEnable;
ACPI_DISABLE = acpi->FADT->AcpiDisable;
@ -220,8 +180,8 @@ namespace ACPI
uint16_t value = ACPI_POWER_BUTTON | ACPI_SLEEP_BUTTON | ACPI_WAKE;
{
uint16_t a = s_cst(uint16_t, acpi->FADT->PM1aEventBlock + (acpi->FADT->PM1EventLength / 2));
uint16_t b = s_cst(uint16_t, acpi->FADT->PM1bEventBlock + (acpi->FADT->PM1EventLength / 2));
uint16_t a = acpi->FADT->PM1aEventBlock + (acpi->FADT->PM1EventLength / 2);
uint16_t b = acpi->FADT->PM1bEventBlock + (acpi->FADT->PM1EventLength / 2);
debug("SCI Event: %#llx [a:%#x b:%#x]", value, a, b);
if (acpi->FADT->PM1aEventBlock)
outw(a, value);
@ -233,13 +193,13 @@ namespace ACPI
uint16_t a = 0, b = 0;
if (acpi->FADT->PM1aEventBlock)
{
a = inw(s_cst(uint16_t, acpi->FADT->PM1aEventBlock));
outw(s_cst(uint16_t, acpi->FADT->PM1aEventBlock), a);
a = inw(acpi->FADT->PM1aEventBlock);
outw(acpi->FADT->PM1aEventBlock, a);
}
if (acpi->FADT->PM1bEventBlock)
{
b = inw(s_cst(uint16_t, acpi->FADT->PM1bEventBlock));
outw(s_cst(uint16_t, acpi->FADT->PM1bEventBlock), b);
b = inw(acpi->FADT->PM1bEventBlock);
outw(acpi->FADT->PM1bEventBlock, b);
}
}
((APIC::APIC *)Interrupts::apic[0])->RedirectIRQ(0, acpi->FADT->SCI_Interrupt, 1);

View File

@ -1,20 +1,3 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "acpi.hpp"
#include <memory.hpp>
@ -49,7 +32,7 @@ namespace ACPI
{
ioapic.push_back((MADTIOApic *)ptr);
KPrint("I/O APIC \e8888FF%d\eCCCCCC (Address \e8888FF%#lx\eCCCCCC) found.", ioapic.back()->APICID, ioapic.back()->Address);
Memory::Virtual(KernelPageTable).Map((void *)(uintptr_t)ioapic.back()->Address, (void *)(uintptr_t)ioapic.back()->Address, Memory::PTFlag::RW | Memory::PTFlag::PCD); // Make sure that the address is mapped.
Memory::Virtual().Map((void *)(uintptr_t)ioapic.back()->Address, (void *)(uintptr_t)ioapic.back()->Address, Memory::PTFlag::RW | Memory::PTFlag::PCD); // Make sure that the address is mapped.
break;
}
case 2:
@ -73,13 +56,8 @@ namespace ACPI
KPrint("APIC found at \e8888FF%#lx\eCCCCCC", LAPICAddress);
break;
}
default:
{
KPrint("Unknown MADT entry \e8888FF%#lx\eCCCCCC", *(ptr));
break;
}
}
Memory::Virtual(KernelPageTable).Map((void *)LAPICAddress, (void *)LAPICAddress, Memory::PTFlag::RW | Memory::PTFlag::PCD); // I should map more than one page?
Memory::Virtual().Map((void *)LAPICAddress, (void *)LAPICAddress, Memory::PTFlag::RW | Memory::PTFlag::PCD); // I should map more than one page?
}
CPUCores--; // We start at 0 (BSP) and end at 11 (APs), so we have 12 cores.
KPrint("Total CPU cores: %d", CPUCores + 1);

View File

@ -1,20 +1,3 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include <syscalls.hpp>
#include <cpu.hpp>
@ -29,58 +12,68 @@ extern "C" uint64_t SystemCallsHandler(SyscallsFrame *regs);
extern "C" void SystemCallHandlerStub();
extern "C" __naked __used __no_stack_protector __aligned(16) void SystemCallHandlerStub()
extern "C" __attribute__((naked, used, no_stack_protector)) void SystemCallHandlerStub_broken()
{
asmv("swapgs\n"
// asmv(
// // "cmp $0x08, 0x8(%rsp)\n"
// // "je 1f\n"
// "swapgs\n"
// // "1:\n"
"mov %rsp, %gs:0x8\n" // CPUData->TempStack
"mov %gs:0x0, %rsp\n" // CPUData->SystemCallStack
"push $0x1b\n" // user data segment
"push %gs:0x8\n" // saved stack
"push %r11\n" // saved rflags
"push $0x23\n" // user code segment
"push %rcx\n" // Current RIP
// "mov %rsp, 0x8(%gs)\n" // CPUData->TempStack
// "mov 0x0(%gs), %rsp\n" // CPUData->SystemCallStack
// "push $0x1b\n" // user data segment
// "push 0x8(%gs)\n" // saved stack
// "push %r11\n" // saved rflags
// "push $0x23\n" // user code segment
// "push %rcx\n" // Current RIP
"push %rax\n"
"push %rbx\n"
"push %rcx\n"
"push %rdx\n"
"push %rsi\n"
"push %rdi\n"
"push %rbp\n"
"push %r8\n"
"push %r9\n"
"push %r10\n"
"push %r11\n"
"push %r12\n"
"push %r13\n"
"push %r14\n"
"push %r15\n"
// "push %rax\n"
// "push %rbx\n"
// "push %rcx\n"
// "push %rdx\n"
// "push %rsi\n"
// "push %rdi\n"
// "push %rbp\n"
// "push %r8\n"
// "push %r9\n"
// "push %r10\n"
// "push %r11\n"
// "push %r12\n"
// "push %r13\n"
// "push %r14\n"
// "push %r15\n"
"mov %rsp, %rdi\n"
"mov $0, %rbp\n"
"call SystemCallsHandler\n"
// "mov %rsp, %rdi\n"
// "mov $0, %rbp\n"
// "call SystemCallsHandler\n"
"pop %r15\n"
"pop %r14\n"
"pop %r13\n"
"pop %r12\n"
"pop %r11\n"
"pop %r10\n"
"pop %r9\n"
"pop %r8\n"
"pop %rbp\n"
"pop %rdi\n"
"pop %rsi\n"
"pop %rdx\n"
"pop %rcx\n"
"pop %rbx\n"
// "pop %r15\n"
// "pop %r14\n"
// "pop %r13\n"
// "pop %r12\n"
// "pop %r11\n"
// "pop %r10\n"
// "pop %r9\n"
// "pop %r8\n"
// "pop %rbp\n"
// "pop %rdi\n"
// "pop %rsi\n"
// "pop %rdx\n"
// "pop %rcx\n"
// "pop %rbx\n"
// /* "pop %rax\n" */
"mov %gs:0x8, %rsp\n" // CPUData->TempStack
// "mov 0x8(%gs), %rsp\n" // CPUData->TempStack
"swapgs\n"
"sti\n"
"sysretq\n");
// // "cmp $0x08, 0x8(%rsp)\n"
// // "je 1f\n"
// "swapgs\n"
// // "1:\n"
// "sti\n"
// "sysretq\n");
}
void InitializeSystemCalls()

View File

@ -0,0 +1,59 @@
[BITS 64]
%macro PushAllSC 0
push rax
push rbx
push rcx
push rdx
push rsi
push rdi
push rbp
push r8
push r9
push r10
push r11
push r12
push r13
push r14
push r15
%endmacro
%macro PopAllSC 0
pop r15
pop r14
pop r13
pop r12
pop r11
pop r10
pop r9
pop r8
pop rbp
pop rdi
pop rsi
pop rdx
pop rcx
pop rbx
%endmacro
ALIGN 4096
extern SystemCallsHandler
global SystemCallHandlerStub
SystemCallHandlerStub:
swapgs ; Swap gs and kernelgs
mov [gs:0x8], rsp ; CPUData->TempStack
mov rsp, [gs:0x0] ; CPUData->SystemCallStack
push qword 0x1b ; User data segment
push qword [gs:0x8] ; Saved stack
push r11 ; Saved rflags
push qword 0x23 ; User code segment
push rcx ; Current instruction pointer
cld ; Clear direction flag
PushAllSC ; Push all registers
mov rdi, rsp ; Pass pointer to registers
mov rbp, 0 ; Pass 0 as return address
call SystemCallsHandler ; Call system call handler
PopAllSC ; Pop all registers except rax
mov rsp, [gs:0x8] ; Restore stack
swapgs ; Swap back gs and kernelgs
sti ; Enable interrupts
o64 sysret ; Return to user mode

View File

@ -1,20 +1,3 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef __FENNIX_KERNEL_ACPI_H__
#define __FENNIX_KERNEL_ACPI_H__
@ -22,8 +5,8 @@
#include <boot/binfo.h>
#include <ints.hpp>
#include <vector.hpp>
#include <cpu.hpp>
#include <vector>
namespace ACPI
{
@ -41,7 +24,7 @@ namespace ACPI
uint32_t OEMRevision;
uint32_t CreatorID;
uint32_t CreatorRevision;
} __packed;
} __attribute__((packed));
struct GenericAddressStructure
{
@ -50,13 +33,13 @@ namespace ACPI
uint8_t BitOffset;
uint8_t AccessSize;
uint64_t Address;
} __packed;
} __attribute__((packed));
struct MCFGHeader
{
struct ACPIHeader Header;
uint64_t Reserved;
} __packed;
} __attribute__((packed));
struct HPETHeader
{
@ -71,7 +54,7 @@ namespace ACPI
uint8_t HPETNumber;
uint16_t MinimumTick;
uint8_t PageProtection;
} __packed;
} __attribute__((packed));
struct FADTHeader
{
@ -127,7 +110,7 @@ namespace ACPI
struct GenericAddressStructure X_PMTimerBlock;
struct GenericAddressStructure X_GPE0Block;
struct GenericAddressStructure X_GPE1Block;
} __packed;
} __attribute__((packed));
struct BGRTHeader
{
@ -181,7 +164,7 @@ namespace ACPI
uint32_t LocalControllerAddress;
uint32_t Flags;
char Entries[];
} __packed;
} __attribute__((packed));
ACPIHeader *XSDT = nullptr;
MCFGHeader *MCFG = nullptr;
@ -198,7 +181,7 @@ namespace ACPI
void *FindTable(ACPIHeader *ACPIHeader, char *Signature);
void SearchTables(ACPIHeader *Header);
ACPI();
ACPI(BootInfo *Info);
~ACPI();
};
@ -209,7 +192,7 @@ namespace ACPI
{
uint8_t Type;
uint8_t Length;
} __packed;
} __attribute__((packed));
struct MADTIOApic
{
@ -218,7 +201,7 @@ namespace ACPI
uint8_t reserved;
uint32_t Address;
uint32_t GSIBase;
} __packed;
} __attribute__((packed));
struct MADTIso
{
@ -227,7 +210,7 @@ namespace ACPI
uint8_t IRQSource;
uint32_t GSI;
uint16_t Flags;
} __packed;
} __attribute__((packed));
struct MADTNmi
{
@ -235,7 +218,7 @@ namespace ACPI
uint8_t processor;
uint16_t flags;
uint8_t lint;
} __packed;
} __attribute__((packed));
struct LocalAPIC
{
@ -243,7 +226,7 @@ namespace ACPI
uint8_t ACPIProcessorId;
uint8_t APICId;
uint32_t Flags;
} __packed;
} __attribute__((packed));
struct LAPIC
{
@ -252,10 +235,10 @@ namespace ACPI
void *VirtualAddress;
};
std::vector<MADTIOApic *> ioapic;
std::vector<MADTIso *> iso;
std::vector<MADTNmi *> nmi;
std::vector<LocalAPIC *> lapic;
Vector<MADTIOApic *> ioapic;
Vector<MADTIso *> iso;
Vector<MADTNmi *> nmi;
Vector<LocalAPIC *> lapic;
struct LAPIC *LAPICAddress;
uint16_t CPUCores;

View File

@ -1,20 +1,3 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "apic.hpp"
#include <memory.hpp>
@ -48,18 +31,16 @@ namespace APIC
uint32_t APIC::Read(uint32_t Register)
{
#ifdef DEBUG
if (Register != APIC_ICRLO &&
Register != APIC_ICRHI &&
Register != APIC_ID)
debug("APIC::Read(%#lx) [x2=%d]", Register, x2APICSupported ? 1 : 0);
#endif
if (x2APICSupported)
{
if (Register != APIC_ICRHI)
return s_cst(uint32_t, rdmsr((Register >> 4) + 0x800));
return rdmsr((Register >> 4) + 0x800);
else
return s_cst(uint32_t, rdmsr(0x30 + 0x800));
return rdmsr(0x30 + 0x800);
}
else
{
@ -72,7 +53,6 @@ namespace APIC
void APIC::Write(uint32_t Register, uint32_t Value)
{
#ifdef DEBUG
if (Register != APIC_EOI &&
Register != APIC_TDCR &&
Register != APIC_TIMER &&
@ -80,7 +60,6 @@ namespace APIC
Register != APIC_ICRLO &&
Register != APIC_ICRHI)
debug("APIC::Write(%#lx, %#lx) [x2=%d]", Register, Value, x2APICSupported ? 1 : 0);
#endif
if (x2APICSupported)
{
if (Register != APIC_ICRHI)
@ -128,32 +107,29 @@ namespace APIC
} while (icr.DeliveryStatus != Idle);
}
void APIC::IPI(int CPU, InterruptCommandRegisterLow icr)
void APIC::IPI(uint8_t CPU, InterruptCommandRegisterLow icr)
{
SmartCriticalSection(APICLock);
if (x2APICSupported)
{
wrmsr(MSR_X2APIC_ICR, s_cst(uint32_t, icr.raw));
this->WaitForIPI();
fixme("Not implemented for x2APIC");
// wrmsr(MSR_X2APIC_ICR, ((uint64_t)CPU) << 32);
}
else
{
this->Write(APIC_ICRHI, (CPU << 24));
this->Write(APIC_ICRLO, s_cst(uint32_t, icr.raw));
this->Write(APIC_ICRLO, icr.raw);
this->WaitForIPI();
}
}
void APIC::SendInitIPI(int CPU)
void APIC::SendInitIPI(uint8_t CPU)
{
SmartCriticalSection(APICLock);
if (x2APICSupported)
{
InterruptCommandRegisterLow icr = {.raw = 0};
icr.DeliveryMode = INIT;
icr.Level = Assert;
wrmsr(MSR_X2APIC_ICR, s_cst(uint32_t, icr.raw));
this->WaitForIPI();
fixme("Not implemented for x2APIC");
// wrmsr(MSR_X2APIC_ICR, ((uint64_t)CPU) << 32);
}
else
{
@ -161,31 +137,27 @@ namespace APIC
icr.DeliveryMode = INIT;
icr.Level = Assert;
this->Write(APIC_ICRHI, (CPU << 24));
this->Write(APIC_ICRLO, s_cst(uint32_t, icr.raw));
this->Write(APIC_ICRLO, icr.raw);
this->WaitForIPI();
}
}
void APIC::SendStartupIPI(int CPU, uint64_t StartupAddress)
void APIC::SendStartupIPI(uint8_t CPU, uint64_t StartupAddress)
{
SmartCriticalSection(APICLock);
if (x2APICSupported)
{
InterruptCommandRegisterLow icr = {.raw = 0};
icr.Vector = s_cst(uint8_t, StartupAddress >> 12);
icr.DeliveryMode = Startup;
icr.Level = Assert;
wrmsr(MSR_X2APIC_ICR, s_cst(uint32_t, icr.raw));
this->WaitForIPI();
warn("Not tested for x2APIC");
wrmsr(MSR_X2APIC_ICR, ((uint64_t)CPU) << 32 | StartupAddress);
}
else
{
InterruptCommandRegisterLow icr = {.raw = 0};
icr.Vector = s_cst(uint8_t, StartupAddress >> 12);
icr.Vector = StartupAddress >> 12;
icr.DeliveryMode = Startup;
icr.Level = Assert;
this->Write(APIC_ICRHI, (CPU << 24));
this->Write(APIC_ICRLO, s_cst(uint32_t, icr.raw));
this->Write(APIC_ICRLO, icr.raw);
this->WaitForIPI();
}
}
@ -196,14 +168,14 @@ namespace APIC
return ((IOAPICVersion *)&TableAddress)->MaximumRedirectionEntry;
}
void APIC::RawRedirectIRQ(uint16_t Vector, uint32_t GSI, uint16_t Flags, int CPU, int Status)
void APIC::RawRedirectIRQ(uint8_t Vector, uint32_t GSI, uint16_t Flags, int CPU, int Status)
{
uint64_t Value = Vector;
int64_t IOAPICTarget = -1;
for (uint64_t i = 0; ((ACPI::MADT *)PowerManager->GetMADT())->ioapic[i] != 0; i++)
if (((ACPI::MADT *)PowerManager->GetMADT())->ioapic[i]->GSIBase <= GSI)
if (((ACPI::MADT *)PowerManager->GetMADT())->ioapic[i]->GSIBase + IOGetMaxRedirect(s_cst(uint32_t, i)) > GSI)
if (((ACPI::MADT *)PowerManager->GetMADT())->ioapic[i]->GSIBase + IOGetMaxRedirect(i) > GSI)
{
IOAPICTarget = i;
break;
@ -233,7 +205,7 @@ namespace APIC
this->IOWrite(((ACPI::MADT *)PowerManager->GetMADT())->ioapic[IOAPICTarget]->Address, IORegister + 1, (uint32_t)(Value >> 32));
}
void APIC::RedirectIRQ(int CPU, uint16_t IRQ, int Status)
void APIC::RedirectIRQ(int CPU, uint8_t IRQ, int Status)
{
for (uint64_t i = 0; i < ((ACPI::MADT *)PowerManager->GetMADT())->iso.size(); i++)
if (((ACPI::MADT *)PowerManager->GetMADT())->iso[i]->IRQSource == IRQ)
@ -252,7 +224,7 @@ namespace APIC
{
SmartCriticalSection(APICLock);
debug("Redirecting IRQs...");
for (uint8_t i = 0; i < 16; i++)
for (int i = 0; i < 16; i++)
this->RedirectIRQ(CPU, i, 1);
debug("Redirecting IRQs completed.");
}
@ -265,28 +237,37 @@ namespace APIC
uint64_t BaseHigh = BaseStruct.ApicBaseHi;
this->APICBaseAddress = BaseLow << 12u | BaseHigh << 32u;
trace("APIC Address: %#lx", this->APICBaseAddress);
Memory::Virtual().Map((void *)this->APICBaseAddress, (void *)this->APICBaseAddress, Memory::PTFlag::RW | Memory::PTFlag::PCD);
bool x2APICSupported = false;
if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_AMD) == 0)
{
CPU::x86::AMD::CPUID0x00000001 cpuid;
cpuid.Get();
if (cpuid.ECX.x2APIC)
{
// x2APICSupported = cpuid.ECX.x2APIC;
fixme("x2APIC is supported");
}
#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
// 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)
{
CPU::x86::Intel::CPUID0x00000001 cpuid;
cpuid.Get();
if (cpuid.ECX.x2APIC)
{
// x2APICSupported = cpuid.ECX.x2APIC;
fixme("x2APIC is supported");
}
#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)
@ -333,7 +314,7 @@ namespace APIC
Spurious Spurious = {.raw = this->Read(APIC_SVR)};
Spurious.Vector = IRQ223; // TODO: Should I map the IRQ to something?
Spurious.Software = 1;
this->Write(APIC_SVR, s_cst(uint32_t, Spurious.raw));
this->Write(APIC_SVR, Spurious.raw);
static int once = 0;
if (!once++)
@ -356,17 +337,17 @@ namespace APIC
{
SmartCriticalSection(APICLock);
LVTTimer timer = {.raw = 0};
timer.Vector = s_cst(uint8_t, Vector);
timer.Vector = Vector;
timer.TimerMode = 0;
if (strcmp(CPU::Hypervisor(), x86_CPUID_VENDOR_TCG) != 0)
this->lapic->Write(APIC_TDCR, DivideBy128);
else
this->lapic->Write(APIC_TDCR, DivideBy16);
this->lapic->Write(APIC_TICR, s_cst(uint32_t, Ticks * Miliseconds));
this->lapic->Write(APIC_TIMER, s_cst(uint32_t, timer.raw));
this->lapic->Write(APIC_TICR, Ticks * Miliseconds);
this->lapic->Write(APIC_TIMER, timer.raw);
}
Timer::Timer(APIC *apic) : Interrupts::Handler(0) /* IRQ0 */
Timer::Timer(APIC *apic) : Interrupts::Handler(IRQ0)
{
SmartCriticalSection(APICLock);
this->lapic = apic;
@ -377,7 +358,7 @@ namespace APIC
this->lapic->Write(APIC_TDCR, Divider);
this->lapic->Write(APIC_TICR, 0xFFFFFFFF);
TimeManager->Sleep(1, Time::Units::Milliseconds);
TimeManager->Sleep(1);
// Mask the timer
this->lapic->Write(APIC_TIMER, 0x10000 /* LVTTimer.Mask flag */);
@ -391,8 +372,8 @@ namespace APIC
// Initialize APIC timer
this->lapic->Write(APIC_TDCR, Divider);
this->lapic->Write(APIC_TICR, s_cst(uint32_t, Ticks));
this->lapic->Write(APIC_TIMER, s_cst(uint32_t, timer.raw));
this->lapic->Write(APIC_TICR, Ticks);
this->lapic->Write(APIC_TIMER, timer.raw);
trace("%d APIC Timer %d ticks in.", GetCurrentCPU()->ID, Ticks);
KPrint("APIC Timer: \e8888FF%ld\eCCCCCC ticks.", Ticks);
}

View File

@ -1,20 +1,3 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "gdt.hpp"
#include <memory.hpp>
@ -25,98 +8,75 @@
namespace GlobalDescriptorTable
{
static GlobalDescriptorTableEntries GDTEntriesTemplate = {
.Null =
{
.Length = 0x0,
.BaseLow = 0x0,
.BaseMiddle = 0x0,
.Access = {.Raw = 0x0},
.Flags = {.Raw = 0x0},
.BaseHigh = 0x0,
},
// null
{.Length = 0x0,
.BaseLow = 0x0,
.BaseMiddle = 0x0,
.Access = {.Raw = 0x0},
.Flags = {.Raw = 0x0},
.BaseHigh = 0x0},
.Code =
{
.Length = 0x0,
.BaseLow = 0x0,
.BaseMiddle = 0x0,
.Access = {
.A = 0,
// 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,
},
.P = 1},
.Flags = {.Unknown = 0x0, .L = 1},
.BaseHigh = 0x0},
.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,
},
// 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},
.UserData = {
.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 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},
.UserCode = {
.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,
},
// 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},
.TaskStateSegment = {},
};
// tss
{}};
GlobalDescriptorTableEntries GDTEntries[MAX_CPU] __aligned(16);
GlobalDescriptorTableDescriptor gdt[MAX_CPU] __aligned(16);
GlobalDescriptorTableEntries GDTEntries[MAX_CPU];
GlobalDescriptorTableDescriptor gdt[MAX_CPU];
TaskStateSegment tss[MAX_CPU] = {
0,
@ -154,35 +114,32 @@ namespace GlobalDescriptorTable
"movw %%ax, %%es\n" ::
: "memory", "rax");
CPUStackPointer[Core] = KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE + 1));
CPUStackPointer[Core] = KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE));
memset(CPUStackPointer[Core], 0, STACK_SIZE);
debug("CPU %d Stack Pointer: %#lx-%#lx (%d pages)", Core,
CPUStackPointer[Core], (uintptr_t)CPUStackPointer[Core] + STACK_SIZE,
TO_PAGES(STACK_SIZE + 1));
debug("CPU %d Stack Pointer: %#lx", Core, CPUStackPointer[Core]);
uintptr_t Base = (uintptr_t)&tss[Core];
size_t Limit = Base + sizeof(TaskStateSegment);
uint64_t Base = (uint64_t)&tss[Core];
uint64_t Limit = Base + sizeof(TaskStateSegment);
gdt[Core].Entries->TaskStateSegment.Length = Limit & 0xFFFF;
gdt[Core].Entries->TaskStateSegment.BaseLow = Base & 0xFFFF;
gdt[Core].Entries->TaskStateSegment.BaseMiddle = (Base >> 16) & 0xFF;
gdt[Core].Entries->TaskStateSegment.BaseHigh = (Base >> 24) & 0xFF;
gdt[Core].Entries->TaskStateSegment.BaseUpper = s_cst(uint32_t, (Base >> 32) & 0xFFFFFFFF);
gdt[Core].Entries->TaskStateSegment.BaseUpper = (Base >> 32) & 0xFFFFFFFF;
gdt[Core].Entries->TaskStateSegment.Flags = {.A = 1, .RW = 0, .DC = 0, .E = 1, .S = 0, .DPL = 0, .P = 1};
gdt[Core].Entries->TaskStateSegment.Granularity = (0 << 4) | ((Limit >> 16) & 0xF);
tss[Core].IOMapBaseAddressOffset = sizeof(TaskStateSegment);
tss[Core].StackPointer[0] = (uint64_t)CPUStackPointer[Core] + STACK_SIZE;
for (size_t i = 0; i < sizeof(tss[Core].InterruptStackTable) / sizeof(tss[Core].InterruptStackTable[7]); i++)
{
void *NewStack = KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE + 1));
tss[Core].InterruptStackTable[i] = (uint64_t)NewStack + STACK_SIZE;
memset((void *)(tss[Core].InterruptStackTable[i] - STACK_SIZE), 0, STACK_SIZE);
debug("IST-%d: %#lx-%#lx", i, NewStack, (uintptr_t)NewStack + 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[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);
asmv("mov %%rsp, %0"
: "=r"(tss[Core].StackPointer[0]));
debug("GDT_KERNEL_CODE: %#lx", GDT_KERNEL_CODE);
debug("GDT_KERNEL_DATA: %#lx", GDT_KERNEL_DATA);
@ -200,15 +157,8 @@ namespace GlobalDescriptorTable
else
tss[CPUID].StackPointer[0] = (uint64_t)CPUStackPointer[CPUID] + STACK_SIZE;
/*
FIXME: There's a bug in kernel which if
we won't update "tss[CPUID].StackPointer[0]"
with the current stack pointer, the kernel
will crash.
*/
// TODO: This may cause problems in the future I guess? This should be checked later
asmv("mov %%rsp, %0"
: "=r"(tss[CPUID].StackPointer[0]));
}
void *GetKernelStack() { return (void *)tss[GetCurrentCPU()->ID].StackPointer[0]; }
}

View File

@ -1,20 +1,3 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "idt.hpp"
#include <memory.hpp>
@ -23,10 +6,6 @@
#include <io.h>
#include "gdt.hpp"
#include "../../../kernel.h"
/* conversion from uint64_t {aka long unsigned int} to unsigned char:2 may change value */
#pragma GCC diagnostic ignored "-Wconversion"
extern "C" void MainInterruptHandler(void *Data);
extern "C" void ExceptionHandler(void *Data);
@ -35,36 +14,41 @@ namespace InterruptDescriptorTable
{
static InterruptDescriptorTableEntry Entries[0x100];
InterruptDescriptorTableDescriptor idtd = {
.Length = sizeof(Entries) - 1,
.Entries = Entries,
};
InterruptDescriptorTableDescriptor idtd = {.Length = sizeof(Entries) - 1,
.Entries = Entries};
void SetEntry(uint8_t Index,
void (*Base)(),
InterruptStackTableType InterruptStackTable,
InterruptGateType Gate,
InterruptRingType Ring,
bool Present,
InterruptDescriptorTableFlags Attribute,
uint8_t InterruptStackTable,
InterruptDescriptorTableFlags Ring,
uint16_t SegmentSelector)
{
Entries[Index].BaseLow = s_cst(uint16_t, ((uint64_t)Base & 0xFFFF));
Entries[Index].BaseHigh = s_cst(uint64_t, ((uint64_t)Base >> 16 /* & 0xFFFF */));
Entries[Index].BaseLow = (uint16_t)((uint64_t)Base & 0xFFFF);
Entries[Index].BaseHigh = (uint64_t)((uint64_t)Base >> 16 /* & 0xFFFF */);
Entries[Index].SegmentSelector = SegmentSelector;
Entries[Index].Flags = Gate;
Entries[Index].Flags = Attribute;
Entries[Index].Reserved1 = 0;
Entries[Index].Reserved2 = 0;
Entries[Index].Reserved3 = 0;
Entries[Index].InterruptStackTable = InterruptStackTable;
Entries[Index].Ring = Ring;
Entries[Index].Present = Present;
Entries[Index].Present = 1;
}
extern "C" __naked __used __no_stack_protector __aligned(16) void ExceptionHandlerStub()
extern "C" __attribute__((naked, used, no_stack_protector)) void ExceptionHandlerStub()
{
asm("cld\n"
"cli\n"
asm(
// "cmp $0x1000, %rsp\n" // Just in case the stack is corrupted
// "jng .skip_swap_check_1\n" /* if is not greater than */
// "cmpw $0x8, 0x8(%rsp)\n"
// "je .skip_swap_check_1\n"
// "swapgs\n"
// ".skip_swap_check_1:\n"
"cld\n" // clear direction flag
// push all registers
"pushq %rax\n"
"pushq %rbx\n"
"pushq %rcx\n"
@ -84,6 +68,7 @@ namespace InterruptDescriptorTable
"movq %rsp, %rdi\n"
"call ExceptionHandler\n"
// pop all registers
"popq %r15\n"
"popq %r14\n"
"popq %r13\n"
@ -102,14 +87,44 @@ namespace InterruptDescriptorTable
"addq $16, %rsp\n"
// "cmp $0x1000, %rsp\n"
// "jng .skip_swap_check_2\n"
// "cmpw $0x8, 0x8(%rsp)\n"
// "je .skip_swap_check_2\n"
// "swapgs\n"
// ".skip_swap_check_2:\n"
"iretq"); // pop CS RIP RFLAGS SS RSP
}
extern "C" __naked __used __no_stack_protector __aligned(16) void InterruptHandlerStub()
{
asm("cld\n"
"cli\n"
extern "C" void WarnSwapgs() { warn("swapgs"); }
// void *OriginalCR3;
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(
// "cmp $0x1000, %rsp\n"
// "jng .skip_swap_check__1\n"
// "cmpw $0x8, 0x8(%rsp)\n"
// "je .skip_swap_check__1\n"
// "swapgs\n"
// "call WarnSwapgs\n"
// ".skip_swap_check__1:\n"
"cld\n"
"pushq %rax\n"
"pushq %rbx\n"
"pushq %rcx\n"
@ -127,9 +142,28 @@ namespace InterruptDescriptorTable
"pushq %r15\n"
"movq %rsp, %rdi\n"
"call MainInterruptHandler\n"
"call MainInterruptHandler\n");
"popq %r15\n"
// // Check if the current cr3 is the same as the KPT
// // 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 %r13\n"
"popq %r12\n"
@ -147,31 +181,38 @@ namespace InterruptDescriptorTable
"addq $16, %rsp\n"
"sti\n"
"iretq"); // pop CS RIP RFLAGS SS RSP
// "cmp $0x1000, %rsp\n"
// "jng .skip_swap_check__2\n"
// "cmpw $0x8, 0x8(%rsp)\n"
// "je .skip_swap_check__2\n"
// "call WarnSwapgs\n"
// "swapgs\n"
// ".skip_swap_check__2:\n"
"iretq");
}
#pragma region Exceptions
#define EXCEPTION_HANDLER(num) \
__naked __used __no_stack_protector __aligned(16) static void InterruptHandler_##num() \
{ \
asm("pushq $0\npushq $" #num "\n" \
"jmp ExceptionHandlerStub"); \
}
#define EXCEPTION_ERROR_HANDLER(num) \
__naked __used __no_stack_protector __aligned(16) static void InterruptHandler_##num() \
{ \
asm("pushq $" #num "\n" \
"jmp ExceptionHandlerStub"); \
}
#define INTERRUPT_HANDLER(num) \
__naked __used __no_stack_protector __aligned(16) void InterruptHandler_##num() \
#define EXCEPTION_HANDLER(num) \
__attribute__((naked, no_stack_protector)) static void InterruptHandler_##num() \
{ \
asm("pushq $0\npushq $" #num "\n" \
"jmp InterruptHandlerStub\n"); \
"jmp ExceptionHandlerStub"); \
}
#define EXCEPTION_ERROR_HANDLER(num) \
__attribute__((naked, no_stack_protector)) static void InterruptHandler_##num() \
{ \
asm("pushq $" #num "\n" \
"jmp ExceptionHandlerStub"); \
}
#define INTERRUPT_HANDLER(num) \
__attribute__((naked, used, no_stack_protector)) void InterruptHandler_##num() \
{ \
asm("pushq $0\npushq $" #num "\n" \
"jmp InterruptHandlerStub\n"); \
}
/* ISR */
@ -446,7 +487,9 @@ namespace InterruptDescriptorTable
void Init(int Core)
{
if (Core == 0) /* Disable PIC using BSP */
UNUSED(Core);
static int once = 0;
if (!once++)
{
// PIC
outb(0x20, 0x10 | 0x1);
@ -477,281 +520,271 @@ namespace InterruptDescriptorTable
/* ISR */
#ifdef DEBUG
// if (!DebuggerIsAttached)
if (true)
{
#endif
SetEntry(0x0, InterruptHandler_0x0, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x1, InterruptHandler_0x1, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x2, InterruptHandler_0x2, IST2, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x3, InterruptHandler_0x3, IST1, TRAP_32BIT, RING3, (!DebuggerIsAttached), GDT_KERNEL_CODE); /* Do not handle breakpoints if we are debugging the kernel. */
SetEntry(0x4, InterruptHandler_0x4, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x5, InterruptHandler_0x5, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x6, InterruptHandler_0x6, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x7, InterruptHandler_0x7, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x8, InterruptHandler_0x8, IST3, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x9, InterruptHandler_0x9, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xa, InterruptHandler_0xa, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xb, InterruptHandler_0xb, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xc, InterruptHandler_0xc, IST3, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xd, InterruptHandler_0xd, IST3, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xe, InterruptHandler_0xe, IST3, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xf, InterruptHandler_0xf, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x10, InterruptHandler_0x10, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x11, InterruptHandler_0x11, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x12, InterruptHandler_0x12, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x13, InterruptHandler_0x13, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x14, InterruptHandler_0x14, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x15, InterruptHandler_0x15, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x16, InterruptHandler_0x16, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x17, InterruptHandler_0x17, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x18, InterruptHandler_0x18, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x19, InterruptHandler_0x19, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x1a, InterruptHandler_0x1a, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x1b, InterruptHandler_0x1b, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x1c, InterruptHandler_0x1c, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x1d, InterruptHandler_0x1d, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x1e, InterruptHandler_0x1e, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x1f, InterruptHandler_0x1f, IST1, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
#ifdef DEBUG
}
else
KPrint("\eFFA500The debugger is attached, not setting up the ISR.");
#endif
SetEntry(0x0, InterruptHandler_0x0, FlagGate_32BIT_TRAP, 1, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x1, InterruptHandler_0x1, FlagGate_32BIT_TRAP, 1, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x2, InterruptHandler_0x2, FlagGate_32BIT_TRAP, 2, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x3, InterruptHandler_0x3, FlagGate_32BIT_TRAP, 1, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x4, InterruptHandler_0x4, FlagGate_32BIT_TRAP, 1, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x5, InterruptHandler_0x5, FlagGate_32BIT_TRAP, 1, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x6, InterruptHandler_0x6, FlagGate_32BIT_TRAP, 1, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x7, InterruptHandler_0x7, FlagGate_32BIT_TRAP, 1, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x8, InterruptHandler_0x8, FlagGate_32BIT_TRAP, 3, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x9, InterruptHandler_0x9, FlagGate_32BIT_TRAP, 1, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xa, InterruptHandler_0xa, FlagGate_32BIT_TRAP, 1, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xb, InterruptHandler_0xb, FlagGate_32BIT_TRAP, 1, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xc, InterruptHandler_0xc, FlagGate_32BIT_TRAP, 3, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xd, InterruptHandler_0xd, FlagGate_32BIT_TRAP, 3, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xe, InterruptHandler_0xe, FlagGate_32BIT_TRAP, 3, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xf, InterruptHandler_0xf, FlagGate_32BIT_TRAP, 1, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x10, InterruptHandler_0x10, FlagGate_32BIT_TRAP, 1, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x11, InterruptHandler_0x11, FlagGate_32BIT_TRAP, 1, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x12, InterruptHandler_0x12, FlagGate_32BIT_TRAP, 1, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x13, InterruptHandler_0x13, FlagGate_32BIT_TRAP, 1, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x14, InterruptHandler_0x14, FlagGate_32BIT_TRAP, 1, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x15, InterruptHandler_0x15, FlagGate_32BIT_TRAP, 1, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x16, InterruptHandler_0x16, FlagGate_32BIT_TRAP, 1, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x17, InterruptHandler_0x17, FlagGate_32BIT_TRAP, 1, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x18, InterruptHandler_0x18, FlagGate_32BIT_TRAP, 1, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x19, InterruptHandler_0x19, FlagGate_32BIT_TRAP, 1, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x1a, InterruptHandler_0x1a, FlagGate_32BIT_TRAP, 1, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x1b, InterruptHandler_0x1b, FlagGate_32BIT_TRAP, 1, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x1c, InterruptHandler_0x1c, FlagGate_32BIT_TRAP, 1, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x1d, InterruptHandler_0x1d, FlagGate_32BIT_TRAP, 1, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x1e, InterruptHandler_0x1e, FlagGate_32BIT_TRAP, 1, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x1f, InterruptHandler_0x1f, FlagGate_32BIT_TRAP, 1, FlagGate_RING0, GDT_KERNEL_CODE);
/* IRQ */
SetEntry(0x20, InterruptHandler_0x20, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x21, InterruptHandler_0x21, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x22, InterruptHandler_0x22, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x23, InterruptHandler_0x23, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x24, InterruptHandler_0x24, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x25, InterruptHandler_0x25, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x26, InterruptHandler_0x26, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x27, InterruptHandler_0x27, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x28, InterruptHandler_0x28, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x29, InterruptHandler_0x29, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x2a, InterruptHandler_0x2a, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x2b, InterruptHandler_0x2b, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x2c, InterruptHandler_0x2c, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x2d, InterruptHandler_0x2d, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x2e, InterruptHandler_0x2e, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x2f, InterruptHandler_0x2f, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x20, InterruptHandler_0x20, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x21, InterruptHandler_0x21, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x22, InterruptHandler_0x22, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x23, InterruptHandler_0x23, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x24, InterruptHandler_0x24, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x25, InterruptHandler_0x25, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x26, InterruptHandler_0x26, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x27, InterruptHandler_0x27, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x28, InterruptHandler_0x28, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x29, InterruptHandler_0x29, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x2a, InterruptHandler_0x2a, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x2b, InterruptHandler_0x2b, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x2c, InterruptHandler_0x2c, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x2d, InterruptHandler_0x2d, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x2e, InterruptHandler_0x2e, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x2f, InterruptHandler_0x2f, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
/* Reserved by OS */
SetEntry(0x30, InterruptHandler_0x30, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x31, InterruptHandler_0x31, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x32, InterruptHandler_0x32, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x33, InterruptHandler_0x33, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x34, InterruptHandler_0x34, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x35, InterruptHandler_0x35, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x36, InterruptHandler_0x36, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x37, InterruptHandler_0x37, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x38, InterruptHandler_0x38, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x39, InterruptHandler_0x39, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x3a, InterruptHandler_0x3a, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x3b, InterruptHandler_0x3b, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x3c, InterruptHandler_0x3c, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x3d, InterruptHandler_0x3d, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x30, InterruptHandler_0x30, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x31, InterruptHandler_0x31, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x32, InterruptHandler_0x32, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x33, InterruptHandler_0x33, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x34, InterruptHandler_0x34, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x35, InterruptHandler_0x35, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x36, InterruptHandler_0x36, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x37, InterruptHandler_0x37, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x38, InterruptHandler_0x38, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x39, InterruptHandler_0x39, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x3a, InterruptHandler_0x3a, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x3b, InterruptHandler_0x3b, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x3c, InterruptHandler_0x3c, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x3d, InterruptHandler_0x3d, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
/* Free */
SetEntry(0x3e, InterruptHandler_0x3e, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x3f, InterruptHandler_0x3f, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x40, InterruptHandler_0x40, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x41, InterruptHandler_0x41, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x42, InterruptHandler_0x42, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x43, InterruptHandler_0x43, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x44, InterruptHandler_0x44, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x45, InterruptHandler_0x45, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x46, InterruptHandler_0x46, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x47, InterruptHandler_0x47, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x48, InterruptHandler_0x48, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x49, InterruptHandler_0x49, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x4a, InterruptHandler_0x4a, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x4b, InterruptHandler_0x4b, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x4c, InterruptHandler_0x4c, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x4d, InterruptHandler_0x4d, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x4e, InterruptHandler_0x4e, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x4f, InterruptHandler_0x4f, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x50, InterruptHandler_0x50, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x51, InterruptHandler_0x51, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x52, InterruptHandler_0x52, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x53, InterruptHandler_0x53, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x54, InterruptHandler_0x54, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x55, InterruptHandler_0x55, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x56, InterruptHandler_0x56, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x57, InterruptHandler_0x57, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x58, InterruptHandler_0x58, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x59, InterruptHandler_0x59, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x5a, InterruptHandler_0x5a, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x5b, InterruptHandler_0x5b, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x5c, InterruptHandler_0x5c, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x5d, InterruptHandler_0x5d, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x5e, InterruptHandler_0x5e, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x5f, InterruptHandler_0x5f, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x60, InterruptHandler_0x60, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x61, InterruptHandler_0x61, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x62, InterruptHandler_0x62, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x63, InterruptHandler_0x63, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x64, InterruptHandler_0x64, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x65, InterruptHandler_0x65, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x66, InterruptHandler_0x66, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x67, InterruptHandler_0x67, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x68, InterruptHandler_0x68, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x69, InterruptHandler_0x69, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x6a, InterruptHandler_0x6a, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x6b, InterruptHandler_0x6b, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x6c, InterruptHandler_0x6c, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x6d, InterruptHandler_0x6d, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x6e, InterruptHandler_0x6e, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x6f, InterruptHandler_0x6f, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x70, InterruptHandler_0x70, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x71, InterruptHandler_0x71, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x72, InterruptHandler_0x72, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x73, InterruptHandler_0x73, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x74, InterruptHandler_0x74, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x75, InterruptHandler_0x75, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x76, InterruptHandler_0x76, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x77, InterruptHandler_0x77, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x78, InterruptHandler_0x78, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x79, InterruptHandler_0x79, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x7a, InterruptHandler_0x7a, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x7b, InterruptHandler_0x7b, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x7c, InterruptHandler_0x7c, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x7d, InterruptHandler_0x7d, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x7e, InterruptHandler_0x7e, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x7f, InterruptHandler_0x7f, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x80, InterruptHandler_0x80, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x81, InterruptHandler_0x81, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x82, InterruptHandler_0x82, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x83, InterruptHandler_0x83, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x84, InterruptHandler_0x84, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x85, InterruptHandler_0x85, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x86, InterruptHandler_0x86, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x87, InterruptHandler_0x87, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x88, InterruptHandler_0x88, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x89, InterruptHandler_0x89, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x8a, InterruptHandler_0x8a, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x8b, InterruptHandler_0x8b, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x8c, InterruptHandler_0x8c, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x8d, InterruptHandler_0x8d, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x8e, InterruptHandler_0x8e, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x8f, InterruptHandler_0x8f, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x90, InterruptHandler_0x90, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x91, InterruptHandler_0x91, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x92, InterruptHandler_0x92, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x93, InterruptHandler_0x93, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x94, InterruptHandler_0x94, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x95, InterruptHandler_0x95, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x96, InterruptHandler_0x96, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x97, InterruptHandler_0x97, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x98, InterruptHandler_0x98, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x99, InterruptHandler_0x99, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x9a, InterruptHandler_0x9a, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x9b, InterruptHandler_0x9b, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x9c, InterruptHandler_0x9c, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x9d, InterruptHandler_0x9d, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x9e, InterruptHandler_0x9e, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x9f, InterruptHandler_0x9f, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xa0, InterruptHandler_0xa0, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xa1, InterruptHandler_0xa1, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xa2, InterruptHandler_0xa2, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xa3, InterruptHandler_0xa3, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xa4, InterruptHandler_0xa4, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xa5, InterruptHandler_0xa5, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xa6, InterruptHandler_0xa6, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xa7, InterruptHandler_0xa7, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xa8, InterruptHandler_0xa8, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xa9, InterruptHandler_0xa9, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xaa, InterruptHandler_0xaa, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xab, InterruptHandler_0xab, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xac, InterruptHandler_0xac, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xad, InterruptHandler_0xad, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xae, InterruptHandler_0xae, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xaf, InterruptHandler_0xaf, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xb0, InterruptHandler_0xb0, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xb1, InterruptHandler_0xb1, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xb2, InterruptHandler_0xb2, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xb3, InterruptHandler_0xb3, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xb4, InterruptHandler_0xb4, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xb5, InterruptHandler_0xb5, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xb6, InterruptHandler_0xb6, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xb7, InterruptHandler_0xb7, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xb8, InterruptHandler_0xb8, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xb9, InterruptHandler_0xb9, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xba, InterruptHandler_0xba, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xbb, InterruptHandler_0xbb, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xbc, InterruptHandler_0xbc, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xbd, InterruptHandler_0xbd, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xbe, InterruptHandler_0xbe, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xbf, InterruptHandler_0xbf, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xc0, InterruptHandler_0xc0, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xc1, InterruptHandler_0xc1, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xc2, InterruptHandler_0xc2, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xc3, InterruptHandler_0xc3, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xc4, InterruptHandler_0xc4, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xc5, InterruptHandler_0xc5, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xc6, InterruptHandler_0xc6, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xc7, InterruptHandler_0xc7, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xc8, InterruptHandler_0xc8, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xc9, InterruptHandler_0xc9, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xca, InterruptHandler_0xca, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xcb, InterruptHandler_0xcb, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xcc, InterruptHandler_0xcc, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xcd, InterruptHandler_0xcd, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xce, InterruptHandler_0xce, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xcf, InterruptHandler_0xcf, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xd0, InterruptHandler_0xd0, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xd1, InterruptHandler_0xd1, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xd2, InterruptHandler_0xd2, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xd3, InterruptHandler_0xd3, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xd4, InterruptHandler_0xd4, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xd5, InterruptHandler_0xd5, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xd6, InterruptHandler_0xd6, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xd7, InterruptHandler_0xd7, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xd8, InterruptHandler_0xd8, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xd9, InterruptHandler_0xd9, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xda, InterruptHandler_0xda, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xdb, InterruptHandler_0xdb, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xdc, InterruptHandler_0xdc, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xdd, InterruptHandler_0xdd, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xde, InterruptHandler_0xde, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xdf, InterruptHandler_0xdf, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xe0, InterruptHandler_0xe0, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xe1, InterruptHandler_0xe1, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xe2, InterruptHandler_0xe2, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xe3, InterruptHandler_0xe3, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xe4, InterruptHandler_0xe4, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xe5, InterruptHandler_0xe5, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xe6, InterruptHandler_0xe6, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xe7, InterruptHandler_0xe7, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xe8, InterruptHandler_0xe8, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xe9, InterruptHandler_0xe9, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xea, InterruptHandler_0xea, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xeb, InterruptHandler_0xeb, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xec, InterruptHandler_0xec, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xed, InterruptHandler_0xed, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xee, InterruptHandler_0xee, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xef, InterruptHandler_0xef, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xf0, InterruptHandler_0xf0, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xf1, InterruptHandler_0xf1, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xf2, InterruptHandler_0xf2, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xf3, InterruptHandler_0xf3, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xf4, InterruptHandler_0xf4, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xf5, InterruptHandler_0xf5, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xf6, InterruptHandler_0xf6, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xf7, InterruptHandler_0xf7, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xf8, InterruptHandler_0xf8, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xf9, InterruptHandler_0xf9, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xfa, InterruptHandler_0xfa, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xfb, InterruptHandler_0xfb, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xfc, InterruptHandler_0xfc, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xfd, InterruptHandler_0xfd, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xfe, InterruptHandler_0xfe, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0xff, InterruptHandler_0xff, IST0, TRAP_32BIT, RING0, true, GDT_KERNEL_CODE);
SetEntry(0x3e, InterruptHandler_0x3e, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x3f, InterruptHandler_0x3f, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x40, InterruptHandler_0x40, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x41, InterruptHandler_0x41, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x42, InterruptHandler_0x42, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x43, InterruptHandler_0x43, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x44, InterruptHandler_0x44, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x45, InterruptHandler_0x45, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x46, InterruptHandler_0x46, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x47, InterruptHandler_0x47, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x48, InterruptHandler_0x48, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x49, InterruptHandler_0x49, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x4a, InterruptHandler_0x4a, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x4b, InterruptHandler_0x4b, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x4c, InterruptHandler_0x4c, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x4d, InterruptHandler_0x4d, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x4e, InterruptHandler_0x4e, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x4f, InterruptHandler_0x4f, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x50, InterruptHandler_0x50, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x51, InterruptHandler_0x51, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x52, InterruptHandler_0x52, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x53, InterruptHandler_0x53, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x54, InterruptHandler_0x54, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x55, InterruptHandler_0x55, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x56, InterruptHandler_0x56, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x57, InterruptHandler_0x57, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x58, InterruptHandler_0x58, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x59, InterruptHandler_0x59, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x5a, InterruptHandler_0x5a, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x5b, InterruptHandler_0x5b, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x5c, InterruptHandler_0x5c, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x5d, InterruptHandler_0x5d, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x5e, InterruptHandler_0x5e, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x5f, InterruptHandler_0x5f, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x60, InterruptHandler_0x60, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x61, InterruptHandler_0x61, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x62, InterruptHandler_0x62, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x63, InterruptHandler_0x63, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x64, InterruptHandler_0x64, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x65, InterruptHandler_0x65, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x66, InterruptHandler_0x66, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x67, InterruptHandler_0x67, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x68, InterruptHandler_0x68, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x69, InterruptHandler_0x69, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x6a, InterruptHandler_0x6a, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x6b, InterruptHandler_0x6b, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x6c, InterruptHandler_0x6c, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x6d, InterruptHandler_0x6d, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x6e, InterruptHandler_0x6e, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x6f, InterruptHandler_0x6f, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x70, InterruptHandler_0x70, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x71, InterruptHandler_0x71, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x72, InterruptHandler_0x72, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x73, InterruptHandler_0x73, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x74, InterruptHandler_0x74, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x75, InterruptHandler_0x75, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x76, InterruptHandler_0x76, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x77, InterruptHandler_0x77, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x78, InterruptHandler_0x78, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x79, InterruptHandler_0x79, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x7a, InterruptHandler_0x7a, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x7b, InterruptHandler_0x7b, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x7c, InterruptHandler_0x7c, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x7d, InterruptHandler_0x7d, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x7e, InterruptHandler_0x7e, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x7f, InterruptHandler_0x7f, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x80, InterruptHandler_0x80, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x81, InterruptHandler_0x81, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x82, InterruptHandler_0x82, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x83, InterruptHandler_0x83, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x84, InterruptHandler_0x84, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x85, InterruptHandler_0x85, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x86, InterruptHandler_0x86, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x87, InterruptHandler_0x87, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x88, InterruptHandler_0x88, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x89, InterruptHandler_0x89, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x8a, InterruptHandler_0x8a, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x8b, InterruptHandler_0x8b, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x8c, InterruptHandler_0x8c, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x8d, InterruptHandler_0x8d, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x8e, InterruptHandler_0x8e, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x8f, InterruptHandler_0x8f, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x90, InterruptHandler_0x90, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x91, InterruptHandler_0x91, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x92, InterruptHandler_0x92, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x93, InterruptHandler_0x93, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x94, InterruptHandler_0x94, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x95, InterruptHandler_0x95, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x96, InterruptHandler_0x96, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x97, InterruptHandler_0x97, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x98, InterruptHandler_0x98, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x99, InterruptHandler_0x99, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x9a, InterruptHandler_0x9a, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x9b, InterruptHandler_0x9b, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x9c, InterruptHandler_0x9c, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x9d, InterruptHandler_0x9d, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x9e, InterruptHandler_0x9e, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0x9f, InterruptHandler_0x9f, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xa0, InterruptHandler_0xa0, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xa1, InterruptHandler_0xa1, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xa2, InterruptHandler_0xa2, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xa3, InterruptHandler_0xa3, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xa4, InterruptHandler_0xa4, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xa5, InterruptHandler_0xa5, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xa6, InterruptHandler_0xa6, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xa7, InterruptHandler_0xa7, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xa8, InterruptHandler_0xa8, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xa9, InterruptHandler_0xa9, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xaa, InterruptHandler_0xaa, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xab, InterruptHandler_0xab, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xac, InterruptHandler_0xac, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xad, InterruptHandler_0xad, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xae, InterruptHandler_0xae, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xaf, InterruptHandler_0xaf, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xb0, InterruptHandler_0xb0, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xb1, InterruptHandler_0xb1, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xb2, InterruptHandler_0xb2, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xb3, InterruptHandler_0xb3, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xb4, InterruptHandler_0xb4, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xb5, InterruptHandler_0xb5, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xb6, InterruptHandler_0xb6, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xb7, InterruptHandler_0xb7, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xb8, InterruptHandler_0xb8, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xb9, InterruptHandler_0xb9, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xba, InterruptHandler_0xba, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xbb, InterruptHandler_0xbb, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xbc, InterruptHandler_0xbc, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xbd, InterruptHandler_0xbd, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xbe, InterruptHandler_0xbe, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xbf, InterruptHandler_0xbf, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xc0, InterruptHandler_0xc0, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xc1, InterruptHandler_0xc1, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xc2, InterruptHandler_0xc2, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xc3, InterruptHandler_0xc3, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xc4, InterruptHandler_0xc4, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xc5, InterruptHandler_0xc5, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xc6, InterruptHandler_0xc6, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xc7, InterruptHandler_0xc7, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xc8, InterruptHandler_0xc8, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xc9, InterruptHandler_0xc9, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xca, InterruptHandler_0xca, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xcb, InterruptHandler_0xcb, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xcc, InterruptHandler_0xcc, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xcd, InterruptHandler_0xcd, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xce, InterruptHandler_0xce, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xcf, InterruptHandler_0xcf, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xd0, InterruptHandler_0xd0, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xd1, InterruptHandler_0xd1, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xd2, InterruptHandler_0xd2, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xd3, InterruptHandler_0xd3, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xd4, InterruptHandler_0xd4, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xd5, InterruptHandler_0xd5, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xd6, InterruptHandler_0xd6, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xd7, InterruptHandler_0xd7, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xd8, InterruptHandler_0xd8, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xd9, InterruptHandler_0xd9, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xda, InterruptHandler_0xda, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xdb, InterruptHandler_0xdb, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xdc, InterruptHandler_0xdc, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xdd, InterruptHandler_0xdd, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xde, InterruptHandler_0xde, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xdf, InterruptHandler_0xdf, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xe0, InterruptHandler_0xe0, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xe1, InterruptHandler_0xe1, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xe2, InterruptHandler_0xe2, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xe3, InterruptHandler_0xe3, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xe4, InterruptHandler_0xe4, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xe5, InterruptHandler_0xe5, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xe6, InterruptHandler_0xe6, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xe7, InterruptHandler_0xe7, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xe8, InterruptHandler_0xe8, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xe9, InterruptHandler_0xe9, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xea, InterruptHandler_0xea, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xeb, InterruptHandler_0xeb, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xec, InterruptHandler_0xec, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xed, InterruptHandler_0xed, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xee, InterruptHandler_0xee, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xef, InterruptHandler_0xef, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xf0, InterruptHandler_0xf0, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xf1, InterruptHandler_0xf1, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xf2, InterruptHandler_0xf2, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xf3, InterruptHandler_0xf3, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xf4, InterruptHandler_0xf4, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xf5, InterruptHandler_0xf5, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xf6, InterruptHandler_0xf6, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xf7, InterruptHandler_0xf7, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xf8, InterruptHandler_0xf8, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xf9, InterruptHandler_0xf9, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xfa, InterruptHandler_0xfa, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xfb, InterruptHandler_0xfb, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xfc, InterruptHandler_0xfc, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xfd, InterruptHandler_0xfd, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xfe, InterruptHandler_0xfe, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
SetEntry(0xff, InterruptHandler_0xff, FlagGate_32BIT_TRAP, 0, FlagGate_RING0, GDT_KERNEL_CODE);
CPU::x64::lidt(&idtd);
}
}

View File

@ -1,28 +1,5 @@
; This file is part of Fennix Kernel.
;
; Fennix Kernel is free software: you can redistribute it and/or
; modify it under the terms of the GNU General Public License as
; published by the Free Software Foundation, either version 3 of
; the License, or (at your option) any later version.
;
; Fennix Kernel is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
; This has to be the same as enum SMPTrampolineAddress.
TRAMPOLINE_PAGE_TABLE equ 0x500
TRAMPOLINE_START_ADDR equ 0x520
TRAMPOLINE_STACK equ 0x570
TRAMPOLINE_GDT equ 0x580
TRAMPOLINE_IDT equ 0x590
TRAMPOLINE_CORE equ 0x600
TRAMPOLINE_START equ 0x2000
[bits 16]
TRAMPOLINE_BASE equ 0x2000
extern StartCPU
global _trampoline_start
@ -34,11 +11,11 @@ _trampoline_start:
mov fs, ax
mov gs, ax
mov ss, ax
o32 lgdt [ProtectedMode_gdtr - _trampoline_start + TRAMPOLINE_START]
o32 lgdt [ProtectedMode_gdtr - _trampoline_start + TRAMPOLINE_BASE]
mov eax, cr0
or al, 0x1
mov cr0, eax
jmp 0x8:(Trampoline32 - _trampoline_start + TRAMPOLINE_START)
jmp 0x8:(Trampoline32 - _trampoline_start + TRAMPOLINE_BASE)
[bits 32]
section .text
@ -47,7 +24,7 @@ Trampoline32:
mov ds, bx
mov es, bx
mov ss, bx
mov eax, dword [TRAMPOLINE_PAGE_TABLE]
mov eax, dword [0x500]
mov cr3, eax
mov eax, cr4
or eax, 1 << 5 ; Set the PAE-bit, which is the 6th bit (bit 5).
@ -60,8 +37,8 @@ Trampoline32:
mov eax, cr0
or eax, 1 << 31
mov cr0, eax
lgdt [LongMode_gdtr - _trampoline_start + TRAMPOLINE_START]
jmp 0x8:(Trampoline64 - _trampoline_start + TRAMPOLINE_START)
lgdt [LongMode_gdtr - _trampoline_start + TRAMPOLINE_BASE]
jmp 0x8:(Trampoline64 - _trampoline_start + TRAMPOLINE_BASE)
[bits 64]
Trampoline64:
@ -72,9 +49,9 @@ Trampoline64:
mov ax, 0x0
mov fs, ax
mov gs, ax
lgdt [TRAMPOLINE_GDT]
lidt [TRAMPOLINE_IDT]
mov rsp, [TRAMPOLINE_STACK]
lgdt [0x580]
lidt [0x590]
mov rsp, [0x570]
mov rbp, 0x0 ; Terminate stack traces here.
; Reset RFLAGS.
push 0x0
@ -99,7 +76,7 @@ vcode64:
align 16
LongMode_gdtr:
dw LongModeGDTEnd - LongModeGDTStart - 1
dq LongModeGDTStart - _trampoline_start + TRAMPOLINE_START
dq LongModeGDTStart - _trampoline_start + TRAMPOLINE_BASE
align 16
LongModeGDTStart:
@ -111,7 +88,7 @@ LongModeGDTEnd:
align 16
ProtectedMode_gdtr:
dw ProtectedModeGDTEnd - ProtectedModeGDTStart - 1
dd ProtectedModeGDTStart - _trampoline_start + TRAMPOLINE_START
dd ProtectedModeGDTStart - _trampoline_start + TRAMPOLINE_BASE
align 16
ProtectedModeGDTStart:

View File

@ -1,27 +1,9 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include <smp.hpp>
#include <memory.hpp>
#include <ints.hpp>
#include <memory.hpp>
#include <assert.h>
#include <cpu.hpp>
#include <atomic>
#include "../../../kernel.h"
#include "../acpi.hpp"
@ -29,7 +11,6 @@
extern "C" uint64_t _trampoline_start, _trampoline_end;
/* https://wiki.osdev.org/Memory_Map_(x86) */
enum SMPTrampolineAddress
{
PAGE_TABLE = 0x500,
@ -41,10 +22,10 @@ enum SMPTrampolineAddress
TRAMPOLINE_START = 0x2000
};
std::atomic_bool CPUEnabled = false;
volatile bool CPUEnabled = false;
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
static __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]; }
@ -52,7 +33,6 @@ SafeFunction CPUData *GetCurrentCPU()
{
if (unlikely(!Interrupts::apic[0]))
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))
@ -69,17 +49,16 @@ SafeFunction CPUData *GetCurrentCPU()
extern "C" void StartCPU()
{
CPU::Interrupts(CPU::Disable);
int CoreID = (int)*reinterpret_cast<int *>(CORE);
uint64_t CoreID = (int)*reinterpret_cast<int *>(CORE);
CPU::InitializeFeatures(CoreID);
// Initialize GDT and IDT
Interrupts::Initialize(CoreID);
Interrupts::Enable(CoreID);
Interrupts::InitializeTimer(CoreID);
asmv("mov %0, %%rsp" ::"r"((&CPUs[CoreID])->Stack));
CPU::Interrupts(CPU::Enable);
KPrint("\e058C19CPU \e8888FF%d \e058C19is online", CoreID);
CPUEnabled.store(true, std::memory_order_release);
CPUEnabled = true;
CPU::Halt(true);
}
@ -98,44 +77,43 @@ namespace SMP
CPUCores = Cores;
uint64_t TrampolineLength = (uintptr_t)&_trampoline_end - (uintptr_t)&_trampoline_start;
Memory::Virtual().Map(0x0, 0x0, Memory::PTFlag::RW);
/* We reserved the TRAMPOLINE_START address inside Physical class. */
Memory::Virtual().Map((void *)TRAMPOLINE_START, (void *)TRAMPOLINE_START, TrampolineLength, Memory::PTFlag::RW);
memcpy((void *)TRAMPOLINE_START, &_trampoline_start, TrampolineLength);
debug("Trampoline address: %#lx-%#lx", TRAMPOLINE_START, TRAMPOLINE_START + TrampolineLength);
void *CPUTmpStack = KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE + 1));
asmv("sgdt [0x580]\n"
"sidt [0x590]\n");
VPOKE(uintptr_t, STACK) = (uintptr_t)CPUTmpStack + STACK_SIZE;
VPOKE(uintptr_t, PAGE_TABLE) = (uintptr_t)KernelPageTable;
VPOKE(uint64_t, START_ADDR) = (uintptr_t)&StartCPU;
for (int i = 0; i < Cores; i++)
{
debug("Initializing CPU %d", i);
if ((((APIC::APIC *)Interrupts::apic[0])->Read(APIC::APIC_ID) >> 24) != ((ACPI::MADT *)madt)->lapic[i]->ACPIProcessorId)
{
VPOKE(int, CORE) = i;
((APIC::APIC *)Interrupts::apic[0])->Write(APIC::APIC_ICRHI, (((ACPI::MADT *)madt)->lapic[i]->APICId << 24));
((APIC::APIC *)Interrupts::apic[0])->Write(APIC::APIC_ICRLO, 0x500);
Memory::Virtual().Map(0x0, 0x0, Memory::PTFlag::RW | Memory::PTFlag::US);
uint64_t TrampolineLength = (uintptr_t)&_trampoline_end - (uintptr_t)&_trampoline_start;
for (uint64_t i = 0; i < (TrampolineLength / PAGE_SIZE) + 2; i++)
Memory::Virtual().Map((void *)(TRAMPOLINE_START + (i * PAGE_SIZE)), (void *)(TRAMPOLINE_START + (i * PAGE_SIZE)), Memory::PTFlag::RW | Memory::PTFlag::US);
memcpy((void *)TRAMPOLINE_START, &_trampoline_start, TrampolineLength);
POKE(volatile uint64_t, PAGE_TABLE) = CPU::x64::readcr3().raw;
POKE(volatile uint64_t, STACK) = (uint64_t)KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE)) + STACK_SIZE;
POKE(volatile uint64_t, CORE) = i;
asmv("sgdt [0x580]\n"
"sidt [0x590]\n");
POKE(volatile uint64_t, START_ADDR) = (uintptr_t)&StartCPU;
((APIC::APIC *)Interrupts::apic[0])->SendInitIPI(((ACPI::MADT *)madt)->lapic[i]->APICId);
((APIC::APIC *)Interrupts::apic[0])->SendStartupIPI(((ACPI::MADT *)madt)->lapic[i]->APICId, TRAMPOLINE_START);
while (!CPUEnabled.load(std::memory_order_acquire))
while (!CPUEnabled)
CPU::Pause();
CPUEnabled.store(false, std::memory_order_release);
trace("CPU %d loaded.", ((ACPI::MADT *)madt)->lapic[i]->APICId);
KernelAllocator.FreePages((void *)*reinterpret_cast<long *>(STACK), TO_PAGES(STACK_SIZE));
CPUEnabled = false;
}
else
KPrint("\e058C19CPU \e8888FF%d \e058C19is the BSP", ((ACPI::MADT *)madt)->lapic[i]->APICId);
}
KernelAllocator.FreePages(CPUTmpStack, TO_PAGES(STACK_SIZE + 1));
/* We are going to unmap the page after we are done with it. */
Memory::Virtual().Unmap(0x0);
}
}

View File

@ -1,20 +1,3 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef __FENNIX_KERNEL_APIC_H__
#define __FENNIX_KERNEL_APIC_H__
@ -170,7 +153,7 @@ namespace APIC
uint64_t Reserved2 : 14;
};
uint64_t raw;
} __packed LVTTimer;
} __attribute__((packed)) LVTTimer;
typedef union
{
@ -190,7 +173,7 @@ namespace APIC
uint64_t Reserved1 : 19;
};
uint64_t raw;
} __packed Spurious;
} __attribute__((packed)) Spurious;
typedef union
{
@ -239,7 +222,7 @@ namespace APIC
uint64_t Reserved2 : 12;
};
uint64_t raw;
} __packed InterruptCommandRegisterLow;
} __attribute__((packed)) InterruptCommandRegisterLow;
typedef union
{
@ -251,7 +234,7 @@ namespace APIC
uint64_t Destination : 8;
};
uint64_t raw;
} __packed InterruptCommandRegisterHigh;
} __attribute__((packed)) InterruptCommandRegisterHigh;
typedef union
{
@ -298,7 +281,7 @@ namespace APIC
uint64_t High;
} split;
uint64_t raw;
} __packed IOAPICRedirectEntry;
} __attribute__((packed)) IOAPICRedirectEntry;
typedef union
{
@ -310,7 +293,7 @@ namespace APIC
uint64_t Reserved2 : 8;
};
uint64_t raw;
} __packed IOAPICVersion;
} __attribute__((packed)) IOAPICVersion;
class APIC
{
@ -326,12 +309,12 @@ namespace APIC
void EOI();
void RedirectIRQs(int CPU = 0);
void WaitForIPI();
void IPI(int CPU, InterruptCommandRegisterLow icr);
void SendInitIPI(int CPU);
void SendStartupIPI(int CPU, uint64_t StartupAddress);
void IPI(uint8_t CPU, InterruptCommandRegisterLow icr);
void SendInitIPI(uint8_t CPU);
void SendStartupIPI(uint8_t CPU, uint64_t StartupAddress);
uint32_t IOGetMaxRedirect(uint32_t APICID);
void RawRedirectIRQ(uint16_t Vector, uint32_t GSI, uint16_t Flags, int CPU, int Status);
void RedirectIRQ(int CPU, uint16_t IRQ, int Status);
void RawRedirectIRQ(uint8_t Vector, uint32_t GSI, uint16_t Flags, int CPU, int Status);
void RedirectIRQ(int CPU, uint8_t IRQ, int Status);
APIC(int Core);
~APIC();
};

View File

@ -1,20 +1,3 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef __FENNIX_KERNEL_GDT_H__
#define __FENNIX_KERNEL_GDT_H__
@ -32,43 +15,43 @@ namespace GlobalDescriptorTable
/** @brief Access bit.
* @note The CPU sets this bit to 1 when the segment is accessed.
*/
uint64_t A : 1;
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.
*/
uint64_t RW : 1;
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.
*/
uint64_t DC : 1;
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.
*/
uint64_t E : 1;
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.
*/
uint64_t S : 1;
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.
*/
uint64_t DPL : 2;
uint8_t DPL : 2;
/** @brief Present bit.
* @details This bit must be 1 for all valid descriptors.
*/
uint64_t P : 1;
} __packed;
uint8_t P : 1;
} __attribute__((packed));
uint8_t Raw;
};
@ -78,14 +61,14 @@ namespace GlobalDescriptorTable
struct
{
/** @brief Unknown. */
uint64_t Unknown : 5;
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.
*/
uint64_t L : 1;
} __packed;
uint8_t L : 1;
} __attribute__((packed));
uint8_t Raw;
};
@ -101,18 +84,18 @@ namespace GlobalDescriptorTable
/* HIGH */
uint32_t BaseUpper;
uint32_t Reserved;
} __packed TaskStateSegmentEntry;
} __attribute__((packed)) TaskStateSegmentEntry;
typedef struct _TaskStateSegment
{
uint32_t Reserved0 __aligned(16);
uint32_t Reserved0 __attribute__((aligned(16)));
uint64_t StackPointer[3];
uint64_t Reserved1;
uint64_t InterruptStackTable[7];
uint64_t Reserved2;
uint16_t Reserved3;
uint16_t IOMapBaseAddressOffset;
} __packed TaskStateSegment;
} __attribute__((packed)) TaskStateSegment;
typedef struct _GlobalDescriptorTableEntry
{
@ -128,7 +111,7 @@ namespace GlobalDescriptorTable
GlobalDescriptorTableFlags Flags;
/** @brief High Base */
uint8_t BaseHigh;
} __packed GlobalDescriptorTableEntry;
} __attribute__((packed)) GlobalDescriptorTableEntry;
typedef struct _GlobalDescriptorTableEntries
{
@ -138,7 +121,7 @@ namespace GlobalDescriptorTable
GlobalDescriptorTableEntry UserData;
GlobalDescriptorTableEntry UserCode;
TaskStateSegmentEntry TaskStateSegment;
} __packed GlobalDescriptorTableEntries;
} __attribute__((packed)) GlobalDescriptorTableEntries;
typedef struct _GlobalDescriptorTableDescriptor
{
@ -146,13 +129,12 @@ namespace GlobalDescriptorTable
uint16_t Length;
/** @brief GDT entries address */
GlobalDescriptorTableEntries *Entries;
} __packed GlobalDescriptorTableDescriptor;
} __attribute__((packed)) GlobalDescriptorTableDescriptor;
extern void *CPUStackPointer[];
extern TaskStateSegment tss[];
void Init(int Core);
void SetKernelStack(void *Stack);
void *GetKernelStack();
}
#define GDT_KERNEL_CODE offsetof(GlobalDescriptorTable::GlobalDescriptorTableEntries, Code)

View File

@ -1,20 +1,3 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef __FENNIX_KERNEL_IDT_H__
#define __FENNIX_KERNEL_IDT_H__
@ -22,33 +5,19 @@
namespace InterruptDescriptorTable
{
typedef enum _InterruptGateType
typedef enum _InterruptDescriptorTableFlags
{
TASK = 0b101,
INT_16BIT = 0b110,
TRAP_16BIT = 0b111,
INT_32BIT = 0b1110,
TRAP_32BIT = 0b1111,
} InterruptGateType;
typedef enum _InterruptRingType
{
RING0 = 0b0,
RING1 = 0b1,
RING2 = 0b10,
RING3 = 0b11,
} InterruptRingType;
typedef enum _InterruptStackTableType
{
IST0 = 0b0,
IST1 = 0b1,
IST2 = 0b10,
IST3 = 0b11,
IST4 = 0b100,
IST5 = 0b101,
IST6 = 0b110,
} InterruptStackTableType;
FlagGate_TASK = 0b101,
FlagGate_16BIT_INT = 0b110,
FlagGate_16BIT_TRAP = 0b111,
FlagGate_32BIT_INT = 0b1110,
FlagGate_32BIT_TRAP = 0b1111,
FlagGate_RING0 = 0b0,
FlagGate_RING1 = 0b1,
FlagGate_RING2 = 0b10,
FlagGate_RING3 = 0b11,
FlagGate_PRESENT = 0b1, // Not sure if this is correct.
} InterruptDescriptorTableFlags;
typedef struct _InterruptDescriptorTableEntry
{
@ -56,28 +25,21 @@ namespace InterruptDescriptorTable
uint64_t SegmentSelector : 16;
uint64_t InterruptStackTable : 3;
uint64_t Reserved1 : 5;
uint64_t Flags : 4;
InterruptDescriptorTableFlags Flags : 4;
uint64_t Reserved2 : 1;
uint64_t Ring : 2;
uint64_t Present : 1;
uint64_t BaseHigh : 48;
uint64_t Reserved3 : 32;
} __packed InterruptDescriptorTableEntry;
} __attribute__((packed)) InterruptDescriptorTableEntry;
typedef struct _InterruptDescriptorTableDescriptor
{
uint16_t Length;
InterruptDescriptorTableEntry *Entries;
} __packed InterruptDescriptorTableDescriptor;
void SetEntry(uint8_t Index,
void (*Base)(),
InterruptStackTableType InterruptStackTable,
InterruptGateType Gate,
InterruptRingType Ring,
bool Present,
uint16_t SegmentSelector);
} __attribute__((packed)) InterruptDescriptorTableDescriptor;
void SetEntry(uint8_t Index, void (*Base)(), InterruptDescriptorTableFlags Attribute, uint8_t InterruptStackTable, InterruptDescriptorTableFlags Ring, uint16_t SegmentSelector);
void Init(int Core);
}

View File

@ -1,44 +1,31 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
OUTPUT_FORMAT(elf64-x86-64)
OUTPUT_ARCH(i386:x86-64)
KERNEL_LMA = 16M;
KERNEL_VMA = 0xFFFFFFFF80000000;
ENTRY(_start)
SECTIONS
{
. = 0x100000;
. = KERNEL_LMA;
.multiboot2 :
{
*(.multiboot2 .multiboot2.*)
}
_bootstrap_start = .;
.bootstrap :
{
*(.multiboot)
*(.multiboot2)
*(.bootstrap .bootstrap.*)
*(.bootstrap.text .bootstrap.text.*)
*(.bootstrap.data .bootstrap.data.*)
*(.bootstrap.rodata .bootstrap.rodata.*)
*(.bootstrap.bss .bootstrap.bss.*)
}
. += CONSTANT(MAXPAGESIZE);
_bootstrap_end = ALIGN(CONSTANT(MAXPAGESIZE));
. += KERNEL_VMA;
. += CONSTANT(MAXPAGESIZE);
_kernel_start = ALIGN(CONSTANT(MAXPAGESIZE));
_kernel_start = .;
.text : AT(ADDR(.text) - KERNEL_VMA)
{
*(.text .text.*)
@ -57,6 +44,8 @@ SECTIONS
{
*(.rodata .rodata.*)
}
_kernel_rodata_end = ALIGN(CONSTANT(MAXPAGESIZE));
. += CONSTANT(MAXPAGESIZE);
.init_array : AT(ADDR(.init_array) - KERNEL_VMA)
{
@ -73,7 +62,6 @@ SECTIONS
KEEP(*(.fini_array .dtors))
PROVIDE_HIDDEN (__fini_array_end = .);
}
_kernel_rodata_end = ALIGN(CONSTANT(MAXPAGESIZE));
. += CONSTANT(MAXPAGESIZE);
.bss : AT(ADDR(.bss) - KERNEL_VMA)

View File

@ -4,12 +4,12 @@
int Entry(void *Info);
// void _start(void *Raw)
// {
// UNUSED(Raw);
// error("ERROR! INVALID BOOT PROTOCOL!");
// while (1)
// asmv("hlt");
// Entry(NULL);
// return;
// }
void _start(void *Raw)
{
UNUSED(Raw);
error("ERROR! INVALID BOOT PROTOCOL!");
while (1)
asmv("hlt");
Entry(NULL);
return;
}

View File

@ -1,5 +0,0 @@
section .multiboot
align 4
dd 0x1BADB002
dd 1 << 0 | 1 << 1
dd -(0x1BADB002 + (1 << 0 | 1 << 1))

View File

@ -1,10 +0,0 @@
KERNEL_PAGE_NUMBER equ 768 ; 0xC0000000
section .data
global BootPageTable
align 0x1000
BootPageTable:
dd 0x00000083
times (KERNEL_PAGE_NUMBER - 1) dd 0
dd 0x00000083
times (1024 - KERNEL_PAGE_NUMBER - 1) dd 0

View File

@ -1,30 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include <syscalls.hpp>
#include <cpu.hpp>
#include "cpu/gdt.hpp"
using namespace CPU::x32;
extern "C" uint32_t SystemCallsHandler(SyscallsFrame *regs);
void InitializeSystemCalls()
{
}

View File

@ -1,294 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef __FENNIX_KERNEL_ACPI_H__
#define __FENNIX_KERNEL_ACPI_H__
#include <types.h>
#include <boot/binfo.h>
#include <ints.hpp>
#include <cpu.hpp>
#include <vector>
namespace ACPI
{
class ACPI
{
public:
struct ACPIHeader
{
unsigned char Signature[4];
uint32_t Length;
uint8_t Revision;
uint8_t Checksum;
uint8_t OEMID[6];
uint8_t OEMTableID[8];
uint32_t OEMRevision;
uint32_t CreatorID;
uint32_t CreatorRevision;
} __packed;
struct GenericAddressStructure
{
uint8_t AddressSpace;
uint8_t BitWidth;
uint8_t BitOffset;
uint8_t AccessSize;
uint64_t Address;
} __packed;
struct MCFGHeader
{
struct ACPIHeader Header;
uint64_t Reserved;
} __packed;
struct HPETHeader
{
ACPIHeader Header;
uint8_t HardwareRevID;
uint8_t ComparatorCount : 5;
uint8_t CounterSize : 1;
uint8_t Reserved : 1;
uint8_t LegacyReplacement : 1;
uint16_t PCIVendorID;
struct GenericAddressStructure Address;
uint8_t HPETNumber;
uint16_t MinimumTick;
uint8_t PageProtection;
} __packed;
struct FADTHeader
{
ACPIHeader Header;
uint32_t FirmwareCtrl;
uint32_t Dsdt;
uint8_t Reserved;
uint8_t PreferredPowerManagementProfile;
uint16_t SCI_Interrupt;
uint32_t SMI_CommandPort;
uint8_t AcpiEnable;
uint8_t AcpiDisable;
uint8_t S4BIOS_REQ;
uint8_t PSTATE_Control;
uint32_t PM1aEventBlock;
uint32_t PM1bEventBlock;
uint32_t PM1aControlBlock;
uint32_t PM1bControlBlock;
uint32_t PM2ControlBlock;
uint32_t PMTimerBlock;
uint32_t GPE0Block;
uint32_t GPE1Block;
uint8_t PM1EventLength;
uint8_t PM1ControlLength;
uint8_t PM2ControlLength;
uint8_t PMTimerLength;
uint8_t GPE0Length;
uint8_t GPE1Length;
uint8_t GPE1Base;
uint8_t CStateControl;
uint16_t WorstC2Latency;
uint16_t WorstC3Latency;
uint16_t FlushSize;
uint16_t FlushStride;
uint8_t DutyOffset;
uint8_t DutyWidth;
uint8_t DayAlarm;
uint8_t MonthAlarm;
uint8_t Century;
uint16_t BootArchitectureFlags;
uint8_t Reserved2;
uint32_t Flags;
struct GenericAddressStructure ResetReg;
uint8_t ResetValue;
uint8_t Reserved3[3];
uint64_t X_FirmwareControl;
uint64_t X_Dsdt;
struct GenericAddressStructure X_PM1aEventBlock;
struct GenericAddressStructure X_PM1bEventBlock;
struct GenericAddressStructure X_PM1aControlBlock;
struct GenericAddressStructure X_PM1bControlBlock;
struct GenericAddressStructure X_PM2ControlBlock;
struct GenericAddressStructure X_PMTimerBlock;
struct GenericAddressStructure X_GPE0Block;
struct GenericAddressStructure X_GPE1Block;
} __packed;
struct BGRTHeader
{
ACPIHeader Header;
uint16_t Version;
uint8_t Status;
uint8_t ImageType;
uint64_t ImageAddress;
uint32_t ImageOffsetX;
uint32_t ImageOffsetY;
};
struct SRATHeader
{
ACPIHeader Header;
uint32_t TableRevision; // Must be value 1
uint64_t Reserved; // Reserved, must be zero
};
struct TPM2Header
{
ACPIHeader Header;
uint32_t Flags;
uint64_t ControlAddress;
uint32_t StartMethod;
};
struct TCPAHeader
{
ACPIHeader Header;
uint16_t Reserved;
uint32_t MaxLogLength;
uint64_t LogAddress;
};
struct WAETHeader
{
ACPIHeader Header;
uint32_t Flags;
};
struct HESTHeader
{
ACPIHeader Header;
uint32_t ErrorSourceCount;
};
struct MADTHeader
{
ACPIHeader Header;
uint32_t LocalControllerAddress;
uint32_t Flags;
char Entries[];
} __packed;
ACPIHeader *XSDT = nullptr;
MCFGHeader *MCFG = nullptr;
HPETHeader *HPET = nullptr;
FADTHeader *FADT = nullptr;
BGRTHeader *BGRT = nullptr;
SRATHeader *SRAT = nullptr;
TPM2Header *TPM2 = nullptr;
TCPAHeader *TCPA = nullptr;
WAETHeader *WAET = nullptr;
MADTHeader *MADT = nullptr;
HESTHeader *HEST = nullptr;
bool XSDTSupported = false;
void *FindTable(ACPIHeader *ACPIHeader, char *Signature);
void SearchTables(ACPIHeader *Header);
ACPI();
~ACPI();
};
class MADT
{
public:
struct APICHeader
{
uint8_t Type;
uint8_t Length;
} __packed;
struct MADTIOApic
{
struct APICHeader Header;
uint8_t APICID;
uint8_t reserved;
uint32_t Address;
uint32_t GSIBase;
} __packed;
struct MADTIso
{
struct APICHeader Header;
uint8_t BuSSource;
uint8_t IRQSource;
uint32_t GSI;
uint16_t Flags;
} __packed;
struct MADTNmi
{
struct APICHeader Header;
uint8_t processor;
uint16_t flags;
uint8_t lint;
} __packed;
struct LocalAPIC
{
struct APICHeader Header;
uint8_t ACPIProcessorId;
uint8_t APICId;
uint32_t Flags;
} __packed;
struct LAPIC
{
uint8_t id;
uintptr_t PhysicalAddress;
void *VirtualAddress;
};
std::vector<MADTIOApic *> ioapic;
std::vector<MADTIso *> iso;
std::vector<MADTNmi *> nmi;
std::vector<LocalAPIC *> lapic;
struct LAPIC *LAPICAddress;
uint16_t CPUCores;
MADT(ACPI::MADTHeader *madt);
~MADT();
};
class DSDT : public Interrupts::Handler
{
private:
uint32_t SMI_CMD = 0;
uint8_t ACPI_ENABLE = 0;
uint8_t ACPI_DISABLE = 0;
uint32_t PM1a_CNT = 0;
uint32_t PM1b_CNT = 0;
uint16_t SLP_TYPa = 0;
uint16_t SLP_TYPb = 0;
uint16_t SLP_EN = 0;
uint16_t SCI_EN = 0;
uint8_t PM1_CNT_LEN = 0;
ACPI *acpi;
void OnInterruptReceived(CPU::x64::TrapFrame *Frame);
public:
bool ACPIShutdownSupported = false;
void Reboot();
void Shutdown();
DSDT(ACPI *acpi);
~DSDT();
};
}
#endif // !__FENNIX_KERNEL_ACPI_H__

View File

@ -1,54 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include <smp.hpp>
#include <ints.hpp>
#include <memory.hpp>
#include <assert.h>
#include <cpu.hpp>
#include "../../../kernel.h"
volatile bool CPUEnabled = false;
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
static __aligned(0x1000) CPUData CPUs[MAX_CPU] = {0};
CPUData *GetCPU(uint64_t id) { return &CPUs[id]; }
CPUData *GetCurrentCPU()
{
uint64_t ret = 0;
if (!(&CPUs[ret])->IsActive)
{
// error("CPU %d is not active!", ret);
return &CPUs[0];
}
assert((&CPUs[ret])->Checksum == CPU_DATA_CHECKSUM);
return &CPUs[ret];
}
namespace SMP
{
int CPUCores = 0;
void Initialize(void *madt)
{
fixme("SMP::Initialize() is not implemented!");
}
}

View File

@ -1,28 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef __FENNIX_KERNEL_IDT_H__
#define __FENNIX_KERNEL_IDT_H__
#include <types.h>
namespace InterruptDescriptorTable
{
void Init(int Core);
}
#endif // !__FENNIX_KERNEL_IDT_H__

View File

@ -1,93 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
OUTPUT_FORMAT(elf32-i386)
OUTPUT_ARCH(i386)
KERNEL_VMA = 0xC0000000;
ENTRY(_start)
SECTIONS
{
. = 0x100000;
_bootstrap_start = .;
.bootstrap :
{
*(.multiboot)
*(.multiboot2)
*(.bootstrap .bootstrap.*)
}
. += CONSTANT(MAXPAGESIZE);
_bootstrap_end = ALIGN(CONSTANT(MAXPAGESIZE));
. += KERNEL_VMA;
. += CONSTANT(MAXPAGESIZE);
_kernel_start = ALIGN(CONSTANT(MAXPAGESIZE));
.text : AT(ADDR(.text) - KERNEL_VMA)
{
*(.text .text.*)
}
_kernel_text_end = ALIGN(CONSTANT(MAXPAGESIZE));
. += CONSTANT(MAXPAGESIZE);
.data : AT(ADDR(.data) - KERNEL_VMA)
{
*(.data .data.*)
}
_kernel_data_end = ALIGN(CONSTANT(MAXPAGESIZE));
. += CONSTANT(MAXPAGESIZE);
.rodata : AT(ADDR(.rodata) - KERNEL_VMA)
{
*(.rodata .rodata.*)
}
_kernel_rodata_end = ALIGN(CONSTANT(MAXPAGESIZE));
. += CONSTANT(MAXPAGESIZE);
.init_array : AT(ADDR(.init_array) - KERNEL_VMA)
{
PROVIDE_HIDDEN(__init_array_start = .);
KEEP(*(.init_array .ctors))
KEEP(*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
PROVIDE_HIDDEN (__init_array_end = .);
}
.fini_array : AT(ADDR(.fini_array) - KERNEL_VMA)
{
PROVIDE_HIDDEN(__fini_array_start = .);
KEEP(*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
KEEP(*(.fini_array .dtors))
PROVIDE_HIDDEN (__fini_array_end = .);
}
. += CONSTANT(MAXPAGESIZE);
.bss : AT(ADDR(.bss) - KERNEL_VMA)
{
*(COMMON)
*(.bss .bss.*)
}
. += CONSTANT(MAXPAGESIZE);
_kernel_end = ALIGN(CONSTANT(MAXPAGESIZE));
/DISCARD/ :
{
*(.comment*)
*(.note*)
}
}

View File

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

View File

@ -1,50 +1,54 @@
[bits 32]
; 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 multiboot_main
extern Multiboot2Entry
extern BootPageTable
global _start
global MB2_start
section .text
MB_HeaderMagic:
dq 0
MB_HeaderInfo:
dq 0
_start:
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 [MB_HeaderMagic], eax
mov [MB_HeaderInfo], ebx
mov word [0xb8F08], 0x072E ; .
mov dword [BootPageTable], 0
invlpg [0]
mov esp, KernelStack + KERNEL_STACK_SIZE
mov eax, [MB_HeaderMagic]
mov ebx, [MB_HeaderInfo]
push ebx ; Multiboot2 Header
add ebx, KERNEL_VIRTUAL_BASE
push eax ; Multiboot2 Magic
call multiboot_main
.Hang:
add ebx, KERNEL_VIRTUAL_BASE
push ebx ; Multiboot2 Header
call Multiboot2Entry
Loop:
hlt
jmp .Hang
jmp Loop
section .bss
align 16
KernelStack:
KernelStack:
resb KERNEL_STACK_SIZE

View File

@ -0,0 +1,13 @@
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

View File

@ -0,0 +1,339 @@
#include <types.h>
#include <boot/protocols/multiboot2.h>
#include <memory.hpp>
#include <io.h>
#include "../../../kernel.h"
BootInfo mb2binfo;
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
}
}
void ProcessMB2(unsigned long Info)
{
uint8_t *VideoBuffer = (uint8_t *)0xB8F00 + 0xC0000000;
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 *)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:
{
fixme("indexed");
break;
}
case MULTIBOOT_FRAMEBUFFER_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:
{
fixme("ega_text");
break;
}
}
debug("Framebuffer %d: %dx%d %d bpp", Tag, fb->common.framebuffer_width, fb->common.framebuffer_height, fb->common.framebuffer_bpp);
debug("More info:\nAddress: %p\nPitch: %lld\nMemoryModel: %d\nRedMaskSize: %d\nRedMaskShift: %d\nGreenMaskSize: %d\nGreenMaskShift: %d\nBlueMaskSize: %d\nBlueMaskShift: %d",
fb->common.framebuffer_addr, fb->common.framebuffer_pitch, fb->common.framebuffer_type,
fb->framebuffer_red_mask_size, fb->framebuffer_red_field_position, fb->framebuffer_green_mask_size,
fb->framebuffer_green_field_position, fb->framebuffer_blue_mask_size, fb->framebuffer_blue_field_position);
fb_count++;
break;
}
case MULTIBOOT_TAG_TYPE_ELF_SECTIONS:
{
multiboot_tag_elf_sections *elf = (multiboot_tag_elf_sections *)Tag;
fixme("elf_sections->[num=%d, size=%d, entsize=%d, shndx=%d]",
elf->num, elf->size, elf->entsize, elf->shndx);
break;
}
case MULTIBOOT_TAG_TYPE_APM:
{
multiboot_tag_apm *apm = (multiboot_tag_apm *)Tag;
fixme("apm->[version: %d, cseg: %d, offset: %d, cseg_16: %d, dseg: %d, flags: %d, cseg_len: %d, cseg_16_len: %d, dseg_len: %d]",
apm->version, apm->cseg, apm->offset, apm->cseg_16, apm->dseg, apm->flags, apm->cseg_len, apm->cseg_16_len, apm->dseg_len);
break;
}
case MULTIBOOT_TAG_TYPE_EFI32:
{
multiboot_tag_efi32 *efi32 = (multiboot_tag_efi32 *)Tag;
fixme("efi32->[pointer: %p, size: %d]", efi32->pointer, efi32->size);
break;
}
case MULTIBOOT_TAG_TYPE_EFI64:
{
multiboot_tag_efi64 *efi64 = (multiboot_tag_efi64 *)Tag;
fixme("efi64->[pointer: %p, size: %d]", efi64->pointer, efi64->size);
break;
}
case MULTIBOOT_TAG_TYPE_SMBIOS:
{
multiboot_tag_smbios *smbios = (multiboot_tag_smbios *)Tag;
fixme("smbios->[major: %d, minor: %d]", smbios->major, smbios->minor);
break;
}
case MULTIBOOT_TAG_TYPE_ACPI_OLD:
{
mb2binfo.RSDP = (BootInfo::RSDPInfo *)((multiboot_tag_old_acpi *)Tag)->rsdp;
debug("OLD ACPI RSDP: %p", mb2binfo.RSDP);
break;
}
case MULTIBOOT_TAG_TYPE_ACPI_NEW:
{
mb2binfo.RSDP = (BootInfo::RSDPInfo *)((multiboot_tag_new_acpi *)Tag)->rsdp;
debug("NEW ACPI RSDP: %p", mb2binfo.RSDP);
break;
}
case MULTIBOOT_TAG_TYPE_NETWORK:
{
multiboot_tag_network *net = (multiboot_tag_network *)Tag;
fixme("network->[dhcpack: %p]", net->dhcpack);
break;
}
case MULTIBOOT_TAG_TYPE_EFI_MMAP:
{
multiboot_tag_efi_mmap *efi_mmap = (multiboot_tag_efi_mmap *)Tag;
fixme("efi_mmap->[descr_size: %d, descr_vers: %d, efi_mmap: %p]",
efi_mmap->descr_size, efi_mmap->descr_vers, efi_mmap->efi_mmap);
break;
}
case MULTIBOOT_TAG_TYPE_EFI_BS:
{
fixme("efi_bs->[%p] (unknown structure)", Tag);
break;
}
case MULTIBOOT_TAG_TYPE_EFI32_IH:
{
multiboot_tag_efi32_ih *efi32_ih = (multiboot_tag_efi32_ih *)Tag;
fixme("efi32_ih->[pointer: %p]", efi32_ih->pointer);
break;
}
case MULTIBOOT_TAG_TYPE_EFI64_IH:
{
multiboot_tag_efi64_ih *efi64_ih = (multiboot_tag_efi64_ih *)Tag;
fixme("efi64_ih->[pointer: %p]", efi64_ih->pointer);
break;
}
case MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR:
{
multiboot_tag_load_base_addr *load_base_addr = (multiboot_tag_load_base_addr *)Tag;
mb2binfo.Kernel.PhysicalBase = (void *)load_base_addr->load_base_addr;
mb2binfo.Kernel.VirtualBase = (void *)(load_base_addr->load_base_addr + 0xC0000000);
debug("Kernel base: %p (physical) %p (virtual)", mb2binfo.Kernel.PhysicalBase, mb2binfo.Kernel.VirtualBase);
break;
}
default:
{
error("Unknown multiboot2 tag type: %d", Tag->type);
break;
}
}
}
}
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;
outb(0x61, tmp);
CPU::Stop();
Entry(&mb2binfo);
}

View File

@ -1,20 +1,3 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "pic.hpp"
#include <io.h>

View File

@ -1,20 +1,3 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef __FENNIX_KERNEL_8259PIC_H__
#define __FENNIX_KERNEL_8259PIC_H__

View File

@ -0,0 +1,13 @@
#include <syscalls.hpp>
#include <cpu.hpp>
#include "cpu/gdt.hpp"
using namespace CPU::x32;
extern "C" uint32_t SystemCallsHandler(SyscallsFrame *regs);
void InitializeSystemCalls()
{
}

View File

@ -1,20 +1,3 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "gdt.hpp"
#include <memory.hpp>

View File

@ -0,0 +1,37 @@
#include <smp.hpp>
#include <ints.hpp>
#include <memory.hpp>
#include <assert.h>
#include <cpu.hpp>
#include "../../../kernel.h"
volatile bool CPUEnabled = false;
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
static __attribute__((aligned(PAGE_SIZE))) CPUData CPUs[MAX_CPU] = {0};
CPUData *GetCPU(uint64_t id) { return &CPUs[id]; }
CPUData *GetCurrentCPU()
{
uint64_t ret = 0;
if (!(&CPUs[ret])->IsActive)
{
error("CPU %d is not active!", ret);
return &CPUs[0];
}
assert((&CPUs[ret])->Checksum == CPU_DATA_CHECKSUM);
return &CPUs[ret];
}
namespace SMP
{
int CPUCores = 0;
void Initialize(void *madt)
{
fixme("SMP::Initialize() is not implemented!");
}
}

View File

@ -1,20 +1,3 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef __FENNIX_KERNEL_APIC_H__
#define __FENNIX_KERNEL_APIC_H__
@ -170,7 +153,7 @@ namespace APIC
uint64_t Reserved2 : 14;
};
uint64_t raw;
} __packed LVTTimer;
} __attribute__((packed)) LVTTimer;
typedef union
{
@ -190,7 +173,7 @@ namespace APIC
uint64_t Reserved1 : 19;
};
uint64_t raw;
} __packed Spurious;
} __attribute__((packed)) Spurious;
typedef union
{
@ -239,7 +222,7 @@ namespace APIC
uint64_t Reserved2 : 12;
};
uint64_t raw;
} __packed InterruptCommandRegisterLow;
} __attribute__((packed)) InterruptCommandRegisterLow;
typedef union
{
@ -251,7 +234,7 @@ namespace APIC
uint64_t Destination : 8;
};
uint64_t raw;
} __packed InterruptCommandRegisterHigh;
} __attribute__((packed)) InterruptCommandRegisterHigh;
typedef union
{
@ -298,7 +281,7 @@ namespace APIC
uint64_t High;
} split;
uint64_t raw;
} __packed IOAPICRedirectEntry;
} __attribute__((packed)) IOAPICRedirectEntry;
typedef union
{
@ -310,7 +293,7 @@ namespace APIC
uint64_t Reserved2 : 8;
};
uint64_t raw;
} __packed IOAPICVersion;
} __attribute__((packed)) IOAPICVersion;
class APIC
{
@ -331,7 +314,7 @@ namespace APIC
void SendStartupIPI(uint8_t CPU, uint64_t StartupAddress);
uint32_t IOGetMaxRedirect(uint32_t APICID);
void RawRedirectIRQ(uint8_t Vector, uint32_t GSI, uint16_t Flags, int CPU, int Status);
void RedirectIRQ(int CPU, uint16_t IRQ, int Status);
void RedirectIRQ(int CPU, uint8_t IRQ, int Status);
APIC(int Core);
~APIC();
};

View File

@ -1,20 +1,3 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef __FENNIX_KERNEL_GDT_H__
#define __FENNIX_KERNEL_GDT_H__
@ -68,7 +51,7 @@ namespace GlobalDescriptorTable
* @details This bit must be 1 for all valid descriptors.
*/
uint8_t P : 1;
} __packed;
} __attribute__((packed));
uint8_t Raw;
};
@ -85,7 +68,7 @@ namespace GlobalDescriptorTable
* @details If the long mode bit is set, the segment is in 64-bit long mode.
*/
uint8_t L : 1;
} __packed;
} __attribute__((packed));
uint8_t Raw;
};
@ -101,17 +84,17 @@ namespace GlobalDescriptorTable
/* HIGH */
uint32_t BaseUpper;
uint32_t Reserved;
} __packed TaskStateSegmentEntry;
} __attribute__((packed)) TaskStateSegmentEntry;
typedef struct _TaskStateSegment
{
uint32_t Reserved0 __aligned(16);
uint32_t Reserved0 __attribute__((aligned(16)));
uint64_t StackPointer[3];
uint64_t Reserved1;
uint64_t InterruptStackTable[7];
uint16_t Reserved2;
uint16_t IOMapBaseAddressOffset;
} __packed TaskStateSegment;
} __attribute__((packed)) TaskStateSegment;
typedef struct _GlobalDescriptorTableEntry
{
@ -127,7 +110,7 @@ namespace GlobalDescriptorTable
GlobalDescriptorTableFlags Flags;
/** @brief High Base */
uint8_t BaseHigh;
} __packed GlobalDescriptorTableEntry;
} __attribute__((packed)) GlobalDescriptorTableEntry;
typedef struct _GlobalDescriptorTableEntries
{
@ -137,7 +120,7 @@ namespace GlobalDescriptorTable
GlobalDescriptorTableEntry UserData;
GlobalDescriptorTableEntry UserCode;
TaskStateSegmentEntry TaskStateSegment;
} __packed GlobalDescriptorTableEntries;
} __attribute__((packed)) GlobalDescriptorTableEntries;
typedef struct _GlobalDescriptorTableDescriptor
{
@ -145,7 +128,7 @@ namespace GlobalDescriptorTable
uint16_t Length;
/** @brief GDT entries address */
GlobalDescriptorTableEntries *Entries;
} __packed GlobalDescriptorTableDescriptor;
} __attribute__((packed)) GlobalDescriptorTableDescriptor;
extern void *CPUStackPointer[];
extern TaskStateSegment tss[];

View File

@ -0,0 +1,11 @@
#ifndef __FENNIX_KERNEL_IDT_H__
#define __FENNIX_KERNEL_IDT_H__
#include <types.h>
namespace InterruptDescriptorTable
{
void Init(int Core);
}
#endif // !__FENNIX_KERNEL_IDT_H__

View File

@ -0,0 +1,59 @@
OUTPUT_FORMAT(elf32-i386)
OUTPUT_ARCH(i386)
ENTRY(MB2_start)
SECTIONS
{
. = 0xC0100000;
_kernel_start = .;
.text ALIGN(4096) : AT(ADDR(.text) - 0xC0000000)
{
*(.multiboot2)
*(.text .text.*)
}
_kernel_text_end = .;
.data ALIGN (4096) : AT(ADDR(.data) - 0xC0000000)
{
*(.data .data.*)
}
_kernel_data_end = .;
.rodata ALIGN (4096) : AT(ADDR(.rodata) - 0xC0000000)
{
*(.rodata .rodata.*)
}
_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)
{
*(COMMON)
*(.bss .bss.*)
}
_kernel_end = .;
/DISCARD/ :
{
*(.comment*)
*(.note*)
}
}

View File

@ -0,0 +1,15 @@
#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;
}

View File

@ -1,20 +1,3 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include <cpu.hpp>
#include <memory.hpp>
@ -30,21 +13,19 @@ namespace CPU
char *Vendor()
{
static char Vendor[13] = {0};
if (Vendor[0] != 0)
return Vendor;
static char Vendor[13];
#if defined(a64)
uint32_t eax, ebx, ecx, edx;
x64::cpuid(0x0, &eax, &ebx, &ecx, &edx);
memcpy(Vendor + 0, &ebx, 4);
memcpy(Vendor + 4, &edx, 4);
memcpy(Vendor + 8, &ecx, 4);
memcpy_unsafe(Vendor + 0, &ebx, 4);
memcpy_unsafe(Vendor + 4, &edx, 4);
memcpy_unsafe(Vendor + 8, &ecx, 4);
#elif defined(a32)
uint32_t eax, ebx, ecx, edx;
x32::cpuid(0x0, &eax, &ebx, &ecx, &edx);
memcpy(Vendor + 0, &ebx, 4);
memcpy(Vendor + 4, &edx, 4);
memcpy(Vendor + 8, &ecx, 4);
memcpy_unsafe(Vendor + 0, &ebx, 4);
memcpy_unsafe(Vendor + 4, &edx, 4);
memcpy_unsafe(Vendor + 8, &ecx, 4);
#elif defined(aa64)
asmv("mrs %0, MIDR_EL1"
: "=r"(Vendor[0]));
@ -54,43 +35,41 @@ namespace CPU
char *Name()
{
static char Name[49] = {0};
if (Name[0] != 0)
return Name;
static char Name[49];
#if defined(a64)
uint32_t eax, ebx, ecx, edx;
x64::cpuid(0x80000002, &eax, &ebx, &ecx, &edx);
memcpy(Name + 0, &eax, 4);
memcpy(Name + 4, &ebx, 4);
memcpy(Name + 8, &ecx, 4);
memcpy(Name + 12, &edx, 4);
memcpy_unsafe(Name + 0, &eax, 4);
memcpy_unsafe(Name + 4, &ebx, 4);
memcpy_unsafe(Name + 8, &ecx, 4);
memcpy_unsafe(Name + 12, &edx, 4);
x64::cpuid(0x80000003, &eax, &ebx, &ecx, &edx);
memcpy(Name + 16, &eax, 4);
memcpy(Name + 20, &ebx, 4);
memcpy(Name + 24, &ecx, 4);
memcpy(Name + 28, &edx, 4);
memcpy_unsafe(Name + 16, &eax, 4);
memcpy_unsafe(Name + 20, &ebx, 4);
memcpy_unsafe(Name + 24, &ecx, 4);
memcpy_unsafe(Name + 28, &edx, 4);
x64::cpuid(0x80000004, &eax, &ebx, &ecx, &edx);
memcpy(Name + 32, &eax, 4);
memcpy(Name + 36, &ebx, 4);
memcpy(Name + 40, &ecx, 4);
memcpy(Name + 44, &edx, 4);
memcpy_unsafe(Name + 32, &eax, 4);
memcpy_unsafe(Name + 36, &ebx, 4);
memcpy_unsafe(Name + 40, &ecx, 4);
memcpy_unsafe(Name + 44, &edx, 4);
#elif defined(a32)
uint32_t eax, ebx, ecx, edx;
x32::cpuid(0x80000002, &eax, &ebx, &ecx, &edx);
memcpy(Name + 0, &eax, 4);
memcpy(Name + 4, &ebx, 4);
memcpy(Name + 8, &ecx, 4);
memcpy(Name + 12, &edx, 4);
memcpy_unsafe(Name + 0, &eax, 4);
memcpy_unsafe(Name + 4, &ebx, 4);
memcpy_unsafe(Name + 8, &ecx, 4);
memcpy_unsafe(Name + 12, &edx, 4);
x32::cpuid(0x80000003, &eax, &ebx, &ecx, &edx);
memcpy(Name + 16, &eax, 4);
memcpy(Name + 20, &ebx, 4);
memcpy(Name + 24, &ecx, 4);
memcpy(Name + 28, &edx, 4);
memcpy_unsafe(Name + 16, &eax, 4);
memcpy_unsafe(Name + 20, &ebx, 4);
memcpy_unsafe(Name + 24, &ecx, 4);
memcpy_unsafe(Name + 28, &edx, 4);
x32::cpuid(0x80000004, &eax, &ebx, &ecx, &edx);
memcpy(Name + 32, &eax, 4);
memcpy(Name + 36, &ebx, 4);
memcpy(Name + 40, &ecx, 4);
memcpy(Name + 44, &edx, 4);
memcpy_unsafe(Name + 32, &eax, 4);
memcpy_unsafe(Name + 36, &ebx, 4);
memcpy_unsafe(Name + 40, &ecx, 4);
memcpy_unsafe(Name + 44, &edx, 4);
#elif defined(aa64)
asmv("mrs %0, MIDR_EL1"
: "=r"(Name[0]));
@ -100,21 +79,19 @@ namespace CPU
char *Hypervisor()
{
static char Hypervisor[13] = {0};
if (Hypervisor[0] != 0)
return Hypervisor;
static char Hypervisor[13];
#if defined(a64)
uint32_t eax, ebx, ecx, edx;
x64::cpuid(0x40000000, &eax, &ebx, &ecx, &edx);
memcpy(Hypervisor + 0, &ebx, 4);
memcpy(Hypervisor + 4, &ecx, 4);
memcpy(Hypervisor + 8, &edx, 4);
memcpy_unsafe(Hypervisor + 0, &ebx, 4);
memcpy_unsafe(Hypervisor + 4, &ecx, 4);
memcpy_unsafe(Hypervisor + 8, &edx, 4);
#elif defined(a32)
uint32_t eax, ebx, ecx, edx;
x64::cpuid(0x40000000, &eax, &ebx, &ecx, &edx);
memcpy(Hypervisor + 0, &ebx, 4);
memcpy(Hypervisor + 4, &ecx, 4);
memcpy(Hypervisor + 8, &edx, 4);
memcpy_unsafe(Hypervisor + 0, &ebx, 4);
memcpy_unsafe(Hypervisor + 4, &ecx, 4);
memcpy_unsafe(Hypervisor + 8, &edx, 4);
#elif defined(aa64)
asmv("mrs %0, MIDR_EL1"
: "=r"(Hypervisor[0]));
@ -147,7 +124,7 @@ namespace CPU
}
case Enable:
{
#if defined(a86)
#if defined(a64) || defined(a32)
asmv("sti");
#elif defined(aa64)
asmv("msr daifclr, #2");
@ -156,15 +133,13 @@ namespace CPU
}
case Disable:
{
#if defined(a86)
#if defined(a64) || defined(a32)
asmv("cli");
#elif defined(aa64)
asmv("msr daifset, #2");
#endif
return true;
}
default:
break;
}
return false;
}
@ -201,41 +176,46 @@ namespace CPU
void InitializeFeatures(long Core)
{
#if defined(a64)
bool PGESupport = false;
bool SSESupport = false;
bool UMIPSupport = false;
bool SMEPSupport = false;
bool SMAPSupport = false;
#if defined(a64)
static int BSP = 0;
x64::CR0 cr0 = x64::readcr0();
x64::CR4 cr4 = x64::readcr4();
if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_AMD) == 0)
{
CPU::x86::AMD::CPUID0x00000001 cpuid1;
CPU::x86::AMD::CPUID0x00000007 cpuid7;
cpuid1.Get();
cpuid7.Get();
PGESupport = cpuid1.EDX.PGE;
SSESupport = cpuid1.EDX.SSE;
SMEPSupport = cpuid7.EBX.SMEP;
SMAPSupport = cpuid7.EBX.SMAP;
UMIPSupport = cpuid7.ECX.UMIP;
#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)
{
CPU::x86::Intel::CPUID0x00000001 cpuid1;
CPU::x86::Intel::CPUID0x00000007_0 cpuid7_0;
cpuid1.Get();
cpuid7_0.Get();
PGESupport = cpuid1.EDX.PGE;
SSESupport = cpuid1.EDX.SSE;
SMEPSupport = cpuid7_0.EBX.SMEP;
SMAPSupport = cpuid7_0.EBX.SMAP;
UMIPSupport = cpuid7_0.ECX.UMIP;
#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)
@ -268,7 +248,7 @@ namespace CPU
cr4.OSXMMEXCPT = 1;
CPUData *CoreData = GetCPU(Core);
CoreData->Data.FPU = (CPU::x64::FXState *)KernelAllocator.RequestPages(TO_PAGES(sizeof(CPU::x64::FXState) + 1));
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;
@ -278,40 +258,47 @@ namespace CPU
SSEEnableAfter = true;
}
if (!BSP)
KPrint("Enabling CPU cache.");
cr0.NW = 0;
cr0.CD = 0;
cr0.WP = 1;
x64::writecr0(cr0);
// FIXME: I don't think this is reporting correctly. This has to be fixed asap.
debug("Enabling UMIP, SMEP & SMAP support...");
uint32_t eax, ebx, ecx, edx;
x64::cpuid(0x1, &eax, &ebx, &ecx, &edx);
if (edx & (1 << 2)) // https://en.wikipedia.org/wiki/Control_register
{
if (!BSP)
KPrint("UMIP is supported.");
debug("UMIP is supported.");
// cr4.UMIP = 1;
}
if (edx & (1 << 7)) // https://en.wikipedia.org/wiki/Control_register#SMEP
// https://web.archive.org/web/20160312223150/http://ncsi.com/nsatc11/presentations/wednesday/emerging_technologies/fischer.pdf
{
if (!BSP)
KPrint("SMEP is supported.");
debug("SMEP is supported.");
// cr4.SMEP = 1;
}
if (edx & (1 << 20)) // https://en.wikipedia.org/wiki/Supervisor_Mode_Access_Prevention
{
if (!BSP)
KPrint("SMAP is supported.");
debug("SMAP is supported.");
// cr4.SMAP = 1;
}
if (strcmp(Hypervisor(), x86_CPUID_VENDOR_VIRTUALBOX) != 0 &&
strcmp(Hypervisor(), x86_CPUID_VENDOR_TCG) != 0)
{
// FIXME: I don't think this is reporting correctly. This has to be fixed asap.
debug("Enabling UMIP, SMEP & SMAP support...");
if (UMIPSupport)
{
if (!BSP)
KPrint("UMIP is supported.");
debug("UMIP is supported.");
// cr4.UMIP = 1;
}
if (SMEPSupport)
{
if (!BSP)
KPrint("SMEP is supported.");
debug("SMEP is supported.");
// cr4.SMEP = 1;
}
if (SMAPSupport)
{
if (!BSP)
KPrint("SMAP is supported.");
debug("SMAP is supported.");
// cr4.SMAP = 1;
}
debug("Writing CR4...");
x64::writecr4(cr4);
debug("Wrote CR4.");
}
else
{
@ -323,11 +310,6 @@ namespace CPU
KPrint("QEMU (TCG) detected. Not using UMIP, SMEP & SMAP");
}
}
debug("Writing CR4...");
x64::writecr4(cr4);
debug("Wrote CR4.");
debug("Enabling PAT support...");
x64::wrmsr(x64::MSR_CR_PAT, 0x6 | (0x0 << 8) | (0x1 << 16));
if (!BSP++)
@ -356,7 +338,7 @@ namespace CPU
return Counter;
}
uint64_t CheckSIMD()
x86SIMDType CheckSIMD()
{
#if defined(a32)
return SIMD_NONE; /* TODO: Support x86 SIMD on x32 */
@ -365,42 +347,44 @@ namespace CPU
if (unlikely(!SSEEnabled))
return SIMD_NONE;
// return SIMD_SSE;
#if defined(a86)
static uint64_t SIMDType = SIMD_NONE;
static x86SIMDType SIMDType = SIMD_NONE;
if (likely(SIMDType != SIMD_NONE))
return SIMDType;
if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_AMD) == 0)
{
CPU::x86::AMD::CPUID0x00000001 cpuid;
#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"(cpuid.EAX.raw), "=b"(cpuid.EBX.raw), "=c"(cpuid.ECX.raw), "=d"(cpuid.EDX.raw)
: "=a"(cpuid1amd.EAX.raw), "=b"(cpuid1amd.EBX.raw), "=c"(cpuid1amd.ECX.raw), "=d"(cpuid1amd.EDX.raw)
: "a"(0x1));
if (cpuid.ECX.SSE42)
SIMDType |= SIMD_SSE42;
else if (cpuid.ECX.SSE41)
SIMDType |= SIMD_SSE41;
else if (cpuid.ECX.SSE3)
SIMDType |= SIMD_SSE3;
else if (cpuid.EDX.SSE2)
SIMDType |= SIMD_SSE2;
else if (cpuid.EDX.SSE)
SIMDType |= SIMD_SSE;
#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 (cpuid.ECX.SSE42)
if (cpuid1amd.ECX.SSE4_2)
debug("SSE4.2 is supported.");
if (cpuid.ECX.SSE41)
if (cpuid1amd.ECX.SSE4_1)
debug("SSE4.1 is supported.");
if (cpuid.ECX.SSE3)
if (cpuid1amd.ECX.SSE3)
debug("SSE3 is supported.");
if (cpuid.EDX.SSE2)
if (cpuid1amd.EDX.SSE2)
debug("SSE2 is supported.");
if (cpuid.EDX.SSE)
if (cpuid1amd.EDX.SSE)
debug("SSE is supported.");
#endif
@ -408,39 +392,43 @@ namespace CPU
}
else if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_INTEL) == 0)
{
CPU::x86::Intel::CPUID0x00000001 cpuid;
#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"(cpuid.EAX.raw), "=b"(cpuid.EBX.raw), "=c"(cpuid.ECX.raw), "=d"(cpuid.EDX.raw)
: "=a"(cpuid1intel.EAX.raw), "=b"(cpuid1intel.EBX.raw), "=c"(cpuid1intel.ECX.raw), "=d"(cpuid1intel.EDX.raw)
: "a"(0x1));
if (cpuid.ECX.SSE4_2)
SIMDType |= SIMD_SSE42;
else if (cpuid.ECX.SSE4_1)
SIMDType |= SIMD_SSE41;
else if (cpuid.ECX.SSE3)
SIMDType |= SIMD_SSE3;
else if (cpuid.EDX.SSE2)
SIMDType |= SIMD_SSE2;
else if (cpuid.EDX.SSE)
SIMDType |= SIMD_SSE;
#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 (cpuid.ECX.SSE4_2)
if (cpuid1intel.ECX.SSE4_2)
debug("SSE4.2 is supported.");
if (cpuid.ECX.SSE4_1)
if (cpuid1intel.ECX.SSE4_1)
debug("SSE4.1 is supported.");
if (cpuid.ECX.SSE3)
if (cpuid1intel.ECX.SSE3)
debug("SSE3 is supported.");
if (cpuid.EDX.SSE2)
if (cpuid1intel.EDX.SSE2)
debug("SSE2 is supported.");
if (cpuid.EDX.SSE)
if (cpuid1intel.EDX.SSE)
debug("SSE is supported.");
#endif
return SIMDType;
}
debug("No SIMD support.");
#endif // a64 || a32
return SIMD_NONE;
}
@ -449,44 +437,53 @@ namespace CPU
if (unlikely(!SSEEnabled))
return false;
#if defined(a86)
if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_AMD) == 0)
{
CPU::x86::AMD::CPUID0x00000001 cpuid;
#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"(cpuid.EAX.raw), "=b"(cpuid.EBX.raw), "=c"(cpuid.ECX.raw), "=d"(cpuid.EDX.raw)
: "=a"(cpuid1amd.EAX.raw), "=b"(cpuid1amd.EBX.raw), "=c"(cpuid1amd.ECX.raw), "=d"(cpuid1amd.EDX.raw)
: "a"(0x1));
#endif
if (Type == SIMD_SSE42)
return cpuid.ECX.SSE42;
return cpuid1amd.ECX.SSE4_2;
else if (Type == SIMD_SSE41)
return cpuid.ECX.SSE41;
return cpuid1amd.ECX.SSE4_1;
else if (Type == SIMD_SSE3)
return cpuid.ECX.SSE3;
return cpuid1amd.ECX.SSE3;
else if (Type == SIMD_SSE2)
return cpuid.EDX.SSE2;
return cpuid1amd.EDX.SSE2;
else if (Type == SIMD_SSE)
return cpuid.EDX.SSE;
return cpuid1amd.EDX.SSE;
}
else if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_INTEL) == 0)
{
CPU::x86::Intel::CPUID0x00000001 cpuid;
#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"(cpuid.EAX.raw), "=b"(cpuid.EBX.raw), "=c"(cpuid.ECX.raw), "=d"(cpuid.EDX.raw)
: "=a"(cpuid1intel.EAX.raw), "=b"(cpuid1intel.EBX.raw), "=c"(cpuid1intel.ECX.raw), "=d"(cpuid1intel.EDX.raw)
: "a"(0x1));
#endif
if (Type == SIMD_SSE42)
return cpuid.ECX.SSE4_2;
return cpuid1intel.ECX.SSE4_2;
else if (Type == SIMD_SSE41)
return cpuid.ECX.SSE4_1;
return cpuid1intel.ECX.SSE4_1;
else if (Type == SIMD_SSE3)
return cpuid.ECX.SSE3;
return cpuid1intel.ECX.SSE3;
else if (Type == SIMD_SSE2)
return cpuid.EDX.SSE2;
return cpuid1intel.EDX.SSE2;
else if (Type == SIMD_SSE)
return cpuid.EDX.SSE;
return cpuid1intel.EDX.SSE;
}
#endif // a64 || a32
return false;
}
}

View File

@ -1,20 +1,3 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "../crashhandler.hpp"
#include "chfcts.hpp"
@ -195,10 +178,7 @@ SafeFunction void PageFaultExceptionHandler(CHArchTrapFrame *Frame)
#elif defined(a32)
Memory::Virtual vma = Memory::Virtual(((Memory::PageTable4 *)CPU::x32::readcr3().raw));
#elif defined(aa64)
Memory::Virtual vma = Memory::Virtual();
#warning "TODO: aa64"
#endif
bool PageAvailable = vma.Check((void *)CheckPageFaultAddress);
debug("Page available (Check(...)): %s. %s",
PageAvailable ? "Yes" : "No",
@ -243,8 +223,6 @@ SafeFunction void PageFaultExceptionHandler(CHArchTrapFrame *Frame)
#elif defined(a32)
Memory::PageMapLevel4 PML4 = ((Memory::PageTable4 *)CPU::x32::readcr3().raw)->Entries[Index.PMLIndex];
#elif defined(aa64)
Memory::PageMapLevel4 PML4 = {.raw = 0};
#warning "TODO: aa64"
#endif
Memory::PageDirectoryPointerTableEntryPtr *PDPTE = (Memory::PageDirectoryPointerTableEntryPtr *)((uintptr_t)PML4.GetAddress() << 12);

View File

@ -1,20 +1,3 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "../crashhandler.hpp"
#include "chfcts.hpp"
@ -34,8 +17,8 @@
#include "../../Architecture/amd64/cpu/gdt.hpp"
#include "../Architecture/amd64/cpu/apic.hpp"
#elif defined(a32)
#include "../../Architecture/i386/cpu/gdt.hpp"
#include "../Architecture/i386/cpu/apic.hpp"
#include "../../Architecture/i686/cpu/gdt.hpp"
#include "../Architecture/i686/cpu/apic.hpp"
#elif defined(aa64)
#endif
@ -375,10 +358,8 @@ namespace CrashHandler
int tmpidx = SBIdx;
SBIdx = atoi(arg);
Display->SetBuffer(SBIdx);
#if defined(a86)
for (int i = 0; i < 5000000; i++)
inb(0x80);
#endif // a64 || a32
SBIdx = tmpidx;
Display->SetBuffer(SBIdx);
}
@ -410,15 +391,12 @@ namespace CrashHandler
#elif defined(a32)
if ((uintptr_t)EHIntFrames[i] >= 0xC0000000 && (uintptr_t)EHIntFrames[i] <= (uintptr_t)&_kernel_end)
#elif defined(aa64)
if ((uintptr_t)EHIntFrames[i] >= 0xFFFFFFFF80000000 && (uintptr_t)EHIntFrames[i] <= (uintptr_t)&_kernel_end)
#endif
EHPrint("\e25CCC9%s", KernelSymbolTable->GetSymbolFromAddress((uintptr_t)EHIntFrames[i]));
else
EHPrint("\eFF4CA9Outside Kernel");
#if defined(a86)
for (int i = 0; i < 20000; i++)
inb(0x80);
#endif // a64 || a32
Display->SetBuffer(SBIdx);
}
}
@ -530,7 +508,7 @@ namespace CrashHandler
EHPrint("\e00FF000");
if (i % 128 == 127)
{
short Percentage = s_cst(short, (i * 100) / bm.Size);
short Percentage = (i * 100) / bm.Size;
EHPrint("\n\eFAFAFA[%03ld%%] %08ld: ", Percentage, i);
Display->SetBuffer(SBIdx);
}
@ -546,8 +524,8 @@ namespace CrashHandler
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 = s_cst(int, (Used * 100) / Total);
int ReservedProgress = s_cst(int, (Reserved * 100) / Total);
int Progress = (Used * 100) / Total;
int ReservedProgress = (Reserved * 100) / Total;
EHPrint("\e22AA44%3d%% \eCCCCCC[", Progress);
for (int i = 0; i < Progress; i++)
EHPrint("\eFF0000|");
@ -624,7 +602,6 @@ namespace CrashHandler
}
else
{
#if defined(a86)
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]);
@ -643,9 +620,6 @@ namespace CrashHandler
EHPrint("\eFAFAFAReserved 0: \eAABB22%#lx\n", tss.Reserved0);
EHPrint("\eFAFAFAReserved 1: \eAABB22%#lx\n", tss.Reserved1);
EHPrint("\eFAFAFAReserved 2: \eAABB22%#lx\n", tss.Reserved2);
#elif defined(aa64)
EHPrint("\eFF0000AArch64 does not have TSS\n");
#endif
}
}
else if (strncmp(Input, "dump", 4) == 0)
@ -721,7 +695,7 @@ namespace CrashHandler
if (unlikely(i % 0x1000 == 0))
{
int NewProgress = (int)((i * 100) / ProgressLength);
int NewProgress = (i * 100) / ProgressLength;
if (unlikely(NewProgress != Progress))
{
Progress = NewProgress;
@ -779,7 +753,7 @@ namespace CrashHandler
SafeFunction void StopAllCores()
{
#if defined(a86)
#if defined(a64) || defined(a32)
/* FIXME: Can't send IPIs to other cores
* because it causes another exception on
* the other cores.
@ -818,7 +792,7 @@ namespace CrashHandler
SBIdx = 255;
CHArchTrapFrame *Frame = (CHArchTrapFrame *)Data;
#if defined(a64)
debug("-----------------------------------------------------------------------------------");
error("An exception occurred!");
error("Exception: %#llx", Frame->InterruptNumber);
for (size_t i = 0; i < INT_FRAMES_MAX; i++)
EHIntFrames[i] = Interrupts::InterruptFrames[i];
@ -826,29 +800,7 @@ namespace CrashHandler
if (Frame->cs != GDT_USER_CODE && Frame->cs != GDT_USER_DATA)
{
if (PageFaultAddress)
{
debug("Exception in kernel mode (ip: %#lx cr2: %#lx (%s))",
Frame->rip, PageFaultAddress, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress(Frame->rip) : "No symbol");
}
else
{
debug("Exception in kernel mode (ip: %#lx (%s))",
Frame->rip, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress(Frame->rip) : "No symbol");
}
CPUData *data = GetCurrentCPU();
if (data)
{
if (data->CurrentThread)
{
if (!data->CurrentThread->Security.IsCritical)
{
fixme("Exception in non-critical thread (kernel mode)");
}
}
}
debug("Exception in kernel mode (ip: %#lx (%s), cr2: %#lx)", Frame->rip, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress(Frame->rip) : "No symbol", PageFaultAddress);
if (TaskManager)
TaskManager->Panic();
ForceUnlock = true;
@ -857,16 +809,7 @@ namespace CrashHandler
}
else
{
if (PageFaultAddress)
{
debug("Exception in user mode (ip: %#lx cr2: %#lx (%s))",
Frame->rip, PageFaultAddress, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress(Frame->rip) : "No symbol");
}
else
{
debug("Exception in user mode (ip: %#lx (%s))",
Frame->rip, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress(Frame->rip) : "No symbol");
}
debug("Exception in user mode (ip: %#lx (%s), cr2: %#lx)", Frame->rip, KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress(Frame->rip) : "No symbol", PageFaultAddress);
CPUData *data = GetCurrentCPU();
if (!data)
{
@ -962,7 +905,7 @@ namespace CrashHandler
ExceptionOccurred = true;
if (DriverManager)
DriverManager->Panic();
DriverManager->UnloadAllDrivers();
debug("Reading control registers...");
crashdata.Frame = Frame;
@ -1018,8 +961,8 @@ namespace CrashHandler
if (TaskManager && cpudata != nullptr)
{
crashdata.Process = cpudata->CurrentProcess.load();
crashdata.Thread = cpudata->CurrentThread.load();
crashdata.Process = cpudata->CurrentProcess.Load();
crashdata.Thread = cpudata->CurrentThread.Load();
error("Current Process: %s(%ld)",
cpudata->CurrentProcess->Name,
@ -1086,9 +1029,7 @@ namespace CrashHandler
goto CrashEnd;
#elif defined(a32)
goto CrashEnd;
#elif defined(aa64)
goto CrashEnd;
#endif
CrashEnd:

View File

@ -1,20 +1,3 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "../crashhandler.hpp"
#include "chfcts.hpp"
@ -94,9 +77,8 @@ static inline int GetLetterFromScanCode(uint8_t ScanCode)
namespace CrashHandler
{
CrashKeyboardDriver::CrashKeyboardDriver() : Interrupts::Handler(1) /* IRQ1 */
CrashKeyboardDriver::CrashKeyboardDriver() : Interrupts::Handler(CPU::x86::IRQ1)
{
#if defined(a86)
while (inb(0x64) & 0x1)
inb(0x60);
@ -109,8 +91,6 @@ namespace CrashHandler
outb(0x21, 0xFD);
outb(0xA1, 0xFF);
#endif // defined(a86)
CPU::Interrupts(CPU::Enable); // Just to be sure.
}
@ -127,10 +107,9 @@ namespace CrashHandler
#elif defined(a32)
SafeFunction void CrashKeyboardDriver::OnInterruptReceived(CPU::x32::TrapFrame *Frame)
#elif defined(aa64)
SafeFunction void CrashKeyboardDriver::OnInterruptReceived(CPU::aarch64::TrapFrame *Frame)
SafeFunction void CrashKeyboardDriver::OnInterruptReceived(void *Frame)
#endif
{
#if defined(a86)
UNUSED(Frame);
uint8_t scanCode = inb(0x60);
if (scanCode == KEY_D_TAB ||
@ -147,9 +126,6 @@ namespace CrashHandler
case KEY_D_RIGHT:
case KEY_D_DOWN:
ArrowInput(scanCode);
break;
default:
break;
}
int key = GetLetterFromScanCode(scanCode);
@ -172,23 +148,18 @@ namespace CrashHandler
}
else
{
append(UserInputBuffer, s_cst(char, key));
Display->Print((char)key, SBIdx);
append(UserInputBuffer, key);
Display->Print(key, SBIdx);
BackSpaceLimit++;
}
Display->SetBuffer(SBIdx); // Update as we type.
}
#endif // a64 || a32
}
SafeFunction void HookKeyboard()
{
CrashKeyboardDriver kbd; // We don't want to allocate memory.
#if defined(a86)
asmv("KeyboardHookLoop: nop; jmp KeyboardHookLoop;");
#elif defined(aa64)
asmv("KeyboardHookLoop: nop; b KeyboardHookLoop;");
#endif
// CPU::Halt(true); // This is an infinite loop.
}
}

View File

@ -1,20 +1,3 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "../crashhandler.hpp"
#include "chfcts.hpp"
@ -40,11 +23,29 @@ namespace CrashHandler
uintptr_t rip;
};
SafeFunction void TraceFrames(CRData data, int Count, SymbolResolver::Symbols *SymHandle, bool Kernel)
SafeFunction void TraceFrames(CHArchTrapFrame *Frame, int Count, SymbolResolver::Symbols *SymHandle, bool Kernel)
{
if (!Memory::Virtual().Check(data.Frame))
if (!Memory::Virtual().Check(Frame))
{
EHPrint("Invalid frame pointer: %p\n", data.Frame);
EHPrint("Invalid frame pointer: %p\n", Frame);
return;
}
#if defined(a64)
struct StackFrame *frames = (struct StackFrame *)Frame->rbp; // (struct StackFrame *)__builtin_frame_address(0);
if (!Memory::Virtual().Check((void *)Frame->rbp))
#elif defined(a32)
struct StackFrame *frames = (struct StackFrame *)Frame->ebp; // (struct StackFrame *)__builtin_frame_address(0);
if (!Memory::Virtual().Check((void *)Frame->ebp))
#elif defined(aa64)
#endif
{
#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;
}
@ -54,49 +55,21 @@ namespace CrashHandler
return;
}
bool TriedRetryBP = false;
struct StackFrame *frames = nullptr;
RetryBP:
#if defined(a64)
if (TriedRetryBP == false)
frames = (struct StackFrame *)data.Frame->rbp;
#elif defined(a32)
if (TriedRetryBP == false)
frames = (struct StackFrame *)data.Frame->ebp;
#elif defined(aa64)
#endif
if (!Memory::Virtual().Check((void *)frames))
{
if (TriedRetryBP == false)
{
frames = (struct StackFrame *)Memory::Virtual(data.Process->PageTable).GetPhysical((void *)frames);
TriedRetryBP = true;
goto RetryBP;
}
#if defined(a64)
EHPrint("Invalid rbp pointer: %p\n", data.Frame->rbp);
#elif defined(a32)
EHPrint("Invalid ebp pointer: %p\n", data.Frame->ebp);
#elif defined(aa64)
#endif
return;
}
debug("\nStack tracing... %p %d %p %d", data.Frame, Count, frames, Kernel);
debug("\nStack tracing... %p %d %p %d", Frame, Count, frames, Kernel);
EHPrint("\e7981FC\nStack Trace:\n");
if (!frames || !frames->rip || !frames->rbp)
{
#if defined(a64)
EHPrint("\e2565CC%p", (void *)data.Frame->rip);
EHPrint("\e2565CC%p", (void *)Frame->rip);
#elif defined(a32)
EHPrint("\e2565CC%p", (void *)data.Frame->eip);
EHPrint("\e2565CC%p", (void *)Frame->eip);
#elif defined(aa64)
#endif
EHPrint("\e7925CC-");
#if defined(a64)
EHPrint("\eAA25CC%s", SymHandle->GetSymbolFromAddress(data.Frame->rip));
EHPrint("\eAA25CC%s", SymHandle->GetSymbolFromAddress(Frame->rip));
#elif defined(a32)
EHPrint("\eAA25CC%s", SymHandle->GetSymbolFromAddress(data.Frame->eip));
EHPrint("\eAA25CC%s", SymHandle->GetSymbolFromAddress(Frame->eip));
#elif defined(aa64)
#endif
EHPrint("\e7981FC <- Exception");
@ -105,17 +78,17 @@ namespace CrashHandler
else
{
#if defined(a64)
EHPrint("\e2565CC%p", (void *)data.Frame->rip);
EHPrint("\e2565CC%p", (void *)Frame->rip);
EHPrint("\e7925CC-");
if ((data.Frame->rip >= 0xFFFFFFFF80000000 && data.Frame->rip <= (uintptr_t)&_kernel_end) || !Kernel)
EHPrint("\eAA25CC%s", SymHandle->GetSymbolFromAddress(data.Frame->rip));
if ((Frame->rip >= 0xFFFFFFFF80000000 && Frame->rip <= (uintptr_t)&_kernel_end) || !Kernel)
EHPrint("\eAA25CC%s", SymHandle->GetSymbolFromAddress(Frame->rip));
else
EHPrint("Outside Kernel");
#elif defined(a32)
EHPrint("\e2565CC%p", (void *)data.Frame->eip);
EHPrint("\e2565CC%p", (void *)Frame->eip);
EHPrint("\e7925CC-");
if ((data.Frame->eip >= 0xC0000000 && data.Frame->eip <= (uintptr_t)&_kernel_end) || !Kernel)
EHPrint("\eAA25CC%s", SymHandle->GetSymbolFromAddress(data.Frame->eip));
if ((Frame->eip >= 0xC0000000 && Frame->eip <= (uintptr_t)&_kernel_end) || !Kernel)
EHPrint("\eAA25CC%s", SymHandle->GetSymbolFromAddress(Frame->eip));
else
EHPrint("Outside Kernel");
#elif defined(aa64)
@ -132,7 +105,6 @@ namespace CrashHandler
#elif defined(a32)
if ((frames->rip >= 0xC0000000 && frames->rip <= (uintptr_t)&_kernel_end) || !Kernel)
#elif defined(aa64)
if ((frames->rip >= 0xFFFFFFFF80000000 && frames->rip <= (uintptr_t)&_kernel_end) || !Kernel)
#endif
EHPrint("\e25CCC9%s", SymHandle->GetSymbolFromAddress(frames->rip));
else

View File

@ -1,20 +1,3 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "../../crashhandler.hpp"
#include "../chfcts.hpp"

View File

@ -1,20 +1,3 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "../../crashhandler.hpp"
#include "../chfcts.hpp"
@ -86,8 +69,6 @@ namespace CrashHandler
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)
#endif
#if defined(a86)
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);
@ -113,9 +94,10 @@ namespace CrashHandler
data.cr4.Reserved0, data.cr4.Reserved1, data.cr4.Reserved2);
#elif defined(a32)
data.cr4.Reserved0, data.cr4.Reserved1, 0);
#elif defined(aa64)
#endif
EHPrint("\e79FCF5CR8: TPL:%d\n", data.cr8.TPL);
#endif // a64 || a32
#if defined(a64)
EHPrint("\eFCFC02RFL: CF:%s PF:%s AF:%s ZF:%s\n SF:%s TF:%s IF:%s DF:%s\n OF:%s IOPL:%s NT:%s RF:%s\n VM:%s AC:%s VIF:%s VIP:%s\n ID:%s AlwaysOne:%d\n R0:%#x R1:%#x R2:%#x R3:%#x\n",
@ -136,7 +118,6 @@ namespace CrashHandler
#elif defined(aa64)
#endif
#if defined(a86)
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",
data.dr7.LocalDR0 ? "True " : "False", data.dr7.GlobalDR0 ? "True " : "False", data.dr7.LocalDR1 ? "True " : "False", data.dr7.GlobalDR1 ? "True " : "False",
data.dr7.LocalDR2 ? "True " : "False", data.dr7.GlobalDR2 ? "True " : "False", data.dr7.LocalDR3 ? "True " : "False", data.dr7.GlobalDR3 ? "True " : "False",
@ -148,7 +129,6 @@ namespace CrashHandler
data.efer.SCE ? "True " : "False", data.efer.LME ? "True " : "False", data.efer.LMA ? "True " : "False", data.efer.NXE ? "True " : "False",
data.efer.SVME ? "True " : "False", data.efer.LMSLE ? "True " : "False", data.efer.FFXSR ? "True " : "False", data.efer.TCE ? "True " : "False",
data.efer.Reserved0, data.efer.Reserved1, data.efer.Reserved2);
#endif
switch (data.Frame->InterruptNumber)
{

View File

@ -1,20 +1,3 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "../../crashhandler.hpp"
#include "../chfcts.hpp"
@ -158,13 +141,6 @@ namespace CrashHandler
EHPrint(" %ld\n", SelCode.Idx);
break;
}
default:
{
EHPrint(" ? \n");
EHPrint(" ? \n");
EHPrint(" %ld\n", SelCode.Idx);
break;
}
}
break;
}
@ -205,13 +181,6 @@ namespace CrashHandler
EHPrint(" %ld\n", SelCode.Idx);
break;
}
default:
{
EHPrint(" ? \n");
EHPrint(" ? \n");
EHPrint(" %ld\n", SelCode.Idx);
break;
}
}
break;
}
@ -251,13 +220,6 @@ namespace CrashHandler
EHPrint(" %ld\n", SelCode.Idx);
break;
}
default:
{
EHPrint(" ? \n");
EHPrint(" ? \n");
EHPrint(" %ld\n", SelCode.Idx);
break;
}
}
break;
}
@ -298,13 +260,6 @@ namespace CrashHandler
EHPrint(" %ld\n", SelCode.Idx);
break;
}
default:
{
EHPrint(" ? \n");
EHPrint(" ? \n");
EHPrint(" %ld\n", SelCode.Idx);
break;
}
}
break;
}

View File

@ -1,20 +1,3 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "../../crashhandler.hpp"
#include "../chfcts.hpp"
@ -38,7 +21,7 @@ namespace CrashHandler
SafeFunction void DisplayStackFrameScreen(CRData data)
{
EHPrint("\eFAFAFATracing 10 frames...");
TraceFrames(data, 10, KernelSymbolTable, true);
TraceFrames(data.Frame, 10, KernelSymbolTable, true);
if (data.Process)
{
EHPrint("\n\eFAFAFATracing 10 process frames...");
@ -46,7 +29,7 @@ namespace CrashHandler
if (!sh)
EHPrint("\n\eFF0000< No symbol table available. >\n");
else
TraceFrames(data, 10, sh, false);
TraceFrames(data.Frame, 10, sh, false);
}
EHPrint("\n\eFAFAFATracing interrupt frames...");
for (short i = 0; i < 8; i++)
@ -62,7 +45,6 @@ namespace CrashHandler
#elif defined(a32)
if ((uintptr_t)EHIntFrames[i] >= 0xC0000000 && (uintptr_t)EHIntFrames[i] <= (uintptr_t)&_kernel_end)
#elif defined(aa64)
if ((uintptr_t)EHIntFrames[i] >= 0xFFFFFFFF80000000 && (uintptr_t)EHIntFrames[i] <= (uintptr_t)&_kernel_end)
#endif
EHPrint("\e25CCC9%s", KernelSymbolTable->GetSymbolFromAddress((uintptr_t)EHIntFrames[i]));
else

View File

@ -1,20 +1,3 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "../../crashhandler.hpp"
#include "../chfcts.hpp"
@ -56,7 +39,7 @@ namespace CrashHandler
"Terminated", // Terminated
};
std::vector<Tasking::PCB *> Plist = TaskManager->GetProcessList();
Vector<Tasking::PCB *> Plist = TaskManager->GetProcessList();
if (TaskManager)
{

View File

@ -1,20 +1,3 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "../crashhandler.hpp"
#include "chfcts.hpp"
@ -98,8 +81,6 @@ SafeFunction void UserModeExceptionHandler(CHArchTrapFrame *Frame)
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)
#endif
#if defined(a86)
error("CR0=%#llx CR2=%#llx CR3=%#llx CR4=%#llx CR8=%#llx", cr0.raw, cr2.raw, cr3.raw, cr4.raw, cr8.raw);
error("CR0: PE:%s MP:%s EM:%s TS:%s ET:%s NE:%s WP:%s AM:%s NW:%s CD:%s PG:%s R0:%#x R1:%#x R2:%#x",
@ -113,7 +94,6 @@ SafeFunction void UserModeExceptionHandler(CHArchTrapFrame *Frame)
error("CR3: PWT:%s PCD:%s PDBR:%#llx",
cr3.PWT ? "True " : "False", cr3.PCD ? "True " : "False", cr3.PDBR);
#endif // defined(a86)
#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",
@ -124,7 +104,7 @@ SafeFunction void UserModeExceptionHandler(CHArchTrapFrame *Frame)
cr4.OSXSAVE ? "True " : "False", cr4.SMEP ? "True " : "False", cr4.SMAP ? "True " : "False", cr4.PKE ? "True " : "False",
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",
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",
@ -133,9 +113,7 @@ SafeFunction void UserModeExceptionHandler(CHArchTrapFrame *Frame)
cr4.Reserved0, cr4.Reserved1);
#endif
#if defined(a86)
error("CR8: TPL:%d", cr8.TPL);
#endif // defined(a86)
#if defined(a64)
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",
@ -156,12 +134,10 @@ SafeFunction void UserModeExceptionHandler(CHArchTrapFrame *Frame)
#elif defined(aa64)
#endif
#if defined(a86)
error("EFER: SCE:%s LME:%s LMA:%s NXE:%s SVME:%s LMSLE:%s FFXSR:%s TCE:%s R0:%#x R1:%#x R2:%#x",
efer.SCE ? "True " : "False", efer.LME ? "True " : "False", efer.LMA ? "True " : "False", efer.NXE ? "True " : "False",
efer.SVME ? "True " : "False", efer.LMSLE ? "True " : "False", efer.FFXSR ? "True " : "False", efer.TCE ? "True " : "False",
efer.Reserved0, efer.Reserved1, efer.Reserved2);
#endif // a64 || a32
}
switch (Frame->InterruptNumber)

View File

@ -1,20 +1,3 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef __FENNIX_KERNEL_CRASH_HANDLERS_FUNCTIONS_H__
#define __FENNIX_KERNEL_CRASH_HANDLERS_FUNCTIONS_H__
@ -68,15 +51,6 @@ struct CRData
};
#elif defined(aa64)
typedef struct CPU::aarch64::TrapFrame CHArchTrapFrame;
struct CRData
{
CHArchTrapFrame *Frame;
long ID;
Tasking::PCB *Process;
Tasking::TCB *Thread;
};
#endif
enum Keys
@ -275,14 +249,14 @@ namespace CrashHandler
#elif defined(a32)
void OnInterruptReceived(CPU::x32::TrapFrame *Frame);
#elif defined(aa64)
void OnInterruptReceived(CPU::aarch64::TrapFrame *Frame);
void OnInterruptReceived(void *Frame);
#endif
public:
CrashKeyboardDriver();
~CrashKeyboardDriver();
};
void TraceFrames(CRData data, int Count, SymbolResolver::Symbols *SymHandle, bool Kernel);
void TraceFrames(CHArchTrapFrame *Frame, int Count, SymbolResolver::Symbols *SymHandle, bool Kernel);
void ArrowInput(uint8_t key);
void UserInput(char *Input);

View File

@ -1,20 +1,3 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include <debug.h>
#include <uart.hpp>

View File

@ -1,20 +1,3 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include <disk.hpp>
#include <memory.hpp>
@ -28,76 +11,82 @@ namespace Disk
{
void Manager::FetchDisks(unsigned long DriverUID)
{
KernelCallback callback{};
callback.Reason = FetchReason;
DriverManager->IOCB(DriverUID, &callback);
this->AvailablePorts = callback.DiskCallback.Fetch.Ports;
this->BytesPerSector = callback.DiskCallback.Fetch.BytesPerSector;
KernelCallback *callback = (KernelCallback *)KernelAllocator.RequestPages(TO_PAGES(sizeof(KernelCallback)));
memset(callback, 0, sizeof(KernelCallback));
callback->Reason = FetchReason;
DriverManager->IOCB(DriverUID, (void *)callback);
this->AvailablePorts = callback->DiskCallback.Fetch.Ports;
this->BytesPerSector = callback->DiskCallback.Fetch.BytesPerSector;
debug("AvailablePorts:%ld BytesPerSector:%ld", this->AvailablePorts, this->BytesPerSector);
if (this->AvailablePorts <= 0)
{
KernelAllocator.FreePages((void *)callback, TO_PAGES(sizeof(KernelCallback)));
return;
}
uint8_t *RWBuffer = (uint8_t *)KernelAllocator.RequestPages(TO_PAGES(this->BytesPerSector + 1));
uint8_t *RWBuffer = (uint8_t *)KernelAllocator.RequestPages(TO_PAGES(this->BytesPerSector));
for (unsigned char ItrPort = 0; ItrPort < this->AvailablePorts; ItrPort++)
{
Drive drive{};
sprintf(drive.Name, "sd%ld-%d", DriverUID, this->AvailablePorts);
debug("Drive Name: %s", drive.Name);
Drive *drive = new Drive;
sprintf(drive->Name, "sd%ld-%d", DriverUID, this->AvailablePorts);
debug("Drive Name: %s", drive->Name);
// TODO: Implement disk type detection. Very useful in the future.
drive.MechanicalDisk = true;
drive->MechanicalDisk = true;
memset(RWBuffer, 0, this->BytesPerSector);
callback.Reason = ReceiveReason;
callback.DiskCallback.RW = {
memset(callback, 0, sizeof(KernelCallback));
callback->Reason = ReceiveReason;
callback->DiskCallback.RW = {
.Sector = 0,
.SectorCount = 2,
.Port = ItrPort,
.Buffer = RWBuffer,
.Write = false,
};
DriverManager->IOCB(DriverUID, &callback);
memcpy(&drive.Table, RWBuffer, sizeof(PartitionTable));
DriverManager->IOCB(DriverUID, (void *)callback);
memcpy(&drive->Table, RWBuffer, sizeof(PartitionTable));
/*
TODO: Add to devfs the disk
*/
if (drive.Table.GPT.Signature == GPT_MAGIC)
if (drive->Table.GPT.Signature == GPT_MAGIC)
{
drive.Style = GPT;
uint32_t Entries = 512 / drive.Table.GPT.EntrySize;
uint32_t Sectors = drive.Table.GPT.PartCount / Entries;
drive->Style = GPT;
uint32_t Entries = 512 / drive->Table.GPT.EntrySize;
uint32_t Sectors = drive->Table.GPT.PartCount / Entries;
for (uint32_t Block = 0; Block < Sectors; Block++)
{
memset(RWBuffer, 0, this->BytesPerSector);
callback.Reason = ReceiveReason;
callback.DiskCallback.RW = {
memset(callback, 0, sizeof(KernelCallback));
callback->Reason = ReceiveReason;
callback->DiskCallback.RW = {
.Sector = 2 + Block,
.SectorCount = 1,
.Port = ItrPort,
.Buffer = RWBuffer,
.Write = false,
};
DriverManager->IOCB(DriverUID, &callback);
DriverManager->IOCB(DriverUID, (void *)callback);
for (uint32_t e = 0; e < Entries; e++)
{
GUIDPartitionTablePartition GPTPartition = reinterpret_cast<GUIDPartitionTablePartition *>(RWBuffer)[e];
if (GPTPartition.TypeLow || GPTPartition.TypeHigh)
{
Partition partition{};
memcpy(partition.Label, GPTPartition.Label, sizeof(partition.Label));
partition.StartLBA = GPTPartition.StartLBA;
partition.EndLBA = GPTPartition.EndLBA;
partition.Sectors = partition.EndLBA - partition.StartLBA;
partition.Port = ItrPort;
partition.Flags = Present;
partition.Style = GPT;
Partition *partition = new Partition;
memcpy(partition->Label, GPTPartition.Label, sizeof(partition->Label));
partition->StartLBA = GPTPartition.StartLBA;
partition->EndLBA = GPTPartition.EndLBA;
partition->Sectors = partition->EndLBA - partition->StartLBA;
partition->Port = ItrPort;
partition->Flags = Present;
partition->Style = GPT;
if (GPTPartition.Attributes & 1)
partition.Flags |= EFISystemPartition;
partition.Index = drive.Partitions.size();
partition->Flags |= EFISystemPartition;
partition->Index = drive->Partitions.size();
// why there is NUL (\0) between every char?????
char PartName[72];
memcpy(PartName, GPTPartition.Label, 72);
@ -105,49 +94,49 @@ namespace Disk
if (PartName[i] == '\0')
PartName[i] = ' ';
PartName[71] = '\0';
trace("GPT partition \"%s\" found with %lld sectors", PartName, partition.Sectors);
drive.Partitions.push_back(partition);
trace("GPT partition \"%s\" found with %lld sectors", PartName, partition->Sectors);
drive->Partitions.push_back(partition);
// char *PartitionName = new char[64];
// sprintf(PartitionName, "sd%ldp%ld", drives.size() - 1, partition.Index);
char *PartitionName = new char[64];
sprintf(PartitionName, "sd%ldp%ld", drives.size() - 1, partition->Index);
/*
TODO: Add to devfs the disk
*/
// delete[] PartitionName;
delete[] PartitionName;
}
}
}
trace("%d GPT partitions found.", drive.Partitions.size());
trace("%d GPT partitions found.", drive->Partitions.size());
}
else if (drive.Table.MBR.Signature[0] == MBR_MAGIC0 && drive.Table.MBR.Signature[1] == MBR_MAGIC1)
else if (drive->Table.MBR.Signature[0] == MBR_MAGIC0 && drive->Table.MBR.Signature[1] == MBR_MAGIC1)
{
drive.Style = MBR;
drive->Style = MBR;
for (size_t p = 0; p < 4; p++)
if (drive.Table.MBR.Partitions[p].LBAFirst != 0)
if (drive->Table.MBR.Partitions[p].LBAFirst != 0)
{
Partition partition{};
partition.StartLBA = drive.Table.MBR.Partitions[p].LBAFirst;
partition.EndLBA = drive.Table.MBR.Partitions[p].LBAFirst + drive.Table.MBR.Partitions[p].Sectors;
partition.Sectors = drive.Table.MBR.Partitions[p].Sectors;
partition.Port = ItrPort;
partition.Flags = Present;
partition.Style = MBR;
partition.Index = drive.Partitions.size();
trace("Partition \"%#llx\" found with %lld sectors.", drive.Table.MBR.UniqueID, partition.Sectors);
drive.Partitions.push_back(partition);
Partition *partition = new Partition;
partition->StartLBA = drive->Table.MBR.Partitions[p].LBAFirst;
partition->EndLBA = drive->Table.MBR.Partitions[p].LBAFirst + drive->Table.MBR.Partitions[p].Sectors;
partition->Sectors = drive->Table.MBR.Partitions[p].Sectors;
partition->Port = ItrPort;
partition->Flags = Present;
partition->Style = MBR;
partition->Index = drive->Partitions.size();
trace("Partition \"%#llx\" found with %lld sectors.", drive->Table.MBR.UniqueID, partition->Sectors);
drive->Partitions.push_back(partition);
// char *PartitionName = new char[64];
// sprintf(PartitionName, "sd%ldp%ld", drives.size() - 1, partition.Index);
char *PartitionName = new char[64];
sprintf(PartitionName, "sd%ldp%ld", drives.size() - 1, partition->Index);
/*
TODO: Add to devfs the disk
*/
// delete[] PartitionName;
delete[] PartitionName;
}
trace("%d MBR partitions found.", drive.Partitions.size());
trace("%d MBR partitions found.", drive->Partitions.size());
}
else
warn("No partition table found on port %d!", ItrPort);
@ -155,7 +144,7 @@ namespace Disk
drives.push_back(drive);
}
KernelAllocator.FreePages(RWBuffer, TO_PAGES(this->BytesPerSector + 1));
KernelAllocator.FreePages((void *)callback, TO_PAGES(sizeof(KernelCallback)));
}
Manager::Manager()

View File

@ -1,24 +1,7 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include <driver.hpp>
#include <memory.hpp>
#include <ints.hpp>
#include <memory.hpp>
#include <task.hpp>
#include <lock.hpp>
#include <printf.h>
@ -35,80 +18,63 @@ NewLock(DriverInterruptLock);
namespace Driver
{
void Driver::Panic()
{
#ifdef DEBUG
size_t DriversNum = Drivers.size();
debug("%ld drivers loaded, [DUIDs: %ld]", DriversNum, DriverUIDs);
debug("driver size %ld", DriversNum);
#endif
foreach (auto drv in Drivers)
{
KernelCallback callback{};
callback.Reason = StopReason;
DriverManager->IOCB(drv.DriverUID, &callback);
for (size_t j = 0; j < sizeof(drv.InterruptHook) / sizeof(drv.InterruptHook[0]); j++)
{
if (!drv.InterruptHook[j])
continue;
drv.InterruptHook[j]->Disable();
debug("Interrupt hook %#lx disabled", drv.InterruptHook[j]);
}
}
}
const char *DriverTypesName[] = {
"Unknown",
"Generic",
"Display",
"Network",
"Storage",
"FileSystem",
"Input",
"Audio"};
void Driver::UnloadAllDrivers()
{
#ifdef DEBUG
size_t DriversNum = Drivers.size();
debug("%ld drivers loaded, [DUIDs: %ld]", DriversNum, DriverUIDs);
debug("driver size %ld", DriversNum);
#endif
foreach (auto drv in Drivers)
for (size_t i = 0; i < DriversNum; i++)
{
KernelCallback callback{};
DriverFile *drv = Drivers[i];
KernelCallback callback;
callback.Reason = StopReason;
debug("Stopping & unloading driver %ld [%#lx]", drv.DriverUID, drv.Address);
DriverManager->IOCB(drv.DriverUID, &callback);
debug("Stopping & unloading driver %ld [%#lx]", drv->DriverUID, drv->Address);
DriverManager->IOCB(drv->DriverUID, (void *)&callback);
for (size_t j = 0; j < sizeof(drv.InterruptHook) / sizeof(drv.InterruptHook[0]); j++)
delete drv->MemTrk, drv->MemTrk = nullptr;
for (size_t j = 0; j < sizeof(drv->InterruptHook) / sizeof(drv->InterruptHook[0]); j++)
{
if (!drv.InterruptHook[j])
if (!drv->InterruptHook[j])
continue;
debug("Interrupt hook %#lx", drv.InterruptHook[j]);
delete drv.InterruptHook[j], drv.InterruptHook[j] = nullptr;
delete drv->InterruptHook[j], drv->InterruptHook[j] = nullptr;
}
if (drv.MemTrk)
delete drv.MemTrk, drv.MemTrk = nullptr;
delete drv, drv = nullptr;
Drivers.remove(i);
}
Drivers.clear();
}
bool Driver::UnloadDriver(unsigned long DUID)
{
debug("Searching for driver %ld", DUID);
foreach (auto drv in Drivers)
for (size_t i = 0; i < Drivers.size(); i++)
{
if (drv.DriverUID == DUID)
DriverFile *drv = Drivers[i];
if (drv->DriverUID == DUID)
{
KernelCallback callback{};
KernelCallback callback;
callback.Reason = StopReason;
debug("Stopping and unloading driver %ld [%#lx]", drv.DriverUID, drv.Address);
this->IOCB(drv.DriverUID, &callback);
debug("Stopping and unloading driver %ld [%#lx]", drv->DriverUID, drv->Address);
this->IOCB(drv->DriverUID, (void *)&callback);
for (size_t j = 0; j < sizeof(drv.InterruptHook) / sizeof(drv.InterruptHook[0]); j++)
delete drv->MemTrk, drv->MemTrk = nullptr;
for (size_t i = 0; i < sizeof(drv->InterruptHook) / sizeof(drv->InterruptHook[0]); i++)
{
if (!drv.InterruptHook[j])
if (!drv->InterruptHook[i])
continue;
debug("Interrupt hook %#lx", drv.InterruptHook[j]);
delete drv.InterruptHook[j], drv.InterruptHook[j] = nullptr;
delete drv->InterruptHook[i], drv->InterruptHook[i] = nullptr;
}
delete drv.MemTrk, drv.MemTrk = nullptr;
Drivers.remove(drv);
delete drv, drv = nullptr;
Drivers.remove(i);
return true;
}
}
@ -119,10 +85,10 @@ namespace Driver
{
foreach (auto Drv in Drivers)
{
if (Drv.DriverUID == DUID)
if (Drv->DriverUID == DUID)
{
FexExtended *DrvExtHdr = (FexExtended *)((uintptr_t)Drv.Address + EXTENDED_SECTION_ADDRESS);
int ret = ((int (*)(void *))((uintptr_t)DrvExtHdr->Driver.Callback + (uintptr_t)Drv.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;
}
@ -136,12 +102,6 @@ namespace Driver
((KernelAPI *)KAPIAddress)->Info.Offset = (unsigned long)fex;
((KernelAPI *)KAPIAddress)->Info.DriverUID = DriverUIDs++;
((KernelAPI *)KAPIAddress)->Info.KernelDebug = DebuggerIsAttached;
#ifdef DEBUG
FexExtended *fexExtended = (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
debug("DRIVER: %s HAS DRIVER ID %ld", fexExtended->Driver.Name, ((KernelAPI *)KAPIAddress)->Info.DriverUID);
#endif
debug("Calling driver entry point ( %#lx %ld )", (unsigned long)fex, ((KernelAPI *)KAPIAddress)->Info.DriverUID);
int ret = ((int (*)(KernelAPI *))((uintptr_t)((Fex *)fex)->EntryPoint + (uintptr_t)fex))(((KernelAPI *)KAPIAddress));
@ -214,21 +174,15 @@ namespace Driver
Driver::Driver()
{
SmartCriticalSection(DriverInitLock);
std::string DriverConfigFile = Config.DriverDirectory;
DriverConfigFile << "/config.ini";
fixme("Loading driver config file: %s", DriverConfigFile.c_str());
VirtualFileSystem::File DriverDirectory = vfs->Open(Config.DriverDirectory);
if (DriverDirectory.IsOK())
shared_ptr<VirtualFileSystem::File> DriverDirectory = vfs->Open(Config.DriverDirectory);
if (DriverDirectory->Status == VirtualFileSystem::FileStatus::OK)
{
foreach (auto driver in DriverDirectory.node->Children)
foreach (auto driver in DriverDirectory->node->Children)
if (driver->Flags == VirtualFileSystem::NodeFlags::FILE)
if (cwk_path_has_extension(driver->Name))
{
const char *extension;
size_t extension_length;
cwk_path_get_extension(driver->Name, &extension, &extension_length);
cwk_path_get_extension(driver->Name, &extension, nullptr);
debug("Driver: %s; Extension: %s", driver->Name, extension);
if (strcmp(extension, ".fex") == 0 || strcmp(extension, ".elf") == 0)
{
@ -246,7 +200,7 @@ namespace Driver
}
else
{
KPrint("\eE85230Failed to open driver directory: %s! (Status: %#lx)", Config.DriverDirectory, DriverDirectory.Status);
KPrint("\eE85230Failed to open driver directory: %s! (Status: %#lx)", Config.DriverDirectory, DriverDirectory->Status);
CPU::Stop();
}
vfs->Close(DriverDirectory);
@ -263,81 +217,18 @@ namespace Driver
#elif defined(a32)
SafeFunction void DriverInterruptHook::OnInterruptReceived(CPU::x32::TrapFrame *Frame)
#elif defined(aa64)
SafeFunction void DriverInterruptHook::OnInterruptReceived(CPU::aarch64::TrapFrame *Frame)
SafeFunction void DriverInterruptHook::OnInterruptReceived(void *Frame)
#endif
{
SmartLock(DriverInterruptLock); /* Lock in case of multiple interrupts firing at the same time */
if (!this->Enabled)
{
debug("Interrupt hook is not enabled");
return;
}
if (!Handle.InterruptCallback)
{
#if defined(a86)
uint64_t IntNum = Frame->InterruptNumber - 32;
#elif defined(aa64)
uint64_t IntNum = Frame->InterruptNumber;
#endif
warn("Interrupt callback for %ld is not set for driver %ld!", IntNum, Handle.DriverUID);
return;
}
CPURegisters regs;
#if defined(a64)
regs.r15 = Frame->r15;
regs.r14 = Frame->r14;
regs.r13 = Frame->r13;
regs.r12 = Frame->r12;
regs.r11 = Frame->r11;
regs.r10 = Frame->r10;
regs.r9 = Frame->r9;
regs.r8 = Frame->r8;
regs.rbp = Frame->rbp;
regs.rdi = Frame->rdi;
regs.rsi = Frame->rsi;
regs.rdx = Frame->rdx;
regs.rcx = Frame->rcx;
regs.rbx = Frame->rbx;
regs.rax = Frame->rax;
regs.InterruptNumber = Frame->InterruptNumber;
regs.ErrorCode = Frame->ErrorCode;
regs.rip = Frame->rip;
regs.cs = Frame->cs;
regs.rflags = Frame->rflags.raw;
regs.rsp = Frame->rsp;
regs.ss = Frame->ss;
#elif defined(a32)
regs.ebp = Frame->ebp;
regs.edi = Frame->edi;
regs.esi = Frame->esi;
regs.edx = Frame->edx;
regs.ecx = Frame->ecx;
regs.ebx = Frame->ebx;
regs.eax = Frame->eax;
regs.InterruptNumber = Frame->InterruptNumber;
regs.ErrorCode = Frame->ErrorCode;
regs.eip = Frame->eip;
regs.cs = Frame->cs;
regs.eflags = Frame->eflags.raw;
regs.esp = Frame->esp;
regs.ss = Frame->ss;
#elif defined(aa64)
#endif
((int (*)(void *))(Handle.InterruptCallback))(&regs);
SmartLock(DriverInterruptLock);
((int (*)(void *))(Handle))(Data);
UNUSED(Frame);
}
DriverInterruptHook::DriverInterruptHook(int Interrupt, DriverFile Handle) : Interrupts::Handler(Interrupt)
DriverInterruptHook::DriverInterruptHook(int Interrupt, void *Address, void *ParamData) : Interrupts::Handler(Interrupt)
{
this->Handle = Handle;
#if defined(a86)
trace("Interrupt %d hooked to driver %ld", Interrupt, Handle.DriverUID);
#elif defined(aa64)
trace("Interrupt %d hooked to driver %ld", Interrupt, Handle.DriverUID);
#endif
trace("Interrupt %d Hooked", Interrupt - 32); // x86
Handle = Address;
Data = ParamData;
}
}

View File

@ -1,20 +1,3 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include <driver.hpp>
#include <dumper.hpp>
@ -46,7 +29,7 @@ void DriverDisplayPrint(char *String)
void *RequestPage(unsigned long Size)
{
void *ret = KernelAllocator.RequestPages(Size + 1);
void *ret = KernelAllocator.RequestPages(Size);
drvdbg("Allocated %ld pages (%#lx-%#lx)", Size, (unsigned long)ret, (unsigned long)ret + FROM_PAGES(Size));
return ret;
}
@ -54,21 +37,21 @@ void *RequestPage(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));
KernelAllocator.FreePages(Page, Size + 1);
KernelAllocator.FreePages(Page, Size);
}
void MapMemory(void *VirtualAddress, void *PhysicalAddress, unsigned long Flags)
{
SmartLock(DriverDisplayPrintLock);
drvdbg("Mapping %#lx to %#lx with flags %#lx...", (unsigned long)VirtualAddress, (unsigned long)PhysicalAddress, Flags);
Memory::Virtual(KernelPageTable).Map(VirtualAddress, PhysicalAddress, Flags);
Memory::Virtual().Map(VirtualAddress, PhysicalAddress, Flags);
}
void UnmapMemory(void *VirtualAddress)
{
SmartLock(DriverDisplayPrintLock);
drvdbg("Unmapping %#lx...", (unsigned long)VirtualAddress);
Memory::Virtual(KernelPageTable).Unmap(VirtualAddress);
Memory::Virtual().Unmap(VirtualAddress);
}
void *Drivermemcpy(void *Destination, void *Source, unsigned long Size)
@ -144,7 +127,7 @@ void DriverSleep(unsigned long Milliseconds)
if (TaskManager)
TaskManager->Sleep(Milliseconds);
else
TimeManager->Sleep(Milliseconds, Time::Units::Milliseconds);
TimeManager->Sleep(Milliseconds);
}
int Driversprintf(char *Buffer, const char *Format, ...)
@ -164,7 +147,6 @@ KernelAPI KernelAPITemplate = {
.Info = {
.Offset = 0,
.DriverUID = 0,
.KernelDebug = false,
},
.Memory = {
.PageSize = PAGE_SIZE,

View File

@ -1,73 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "../api.hpp"
#include <ints.hpp>
#include <memory.hpp>
#include <task.hpp>
#include <lock.hpp>
#include <printf.h>
#include <cwalk.h>
#include <md5.h>
#include "../../../kernel.h"
#include "../../../DAPI.hpp"
#include "../../../Fex.hpp"
namespace Driver
{
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 + 1));
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) + 1));
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;
}
}

View File

@ -1,85 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "../api.hpp"
#include <ints.hpp>
#include <memory.hpp>
#include <task.hpp>
#include <lock.hpp>
#include <printf.h>
#include <cwalk.h>
#include <md5.h>
#include "../../../kernel.h"
#include "../../../DAPI.hpp"
#include "../../../Fex.hpp"
namespace Driver
{
DriverCode Driver::DriverLoadBindInterrupt(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 + 1));
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) + 1));
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;
}
}

View File

@ -1,201 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "../api.hpp"
#include <ints.hpp>
#include <memory.hpp>
#include <task.hpp>
#include <lock.hpp>
#include <printf.h>
#include <cwalk.h>
#include <md5.h>
#include "../../../kernel.h"
#include "../../../DAPI.hpp"
#include "../../../Fex.hpp"
namespace Driver
{
void Driver::MapPCIAddresses(PCI::PCIDeviceHeader *PCIDevice)
{
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;
#ifdef DEBUG
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);
#endif
/* BARs Size */
for (short 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%d %#lx size: %d", i, BAR[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%d %#lx size: %d", i, BAR[i], BARsSize[i]);
}
}
/* Mapping the BARs */
for (short i = 0; i < 6; i++)
{
if (BAR[i] == 0)
continue;
if ((BAR[i] & 1) == 0) // Memory Base
{
uintptr_t BARBase = BAR[i] & (~15);
size_t BARSize = BARsSize[i];
debug("Mapping BAR%d %#lx-%#lx", i, BARBase, BARBase + BARSize);
Memory::Virtual().Map((void *)BARBase, (void *)BARBase, BARSize, Memory::PTFlag::RW | Memory::PTFlag::PWT);
}
else if ((BAR[i] & 1) == 1) // I/O Base
{
uintptr_t BARBase = BAR[i] & (~3);
size_t BARSize = BARsSize[i];
debug("Mapping BAR%d %#x-%#x", i, BARBase, BARBase + BARSize);
Memory::Virtual().Map((void *)BARBase, (void *)BARBase, BARSize, 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::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;
std::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 + 1));
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) + 1));
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;
}
}

View File

@ -1,42 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "../api.hpp"
#include <ints.hpp>
#include <memory.hpp>
#include <task.hpp>
#include <lock.hpp>
#include <printf.h>
#include <cwalk.h>
#include <md5.h>
#include "../../../kernel.h"
#include "../../../DAPI.hpp"
#include "../../../Fex.hpp"
namespace Driver
{
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;
}
}

View File

@ -1,40 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "../../api.hpp"
#include <ints.hpp>
#include <memory.hpp>
#include <task.hpp>
#include <lock.hpp>
#include <printf.h>
#include <cwalk.h>
#include <md5.h>
#include "../../../../kernel.h"
#include "../../../../DAPI.hpp"
#include "../../../../Fex.hpp"
namespace Driver
{
DriverCode Driver::BindInputAudio(Memory::MemMgr *mem, void *fex)
{
UNUSED(mem);
UNUSED(fex);
return DriverCode::NOT_IMPLEMENTED;
}
}

View File

@ -1,40 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "../../api.hpp"
#include <ints.hpp>
#include <memory.hpp>
#include <task.hpp>
#include <lock.hpp>
#include <printf.h>
#include <cwalk.h>
#include <md5.h>
#include "../../../../kernel.h"
#include "../../../../DAPI.hpp"
#include "../../../../Fex.hpp"
namespace Driver
{
DriverCode Driver::BindInputDisplay(Memory::MemMgr *mem, void *fex)
{
UNUSED(mem);
UNUSED(fex);
return DriverCode::NOT_IMPLEMENTED;
}
}

View File

@ -1,40 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "../../api.hpp"
#include <ints.hpp>
#include <memory.hpp>
#include <task.hpp>
#include <lock.hpp>
#include <printf.h>
#include <cwalk.h>
#include <md5.h>
#include "../../../../kernel.h"
#include "../../../../DAPI.hpp"
#include "../../../../Fex.hpp"
namespace Driver
{
DriverCode Driver::BindInputFileSystem(Memory::MemMgr *mem, void *fex)
{
UNUSED(mem);
UNUSED(fex);
return DriverCode::NOT_IMPLEMENTED;
}
}

View File

@ -1,40 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "../../api.hpp"
#include <ints.hpp>
#include <memory.hpp>
#include <task.hpp>
#include <lock.hpp>
#include <printf.h>
#include <cwalk.h>
#include <md5.h>
#include "../../../../kernel.h"
#include "../../../../DAPI.hpp"
#include "../../../../Fex.hpp"
namespace Driver
{
DriverCode Driver::BindInputGeneric(Memory::MemMgr *mem, void *fex)
{
UNUSED(mem);
UNUSED(fex);
return DriverCode::NOT_IMPLEMENTED;
}
}

View File

@ -1,67 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "../../api.hpp"
#include <ints.hpp>
#include <memory.hpp>
#include <task.hpp>
#include <lock.hpp>
#include <printf.h>
#include <cwalk.h>
#include <md5.h>
#include "../../../../kernel.h"
#include "../../../../DAPI.hpp"
#include "../../../../Fex.hpp"
namespace Driver
{
DriverCode Driver::BindInputInput(Memory::MemMgr *mem, void *fex)
{
FexExtended *fexExtended = (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
KernelCallback KCallback{};
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 = {
.Enabled = true,
.DriverUID = this->DriverUIDs - 1,
.Address = (void *)fex,
.MemTrk = mem,
};
Drivers.push_back(DrvFile);
return DriverCode::OK;
}
}

View File

@ -1,40 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "../../api.hpp"
#include <ints.hpp>
#include <memory.hpp>
#include <task.hpp>
#include <lock.hpp>
#include <printf.h>
#include <cwalk.h>
#include <md5.h>
#include "../../../../kernel.h"
#include "../../../../DAPI.hpp"
#include "../../../../Fex.hpp"
namespace Driver
{
DriverCode Driver::BindInputNetwork(Memory::MemMgr *mem, void *fex)
{
UNUSED(mem);
UNUSED(fex);
return DriverCode::NOT_IMPLEMENTED;
}
}

View File

@ -1,40 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "../../api.hpp"
#include <ints.hpp>
#include <memory.hpp>
#include <task.hpp>
#include <lock.hpp>
#include <printf.h>
#include <cwalk.h>
#include <md5.h>
#include "../../../../kernel.h"
#include "../../../../DAPI.hpp"
#include "../../../../Fex.hpp"
namespace Driver
{
DriverCode Driver::BindInputStorage(Memory::MemMgr *mem, void *fex)
{
UNUSED(mem);
UNUSED(fex);
return DriverCode::NOT_IMPLEMENTED;
}
}

View File

@ -1,81 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "../../api.hpp"
#include <ints.hpp>
#include <memory.hpp>
#include <task.hpp>
#include <lock.hpp>
#include <printf.h>
#include <cwalk.h>
#include <md5.h>
#include "../../../../kernel.h"
#include "../../../../DAPI.hpp"
#include "../../../../Fex.hpp"
namespace Driver
{
DriverCode Driver::BindInterruptAudio(Memory::MemMgr *mem, void *fex)
{
FexExtended *fexExtended = (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
if (fexExtended->Driver.OverrideOnConflict)
{
std::vector<uint64_t> DriversToRemove = std::vector<uint64_t>();
foreach (auto Drv in Drivers)
{
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv.Address + EXTENDED_SECTION_ADDRESS));
if (fe->Driver.OverrideOnConflict)
{
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
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.OverrideOnConflict)
{
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
return DriverCode::DRIVER_CONFLICT;
}
}
}
fixme("Audio driver: %s", fexExtended->Driver.Name);
delete mem, mem = nullptr;
return DriverCode::NOT_IMPLEMENTED;
}
}

View File

@ -1,81 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "../../api.hpp"
#include <ints.hpp>
#include <memory.hpp>
#include <task.hpp>
#include <lock.hpp>
#include <printf.h>
#include <cwalk.h>
#include <md5.h>
#include "../../../../kernel.h"
#include "../../../../DAPI.hpp"
#include "../../../../Fex.hpp"
namespace Driver
{
DriverCode Driver::BindInterruptDisplay(Memory::MemMgr *mem, void *fex)
{
FexExtended *fexExtended = (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
if (fexExtended->Driver.OverrideOnConflict)
{
std::vector<uint64_t> DriversToRemove = std::vector<uint64_t>();
foreach (auto Drv in Drivers)
{
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv.Address + EXTENDED_SECTION_ADDRESS));
if (fe->Driver.OverrideOnConflict)
{
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
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.OverrideOnConflict)
{
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
return DriverCode::DRIVER_CONFLICT;
}
}
}
fixme("Display driver: %s", fexExtended->Driver.Name);
delete mem, mem = nullptr;
return DriverCode::NOT_IMPLEMENTED;
}
}

View File

@ -1,81 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "../../api.hpp"
#include <ints.hpp>
#include <memory.hpp>
#include <task.hpp>
#include <lock.hpp>
#include <printf.h>
#include <cwalk.h>
#include <md5.h>
#include "../../../../kernel.h"
#include "../../../../DAPI.hpp"
#include "../../../../Fex.hpp"
namespace Driver
{
DriverCode Driver::BindInterruptFileSystem(Memory::MemMgr *mem, void *fex)
{
FexExtended *fexExtended = (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
if (fexExtended->Driver.OverrideOnConflict)
{
std::vector<uint64_t> DriversToRemove = std::vector<uint64_t>();
foreach (auto Drv in Drivers)
{
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv.Address + EXTENDED_SECTION_ADDRESS));
if (fe->Driver.OverrideOnConflict)
{
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
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.OverrideOnConflict)
{
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
return DriverCode::DRIVER_CONFLICT;
}
}
}
fixme("Filesystem driver: %s", fexExtended->Driver.Name);
delete mem, mem = nullptr;
return DriverCode::NOT_IMPLEMENTED;
}
}

View File

@ -1,88 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "../../api.hpp"
#include <ints.hpp>
#include <memory.hpp>
#include <task.hpp>
#include <lock.hpp>
#include <printf.h>
#include <cwalk.h>
#include <md5.h>
#include "../../../../kernel.h"
#include "../../../../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)
{
std::vector<uint64_t> DriversToRemove = std::vector<uint64_t>();
foreach (auto Drv in Drivers)
{
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv.Address + EXTENDED_SECTION_ADDRESS));
if (fe->Driver.OverrideOnConflict)
{
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
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.OverrideOnConflict)
{
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
return DriverCode::DRIVER_CONFLICT;
}
}
}
fixme("Generic driver: %s", fexExtended->Driver.Name);
DriverFile DrvFile = {
.Enabled = true,
.DriverUID = this->DriverUIDs - 1,
.Address = (void *)fex,
.InterruptCallback = (void *)((uintptr_t)fex + (uintptr_t)fexExtended->Driver.InterruptCallback),
.MemTrk = mem,
};
Drivers.push_back(DrvFile);
return DriverCode::OK;
}
}

View File

@ -1,124 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "../../api.hpp"
#include <ints.hpp>
#include <memory.hpp>
#include <task.hpp>
#include <lock.hpp>
#include <printf.h>
#include <cwalk.h>
#include <md5.h>
#include "../../../../kernel.h"
#include "../../../../DAPI.hpp"
#include "../../../../Fex.hpp"
namespace Driver
{
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)
{
std::vector<uint64_t> DriversToRemove = std::vector<uint64_t>();
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;
}
}
}
DriverFile DrvFile = {
.Enabled = true,
.DriverUID = this->DriverUIDs - 1,
.Address = (void *)fex,
.InterruptCallback = (void *)((uintptr_t)fex + (uintptr_t)fexExtended->Driver.InterruptCallback),
.MemTrk = mem,
};
if (fexExtended->Driver.InterruptCallback)
{
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;
DrvFile.InterruptHook[i] = new DriverInterruptHook(fexExtended->Driver.Bind.Interrupt.Vector[i], DrvFile);
}
}
KernelCallback KCallback{};
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;
}
Drivers.push_back(DrvFile);
return DriverCode::OK;
}
}

View File

@ -1,81 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "../../api.hpp"
#include <ints.hpp>
#include <memory.hpp>
#include <task.hpp>
#include <lock.hpp>
#include <printf.h>
#include <cwalk.h>
#include <md5.h>
#include "../../../../kernel.h"
#include "../../../../DAPI.hpp"
#include "../../../../Fex.hpp"
namespace Driver
{
DriverCode Driver::BindInterruptNetwork(Memory::MemMgr *mem, void *fex)
{
FexExtended *fexExtended = (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
if (fexExtended->Driver.OverrideOnConflict)
{
std::vector<uint64_t> DriversToRemove = std::vector<uint64_t>();
foreach (auto Drv in Drivers)
{
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv.Address + EXTENDED_SECTION_ADDRESS));
if (fe->Driver.OverrideOnConflict)
{
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
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.OverrideOnConflict)
{
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
return DriverCode::DRIVER_CONFLICT;
}
}
}
fixme("Network driver: %s", fexExtended->Driver.Name);
delete mem, mem = nullptr;
return DriverCode::NOT_IMPLEMENTED;
}
}

View File

@ -1,115 +0,0 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "../../api.hpp"
#include <ints.hpp>
#include <memory.hpp>
#include <task.hpp>
#include <lock.hpp>
#include <printf.h>
#include <cwalk.h>
#include <md5.h>
#include "../../../../kernel.h"
#include "../../../../DAPI.hpp"
#include "../../../../Fex.hpp"
namespace Driver
{
DriverCode Driver::BindInterruptStorage(Memory::MemMgr *mem, void *fex)
{
FexExtended *fexExtended = (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
if (fexExtended->Driver.OverrideOnConflict)
{
std::vector<uint64_t> DriversToRemove = std::vector<uint64_t>();
foreach (auto Drv in Drivers)
{
FexExtended *fe = ((FexExtended *)((uintptr_t)Drv.Address + EXTENDED_SECTION_ADDRESS));
if (fe->Driver.OverrideOnConflict)
{
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
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.OverrideOnConflict)
{
debug("Driver %s is conflicting with %s", fe->Driver.Name, fexExtended->Driver.Name);
return DriverCode::DRIVER_CONFLICT;
}
}
}
DriverFile DrvFile = {
.Enabled = true,
.DriverUID = this->DriverUIDs - 1,
.Address = (void *)fex,
.InterruptCallback = (void *)((uintptr_t)fex + (uintptr_t)fexExtended->Driver.InterruptCallback),
.MemTrk = mem,
};
if (fexExtended->Driver.InterruptCallback)
{
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;
DrvFile.InterruptHook[i] = new DriverInterruptHook(fexExtended->Driver.Bind.Interrupt.Vector[i], DrvFile);
}
}
KernelCallback KCallback{};
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;
}
Drivers.push_back(DrvFile);
return DriverCode::OK;
}
}

Some files were not shown because too many files have changed in this diff Show More