mirror of
https://github.com/Fennix-Project/Kernel.git
synced 2025-05-25 14:04:36 +00:00
Restructured and rewritten entire codebase
This commit is contained in:
parent
446a571018
commit
889e1522a3
2
.github/workflows/flawfinder.yml
vendored
2
.github/workflows/flawfinder.yml
vendored
@ -11,8 +11,6 @@ on:
|
||||
pull_request:
|
||||
# The branches below must be a subset of the branches above
|
||||
branches: [ "master" ]
|
||||
schedule:
|
||||
- cron: '21 1 * * 1'
|
||||
|
||||
jobs:
|
||||
flawfinder:
|
||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -4,4 +4,3 @@
|
||||
*.map
|
||||
*.fsys
|
||||
*.log
|
||||
.dccache
|
||||
|
44
.vscode/c_boilerplates.code-snippets
vendored
44
.vscode/c_boilerplates.code-snippets
vendored
@ -5,20 +5,20 @@
|
||||
],
|
||||
"body": [
|
||||
"/*",
|
||||
" This file is part of Fennix Kernel.",
|
||||
"\tThis 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.",
|
||||
"\tFennix Kernel is free software: you can redistribute it and/or",
|
||||
"\tmodify it under the terms of the GNU General Public License as",
|
||||
"\tpublished by the Free Software Foundation, either version 3 of",
|
||||
"\tthe License, or (at your option) any later version.",
|
||||
"",
|
||||
" 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.",
|
||||
"\tFennix Kernel is distributed in the hope that it will be useful,",
|
||||
"\tbut WITHOUT ANY WARRANTY; without even the implied warranty of",
|
||||
"\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the",
|
||||
"\tGNU General Public License for more details.",
|
||||
"",
|
||||
" You should have received a copy of the GNU General Public License",
|
||||
" along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.",
|
||||
"\tYou should have received a copy of the GNU General Public License",
|
||||
"\talong with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.",
|
||||
"*/",
|
||||
"",
|
||||
"#ifndef __FENNIX_KERNEL_${2:header}_H__",
|
||||
@ -60,20 +60,20 @@
|
||||
],
|
||||
"body": [
|
||||
"/*",
|
||||
" This file is part of Fennix Kernel.",
|
||||
"\tThis 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.",
|
||||
"\tFennix Kernel is free software: you can redistribute it and/or",
|
||||
"\tmodify it under the terms of the GNU General Public License as",
|
||||
"\tpublished by the Free Software Foundation, either version 3 of",
|
||||
"\tthe License, or (at your option) any later version.",
|
||||
"",
|
||||
" 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.",
|
||||
"\tFennix Kernel is distributed in the hope that it will be useful,",
|
||||
"\tbut WITHOUT ANY WARRANTY; without even the implied warranty of",
|
||||
"\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the",
|
||||
"\tGNU General Public License for more details.",
|
||||
"",
|
||||
" You should have received a copy of the GNU General Public License",
|
||||
" along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.",
|
||||
"\tYou should have received a copy of the GNU General Public License",
|
||||
"\talong with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.",
|
||||
"*/"
|
||||
],
|
||||
"description": "Create kernel license."
|
||||
|
6
.vscode/c_cpp_properties.json
vendored
6
.vscode/c_cpp_properties.json
vendored
@ -52,7 +52,7 @@
|
||||
"-fno-exceptions",
|
||||
|
||||
// Linker flags
|
||||
"-T${workspaceFolder}/Architecture/amd64/linker.ld",
|
||||
"-T${workspaceFolder}/arch/amd64/linker.ld",
|
||||
"-Wl,-static,--no-dynamic-linker,-ztext",
|
||||
"-nostdlib",
|
||||
"-nodefaultlibs",
|
||||
@ -130,7 +130,7 @@
|
||||
"-fno-exceptions",
|
||||
|
||||
// Linker flags
|
||||
"-T${workspaceFolder}/Architecture/i386/linker.ld",
|
||||
"-T${workspaceFolder}/arch/i386/linker.ld",
|
||||
"-Wl,-static,--no-dynamic-linker,-ztext",
|
||||
"-nostdlib",
|
||||
"-nodefaultlibs",
|
||||
@ -201,7 +201,7 @@
|
||||
"-fno-exceptions",
|
||||
|
||||
// Linker flags
|
||||
"-T${workspaceFolder}/Architecture/aarch64/linker.ld",
|
||||
"-T${workspaceFolder}/arch/aarch64/linker.ld",
|
||||
"-fPIC",
|
||||
|
||||
// Debug flags
|
||||
|
@ -1,27 +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 <types.h>
|
||||
|
||||
#include <debug.h>
|
||||
#include <cpu.hpp>
|
||||
|
||||
EXTERNC void arm64Entry(uint64_t dtb_ptr32, uint64_t x1, uint64_t x2, uint64_t x3)
|
||||
{
|
||||
trace("Hello, World!");
|
||||
CPU::Halt(true);
|
||||
}
|
@ -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 <memory.hpp>
|
||||
|
||||
#include <convert.h>
|
||||
#include <debug.h>
|
||||
|
||||
namespace Memory
|
||||
{
|
||||
bool Virtual::Check(void *VirtualAddress, PTFlag Flag, MapType Type)
|
||||
{
|
||||
}
|
||||
|
||||
void *Virtual::GetPhysical(void *VirtualAddress)
|
||||
{
|
||||
}
|
||||
|
||||
void Virtual::Map(void *VirtualAddress, void *PhysicalAddress, uint64_t Flags, MapType Type)
|
||||
{
|
||||
}
|
||||
|
||||
void Virtual::Unmap(void *VirtualAddress, MapType Type)
|
||||
{
|
||||
}
|
||||
}
|
@ -1,31 +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>
|
||||
|
||||
extern "C" __naked __used __no_stack_protector void SystemCallHandlerStub()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
extern "C" uint64_t SystemCallsHandler(SyscallsFrame *regs);
|
||||
|
||||
void InitializeSystemCalls()
|
||||
{
|
||||
}
|
@ -1,59 +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 <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];
|
||||
}
|
||||
|
||||
if (CPUs[ret].Checksum != CPU_DATA_CHECKSUM)
|
||||
{
|
||||
error("CPU %d data is corrupted!", ret);
|
||||
return &CPUs[0];
|
||||
}
|
||||
return &CPUs[ret];
|
||||
}
|
||||
|
||||
namespace SMP
|
||||
{
|
||||
int CPUCores = 0;
|
||||
|
||||
void Initialize(void *madt)
|
||||
{
|
||||
fixme("SMP::Initialize() is not implemented!");
|
||||
}
|
||||
}
|
@ -1,90 +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/>.
|
||||
*/
|
||||
|
||||
ENTRY(_start)
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
_bootstrap_start = .;
|
||||
.text.boot :
|
||||
{
|
||||
*(.text.boot)
|
||||
. += CONSTANT(MAXPAGESIZE);
|
||||
_bss_start = .;
|
||||
*(.text.bss)
|
||||
_bss_end = .;
|
||||
}
|
||||
_bootstrap_end = .;
|
||||
|
||||
_kernel_start = .;
|
||||
_kernel_text_start = .;
|
||||
.text :
|
||||
{
|
||||
KEEP(*(.text.boot))
|
||||
*(.text .text.*)
|
||||
}
|
||||
. = ALIGN(4096);
|
||||
_kernel_text_end = .;
|
||||
|
||||
_kernel_data_start = .;
|
||||
.data :
|
||||
{
|
||||
*(.data .data.*)
|
||||
}
|
||||
. = ALIGN(4096);
|
||||
_kernel_data_end = .;
|
||||
|
||||
_kernel_rodata_start = .;
|
||||
.rodata :
|
||||
{
|
||||
*(.rodata .rodata.*)
|
||||
}
|
||||
. = ALIGN(4096);
|
||||
|
||||
.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 = .);
|
||||
}
|
||||
_kernel_rodata_end = .;
|
||||
|
||||
_kernel_bss_start = .;
|
||||
.bss :
|
||||
{
|
||||
*(.bss .bss.*)
|
||||
}
|
||||
. = ALIGN(4096);
|
||||
_kernel_bss_end = .;
|
||||
_kernel_end = .;
|
||||
_bss_size = _kernel_end - _kernel_rodata_end;
|
||||
|
||||
/DISCARD/ :
|
||||
{
|
||||
*(.comment*)
|
||||
*(.note*)
|
||||
}
|
||||
}
|
@ -1,38 +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/>.
|
||||
*/
|
||||
|
||||
.code32
|
||||
.extern Multiboot_start
|
||||
|
||||
.section .multiboot, "a"
|
||||
.align 4
|
||||
|
||||
MULTIBOOT_HEADER:
|
||||
.long 0x1BADB002
|
||||
.long 0x1 | 0x2 | 0x4
|
||||
.long -(0x1BADB002 + (0x1 | 0x2 | 0x4))
|
||||
/* KLUDGE */
|
||||
.long 0
|
||||
.long 0
|
||||
.long 0
|
||||
.long 0
|
||||
.long 0
|
||||
/* VIDEO MODE */
|
||||
.long 0
|
||||
.long 0
|
||||
.long 0
|
||||
.long 0
|
@ -1,64 +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/>.
|
||||
*/
|
||||
|
||||
.code32
|
||||
.section .bootstrap.text, "a"
|
||||
|
||||
.align 32
|
||||
.global gdtr
|
||||
gdtr:
|
||||
.word GDT32_END - GDT32 - 1
|
||||
.long GDT32
|
||||
|
||||
.align 32
|
||||
GDT32:
|
||||
.quad 0x0
|
||||
|
||||
.word 0xFFFF
|
||||
.word 0x0000
|
||||
.byte 0x00
|
||||
.word 0xCF9A
|
||||
.byte 0x00
|
||||
|
||||
.word 0xFFFF
|
||||
.word 0x0000
|
||||
.byte 0x00
|
||||
.word 0xCF92
|
||||
.byte 0x00
|
||||
|
||||
.word 0x0100
|
||||
.word 0x1000
|
||||
.byte 0x00
|
||||
.word 0x4092
|
||||
.byte 0x00
|
||||
GDT32_END:
|
||||
nop
|
||||
|
||||
.global LoadGDT32
|
||||
LoadGDT32:
|
||||
lgdt [gdtr]
|
||||
ljmp $0x8, $ActivateGDT
|
||||
|
||||
ActivateGDT:
|
||||
mov $0x10, %cx
|
||||
mov %cx, %ss
|
||||
mov %cx, %ds
|
||||
mov %cx, %es
|
||||
mov %cx, %fs
|
||||
mov $0x18, %cx
|
||||
mov %cx, %gs
|
||||
ret
|
@ -1,62 +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/>.
|
||||
*/
|
||||
|
||||
.code64
|
||||
.section .bootstrap.data, "a"
|
||||
|
||||
/* Access bits */
|
||||
A = 0x1
|
||||
RW = 0x2
|
||||
DC = 0x4
|
||||
E = 0x8
|
||||
S = 0x10
|
||||
DPL0 = 0x0 /* 0 << 5 ???? */
|
||||
DPL1 = 0x20
|
||||
P = 0x80
|
||||
|
||||
/* Flags bits */
|
||||
LONG_MODE = 0x20
|
||||
SZ_32 = 0x40
|
||||
GRAN_4K = 0x80
|
||||
|
||||
.global GDT64.Null
|
||||
.global GDT64.Code
|
||||
.global GDT64.Data
|
||||
.global GDT64.Tss
|
||||
.global GDT64.Ptr
|
||||
|
||||
GDT64:
|
||||
GDT64.Null = . - GDT64
|
||||
.quad 0
|
||||
GDT64.Code = . - GDT64
|
||||
.long 0xFFFF
|
||||
.byte 0
|
||||
.byte P | S | E | RW
|
||||
.byte GRAN_4K | LONG_MODE | 0xF
|
||||
.byte 0
|
||||
GDT64.Data = . - GDT64
|
||||
.long 0xFFFF
|
||||
.byte 0
|
||||
.byte P | S | RW
|
||||
.byte GRAN_4K | SZ_32 | 0xF
|
||||
.byte 0
|
||||
GDT64.Tss = . - GDT64
|
||||
.long 0x00000068
|
||||
.long 0x00CF8900
|
||||
GDT64.Ptr:
|
||||
.word . - GDT64 - 1
|
||||
.quad GDT64
|
@ -1,38 +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/>.
|
||||
*/
|
||||
|
||||
.code32
|
||||
.extern Multiboot_start
|
||||
|
||||
.section .bootstrap.text, "a"
|
||||
|
||||
.global _start
|
||||
_start:
|
||||
/* Check for multiboot */
|
||||
cmp $0x2BADB002, %eax
|
||||
je .Multiboot
|
||||
|
||||
/* Unkown bootloader */
|
||||
.Hang:
|
||||
cli
|
||||
hlt
|
||||
jmp .Hang
|
||||
|
||||
/* Multiboot */
|
||||
.Multiboot:
|
||||
call Multiboot_start
|
||||
jmp .Hang
|
@ -1,51 +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>
|
||||
#include <cpu/x86/x64/SegmentDescriptors.hpp>
|
||||
|
||||
namespace InterruptDescriptorTable
|
||||
{
|
||||
|
||||
union IDTGateDescriptor
|
||||
{
|
||||
InterruptGate Interrupt;
|
||||
TrapGate Trap;
|
||||
CallGate Call;
|
||||
};
|
||||
|
||||
struct IDTRegister
|
||||
{
|
||||
uint16_t Limit;
|
||||
IDTGateDescriptor *BaseAddress;
|
||||
} __packed;
|
||||
|
||||
void SetEntry(uint8_t Index,
|
||||
void (*Base)(),
|
||||
InterruptStackTableType InterruptStackTable,
|
||||
GateType Gate,
|
||||
PrivilegeLevelType Ring,
|
||||
bool Present,
|
||||
uint16_t SegmentSelector);
|
||||
|
||||
void Init(int Core);
|
||||
}
|
||||
|
||||
#endif // !__FENNIX_KERNEL_IDT_H__
|
@ -1,104 +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(elf64-x86-64)
|
||||
OUTPUT_ARCH(i386:x86-64)
|
||||
|
||||
ENTRY(_start)
|
||||
|
||||
PF_R = 0x4;
|
||||
PF_W = 0x2;
|
||||
PF_X = 0x1;
|
||||
|
||||
PHDRS
|
||||
{
|
||||
bootstrap PT_LOAD FLAGS( PF_R | PF_W /*| PF_X*/ );
|
||||
text PT_LOAD FLAGS( PF_R | PF_X );
|
||||
data PT_LOAD FLAGS( PF_R | PF_W );
|
||||
rodata PT_LOAD FLAGS( PF_R );
|
||||
bss PT_LOAD FLAGS( PF_R | PF_W );
|
||||
}
|
||||
|
||||
KERNEL_VMA = 0xFFFFFFFF80000000;
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
. = 0x100000;
|
||||
_bootstrap_start = .;
|
||||
.bootstrap ALIGN(CONSTANT(MAXPAGESIZE)) :
|
||||
{
|
||||
*(.multiboot)
|
||||
*(.multiboot2)
|
||||
*(.bootstrap .bootstrap.*)
|
||||
} :bootstrap
|
||||
_bootstrap_end = ALIGN(CONSTANT(MAXPAGESIZE));
|
||||
|
||||
. += KERNEL_VMA;
|
||||
|
||||
_kernel_start = ALIGN(CONSTANT(MAXPAGESIZE));
|
||||
_kernel_text_start = ALIGN(CONSTANT(MAXPAGESIZE));
|
||||
.text ALIGN(CONSTANT(MAXPAGESIZE)) : AT(ADDR(.text) - KERNEL_VMA)
|
||||
{
|
||||
*(.text .text.*)
|
||||
} :text
|
||||
_kernel_text_end = ALIGN(CONSTANT(MAXPAGESIZE));
|
||||
|
||||
_kernel_data_start = ALIGN(CONSTANT(MAXPAGESIZE));
|
||||
.data ALIGN(CONSTANT(MAXPAGESIZE)) : AT(ADDR(.data) - KERNEL_VMA)
|
||||
{
|
||||
*(.data .data.*)
|
||||
} :data
|
||||
_kernel_data_end = ALIGN(CONSTANT(MAXPAGESIZE));
|
||||
|
||||
_kernel_rodata_start = ALIGN(CONSTANT(MAXPAGESIZE));
|
||||
.rodata ALIGN(CONSTANT(MAXPAGESIZE)) : AT(ADDR(.rodata) - KERNEL_VMA)
|
||||
{
|
||||
*(.rodata .rodata.*)
|
||||
} :rodata
|
||||
|
||||
.init_array ALIGN(CONSTANT(MAXPAGESIZE)) : AT(ADDR(.init_array) - KERNEL_VMA)
|
||||
{
|
||||
PROVIDE_HIDDEN(__init_array_start = .);
|
||||
KEEP(*(.init_array .ctors))
|
||||
KEEP(*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
|
||||
PROVIDE_HIDDEN (__init_array_end = .);
|
||||
} :rodata
|
||||
|
||||
.fini_array ALIGN(CONSTANT(MAXPAGESIZE)) : AT(ADDR(.fini_array) - KERNEL_VMA)
|
||||
{
|
||||
PROVIDE_HIDDEN(__fini_array_start = .);
|
||||
KEEP(*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
|
||||
KEEP(*(.fini_array .dtors))
|
||||
PROVIDE_HIDDEN (__fini_array_end = .);
|
||||
} :rodata
|
||||
_kernel_rodata_end = ALIGN(CONSTANT(MAXPAGESIZE));
|
||||
|
||||
_kernel_bss_start = ALIGN(CONSTANT(MAXPAGESIZE));
|
||||
.bss ALIGN(CONSTANT(MAXPAGESIZE)) : AT(ADDR(.bss) - KERNEL_VMA)
|
||||
{
|
||||
*(COMMON)
|
||||
*(.bss .bss.*)
|
||||
} :bss
|
||||
_kernel_bss_end = ALIGN(CONSTANT(MAXPAGESIZE));
|
||||
_kernel_end = ALIGN(CONSTANT(MAXPAGESIZE));
|
||||
|
||||
/DISCARD/ :
|
||||
{
|
||||
*(.comment*)
|
||||
*(.note*)
|
||||
}
|
||||
}
|
@ -1,27 +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/>.
|
||||
*/
|
||||
|
||||
.intel_syntax noprefix
|
||||
|
||||
.code32
|
||||
.section .multiboot, "a"
|
||||
.align 4
|
||||
|
||||
MULTIBOOT_HEADER:
|
||||
.long 0x1BADB002
|
||||
.long 1 << 0 | 1 << 1
|
||||
.long -(0x1BADB002 + (1 << 0 | 1 << 1))
|
@ -1,64 +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/>.
|
||||
*/
|
||||
|
||||
.code32
|
||||
.section .bootstrap.text, "a"
|
||||
|
||||
.align 32
|
||||
.global gdtr
|
||||
gdtr:
|
||||
.word GDT32_END - GDT32 - 1
|
||||
.long GDT32
|
||||
|
||||
.align 32
|
||||
GDT32:
|
||||
.quad 0x0
|
||||
|
||||
.word 0xFFFF
|
||||
.word 0x0000
|
||||
.byte 0x00
|
||||
.word 0xCF9A
|
||||
.byte 0x00
|
||||
|
||||
.word 0xFFFF
|
||||
.word 0x0000
|
||||
.byte 0x00
|
||||
.word 0xCF92
|
||||
.byte 0x00
|
||||
|
||||
.word 0x0100
|
||||
.word 0x1000
|
||||
.byte 0x00
|
||||
.word 0x4092
|
||||
.byte 0x00
|
||||
GDT32_END:
|
||||
nop
|
||||
|
||||
.global LoadGDT32
|
||||
LoadGDT32:
|
||||
lgdt [gdtr]
|
||||
ljmp $0x8, $ActivateGDT
|
||||
|
||||
ActivateGDT:
|
||||
mov $0x10, %cx
|
||||
mov %cx, %ss
|
||||
mov %cx, %ds
|
||||
mov %cx, %es
|
||||
mov %cx, %fs
|
||||
mov $0x18, %cx
|
||||
mov %cx, %gs
|
||||
ret
|
@ -1,38 +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/>.
|
||||
*/
|
||||
|
||||
.code32
|
||||
.extern Multiboot_start
|
||||
|
||||
.section .bootstrap.text, "a"
|
||||
|
||||
.global _start
|
||||
_start:
|
||||
/* Check for multiboot */
|
||||
cmp $0x2BADB002, %eax
|
||||
je .Multiboot
|
||||
|
||||
/* Unkown bootloader */
|
||||
.Hang:
|
||||
cli
|
||||
hlt
|
||||
jmp .Hang
|
||||
|
||||
/* Multiboot */
|
||||
.Multiboot:
|
||||
call Multiboot_start
|
||||
jmp .Hang
|
@ -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()
|
||||
{
|
||||
}
|
109
CREDITS.md
Normal file
109
CREDITS.md
Normal file
@ -0,0 +1,109 @@
|
||||
# Credits and References
|
||||
|
||||
This project has been influenced and inspired by other projects and resources.
|
||||
|
||||
License information can be found in the [LICENSES.md](LICENSES.md) file.
|
||||
|
||||
## General
|
||||
- [OSDev Wiki](https://wiki.osdev.org/Main_Page)
|
||||
- [GCC x86 Built-in Functions](https://gcc.gnu.org/onlinedocs/gcc/x86-Built-in-Functions.html#x86-Built-in-Functions)
|
||||
- [GCC Common Function Attributes](https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#Common-Function-Attributes)
|
||||
|
||||
## Font
|
||||
- [Tamsyn Font](http://www.fial.com/~scott/tamsyn-font/)
|
||||
|
||||
## CPU XCR0 Structure
|
||||
- [CPU Registers x86 - XCR0](https://wiki.osdev.org/CPU_Registers_x86#XCR0)
|
||||
|
||||
## CPUID 0x7
|
||||
- [CPUID](https://en.wikipedia.org/wiki/CPUID)
|
||||
|
||||
## Network
|
||||
- [Beej's Guide to Network Programming](https://web.archive.org/web/20051210132103/http://users.pcnet.ro/dmoroian/beej/Beej.html)
|
||||
- [UDP Socket Programming](https://web.archive.org/web/20060229214053/http://www.cs.rutgers.edu/~pxk/417/notes/sockets/udp.html)
|
||||
- [EtherType](https://en.wikipedia.org/wiki/EtherType)
|
||||
- [Linux Network Packet Reception](https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/6/html/performance_tuning_guide/s-network-packet-reception)
|
||||
- [Linux Kernel Networking Labs](https://linux-kernel-labs.github.io/refs/heads/master/labs/networking.html)
|
||||
- [smoltcp](https://github.com/smoltcp-rs/smoltcp)
|
||||
- [Understanding Linux Network Internals](https://www.cs.unh.edu/~cruse/cs326f04/RTL8139D_DataSheet.pdf)
|
||||
- [Address Resolution Protocol (ARP)](https://en.wikipedia.org/wiki/Address_Resolution_Protocol)
|
||||
- [C++ Operators](https://en.cppreference.com/w/cpp/language/operators)
|
||||
- [Dynamic Host Configuration Protocol (DHCP)](https://en.wikipedia.org/wiki/Dynamic_Host_Configuration_Protocol)
|
||||
- [RTL8139 Programmer's Guide](https://www.cs.usfca.edu/~cruse/cs326f04/RTL8139_ProgrammersGuide.pdf)
|
||||
- [RTL8139CP Datasheet](http://realtek.info/pdf/rtl8139cp.pdf)
|
||||
- [IPv4](https://en.wikipedia.org/wiki/IPv4)
|
||||
- [ICMP Parameters](https://www.iana.org/assignments/icmp-parameters/icmp-parameters.xhtml)
|
||||
|
||||
## Loading ELF Shared Libraries and Dynamic Linking
|
||||
- [How To Write Shared Libraries](https://www.akkadia.org/drepper/dsohowto.pdf)
|
||||
- [Dynamic Linker](https://wiki.osdev.org/Dynamic_Linker)
|
||||
- [Nightingale OS](https://github.com/tyler569/nightingale)
|
||||
- [PLT and GOT: The Key to Code Sharing and Dynamic Libraries](https://www.technovelty.org/linux/plt-and-got-the-key-to-code-sharing-and-dynamic-libraries.html)
|
||||
- [YouTube Video on Dynamic Linking](https://www.youtube.com/watch?v=kUk5pw4w0h4)
|
||||
- [Oracle: Position Independent Code](https://docs.oracle.com/cd/E19683-01/817-3677/chapter6-42444/index.html)
|
||||
- [PLT and GOT Explained](https://ir0nstone.gitbook.io/notes/types/stack/aslr/plt_and_got)
|
||||
|
||||
## Inter-Process Communication (IPC)
|
||||
- [Oracle IPC](https://docs.oracle.com/cd/E19048-01/chorus5/806-6897/architecture-103/index.html)
|
||||
- [Inter-Process Communication in OS](https://www.scaler.com/topics/operating-system/inter-process-communication-in-os/)
|
||||
- [IPC on Wikipedia](https://en.wikipedia.org/wiki/Inter-process_communication)
|
||||
- [GeeksforGeeks IPC Guide](https://www.geeksforgeeks.org/inter-process-communication-ipc/)
|
||||
|
||||
## PCI (Peripheral Component Interconnect)
|
||||
- [OSDev PCI](https://wiki.osdev.org/PCI)
|
||||
- [PCI Configuration Space](https://en.wikipedia.org/wiki/PCI_configuration_space)
|
||||
|
||||
## Audio
|
||||
- [FFmpeg Audio Types](https://trac.ffmpeg.org/wiki/audio%20types)
|
||||
- [AC97 on OSDev](https://wiki.osdev.org/AC97)
|
||||
- [LemonOS Project](https://github.com/LemonOSProject/LemonOS)
|
||||
- [AC97 Revision 2.3 Specification](https://inst.eecs.berkeley.edu//~cs150/Documents/ac97_r23.pdf)
|
||||
|
||||
## Intrinsics (x86)
|
||||
- [Microsoft x86 Intrinsics](https://learn.microsoft.com/en-us/cpp/intrinsics/x86-intrinsics-list)
|
||||
- [Intel Intrinsics Guide](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html)
|
||||
|
||||
## CPUID Information
|
||||
- [AMD CPUID Instruction](https://www.amd.com/system/files/TechDocs/40332.pdf)
|
||||
- [CPUID Instruction Note](https://www.scss.tcd.ie/~jones/CS4021/processor-identification-cpuid-instruction-note.pdf)
|
||||
|
||||
## SMBIOS (System Management BIOS)
|
||||
- [DMTF DSP0134](https://www.dmtf.org/dsp/DSP0134)
|
||||
- [DSP0134 Version 3.6.0](https://www.dmtf.org/sites/default/files/standards/documents/DSP0134_3.6.0.pdf)
|
||||
- [OSDev SMBIOS](https://wiki.osdev.org/System_Management_BIOS)
|
||||
|
||||
## EDBA (Effective Direct Bus Access)
|
||||
- [Memory Map (x86)](https://wiki.osdev.org/Memory_Map_(x86))
|
||||
|
||||
## UMIP, SMAP, and SMEP
|
||||
- [Control Register on Wikipedia](https://en.wikipedia.org/wiki/Control_register)
|
||||
- [Control Register and UMIP](https://web.archive.org/web/20160312223150/http://ncsi.com/nsatc11/presentations/wednesday/emerging_technologies/fischer.pdf)
|
||||
- [Supervisor Mode Access Prevention (SMEP)](https://en.wikipedia.org/wiki/Supervisor_Mode_Access_Prevention)
|
||||
|
||||
## Atomic Operations
|
||||
- [C++ Atomic Operations](https://en.cppreference.com/w/cpp/atomic/atomic)
|
||||
|
||||
## ELF (Executable and Linkable Format)
|
||||
- [ELF Header Format](https://www.sco.com/developers/gabi/latest/ch4.eheader.html)
|
||||
- [ELF File Format Specification](https://refspecs.linuxfoundation.org/elf/elf.pdf)
|
||||
- [Oracle: Executable and Linkable Format](https://docs.oracle.com/cd/E19683-01/817-3677/chapter6-42444/index.html)
|
||||
- [Oracle: ELF Program Headers](https://docs.oracle.com/cd/E19683-01/816-1386/chapter6-83432/index.html)
|
||||
- [YouTube Video on ELF](https://www.youtube.com/watch?v=nC1U1LJQL8o)
|
||||
- [Stevens' UNIX Network Programming](https://stevens.netmeister.org/631/elf.html)
|
||||
- [Linux Kernel ELF Header](https://github.com/torvalds/linux/blob/master/include/uapi/linux/elf.h)
|
||||
|
||||
## C++ ABI (Application Binary Interface)
|
||||
- [GCC libstdc++ Source](https://github.com/gcc-mirror/gcc/tree/master/libstdc%2B%2B-v3)
|
||||
- [Itanium C++ ABI](https://itanium-cxx-abi.github.io/cxx-abi/abi.html)
|
||||
|
||||
## Keyboard
|
||||
- [Scan Codes](https://www.win.tue.nl/~aeb/linux/kbd/scancodes-11.html)
|
||||
- [PS/2 Keyboard on OSDev](https://wiki.osdev.org/PS/2_Keyboard)
|
||||
|
||||
## signal.h
|
||||
- [POSIX signal.h](https://pubs.opengroup.org/onlinepubs/009695399/basedefs/signal.h.html)
|
||||
- [Linux signal(7) Manual](https://man7.org/linux/man-pages/man7/signal.7.html)
|
||||
|
||||
---
|
||||
|
||||
Special thanks to all contributors and the creators of the referenced projects and resources!
|
@ -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 "../../crashhandler.hpp"
|
||||
#include "../chfcts.hpp"
|
||||
|
||||
#include <display.hpp>
|
||||
#include <printf.h>
|
||||
#include <debug.h>
|
||||
#include <smp.hpp>
|
||||
#include <cpu.hpp>
|
||||
|
||||
#if defined(a64)
|
||||
#include "../../../Architecture/amd64/cpu/gdt.hpp"
|
||||
#elif defined(a32)
|
||||
#elif defined(aa64)
|
||||
#endif
|
||||
|
||||
#include "../../../kernel.h"
|
||||
|
||||
namespace CrashHandler
|
||||
{
|
||||
SafeFunction void DisplayConsoleScreen(CRData data)
|
||||
{
|
||||
EHPrint("TODO");
|
||||
UNUSED(data);
|
||||
}
|
||||
}
|
@ -1,402 +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 "../crashhandler.hpp"
|
||||
#include "chfcts.hpp"
|
||||
|
||||
#include <display.hpp>
|
||||
#include <printf.h>
|
||||
#include <debug.h>
|
||||
#include <smp.hpp>
|
||||
#include <cpu.hpp>
|
||||
|
||||
#if defined(a64)
|
||||
#include "../../Architecture/amd64/cpu/gdt.hpp"
|
||||
#elif defined(a32)
|
||||
#elif defined(aa64)
|
||||
#endif
|
||||
|
||||
#include "../../kernel.h"
|
||||
|
||||
static const char *PageFaultDescriptions[8] = {
|
||||
"Supervisory process tried to read a non-present page entry\n",
|
||||
"Supervisory process tried to read a page and caused a protection fault\n",
|
||||
"Supervisory process tried to write to a non-present page entry\n",
|
||||
"Supervisory process tried to write a page and caused a protection fault\n",
|
||||
"User process tried to read a non-present page entry\n",
|
||||
"User process tried to read a page and caused a protection fault\n",
|
||||
"User process tried to write to a non-present page entry\n",
|
||||
"User process tried to write a page and caused a protection fault\n"};
|
||||
|
||||
SafeFunction void UserModeExceptionHandler(CHArchTrapFrame *Frame)
|
||||
{
|
||||
CriticalSection cs;
|
||||
debug("Interrupts? %s.", cs.IsInterruptsEnabled() ? "Yes" : "No");
|
||||
fixme("Handling user mode exception");
|
||||
thisThread->Status = Tasking::TaskStatus::Zombie;
|
||||
CPUData *CurCPU = GetCurrentCPU();
|
||||
|
||||
{
|
||||
#if defined(a64)
|
||||
CPU::x64::CR0 cr0 = CPU::x64::readcr0();
|
||||
CPU::x64::CR2 cr2 = CPU::x64::CR2{.PFLA = CrashHandler::PageFaultAddress};
|
||||
CPU::x64::CR3 cr3 = CPU::x64::readcr3();
|
||||
CPU::x64::CR4 cr4 = CPU::x64::readcr4();
|
||||
CPU::x64::CR8 cr8 = CPU::x64::readcr8();
|
||||
CPU::x64::EFER efer;
|
||||
efer.raw = CPU::x64::rdmsr(CPU::x64::MSR_EFER);
|
||||
|
||||
error("Technical Informations on CPU %lld:", CurCPU->ID);
|
||||
uintptr_t ds;
|
||||
asmv("mov %%ds, %0"
|
||||
: "=r"(ds));
|
||||
#elif defined(a32)
|
||||
CPU::x32::CR0 cr0 = CPU::x32::readcr0();
|
||||
CPU::x32::CR2 cr2 = CPU::x32::CR2{.PFLA = CrashHandler::PageFaultAddress};
|
||||
CPU::x32::CR3 cr3 = CPU::x32::readcr3();
|
||||
CPU::x32::CR4 cr4 = CPU::x32::readcr4();
|
||||
CPU::x32::CR8 cr8 = CPU::x32::readcr8();
|
||||
|
||||
error("Technical Informations on CPU %lld:", CurCPU->ID);
|
||||
uintptr_t ds;
|
||||
asmv("mov %%ds, %0"
|
||||
: "=r"(ds));
|
||||
#elif defined(aa64)
|
||||
#endif
|
||||
|
||||
#if defined(a64)
|
||||
error("FS=%#lx GS=%#lx SS=%#lx CS=%#lx DS=%#lx",
|
||||
CPU::x64::rdmsr(CPU::x64::MSR_FS_BASE), CPU::x64::rdmsr(CPU::x64::MSR_GS_BASE),
|
||||
Frame->ss, Frame->cs, ds);
|
||||
error("R8=%#lx R9=%#lx R10=%#lx R11=%#lx", Frame->r8, Frame->r9, Frame->r10, Frame->r11);
|
||||
error("R12=%#lx R13=%#lx R14=%#lx R15=%#lx", Frame->r12, Frame->r13, Frame->r14, Frame->r15);
|
||||
error("RAX=%#lx RBX=%#lx RCX=%#lx RDX=%#lx", Frame->rax, Frame->rbx, Frame->rcx, Frame->rdx);
|
||||
error("RSI=%#lx RDI=%#lx RBP=%#lx RSP=%#lx", Frame->rsi, Frame->rdi, Frame->rbp, Frame->rsp);
|
||||
error("RIP=%#lx RFL=%#lx INT=%#lx ERR=%#lx EFER=%#lx", Frame->rip, Frame->rflags.raw, Frame->InterruptNumber, Frame->ErrorCode, efer.raw);
|
||||
#elif defined(a32)
|
||||
error("FS=%#x GS=%#x CS=%#x DS=%#x",
|
||||
CPU::x32::rdmsr(CPU::x32::MSR_FS_BASE), CPU::x32::rdmsr(CPU::x32::MSR_GS_BASE),
|
||||
Frame->cs, ds);
|
||||
error("EAX=%#x EBX=%#x ECX=%#x EDX=%#x", Frame->eax, Frame->ebx, Frame->ecx, Frame->edx);
|
||||
error("ESI=%#x EDI=%#x EBP=%#x ESP=%#x", Frame->esi, Frame->edi, Frame->ebp, Frame->esp);
|
||||
error("EIP=%#x EFL=%#x INT=%#x ERR=%#x", Frame->eip, Frame->eflags.raw, Frame->InterruptNumber, Frame->ErrorCode);
|
||||
#elif defined(aa64)
|
||||
#endif
|
||||
|
||||
#if defined(a86)
|
||||
error("CR0=%#lx CR2=%#lx CR3=%#lx CR4=%#lx CR8=%#lx", 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",
|
||||
cr0.PE ? "True " : "False", cr0.MP ? "True " : "False", cr0.EM ? "True " : "False", cr0.TS ? "True " : "False",
|
||||
cr0.ET ? "True " : "False", cr0.NE ? "True " : "False", cr0.WP ? "True " : "False", cr0.AM ? "True " : "False",
|
||||
cr0.NW ? "True " : "False", cr0.CD ? "True " : "False", cr0.PG ? "True " : "False",
|
||||
cr0.Reserved0, cr0.Reserved1, cr0.Reserved2);
|
||||
|
||||
error("CR2: PFLA: %#lx",
|
||||
cr2.PFLA);
|
||||
|
||||
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",
|
||||
cr4.VME ? "True " : "False", cr4.PVI ? "True " : "False", cr4.TSD ? "True " : "False", cr4.DE ? "True " : "False",
|
||||
cr4.PSE ? "True " : "False", cr4.PAE ? "True " : "False", cr4.MCE ? "True " : "False", cr4.PGE ? "True " : "False",
|
||||
cr4.PCE ? "True " : "False", cr4.UMIP ? "True " : "False", cr4.OSFXSR ? "True " : "False", cr4.OSXMMEXCPT ? "True " : "False",
|
||||
cr4.LA57 ? "True " : "False", cr4.VMXE ? "True " : "False", cr4.SMXE ? "True " : "False", cr4.PCIDE ? "True " : "False",
|
||||
cr4.OSXSAVE ? "True " : "False", cr4.SMEP ? "True " : "False", cr4.SMAP ? "True " : "False", cr4.PKE ? "True " : "False",
|
||||
cr4.Reserved0, cr4.Reserved1, cr4.Reserved2);
|
||||
#elif defined(a32)
|
||||
error("CR4: VME:%s PVI:%s TSD:%s DE:%s PSE:%s PAE:%s MCE:%s PGE:%s PCE:%s UMIP:%s OSFXSR:%s OSXMMEXCPT:%s LA57:%s VMXE:%s SMXE:%s PCIDE:%s OSXSAVE:%s SMEP:%s SMAP:%s PKE:%s R0:%#x R1:%#x",
|
||||
cr4.VME ? "True " : "False", cr4.PVI ? "True " : "False", cr4.TSD ? "True " : "False", cr4.DE ? "True " : "False",
|
||||
cr4.PSE ? "True " : "False", cr4.PAE ? "True " : "False", cr4.MCE ? "True " : "False", cr4.PGE ? "True " : "False",
|
||||
cr4.PCE ? "True " : "False", cr4.UMIP ? "True " : "False", cr4.OSFXSR ? "True " : "False", cr4.OSXMMEXCPT ? "True " : "False",
|
||||
cr4.LA57 ? "True " : "False", cr4.VMXE ? "True " : "False", cr4.SMXE ? "True " : "False", cr4.PCIDE ? "True " : "False",
|
||||
cr4.OSXSAVE ? "True " : "False", cr4.SMEP ? "True " : "False", cr4.SMAP ? "True " : "False", cr4.PKE ? "True " : "False",
|
||||
cr4.Reserved0, cr4.Reserved1);
|
||||
#endif
|
||||
|
||||
#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",
|
||||
Frame->rflags.CF ? "True " : "False", Frame->rflags.PF ? "True " : "False", Frame->rflags.AF ? "True " : "False", Frame->rflags.ZF ? "True " : "False",
|
||||
Frame->rflags.SF ? "True " : "False", Frame->rflags.TF ? "True " : "False", Frame->rflags.IF ? "True " : "False", Frame->rflags.DF ? "True " : "False",
|
||||
Frame->rflags.OF ? "True " : "False", Frame->rflags.IOPL ? "True " : "False", Frame->rflags.NT ? "True " : "False", Frame->rflags.RF ? "True " : "False",
|
||||
Frame->rflags.VM ? "True " : "False", Frame->rflags.AC ? "True " : "False", Frame->rflags.VIF ? "True " : "False", Frame->rflags.VIP ? "True " : "False",
|
||||
Frame->rflags.ID ? "True " : "False", Frame->rflags.AlwaysOne,
|
||||
Frame->rflags.Reserved0, Frame->rflags.Reserved1, Frame->rflags.Reserved2, Frame->rflags.Reserved3);
|
||||
#elif defined(a32)
|
||||
error("EFL: CF:%s PF:%s AF:%s ZF:%s SF:%s TF:%s IF:%s DF:%s OF:%s IOPL:%s NT:%s RF:%s VM:%s AC:%s VIF:%s VIP:%s ID:%s AlwaysOne:%d R0:%#x R1:%#x R2:%#x",
|
||||
Frame->eflags.CF ? "True " : "False", Frame->eflags.PF ? "True " : "False", Frame->eflags.AF ? "True " : "False", Frame->eflags.ZF ? "True " : "False",
|
||||
Frame->eflags.SF ? "True " : "False", Frame->eflags.TF ? "True " : "False", Frame->eflags.IF ? "True " : "False", Frame->eflags.DF ? "True " : "False",
|
||||
Frame->eflags.OF ? "True " : "False", Frame->eflags.IOPL ? "True " : "False", Frame->eflags.NT ? "True " : "False", Frame->eflags.RF ? "True " : "False",
|
||||
Frame->eflags.VM ? "True " : "False", Frame->eflags.AC ? "True " : "False", Frame->eflags.VIF ? "True " : "False", Frame->eflags.VIP ? "True " : "False",
|
||||
Frame->eflags.ID ? "True " : "False", Frame->eflags.AlwaysOne,
|
||||
Frame->eflags.Reserved0, Frame->eflags.Reserved1, Frame->eflags.Reserved2);
|
||||
#elif defined(aa64)
|
||||
#endif
|
||||
|
||||
#if defined(a64)
|
||||
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
|
||||
}
|
||||
|
||||
switch (Frame->InterruptNumber)
|
||||
{
|
||||
case CPU::x86::DivideByZero:
|
||||
{
|
||||
break;
|
||||
}
|
||||
case CPU::x86::Debug:
|
||||
{
|
||||
break;
|
||||
}
|
||||
case CPU::x86::NonMaskableInterrupt:
|
||||
{
|
||||
break;
|
||||
}
|
||||
case CPU::x86::Breakpoint:
|
||||
{
|
||||
break;
|
||||
}
|
||||
case CPU::x86::Overflow:
|
||||
{
|
||||
break;
|
||||
}
|
||||
case CPU::x86::BoundRange:
|
||||
{
|
||||
break;
|
||||
}
|
||||
case CPU::x86::InvalidOpcode:
|
||||
{
|
||||
break;
|
||||
}
|
||||
case CPU::x86::DeviceNotAvailable:
|
||||
{
|
||||
break;
|
||||
}
|
||||
case CPU::x86::DoubleFault:
|
||||
{
|
||||
break;
|
||||
}
|
||||
case CPU::x86::CoprocessorSegmentOverrun:
|
||||
{
|
||||
break;
|
||||
}
|
||||
case CPU::x86::InvalidTSS:
|
||||
{
|
||||
break;
|
||||
}
|
||||
case CPU::x86::SegmentNotPresent:
|
||||
{
|
||||
break;
|
||||
}
|
||||
case CPU::x86::StackSegmentFault:
|
||||
{
|
||||
break;
|
||||
}
|
||||
case CPU::x86::GeneralProtectionFault:
|
||||
{
|
||||
break;
|
||||
}
|
||||
case CPU::x86::PageFault:
|
||||
{
|
||||
uintptr_t CheckPageFaultAddress = 0;
|
||||
CPU::x64::PageFaultErrorCode params = {.raw = (uint32_t)Frame->ErrorCode};
|
||||
#if defined(a64)
|
||||
CheckPageFaultAddress = CrashHandler::PageFaultAddress;
|
||||
if (CheckPageFaultAddress == 0)
|
||||
CheckPageFaultAddress = Frame->rip;
|
||||
|
||||
error("An exception occurred at %#lx by %#lx", CrashHandler::PageFaultAddress, Frame->rip);
|
||||
#elif defined(a32)
|
||||
CheckPageFaultAddress = CrashHandler::PageFaultAddress;
|
||||
if (CheckPageFaultAddress == 0)
|
||||
CheckPageFaultAddress = Frame->eip;
|
||||
|
||||
error("An exception occurred at %#lx by %#lx", CrashHandler::PageFaultAddress, Frame->eip);
|
||||
#elif defined(aa64)
|
||||
#endif
|
||||
error("Page: %s", params.P ? "Present" : "Not Present");
|
||||
error("Write Operation: %s", params.W ? "Read-Only" : "Read-Write");
|
||||
error("Processor Mode: %s", params.U ? "User-Mode" : "Kernel-Mode");
|
||||
error("CPU Reserved Bits: %s", params.R ? "Reserved" : "Unreserved");
|
||||
error("Caused By An Instruction Fetch: %s", params.I ? "Yes" : "No");
|
||||
error("Caused By A Protection-Key Violation: %s", params.PK ? "Yes" : "No");
|
||||
error("Caused By A Shadow Stack Access: %s", params.SS ? "Yes" : "No");
|
||||
error("Caused By An SGX Violation: %s", params.SGX ? "Yes" : "No");
|
||||
if (Frame->ErrorCode & 0x00000008)
|
||||
error("One or more page directory entries contain reserved bits which are set to 1.");
|
||||
else
|
||||
error(PageFaultDescriptions[Frame->ErrorCode & 0b111]);
|
||||
|
||||
#ifdef DEBUG
|
||||
if (CurCPU)
|
||||
{
|
||||
Memory::Virtual vmm = Memory::Virtual(CurCPU->CurrentProcess->PageTable);
|
||||
bool PageAvailable = vmm.Check((void *)CheckPageFaultAddress);
|
||||
debug("Page available (Check(...)): %s. %s",
|
||||
PageAvailable ? "Yes" : "No",
|
||||
(params.P && !PageAvailable) ? "CR2 == Present; Check() != Present??????" : "CR2 confirms Check() result.");
|
||||
|
||||
if (PageAvailable)
|
||||
{
|
||||
bool Present = vmm.Check((void *)CheckPageFaultAddress);
|
||||
bool ReadWrite = vmm.Check((void *)CheckPageFaultAddress, Memory::PTFlag::RW);
|
||||
bool User = vmm.Check((void *)CheckPageFaultAddress, Memory::PTFlag::US);
|
||||
bool WriteThrough = vmm.Check((void *)CheckPageFaultAddress, Memory::PTFlag::PWT);
|
||||
bool CacheDisabled = vmm.Check((void *)CheckPageFaultAddress, Memory::PTFlag::PCD);
|
||||
bool Accessed = vmm.Check((void *)CheckPageFaultAddress, Memory::PTFlag::A);
|
||||
bool Dirty = vmm.Check((void *)CheckPageFaultAddress, Memory::PTFlag::D);
|
||||
bool Global = vmm.Check((void *)CheckPageFaultAddress, Memory::PTFlag::G);
|
||||
/* ... */
|
||||
|
||||
debug("Page available: %s", Present ? "Yes" : "No");
|
||||
debug("Page read/write: %s", ReadWrite ? "Yes" : "No");
|
||||
debug("Page user/kernel: %s", User ? "User" : "Kernel");
|
||||
debug("Page write-through: %s", WriteThrough ? "Yes" : "No");
|
||||
debug("Page cache disabled: %s", CacheDisabled ? "Yes" : "No");
|
||||
debug("Page accessed: %s", Accessed ? "Yes" : "No");
|
||||
debug("Page dirty: %s", Dirty ? "Yes" : "No");
|
||||
debug("Page global: %s", Global ? "Yes" : "No");
|
||||
|
||||
if (Present)
|
||||
{
|
||||
#if defined(a64)
|
||||
uintptr_t CheckPageFaultLinearAddress = (uintptr_t)CheckPageFaultAddress;
|
||||
CheckPageFaultLinearAddress &= 0xFFFFFFFFFFFFF000;
|
||||
debug("%#lx -> %#lx", CheckPageFaultAddress, CheckPageFaultLinearAddress);
|
||||
|
||||
Memory::Virtual::PageMapIndexer Index = Memory::Virtual::PageMapIndexer((uintptr_t)CheckPageFaultLinearAddress);
|
||||
debug("Index for %#lx is PML:%d PDPTE:%d PDE:%d PTE:%d",
|
||||
CheckPageFaultLinearAddress,
|
||||
Index.PMLIndex,
|
||||
Index.PDPTEIndex,
|
||||
Index.PDEIndex,
|
||||
Index.PTEIndex);
|
||||
Memory::PageMapLevel4 PML4 = CurCPU->CurrentProcess->PageTable->Entries[Index.PMLIndex];
|
||||
|
||||
Memory::PageDirectoryPointerTableEntryPtr *PDPTE = (Memory::PageDirectoryPointerTableEntryPtr *)((uintptr_t)PML4.GetAddress() << 12);
|
||||
Memory::PageDirectoryEntryPtr *PDE = (Memory::PageDirectoryEntryPtr *)((uintptr_t)PDPTE->Entries[Index.PDPTEIndex].GetAddress() << 12);
|
||||
Memory::PageTableEntryPtr *PTE = (Memory::PageTableEntryPtr *)((uintptr_t)PDE->Entries[Index.PDEIndex].GetAddress() << 12);
|
||||
|
||||
debug("# %03d-%03d-%03d-%03d: P:%s RW:%s US:%s PWT:%s PCB:%s A:%s NX:%s Address:%#lx",
|
||||
Index.PMLIndex, 0, 0, 0,
|
||||
PML4.Present ? "1" : "0",
|
||||
PML4.ReadWrite ? "1" : "0",
|
||||
PML4.UserSupervisor ? "1" : "0",
|
||||
PML4.WriteThrough ? "1" : "0",
|
||||
PML4.CacheDisable ? "1" : "0",
|
||||
PML4.Accessed ? "1" : "0",
|
||||
PML4.ExecuteDisable ? "1" : "0",
|
||||
PML4.GetAddress() << 12);
|
||||
|
||||
debug("# %03d-%03d-%03d-%03d: P:%s RW:%s US:%s PWT:%s PCB:%s A:%s NX:%s Address:%#lx",
|
||||
Index.PMLIndex, Index.PDPTEIndex, 0, 0,
|
||||
PDPTE->Entries[Index.PDPTEIndex].Present ? "1" : "0",
|
||||
PDPTE->Entries[Index.PDPTEIndex].ReadWrite ? "1" : "0",
|
||||
PDPTE->Entries[Index.PDPTEIndex].UserSupervisor ? "1" : "0",
|
||||
PDPTE->Entries[Index.PDPTEIndex].WriteThrough ? "1" : "0",
|
||||
PDPTE->Entries[Index.PDPTEIndex].CacheDisable ? "1" : "0",
|
||||
PDPTE->Entries[Index.PDPTEIndex].Accessed ? "1" : "0",
|
||||
PDPTE->Entries[Index.PDPTEIndex].ExecuteDisable ? "1" : "0",
|
||||
PDPTE->Entries[Index.PDPTEIndex].GetAddress() << 12);
|
||||
|
||||
debug("# %03d-%03d-%03d-%03d: P:%s RW:%s US:%s PWT:%s PCB:%s A:%s NX:%s Address:%#lx",
|
||||
Index.PMLIndex, Index.PDPTEIndex, Index.PDEIndex, 0,
|
||||
PDE->Entries[Index.PDEIndex].Present ? "1" : "0",
|
||||
PDE->Entries[Index.PDEIndex].ReadWrite ? "1" : "0",
|
||||
PDE->Entries[Index.PDEIndex].UserSupervisor ? "1" : "0",
|
||||
PDE->Entries[Index.PDEIndex].WriteThrough ? "1" : "0",
|
||||
PDE->Entries[Index.PDEIndex].CacheDisable ? "1" : "0",
|
||||
PDE->Entries[Index.PDEIndex].Accessed ? "1" : "0",
|
||||
PDE->Entries[Index.PDEIndex].ExecuteDisable ? "1" : "0",
|
||||
PDE->Entries[Index.PDEIndex].GetAddress() << 12);
|
||||
|
||||
debug("# %03d-%03d-%03d-%03d: P:%s RW:%s US:%s PWT:%s PCB:%s A:%s D:%s PAT:%s G:%s PK:%d NX:%s Address:%#lx",
|
||||
Index.PMLIndex, Index.PDPTEIndex, Index.PDEIndex, Index.PTEIndex,
|
||||
PTE->Entries[Index.PTEIndex].Present ? "1" : "0",
|
||||
PTE->Entries[Index.PTEIndex].ReadWrite ? "1" : "0",
|
||||
PTE->Entries[Index.PTEIndex].UserSupervisor ? "1" : "0",
|
||||
PTE->Entries[Index.PTEIndex].WriteThrough ? "1" : "0",
|
||||
PTE->Entries[Index.PTEIndex].CacheDisable ? "1" : "0",
|
||||
PTE->Entries[Index.PTEIndex].Accessed ? "1" : "0",
|
||||
PTE->Entries[Index.PTEIndex].Dirty ? "1" : "0",
|
||||
PTE->Entries[Index.PTEIndex].PageAttributeTable ? "1" : "0",
|
||||
PTE->Entries[Index.PTEIndex].Global ? "1" : "0",
|
||||
PTE->Entries[Index.PTEIndex].ProtectionKey,
|
||||
PTE->Entries[Index.PTEIndex].ExecuteDisable ? "1" : "0",
|
||||
PTE->Entries[Index.PTEIndex].GetAddress() << 12);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (CurCPU)
|
||||
if (CurCPU->CurrentThread->Stack->Expand(CrashHandler::PageFaultAddress))
|
||||
{
|
||||
debug("Stack expanded");
|
||||
thisThread->Status = Tasking::TaskStatus::Ready;
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CPU::x86::x87FloatingPoint:
|
||||
{
|
||||
break;
|
||||
}
|
||||
case CPU::x86::AlignmentCheck:
|
||||
{
|
||||
break;
|
||||
}
|
||||
case CPU::x86::MachineCheck:
|
||||
{
|
||||
break;
|
||||
}
|
||||
case CPU::x86::SIMDFloatingPoint:
|
||||
{
|
||||
break;
|
||||
}
|
||||
case CPU::x86::Virtualization:
|
||||
{
|
||||
break;
|
||||
}
|
||||
case CPU::x86::Security:
|
||||
{
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
thisThread->Status = Tasking::TaskStatus::Terminated;
|
||||
__sync;
|
||||
error("End of report.");
|
||||
CPU::Interrupts(CPU::Enable);
|
||||
debug("Interrupts enabled back.");
|
||||
return;
|
||||
}
|
194
Core/Disk.cpp
194
Core/Disk.cpp
@ -1,194 +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 <disk.hpp>
|
||||
|
||||
#include <memory.hpp>
|
||||
#include <printf.h>
|
||||
|
||||
#include "../kernel.h"
|
||||
#include "../DAPI.hpp"
|
||||
#include "../Fex.hpp"
|
||||
|
||||
namespace Disk
|
||||
{
|
||||
void Manager::FetchDisks(unsigned long DriverUID)
|
||||
{
|
||||
KernelCallback callback{};
|
||||
callback.Reason = QueryReason;
|
||||
DriverManager->IOCB(DriverUID, &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)
|
||||
return;
|
||||
|
||||
uint8_t *RWBuffer = (uint8_t *)KernelAllocator.RequestPages(TO_PAGES(this->BytesPerSector + 1));
|
||||
|
||||
for (unsigned char ItrPort = 0; ItrPort < this->AvailablePorts; ItrPort++)
|
||||
{
|
||||
Drive drive{};
|
||||
sprintf(drive.Name, "sd%ld", DriverUID);
|
||||
debug("Drive Name: %s", drive.Name);
|
||||
// TODO: Implement disk type detection. Very useful in the future.
|
||||
drive.MechanicalDisk = true;
|
||||
|
||||
memset(RWBuffer, 0, this->BytesPerSector);
|
||||
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));
|
||||
|
||||
/*
|
||||
TODO: Add to devfs the disk
|
||||
*/
|
||||
|
||||
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;
|
||||
for (uint32_t Block = 0; Block < Sectors; Block++)
|
||||
{
|
||||
memset(RWBuffer, 0, this->BytesPerSector);
|
||||
callback.Reason = ReceiveReason;
|
||||
callback.DiskCallback.RW = {
|
||||
.Sector = 2 + Block,
|
||||
.SectorCount = 1,
|
||||
.Port = ItrPort,
|
||||
.Buffer = RWBuffer,
|
||||
.Write = false,
|
||||
};
|
||||
DriverManager->IOCB(DriverUID, &callback);
|
||||
|
||||
for (uint32_t e = 0; e < Entries; e++)
|
||||
{
|
||||
GUIDPartitionTableEntry GPTPartition = reinterpret_cast<GUIDPartitionTableEntry *>(RWBuffer)[e];
|
||||
if (memcmp(GPTPartition.PartitionType, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", sizeof(GPTPartition.PartitionType)) != 0)
|
||||
{
|
||||
debug("Partition Type: %02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X",
|
||||
GPTPartition.PartitionType[0], GPTPartition.PartitionType[1], GPTPartition.PartitionType[2], GPTPartition.PartitionType[3],
|
||||
GPTPartition.PartitionType[4], GPTPartition.PartitionType[5], GPTPartition.PartitionType[6], GPTPartition.PartitionType[7],
|
||||
GPTPartition.PartitionType[8], GPTPartition.PartitionType[9], GPTPartition.PartitionType[10], GPTPartition.PartitionType[11],
|
||||
GPTPartition.PartitionType[12], GPTPartition.PartitionType[13], GPTPartition.PartitionType[14], GPTPartition.PartitionType[15]);
|
||||
|
||||
debug("Unique Partition GUID: %02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X",
|
||||
GPTPartition.UniquePartitionGUID[0], GPTPartition.UniquePartitionGUID[1], GPTPartition.UniquePartitionGUID[2], GPTPartition.UniquePartitionGUID[3],
|
||||
GPTPartition.UniquePartitionGUID[4], GPTPartition.UniquePartitionGUID[5], GPTPartition.UniquePartitionGUID[6], GPTPartition.UniquePartitionGUID[7],
|
||||
GPTPartition.UniquePartitionGUID[8], GPTPartition.UniquePartitionGUID[9], GPTPartition.UniquePartitionGUID[10], GPTPartition.UniquePartitionGUID[11],
|
||||
GPTPartition.UniquePartitionGUID[12], GPTPartition.UniquePartitionGUID[13], GPTPartition.UniquePartitionGUID[14], GPTPartition.UniquePartitionGUID[15]);
|
||||
|
||||
Partition partition{};
|
||||
memset(partition.Label, '\0', sizeof(partition.Label));
|
||||
/* Convert utf16 to utf8 */
|
||||
for (int i = 0; i < 36; i++)
|
||||
{
|
||||
uint16_t utf16 = GPTPartition.PartitionName[i];
|
||||
if (utf16 == 0)
|
||||
break;
|
||||
if (utf16 < 0x80)
|
||||
partition.Label[i] = (char)utf16;
|
||||
else if (utf16 < 0x800)
|
||||
{
|
||||
partition.Label[i] = (char)(0xC0 | (utf16 >> 6));
|
||||
partition.Label[i + 1] = (char)(0x80 | (utf16 & 0x3F));
|
||||
i++;
|
||||
}
|
||||
else
|
||||
{
|
||||
partition.Label[i] = (char)(0xE0 | (utf16 >> 12));
|
||||
partition.Label[i + 1] = (char)(0x80 | ((utf16 >> 6) & 0x3F));
|
||||
partition.Label[i + 2] = (char)(0x80 | (utf16 & 0x3F));
|
||||
i += 2;
|
||||
}
|
||||
}
|
||||
partition.StartLBA = GPTPartition.FirstLBA;
|
||||
partition.EndLBA = GPTPartition.LastLBA;
|
||||
partition.Sectors = (size_t)(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();
|
||||
trace("GPT partition \"%s\" found with %lld sectors", partition.Label, partition.Sectors);
|
||||
drive.Partitions.push_back(partition);
|
||||
|
||||
char PartitionName[64];
|
||||
sprintf(PartitionName, "sd%ldp%ld", drives.size(), partition.Index);
|
||||
fixme("PartitionName: %s", PartitionName);
|
||||
|
||||
/*
|
||||
TODO: Add to devfs the disk
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
trace("%d GPT partitions found.", drive.Partitions.size());
|
||||
}
|
||||
else if (drive.Table.MBR.Signature[0] == MBR_MAGIC0 && drive.Table.MBR.Signature[1] == MBR_MAGIC1)
|
||||
{
|
||||
drive.Style = MBR;
|
||||
for (size_t p = 0; p < 4; p++)
|
||||
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);
|
||||
|
||||
char PartitionName[64];
|
||||
sprintf(PartitionName, "sd%ldp%ld", drives.size(), partition.Index);
|
||||
fixme("PartitionName: %s", PartitionName);
|
||||
|
||||
/*
|
||||
TODO: Add to devfs the disk
|
||||
*/
|
||||
}
|
||||
trace("%d MBR partitions found.", drive.Partitions.size());
|
||||
}
|
||||
else
|
||||
warn("No partition table found on port %d!", ItrPort);
|
||||
|
||||
drives.push_back(drive);
|
||||
}
|
||||
|
||||
KernelAllocator.FreePages(RWBuffer, TO_PAGES(this->BytesPerSector + 1));
|
||||
}
|
||||
|
||||
Manager::Manager()
|
||||
{
|
||||
}
|
||||
|
||||
Manager::~Manager()
|
||||
{
|
||||
debug("Destructor called");
|
||||
}
|
||||
}
|
@ -1,339 +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 <driver.hpp>
|
||||
|
||||
#include <memory.hpp>
|
||||
#include <ints.hpp>
|
||||
#include <task.hpp>
|
||||
#include <printf.h>
|
||||
#include <cwalk.h>
|
||||
#include <md5.h>
|
||||
|
||||
#include "../../Modules/drv.hpp"
|
||||
#include "../../kernel.h"
|
||||
#include "../../DAPI.hpp"
|
||||
#include "../../Fex.hpp"
|
||||
#include "api.hpp"
|
||||
|
||||
namespace Driver
|
||||
{
|
||||
void Driver::Panic()
|
||||
{
|
||||
debug("%ld drivers loaded, [DriverUIDs: %ld]", Drivers.size(), DriverUIDs - 1);
|
||||
|
||||
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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Driver::UnloadAllDrivers()
|
||||
{
|
||||
debug("%ld drivers loaded, [DriverUIDs: %ld]", Drivers.size(), DriverUIDs - 1);
|
||||
|
||||
foreach (auto Drv in Drivers)
|
||||
{
|
||||
KernelCallback callback{};
|
||||
callback.Reason = StopReason;
|
||||
debug("Stopping & unloading driver %ld [%#lx]", Drv.DriverUID, Drv.Address);
|
||||
DriverManager->IOCB(Drv.DriverUID, &callback);
|
||||
|
||||
for (size_t j = 0; j < sizeof(Drv.InterruptHook) / sizeof(Drv.InterruptHook[0]); j++)
|
||||
{
|
||||
if (!Drv.InterruptHook[j])
|
||||
continue;
|
||||
|
||||
debug("Interrupt hook %#lx", Drv.InterruptHook[j]);
|
||||
delete Drv.InterruptHook[j], Drv.InterruptHook[j] = nullptr;
|
||||
}
|
||||
|
||||
if (Drv.MemTrk)
|
||||
delete Drv.MemTrk, Drv.MemTrk = nullptr;
|
||||
}
|
||||
Drivers.clear();
|
||||
}
|
||||
|
||||
bool Driver::UnloadDriver(unsigned long DUID)
|
||||
{
|
||||
debug("Searching for driver %ld", DUID);
|
||||
|
||||
forItr(Drv, Drivers)
|
||||
{
|
||||
if (Drv->DriverUID != DUID)
|
||||
continue;
|
||||
|
||||
KernelCallback callback{};
|
||||
callback.Reason = StopReason;
|
||||
debug("Stopping & unloading driver %ld [%#lx]", Drv->DriverUID, Drv->Address);
|
||||
this->IOCB(Drv->DriverUID, &callback);
|
||||
|
||||
for (size_t j = 0; j < sizeof(Drv->InterruptHook) / sizeof(Drv->InterruptHook[0]); j++)
|
||||
{
|
||||
if (!Drv->InterruptHook[j])
|
||||
continue;
|
||||
|
||||
debug("Interrupt hook %#lx", Drv->InterruptHook[j]);
|
||||
delete Drv->InterruptHook[j], Drv->InterruptHook[j] = nullptr;
|
||||
}
|
||||
|
||||
if (Drv->MemTrk)
|
||||
delete Drv->MemTrk, Drv->MemTrk = nullptr;
|
||||
|
||||
Drivers.erase(Drv);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int Driver::IOCB(unsigned long DUID, void *KCB)
|
||||
{
|
||||
foreach (auto Drv in Drivers)
|
||||
{
|
||||
if (Drv.DriverUID != DUID)
|
||||
continue;
|
||||
|
||||
FexExtended *fexE = (FexExtended *)Drv.ExtendedHeaderAddress;
|
||||
return ((int (*)(void *))((uintptr_t)fexE->Driver.Callback + (uintptr_t)Drv.Address))(KCB);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
DriverCode Driver::CallDriverEntryPoint(void *fex, bool BuiltIn)
|
||||
{
|
||||
DriverCode ret{};
|
||||
KernelAPI DriverKAPI = KernelAPITemplate;
|
||||
|
||||
DriverKAPI.Info.DriverUID = DriverUIDs++;
|
||||
DriverKAPI.Info.KernelDebug = DebuggerIsAttached;
|
||||
|
||||
debug("Calling driver entry point ( %#lx %ld )", (unsigned long)fex, DriverKAPI.Info.DriverUID);
|
||||
|
||||
if (!BuiltIn)
|
||||
{
|
||||
DriverKAPI.Info.Offset = (unsigned long)fex;
|
||||
|
||||
debug("DRIVER: %s HAS DRIVER ID %ld",
|
||||
((FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS))->Driver.Name,
|
||||
DriverKAPI.Info.DriverUID);
|
||||
ret = ((DriverCode(*)(KernelAPI *))((uintptr_t)((Fex *)fex)->EntryPoint + (uintptr_t)fex))(((KernelAPI *)&DriverKAPI));
|
||||
}
|
||||
else
|
||||
{
|
||||
debug("DRIVER: BUILTIN HAS DRIVER ID %ld", DriverKAPI.Info.DriverUID);
|
||||
ret = ((DriverCode(*)(KernelAPI *))((uintptr_t)fex))(((KernelAPI *)&DriverKAPI));
|
||||
}
|
||||
|
||||
if (DriverCode::OK != ret)
|
||||
{
|
||||
DriverUIDs--;
|
||||
return ret;
|
||||
}
|
||||
return DriverCode::OK;
|
||||
}
|
||||
|
||||
DriverCode Driver::LoadDriver(uintptr_t DriverAddress, size_t Size)
|
||||
{
|
||||
Fex *DrvHdr = (Fex *)DriverAddress;
|
||||
if (DrvHdr->Magic[0] != 'F' || DrvHdr->Magic[1] != 'E' || DrvHdr->Magic[2] != 'X' || DrvHdr->Magic[3] != '\0')
|
||||
return DriverCode::INVALID_FEX_HEADER;
|
||||
|
||||
debug("Fex Magic: \"%s\"; Type: %d; OS: %d; EntryPoint: %#lx", DrvHdr->Magic, DrvHdr->Type, DrvHdr->OS, DrvHdr->EntryPoint);
|
||||
|
||||
if (DrvHdr->Type != FexFormatType::FexFormatType_Driver)
|
||||
return DriverCode::NOT_DRIVER;
|
||||
|
||||
FexExtended *fexE = (FexExtended *)((uintptr_t)DrvHdr + EXTENDED_SECTION_ADDRESS);
|
||||
debug("Name: \"%s\"; Type: %d; Callback: %#lx", fexE->Driver.Name, fexE->Driver.Type, fexE->Driver.Callback);
|
||||
|
||||
switch (fexE->Driver.Bind.Type)
|
||||
{
|
||||
case DriverBindType::BIND_PCI:
|
||||
return this->DriverLoadBindPCI(DriverAddress, Size);
|
||||
case DriverBindType::BIND_INTERRUPT:
|
||||
return this->DriverLoadBindInterrupt(DriverAddress, Size);
|
||||
case DriverBindType::BIND_PROCESS:
|
||||
return this->DriverLoadBindProcess(DriverAddress, Size);
|
||||
case DriverBindType::BIND_INPUT:
|
||||
return this->DriverLoadBindInput(DriverAddress, Size);
|
||||
default:
|
||||
{
|
||||
error("Unknown driver bind type: %d", fexE->Driver.Bind.Type);
|
||||
return DriverCode::UNKNOWN_DRIVER_BIND_TYPE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Driver::LoadDrivers()
|
||||
{
|
||||
SmartCriticalSection(DriverInitLock);
|
||||
|
||||
std::string DriverConfigFile = Config.DriverDirectory;
|
||||
DriverConfigFile << "/config.ini";
|
||||
fixme("Loading driver config file: %s", DriverConfigFile.c_str());
|
||||
|
||||
debug("Loading built-in drivers");
|
||||
StartAHCI();
|
||||
StartVMwareMouse();
|
||||
StartPS2Mouse();
|
||||
StartPS2Keyboard();
|
||||
StartATA();
|
||||
StartAC97();
|
||||
StartRTL8139();
|
||||
StartPCNET();
|
||||
StartGigabit();
|
||||
|
||||
RefNode *DriverDirectory = vfs->Open(Config.DriverDirectory);
|
||||
if (!DriverDirectory)
|
||||
{
|
||||
KPrint("\eE85230Failed to open %s: %d)",
|
||||
Config.DriverDirectory, errno);
|
||||
return;
|
||||
}
|
||||
|
||||
debug("Loading drivers from %s", Config.DriverDirectory);
|
||||
foreach (auto DrvFile in DriverDirectory->GetNode()->Children)
|
||||
{
|
||||
if (DrvFile->Flags != VirtualFileSystem::NodeFlags::FILE)
|
||||
continue;
|
||||
|
||||
if (cwk_path_has_extension(DrvFile->Name))
|
||||
{
|
||||
const char *extension;
|
||||
size_t extension_length;
|
||||
cwk_path_get_extension(DrvFile->Name, &extension, &extension_length);
|
||||
debug("File: %s; Extension: %s", DrvFile->Name, extension);
|
||||
if (strcmp(extension, ".fex") == 0)
|
||||
{
|
||||
uintptr_t ret = this->LoadDriver(DrvFile->Address, DrvFile->Length);
|
||||
std::string RetString;
|
||||
if (ret == DriverCode::OK)
|
||||
RetString << "\e058C19OK";
|
||||
else if (ret == DriverCode::NOT_AVAILABLE)
|
||||
RetString << "\eFF7900NOT AVAILABLE";
|
||||
else
|
||||
RetString << "\eE85230FAILED";
|
||||
KPrint("%s %s %#lx", DrvFile->Name, RetString.c_str(), ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
delete DriverDirectory;
|
||||
}
|
||||
|
||||
Driver::Driver() {}
|
||||
|
||||
Driver::~Driver()
|
||||
{
|
||||
debug("Destructor called");
|
||||
this->UnloadAllDrivers();
|
||||
}
|
||||
|
||||
#if defined(a64)
|
||||
SafeFunction void DriverInterruptHook::OnInterruptReceived(CPU::x64::TrapFrame *Frame)
|
||||
#elif defined(a32)
|
||||
SafeFunction void DriverInterruptHook::OnInterruptReceived(CPU::x32::TrapFrame *Frame)
|
||||
#elif defined(aa64)
|
||||
SafeFunction void DriverInterruptHook::OnInterruptReceived(CPU::aarch64::TrapFrame *Frame)
|
||||
#endif
|
||||
{
|
||||
SmartLock(DriverInterruptLock); /* Lock in case of multiple interrupts firing at the same time */
|
||||
if (!this->Enabled)
|
||||
{
|
||||
debug("Interrupt hook is not enabled");
|
||||
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.edi = Frame->edi;
|
||||
regs.esi = Frame->esi;
|
||||
regs.ebp = Frame->ebp;
|
||||
regs.esp = Frame->esp;
|
||||
regs.ebx = Frame->ebx;
|
||||
regs.edx = Frame->edx;
|
||||
regs.ecx = Frame->ecx;
|
||||
regs.eax = Frame->eax;
|
||||
|
||||
regs.InterruptNumber = Frame->InterruptNumber;
|
||||
regs.ErrorCode = Frame->ErrorCode;
|
||||
regs.eip = Frame->eip;
|
||||
regs.cs = Frame->cs;
|
||||
regs.eflags = Frame->eflags.raw;
|
||||
regs.r3_esp = Frame->r3_esp;
|
||||
regs.r3_ss = Frame->r3_ss;
|
||||
#elif defined(aa64)
|
||||
#endif
|
||||
((int (*)(void *))(Handle.InterruptCallback))(®s);
|
||||
UNUSED(Frame);
|
||||
}
|
||||
|
||||
DriverInterruptHook::DriverInterruptHook(int Interrupt, DriverFile Handle) : 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
|
||||
}
|
||||
}
|
@ -1,230 +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 <driver.hpp>
|
||||
|
||||
#include <dumper.hpp>
|
||||
#include <lock.hpp>
|
||||
|
||||
#include "../../kernel.h"
|
||||
#include "../../Fex.hpp"
|
||||
#include "api.hpp"
|
||||
|
||||
// show debug messages
|
||||
// #define DEBUG_DRIVER_API 1
|
||||
|
||||
#ifdef DEBUG_DRIVER_API
|
||||
#define drvdbg(m, ...) debug(m, ##__VA_ARGS__)
|
||||
#else
|
||||
#define drvdbg(m, ...)
|
||||
#endif
|
||||
|
||||
NewLock(DriverDisplayPrintLock);
|
||||
|
||||
void DriverDebugPrint(char *String, __UINT64_TYPE__ DriverUID)
|
||||
{
|
||||
trace("[%ld] %s", DriverUID, String);
|
||||
}
|
||||
|
||||
void DriverDisplayPrint(char *String)
|
||||
{
|
||||
SmartLock(DriverDisplayPrintLock);
|
||||
for (__UINT64_TYPE__ i = 0; i < strlen(String); i++)
|
||||
Display->Print(String[i], 0, true);
|
||||
}
|
||||
|
||||
void *RequestPage(__UINT64_TYPE__ Size)
|
||||
{
|
||||
void *ret = KernelAllocator.RequestPages(size_t(Size + 1));
|
||||
drvdbg("Allocated %ld pages (%#lx-%#lx)",
|
||||
Size, (__UINT64_TYPE__)ret,
|
||||
(__UINT64_TYPE__)ret + FROM_PAGES(Size));
|
||||
return ret;
|
||||
}
|
||||
|
||||
void FreePage(void *Page, __UINT64_TYPE__ Size)
|
||||
{
|
||||
drvdbg("Freeing %ld pages (%#lx-%#lx)",
|
||||
Size, (__UINT64_TYPE__)Page,
|
||||
(__UINT64_TYPE__)Page + FROM_PAGES(Size));
|
||||
KernelAllocator.FreePages(Page, size_t(Size + 1));
|
||||
}
|
||||
|
||||
void MapMemory(void *VirtualAddress, void *PhysicalAddress, __UINT64_TYPE__ Flags)
|
||||
{
|
||||
SmartLock(DriverDisplayPrintLock);
|
||||
drvdbg("Mapping %#lx to %#lx with flags %#lx...",
|
||||
(__UINT64_TYPE__)VirtualAddress,
|
||||
(__UINT64_TYPE__)PhysicalAddress, Flags);
|
||||
Memory::Virtual(KernelPageTable).Map(VirtualAddress, PhysicalAddress, Flags);
|
||||
}
|
||||
|
||||
void UnmapMemory(void *VirtualAddress)
|
||||
{
|
||||
SmartLock(DriverDisplayPrintLock);
|
||||
drvdbg("Unmapping %#lx...",
|
||||
(__UINT64_TYPE__)VirtualAddress);
|
||||
Memory::Virtual(KernelPageTable).Unmap(VirtualAddress);
|
||||
}
|
||||
|
||||
void *Drivermemcpy(void *Destination, void *Source, __UINT64_TYPE__ Size)
|
||||
{
|
||||
SmartLock(DriverDisplayPrintLock);
|
||||
drvdbg("Copying %ld bytes from %#lx-%#lx to %#lx-%#lx...", Size,
|
||||
(__UINT64_TYPE__)Source, (__UINT64_TYPE__)Source + Size,
|
||||
(__UINT64_TYPE__)Destination, (__UINT64_TYPE__)Destination + Size);
|
||||
return memcpy(Destination, Source, size_t(Size));
|
||||
}
|
||||
|
||||
void *Drivermemset(void *Destination, int Value, __UINT64_TYPE__ Size)
|
||||
{
|
||||
SmartLock(DriverDisplayPrintLock);
|
||||
drvdbg("Setting value %#x at %#lx-%#lx (%ld bytes)...", Value,
|
||||
(__UINT64_TYPE__)Destination,
|
||||
(__UINT64_TYPE__)Destination + Size, Size);
|
||||
return memset(Destination, Value, size_t(Size));
|
||||
}
|
||||
|
||||
void DriverNetSend(__UINT32_TYPE__ DriverID,
|
||||
__UINT8_TYPE__ *Data,
|
||||
__UINT16_TYPE__ Size)
|
||||
{
|
||||
// This is useless I guess...
|
||||
if (NIManager)
|
||||
NIManager->DrvSend(DriverID, Data, Size);
|
||||
}
|
||||
|
||||
void DriverNetReceive(__UINT32_TYPE__ DriverID,
|
||||
__UINT8_TYPE__ *Data,
|
||||
__UINT16_TYPE__ Size)
|
||||
{
|
||||
if (NIManager)
|
||||
NIManager->DrvReceive(DriverID, Data, Size);
|
||||
}
|
||||
|
||||
void DriverAHCIDiskRead(__UINT32_TYPE__ DriverID,
|
||||
__UINT64_TYPE__ Sector,
|
||||
__UINT8_TYPE__ *Data,
|
||||
__UINT32_TYPE__ SectorCount,
|
||||
__UINT8_TYPE__ Port)
|
||||
{
|
||||
DumpData("DriverDiskRead", Data, SectorCount * 512);
|
||||
UNUSED(DriverID);
|
||||
UNUSED(Sector);
|
||||
UNUSED(Port);
|
||||
}
|
||||
|
||||
void DriverAHCIDiskWrite(__UINT32_TYPE__ DriverID,
|
||||
__UINT64_TYPE__ Sector,
|
||||
__UINT8_TYPE__ *Data,
|
||||
__UINT32_TYPE__ SectorCount,
|
||||
__UINT8_TYPE__ Port)
|
||||
{
|
||||
DumpData("DriverDiskWrite",
|
||||
Data, SectorCount * 512);
|
||||
UNUSED(DriverID);
|
||||
UNUSED(Sector);
|
||||
UNUSED(Port);
|
||||
}
|
||||
|
||||
char *DriverPCIGetDeviceName(__UINT32_TYPE__ VendorID,
|
||||
__UINT32_TYPE__ DeviceID)
|
||||
{
|
||||
UNUSED(VendorID);
|
||||
UNUSED(DeviceID);
|
||||
return (char *)"Unknown";
|
||||
}
|
||||
|
||||
__UINT32_TYPE__ DriverGetWidth()
|
||||
{
|
||||
/* TODO: We won't rely only on display buffers,
|
||||
what about graphics drivers and changing resolutions? */
|
||||
return Display->GetBuffer(0)->Width;
|
||||
}
|
||||
|
||||
__UINT32_TYPE__ DriverGetHeight()
|
||||
{
|
||||
/* TODO: We won't rely only on display buffers,
|
||||
what about graphics drivers and changing resolutions? */
|
||||
return Display->GetBuffer(0)->Height;
|
||||
}
|
||||
|
||||
void DriverSleep(__UINT64_TYPE__ Milliseconds)
|
||||
{
|
||||
SmartLock(DriverDisplayPrintLock);
|
||||
drvdbg("Sleeping for %ld milliseconds...", Milliseconds);
|
||||
if (TaskManager)
|
||||
TaskManager->Sleep(Milliseconds);
|
||||
else
|
||||
TimeManager->Sleep(size_t(Milliseconds),
|
||||
Time::Units::Milliseconds);
|
||||
}
|
||||
|
||||
int Driversprintf(char *Buffer, const char *Format, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, Format);
|
||||
int ret = vsprintf(Buffer, Format, args);
|
||||
va_end(args);
|
||||
return ret;
|
||||
}
|
||||
|
||||
KernelAPI KernelAPITemplate = {
|
||||
.Version = {
|
||||
.Major = 0,
|
||||
.Minor = 0,
|
||||
.Patch = 1},
|
||||
.Info = {
|
||||
.Offset = 0,
|
||||
.DriverUID = 0,
|
||||
.KernelDebug = false,
|
||||
},
|
||||
.Memory = {
|
||||
.PageSize = PAGE_SIZE,
|
||||
.RequestPage = RequestPage,
|
||||
.FreePage = FreePage,
|
||||
.Map = MapMemory,
|
||||
.Unmap = UnmapMemory,
|
||||
},
|
||||
.PCI = {
|
||||
.GetDeviceName = DriverPCIGetDeviceName,
|
||||
},
|
||||
.Util = {
|
||||
.DebugPrint = DriverDebugPrint,
|
||||
.DisplayPrint = DriverDisplayPrint,
|
||||
.memcpy = Drivermemcpy,
|
||||
.memset = Drivermemset,
|
||||
.Sleep = DriverSleep,
|
||||
.sprintf = Driversprintf,
|
||||
},
|
||||
.Command = {
|
||||
.Network = {
|
||||
.SendPacket = DriverNetSend,
|
||||
.ReceivePacket = DriverNetReceive,
|
||||
},
|
||||
.Disk = {
|
||||
.AHCI = {
|
||||
.ReadSector = DriverAHCIDiskRead,
|
||||
.WriteSector = DriverAHCIDiskWrite,
|
||||
},
|
||||
},
|
||||
},
|
||||
.Display = {
|
||||
.GetWidth = DriverGetWidth,
|
||||
.GetHeight = DriverGetHeight,
|
||||
},
|
||||
};
|
@ -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::DriverLoadBindInput(uintptr_t DriverAddress, size_t Size, bool IsBuiltIn)
|
||||
{
|
||||
stub;
|
||||
UNUSED(DriverAddress);
|
||||
UNUSED(Size);
|
||||
UNUSED(IsBuiltIn);
|
||||
return DriverCode::NOT_IMPLEMENTED;
|
||||
}
|
||||
}
|
@ -1,118 +0,0 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "../api.hpp"
|
||||
|
||||
#include <ints.hpp>
|
||||
#include <memory.hpp>
|
||||
#include <task.hpp>
|
||||
#include <lock.hpp>
|
||||
#include <printf.h>
|
||||
#include <cwalk.h>
|
||||
#include <md5.h>
|
||||
|
||||
#include "../../../kernel.h"
|
||||
#include "../../../DAPI.hpp"
|
||||
#include "../../../Fex.hpp"
|
||||
|
||||
namespace Driver
|
||||
{
|
||||
DriverCode Driver::DriverLoadBindInterrupt(uintptr_t DriverAddress, size_t Size, bool IsBuiltIn)
|
||||
{
|
||||
Memory::MemMgr *mem = new Memory::MemMgr(nullptr, thisProcess->memDirectory);
|
||||
|
||||
BuiltInDriverInfo *bidi = (BuiltInDriverInfo *)DriverAddress;
|
||||
Fex *fex = nullptr;
|
||||
if (!IsBuiltIn)
|
||||
{
|
||||
fex = (Fex *)mem->RequestPages(TO_PAGES(Size + 1));
|
||||
memcpy(fex, (void *)DriverAddress, Size);
|
||||
debug("Driver allocated at %#lx-%#lx", fex, (uintptr_t)fex + Size);
|
||||
}
|
||||
else
|
||||
fex = (Fex *)bidi->EntryPoint;
|
||||
DriverCode ret = CallDriverEntryPoint(fex, IsBuiltIn);
|
||||
if (ret != DriverCode::OK)
|
||||
{
|
||||
delete mem;
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (IsBuiltIn)
|
||||
fex = 0x0; /* Addresses are absolute if built-in. */
|
||||
|
||||
FexExtended *fexE = IsBuiltIn ? (FexExtended *)bidi->ExtendedHeader : (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
|
||||
|
||||
debug("Starting driver %s", fexE->Driver.Name);
|
||||
|
||||
switch (fexE->Driver.Type)
|
||||
{
|
||||
case FexDriverType::FexDriverType_Generic:
|
||||
case FexDriverType::FexDriverType_Display:
|
||||
case FexDriverType::FexDriverType_Network:
|
||||
case FexDriverType::FexDriverType_Storage:
|
||||
case FexDriverType::FexDriverType_FileSystem:
|
||||
case FexDriverType::FexDriverType_Input:
|
||||
case FexDriverType::FexDriverType_Audio:
|
||||
{
|
||||
FexExtended *DriverExtendedHeader = (FexExtended *)mem->RequestPages(TO_PAGES(sizeof(FexExtended) + 1));
|
||||
memcpy(DriverExtendedHeader, fexE, sizeof(FexExtended));
|
||||
|
||||
DriverFile DrvFile = {
|
||||
.Enabled = true,
|
||||
.BuiltIn = IsBuiltIn,
|
||||
.DriverUID = this->DriverUIDs - 1,
|
||||
.Address = (void *)fex,
|
||||
.ExtendedHeaderAddress = (void *)DriverExtendedHeader,
|
||||
.InterruptCallback = (void *)((uintptr_t)fex + (uintptr_t)fexE->Driver.InterruptCallback),
|
||||
.MemTrk = mem,
|
||||
};
|
||||
|
||||
if (fexE->Driver.InterruptCallback)
|
||||
{
|
||||
for (uint16_t i = 0; i < sizeof(fexE->Driver.Bind.Interrupt.Vector) / sizeof(fexE->Driver.Bind.Interrupt.Vector[0]); i++)
|
||||
{
|
||||
if (fexE->Driver.Bind.Interrupt.Vector[i] == 0)
|
||||
break;
|
||||
DrvFile.InterruptHook[i] = new DriverInterruptHook(fexE->Driver.Bind.Interrupt.Vector[i], DrvFile);
|
||||
}
|
||||
}
|
||||
|
||||
KernelCallback KCallback{};
|
||||
KCallback.RawPtr = nullptr;
|
||||
KCallback.Reason = CallbackReason::ConfigurationReason;
|
||||
DriverCode CallbackRet = ((DriverCode(*)(KernelCallback *))((uintptr_t)fexE->Driver.Callback + (uintptr_t)fex))(&KCallback);
|
||||
|
||||
if (CallbackRet != DriverCode::OK)
|
||||
{
|
||||
error("Driver %s returned error %d", fexE->Driver.Name, CallbackRet);
|
||||
delete mem;
|
||||
return CallbackRet;
|
||||
}
|
||||
|
||||
Drivers.push_back(DrvFile);
|
||||
return DriverCode::OK;
|
||||
}
|
||||
default:
|
||||
{
|
||||
warn("Unknown driver type: %d", fexE->Driver.Type);
|
||||
delete mem;
|
||||
return DriverCode::UNKNOWN_DRIVER_TYPE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,144 +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::DriverLoadBindPCI(uintptr_t DriverAddress, size_t Size, bool IsBuiltIn)
|
||||
{
|
||||
FexExtended *DrvExtHdr = (FexExtended *)(DriverAddress + EXTENDED_SECTION_ADDRESS);
|
||||
if (IsBuiltIn)
|
||||
DrvExtHdr = (FexExtended *)(((BuiltInDriverInfo *)DriverAddress)->ExtendedHeader);
|
||||
|
||||
uint16_t SizeOfVendorID = sizeof(DrvExtHdr->Driver.Bind.PCI.VendorID) /
|
||||
sizeof(DrvExtHdr->Driver.Bind.PCI.VendorID[0]);
|
||||
uint16_t SizeOfDeviceID = sizeof(DrvExtHdr->Driver.Bind.PCI.DeviceID) /
|
||||
sizeof(DrvExtHdr->Driver.Bind.PCI.DeviceID[0]);
|
||||
|
||||
for (uint16_t vID = 0; vID < SizeOfVendorID; vID++)
|
||||
{
|
||||
for (uint16_t dID = 0; dID < SizeOfDeviceID; dID++)
|
||||
{
|
||||
if (DrvExtHdr->Driver.Bind.PCI.VendorID[vID] == 0 ||
|
||||
DrvExtHdr->Driver.Bind.PCI.DeviceID[dID] == 0)
|
||||
continue;
|
||||
|
||||
std::vector<PCI::PCIDeviceHeader *> devices =
|
||||
PCIManager->FindPCIDevice(DrvExtHdr->Driver.Bind.PCI.VendorID[vID],
|
||||
DrvExtHdr->Driver.Bind.PCI.DeviceID[dID]);
|
||||
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, thisProcess->memDirectory);
|
||||
|
||||
BuiltInDriverInfo *bidi = (BuiltInDriverInfo *)DriverAddress;
|
||||
Fex *fex = nullptr;
|
||||
if (!IsBuiltIn)
|
||||
{
|
||||
fex = (Fex *)mem->RequestPages(TO_PAGES(Size + 1));
|
||||
memcpy(fex, (void *)DriverAddress, Size);
|
||||
debug("Driver allocated at %#lx-%#lx", fex, (uintptr_t)fex + Size);
|
||||
}
|
||||
else
|
||||
fex = (Fex *)bidi->EntryPoint;
|
||||
DriverCode ret = CallDriverEntryPoint(fex, IsBuiltIn);
|
||||
if (ret != DriverCode::OK)
|
||||
{
|
||||
delete mem;
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (IsBuiltIn)
|
||||
fex = 0x0; /* Addresses are absolute if built-in. */
|
||||
|
||||
FexExtended *fexE = IsBuiltIn ? (FexExtended *)bidi->ExtendedHeader : (FexExtended *)((uintptr_t)fex + EXTENDED_SECTION_ADDRESS);
|
||||
debug("Starting driver %s", fexE->Driver.Name);
|
||||
|
||||
PCIManager->MapPCIAddresses(PCIDevice);
|
||||
|
||||
switch (fexE->Driver.Type)
|
||||
{
|
||||
case FexDriverType::FexDriverType_Generic:
|
||||
case FexDriverType::FexDriverType_Display:
|
||||
case FexDriverType::FexDriverType_Network:
|
||||
case FexDriverType::FexDriverType_Storage:
|
||||
case FexDriverType::FexDriverType_FileSystem:
|
||||
case FexDriverType::FexDriverType_Input:
|
||||
case FexDriverType::FexDriverType_Audio:
|
||||
{
|
||||
FexExtended *DriverExtendedHeader = (FexExtended *)mem->RequestPages(TO_PAGES(sizeof(FexExtended) + 1));
|
||||
memcpy(DriverExtendedHeader, fexE, sizeof(FexExtended));
|
||||
|
||||
DriverFile DrvFile = {
|
||||
.Enabled = true,
|
||||
.BuiltIn = IsBuiltIn,
|
||||
.DriverUID = this->DriverUIDs - 1,
|
||||
.Address = (void *)fex,
|
||||
.ExtendedHeaderAddress = (void *)DriverExtendedHeader,
|
||||
.InterruptCallback = (void *)((uintptr_t)fex + (uintptr_t)fexE->Driver.InterruptCallback),
|
||||
.MemTrk = mem,
|
||||
};
|
||||
|
||||
if (fexE->Driver.InterruptCallback)
|
||||
DrvFile.InterruptHook[0] = new DriverInterruptHook(((int)((PCI::PCIHeader0 *)PCIDevice)->InterruptLine), DrvFile);
|
||||
|
||||
KernelCallback KCallback{};
|
||||
KCallback.RawPtr = PCIDevice;
|
||||
KCallback.Reason = CallbackReason::ConfigurationReason;
|
||||
DriverCode CallbackRet = ((DriverCode(*)(KernelCallback *))((uintptr_t)fexE->Driver.Callback + (uintptr_t)fex))(&KCallback);
|
||||
|
||||
if (CallbackRet != DriverCode::OK)
|
||||
{
|
||||
error("Driver %s returned error %d", fexE->Driver.Name, CallbackRet);
|
||||
delete mem;
|
||||
return CallbackRet;
|
||||
}
|
||||
|
||||
Drivers.push_back(DrvFile);
|
||||
return DriverCode::OK;
|
||||
}
|
||||
default:
|
||||
{
|
||||
warn("Unknown driver type: %d", fexE->Driver.Type);
|
||||
delete mem;
|
||||
return DriverCode::UNKNOWN_DRIVER_TYPE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return DriverCode::PCI_DEVICE_NOT_FOUND;
|
||||
}
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "../api.hpp"
|
||||
|
||||
#include <ints.hpp>
|
||||
#include <memory.hpp>
|
||||
#include <task.hpp>
|
||||
#include <lock.hpp>
|
||||
#include <printf.h>
|
||||
#include <cwalk.h>
|
||||
#include <md5.h>
|
||||
|
||||
#include "../../../kernel.h"
|
||||
#include "../../../DAPI.hpp"
|
||||
#include "../../../Fex.hpp"
|
||||
|
||||
namespace Driver
|
||||
{
|
||||
DriverCode Driver::DriverLoadBindProcess(uintptr_t DriverAddress, size_t Size, bool IsBuiltIn)
|
||||
{
|
||||
stub;
|
||||
UNUSED(DriverAddress);
|
||||
UNUSED(Size);
|
||||
UNUSED(IsBuiltIn);
|
||||
return DriverCode::NOT_IMPLEMENTED;
|
||||
}
|
||||
}
|
@ -1,27 +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_DRIVER_API_H__
|
||||
#define __FENNIX_KERNEL_DRIVER_API_H__
|
||||
|
||||
#include <types.h>
|
||||
|
||||
#include "../../DAPI.hpp"
|
||||
|
||||
extern KernelAPI KernelAPITemplate;
|
||||
|
||||
#endif // !__FENNIX_KERNEL_DRIVER_API_H__
|
@ -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 "Xalloc.hpp"
|
||||
|
||||
#include <memory.hpp>
|
||||
|
||||
extern "C" void *Xalloc_REQUEST_PAGES(Xsize_t Pages)
|
||||
{
|
||||
return KernelAllocator.RequestPages(Pages);
|
||||
}
|
||||
|
||||
extern "C" void Xalloc_FREE_PAGES(void *Address, Xsize_t Pages)
|
||||
{
|
||||
KernelAllocator.FreePages(Address, Pages);
|
||||
}
|
||||
|
||||
extern "C" void Xalloc_MAP_MEMORY(void *VirtualAddress, void *PhysicalAddress, Xsize_t Flags)
|
||||
{
|
||||
Memory::Virtual(KernelPageTable).Map(VirtualAddress, PhysicalAddress, Flags);
|
||||
}
|
||||
|
||||
extern "C" void Xalloc_UNMAP_MEMORY(void *VirtualAddress)
|
||||
{
|
||||
Memory::Virtual(KernelPageTable).Unmap(VirtualAddress);
|
||||
}
|
@ -1,287 +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 <memory.hpp>
|
||||
#include <debug.h>
|
||||
|
||||
#include "../../kernel.h"
|
||||
|
||||
namespace Memory
|
||||
{
|
||||
ReadFSFunction(MEM_Read)
|
||||
{
|
||||
if (Size <= 0)
|
||||
Size = node->Length;
|
||||
|
||||
if (RefOffset > node->Length)
|
||||
return 0;
|
||||
|
||||
if (RefOffset + (off_t)Size > node->Length)
|
||||
Size = node->Length - RefOffset;
|
||||
|
||||
memcpy(Buffer, (uint8_t *)(node->Address + RefOffset), Size);
|
||||
return Size;
|
||||
}
|
||||
|
||||
WriteFSFunction(MEM_Write)
|
||||
{
|
||||
if (Size <= 0)
|
||||
Size = node->Length;
|
||||
|
||||
if (RefOffset > node->Length)
|
||||
return 0;
|
||||
|
||||
if (RefOffset + (off_t)Size > node->Length)
|
||||
Size = node->Length - RefOffset;
|
||||
|
||||
memcpy((uint8_t *)(node->Address + RefOffset), Buffer, Size);
|
||||
return Size;
|
||||
}
|
||||
|
||||
VirtualFileSystem::FileSystemOperations mem_op = {
|
||||
.Name = "mem",
|
||||
.Read = MEM_Read,
|
||||
.Write = MEM_Write,
|
||||
};
|
||||
|
||||
uint64_t MemMgr::GetAllocatedMemorySize()
|
||||
{
|
||||
SmartLock(MgrLock);
|
||||
uint64_t Size = 0;
|
||||
foreach (auto ap in AllocatedPagesList)
|
||||
Size += ap.PageCount;
|
||||
return FROM_PAGES(Size);
|
||||
}
|
||||
|
||||
bool MemMgr::Add(void *Address, size_t Count)
|
||||
{
|
||||
SmartLock(MgrLock);
|
||||
if (Address == nullptr)
|
||||
{
|
||||
error("Address is null!");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Count == 0)
|
||||
{
|
||||
error("Count is 0!");
|
||||
return false;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < AllocatedPagesList.size(); i++)
|
||||
{
|
||||
if (AllocatedPagesList[i].Address == Address)
|
||||
{
|
||||
error("Address already exists!");
|
||||
return false;
|
||||
}
|
||||
else if ((uintptr_t)Address < (uintptr_t)AllocatedPagesList[i].Address)
|
||||
{
|
||||
if ((uintptr_t)Address + (Count * PAGE_SIZE) > (uintptr_t)AllocatedPagesList[i].Address)
|
||||
{
|
||||
error("Address intersects with an allocated page!");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((uintptr_t)AllocatedPagesList[i].Address + (AllocatedPagesList[i].PageCount * PAGE_SIZE) > (uintptr_t)Address)
|
||||
{
|
||||
error("Address intersects with an allocated page!");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this->Directory)
|
||||
{
|
||||
char FileName[64];
|
||||
#if defined(a64) || defined(aa64)
|
||||
sprintf(FileName, "%lx-%ld", (uintptr_t)Address, Count);
|
||||
#elif defined(a32)
|
||||
sprintf(FileName, "%x-%ld", (uintptr_t)Address, Count);
|
||||
#endif
|
||||
VirtualFileSystem::Node *n = vfs->Create(FileName, VirtualFileSystem::NodeFlags::FILE, this->Directory);
|
||||
if (n)
|
||||
{
|
||||
n->Address = (uintptr_t)Address;
|
||||
n->Length = Count * PAGE_SIZE;
|
||||
n->Operator = &mem_op;
|
||||
}
|
||||
}
|
||||
|
||||
AllocatedPagesList.push_back({Address, Count});
|
||||
return true;
|
||||
}
|
||||
|
||||
void *MemMgr::RequestPages(size_t Count, bool User)
|
||||
{
|
||||
SmartLock(MgrLock);
|
||||
void *Address = KernelAllocator.RequestPages(Count);
|
||||
for (size_t i = 0; i < Count; i++)
|
||||
{
|
||||
int Flags = Memory::PTFlag::RW;
|
||||
if (User)
|
||||
Flags |= Memory::PTFlag::US;
|
||||
|
||||
void *AddressToMap = (void *)((uintptr_t)Address + (i * PAGE_SIZE));
|
||||
|
||||
Memory::Virtual vmm = Memory::Virtual(this->Table);
|
||||
vmm.Remap(AddressToMap, AddressToMap, Flags);
|
||||
}
|
||||
|
||||
if (this->Directory)
|
||||
{
|
||||
char FileName[64];
|
||||
#if defined(a64) || defined(aa64)
|
||||
sprintf(FileName, "%lx-%ld", (uintptr_t)Address, Count);
|
||||
#elif defined(a32)
|
||||
sprintf(FileName, "%x-%ld", (uintptr_t)Address, Count);
|
||||
#endif
|
||||
VirtualFileSystem::Node *n = vfs->Create(FileName, VirtualFileSystem::NodeFlags::FILE, this->Directory);
|
||||
if (n) // If null, error or file already exists
|
||||
{
|
||||
n->Address = (uintptr_t)Address;
|
||||
n->Length = Count * PAGE_SIZE;
|
||||
n->Operator = &mem_op;
|
||||
}
|
||||
}
|
||||
|
||||
AllocatedPagesList.push_back({Address, Count});
|
||||
|
||||
/* For security reasons, we clear the allocated page
|
||||
if it's a user page. */
|
||||
if (User)
|
||||
memset(Address, 0, Count * PAGE_SIZE);
|
||||
|
||||
return Address;
|
||||
}
|
||||
|
||||
void MemMgr::FreePages(void *Address, size_t Count)
|
||||
{
|
||||
SmartLock(MgrLock);
|
||||
forItr(itr, AllocatedPagesList)
|
||||
{
|
||||
if (itr->Address == Address)
|
||||
{
|
||||
/** TODO: Advanced checks. Allow if the page count is less than the requested one.
|
||||
* This will allow the user to free only a part of the allocated pages.
|
||||
*
|
||||
* But this will be in a separate function because we need to specify if we
|
||||
* want to free from the start or from the end and return the new address.
|
||||
*/
|
||||
if (itr->PageCount != Count)
|
||||
{
|
||||
error("Page count mismatch! (Allocated: %lld, Requested: %lld)", itr->PageCount, Count);
|
||||
return;
|
||||
}
|
||||
|
||||
KernelAllocator.FreePages(Address, Count);
|
||||
|
||||
Memory::Virtual vmm = Memory::Virtual(this->Table);
|
||||
for (size_t i = 0; i < Count; i++)
|
||||
{
|
||||
void *AddressToMap = (void *)((uintptr_t)Address + (i * PAGE_SIZE));
|
||||
vmm.Remap(AddressToMap, AddressToMap, Memory::PTFlag::RW);
|
||||
// vmm.Unmap((void *)((uintptr_t)Address + (i * PAGE_SIZE)));
|
||||
}
|
||||
|
||||
if (this->Directory)
|
||||
{
|
||||
char FileName[64];
|
||||
#if defined(a64) || defined(aa64)
|
||||
sprintf(FileName, "%lx-%ld", (uintptr_t)Address, Count);
|
||||
#elif defined(a32)
|
||||
sprintf(FileName, "%x-%ld", (uintptr_t)Address, Count);
|
||||
#endif
|
||||
if (!vfs->Delete(FileName, false, this->Directory))
|
||||
error("Failed to delete file %s", FileName);
|
||||
}
|
||||
|
||||
AllocatedPagesList.erase(itr);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MemMgr::DetachAddress(void *Address)
|
||||
{
|
||||
SmartLock(MgrLock);
|
||||
forItr(itr, AllocatedPagesList)
|
||||
{
|
||||
if (itr->Address == Address)
|
||||
{
|
||||
if (this->Directory)
|
||||
{
|
||||
char FileName[64];
|
||||
#if defined(a64) || defined(aa64)
|
||||
sprintf(FileName, "%lx-%ld", (uintptr_t)Address, itr->PageCount);
|
||||
#elif defined(a32)
|
||||
sprintf(FileName, "%x-%ld", (uintptr_t)Address, itr->PageCount);
|
||||
#endif
|
||||
if (!vfs->Delete(FileName, false, this->Directory))
|
||||
error("Failed to delete file %s", FileName);
|
||||
}
|
||||
|
||||
AllocatedPagesList.erase(itr);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MemMgr::MemMgr(PageTable *Table, VirtualFileSystem::Node *Directory)
|
||||
{
|
||||
SmartLock(MgrLock);
|
||||
if (Table)
|
||||
this->Table = Table;
|
||||
else
|
||||
{
|
||||
#if defined(a64)
|
||||
this->Table = (PageTable *)CPU::x64::readcr3().raw;
|
||||
#elif defined(a32)
|
||||
this->Table = (PageTable *)CPU::x32::readcr3().raw;
|
||||
#endif
|
||||
}
|
||||
|
||||
this->Directory = Directory;
|
||||
debug("+ %#lx %s", this,
|
||||
KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "");
|
||||
}
|
||||
|
||||
MemMgr::~MemMgr()
|
||||
{
|
||||
SmartLock(MgrLock);
|
||||
foreach (auto ap in AllocatedPagesList)
|
||||
{
|
||||
KernelAllocator.FreePages(ap.Address, ap.PageCount);
|
||||
Memory::Virtual vmm = Memory::Virtual(this->Table);
|
||||
for (size_t i = 0; i < ap.PageCount; i++)
|
||||
vmm.Remap((void *)((uintptr_t)ap.Address + (i * PAGE_SIZE)),
|
||||
(void *)((uintptr_t)ap.Address + (i * PAGE_SIZE)),
|
||||
Memory::PTFlag::RW);
|
||||
}
|
||||
|
||||
if (this->Directory)
|
||||
{
|
||||
foreach (auto Child in this->Directory->Children)
|
||||
vfs->Delete(Child, true);
|
||||
}
|
||||
|
||||
debug("- %#lx %s", this,
|
||||
KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "");
|
||||
}
|
||||
}
|
@ -1,98 +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 <memory.hpp>
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <debug.h>
|
||||
|
||||
namespace Memory
|
||||
{
|
||||
void *ProgramBreak::brk(void *Address)
|
||||
{
|
||||
if (HeapStart == 0x0 || Break == 0x0)
|
||||
{
|
||||
error("HeapStart or Break is 0x0");
|
||||
return (void *)-EAGAIN;
|
||||
}
|
||||
|
||||
/* Get the current program break. */
|
||||
if (Address == nullptr)
|
||||
return (void *)Break;
|
||||
|
||||
/* Check if the address is valid. */
|
||||
if (Address < (void *)HeapStart)
|
||||
return (void *)-ENOMEM;
|
||||
|
||||
Virtual vmm = Virtual(this->Table);
|
||||
|
||||
if (Address > (void *)Break)
|
||||
{
|
||||
/* Allocate more memory. */
|
||||
size_t Pages = TO_PAGES(uintptr_t(Address) - Break);
|
||||
void *Allocated = mm->RequestPages(Pages);
|
||||
if (Allocated == nullptr)
|
||||
return (void *)-ENOMEM;
|
||||
|
||||
/* Map the allocated pages. */
|
||||
for (size_t i = 0; i < Pages; i++)
|
||||
{
|
||||
void *VirtAddr = (void *)(Break + (i * PAGE_SIZE));
|
||||
void *PhysAddr = (void *)(uintptr_t(Allocated) + (i * PAGE_SIZE));
|
||||
vmm.Map(VirtAddr, PhysAddr, RW | US);
|
||||
}
|
||||
|
||||
Break = (uint64_t)Address;
|
||||
return (void *)Break;
|
||||
}
|
||||
else if (Address < (void *)Break)
|
||||
{
|
||||
/* Free memory. */
|
||||
size_t Pages = TO_PAGES(uintptr_t(Address) - Break);
|
||||
mm->FreePages((void *)Break, Pages);
|
||||
|
||||
/* Unmap the freed pages. */
|
||||
for (size_t i = 0; i < Pages; i++)
|
||||
{
|
||||
uint64_t Page = Break - (i * 0x1000);
|
||||
vmm.Unmap((void *)Page);
|
||||
}
|
||||
|
||||
Break = (uint64_t)Address;
|
||||
return (void *)Break;
|
||||
}
|
||||
|
||||
assert(false);
|
||||
}
|
||||
|
||||
ProgramBreak::ProgramBreak(PageTable *Table, MemMgr *mm)
|
||||
{
|
||||
assert(Table != nullptr);
|
||||
assert(mm != nullptr);
|
||||
|
||||
this->Table = Table;
|
||||
this->mm = mm;
|
||||
}
|
||||
|
||||
ProgramBreak::~ProgramBreak()
|
||||
{
|
||||
/* Do nothing because MemMgr
|
||||
will be destroyed later. */
|
||||
}
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
#include <memory.hpp>
|
||||
|
||||
namespace Memory
|
||||
{
|
||||
SmartHeap::SmartHeap(size_t Size)
|
||||
{
|
||||
this->Object = kmalloc(Size);
|
||||
this->ObjectSize = Size;
|
||||
}
|
||||
|
||||
SmartHeap::~SmartHeap()
|
||||
{
|
||||
kfree(this->Object);
|
||||
}
|
||||
}
|
@ -1,181 +0,0 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <memory.hpp>
|
||||
|
||||
#include <debug.h>
|
||||
|
||||
namespace Memory
|
||||
{
|
||||
bool StackGuard::Expand(uintptr_t FaultAddress)
|
||||
{
|
||||
if (this->UserMode)
|
||||
{
|
||||
if (FaultAddress < (uintptr_t)this->StackBottom - USER_STACK_SIZE ||
|
||||
FaultAddress > (uintptr_t)this->StackTop)
|
||||
{
|
||||
info("Fault address %#lx is not in range of stack %#lx - %#lx", FaultAddress,
|
||||
(uintptr_t)this->StackBottom - USER_STACK_SIZE, (uintptr_t)this->StackTop);
|
||||
return false; /* It's not about the stack. */
|
||||
}
|
||||
else
|
||||
{
|
||||
void *AllocatedStack = KernelAllocator.RequestPages(TO_PAGES(USER_STACK_SIZE + 1));
|
||||
debug("AllocatedStack: %#lx", AllocatedStack);
|
||||
memset(AllocatedStack, 0, USER_STACK_SIZE);
|
||||
|
||||
Virtual va = Virtual(this->Table);
|
||||
for (size_t i = 0; i < TO_PAGES(USER_STACK_SIZE); i++)
|
||||
{
|
||||
void *VirtualPage = (void *)((uintptr_t)this->StackBottom - (i * PAGE_SIZE));
|
||||
void *PhysicalPage = (void *)((uintptr_t)AllocatedStack + (i * PAGE_SIZE));
|
||||
|
||||
va.Map(VirtualPage, PhysicalPage, PTFlag::RW | PTFlag::US);
|
||||
AllocatedPages pa = {
|
||||
.PhysicalAddress = PhysicalPage,
|
||||
.VirtualAddress = VirtualPage,
|
||||
};
|
||||
AllocatedPagesList.push_back(pa);
|
||||
debug("Mapped %#lx to %#lx", PhysicalPage, VirtualPage);
|
||||
}
|
||||
|
||||
this->StackBottom = (void *)((uintptr_t)this->StackBottom - USER_STACK_SIZE);
|
||||
this->Size += USER_STACK_SIZE;
|
||||
info("Stack expanded to %#lx", this->StackBottom);
|
||||
this->Expanded = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fixme("Not implemented and probably not needed");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void StackGuard::Fork(StackGuard *Parent)
|
||||
{
|
||||
this->UserMode = Parent->GetUserMode();
|
||||
this->StackBottom = Parent->GetStackBottom();
|
||||
this->StackTop = Parent->GetStackTop();
|
||||
this->StackPhysicalBottom = Parent->GetStackPhysicalBottom();
|
||||
this->StackPhysicalTop = Parent->GetStackPhysicalTop();
|
||||
this->Size = Parent->GetSize();
|
||||
this->Expanded = Parent->IsExpanded();
|
||||
|
||||
if (this->UserMode)
|
||||
{
|
||||
std::vector<AllocatedPages> ParentAllocatedPages = Parent->GetAllocatedPages();
|
||||
|
||||
Virtual va = Virtual(Table);
|
||||
|
||||
foreach (auto Page in AllocatedPagesList)
|
||||
{
|
||||
va.Unmap(Page.VirtualAddress);
|
||||
KernelAllocator.FreePage(Page.PhysicalAddress);
|
||||
debug("Freed %#lx and unmapped %#lx", Page.PhysicalAddress, Page.VirtualAddress);
|
||||
}
|
||||
|
||||
foreach (auto Page in ParentAllocatedPages)
|
||||
{
|
||||
void *NewPhysical = KernelAllocator.RequestPage();
|
||||
memcpy(NewPhysical, Page.PhysicalAddress, PAGE_SIZE);
|
||||
va.Map(Page.VirtualAddress, NewPhysical, PTFlag::RW | PTFlag::US);
|
||||
|
||||
AllocatedPages pa = {
|
||||
.PhysicalAddress = NewPhysical,
|
||||
.VirtualAddress = Page.VirtualAddress,
|
||||
};
|
||||
AllocatedPagesList.push_back(pa);
|
||||
debug("Mapped %#lx to %#lx", NewPhysical, Page.VirtualAddress);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fixme("Kernel mode stack fork not implemented");
|
||||
}
|
||||
}
|
||||
|
||||
StackGuard::StackGuard(bool User, PageTable *Table)
|
||||
{
|
||||
this->UserMode = User;
|
||||
this->Table = Table;
|
||||
|
||||
if (this->UserMode)
|
||||
{
|
||||
void *AllocatedStack = KernelAllocator.RequestPages(TO_PAGES(USER_STACK_SIZE + 1));
|
||||
memset(AllocatedStack, 0, USER_STACK_SIZE);
|
||||
debug("AllocatedStack: %#lx", AllocatedStack);
|
||||
|
||||
Virtual va = Virtual(Table);
|
||||
for (size_t i = 0; i < TO_PAGES(USER_STACK_SIZE); i++)
|
||||
{
|
||||
void *VirtualPage = (void *)(USER_STACK_BASE + (i * PAGE_SIZE));
|
||||
void *PhysicalPage = (void *)((uintptr_t)AllocatedStack + (i * PAGE_SIZE));
|
||||
va.Map(VirtualPage, PhysicalPage, PTFlag::RW | PTFlag::US);
|
||||
|
||||
AllocatedPages pa = {
|
||||
.PhysicalAddress = PhysicalPage,
|
||||
.VirtualAddress = VirtualPage,
|
||||
};
|
||||
AllocatedPagesList.push_back(pa);
|
||||
debug("Mapped %#lx to %#lx", PhysicalPage, VirtualPage);
|
||||
}
|
||||
|
||||
this->StackBottom = (void *)USER_STACK_BASE;
|
||||
this->StackTop = (void *)(USER_STACK_BASE + USER_STACK_SIZE);
|
||||
|
||||
this->StackPhysicalBottom = AllocatedStack;
|
||||
this->StackPhysicalTop = (void *)((uintptr_t)AllocatedStack + USER_STACK_SIZE);
|
||||
|
||||
this->Size = USER_STACK_SIZE;
|
||||
}
|
||||
else
|
||||
{
|
||||
this->StackBottom = KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE + 1));
|
||||
memset(this->StackBottom, 0, STACK_SIZE);
|
||||
debug("StackBottom: %#lx", this->StackBottom);
|
||||
|
||||
this->StackTop = (void *)((uintptr_t)this->StackBottom + STACK_SIZE);
|
||||
|
||||
this->StackPhysicalBottom = this->StackBottom;
|
||||
this->StackPhysicalTop = this->StackTop;
|
||||
|
||||
this->Size = STACK_SIZE;
|
||||
|
||||
for (size_t i = 0; i < TO_PAGES(STACK_SIZE); i++)
|
||||
{
|
||||
AllocatedPages pa = {
|
||||
.PhysicalAddress = (void *)((uintptr_t)this->StackBottom + (i * PAGE_SIZE)),
|
||||
.VirtualAddress = (void *)((uintptr_t)this->StackBottom + (i * PAGE_SIZE)),
|
||||
};
|
||||
AllocatedPagesList.push_back(pa);
|
||||
}
|
||||
}
|
||||
|
||||
debug("Allocated stack at %#lx", this->StackBottom);
|
||||
}
|
||||
|
||||
StackGuard::~StackGuard()
|
||||
{
|
||||
foreach (auto Page in AllocatedPagesList)
|
||||
{
|
||||
KernelAllocator.FreePage(Page.PhysicalAddress);
|
||||
debug("Freed page at %#lx", Page.PhysicalAddress);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,34 +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 <memory.hpp>
|
||||
|
||||
#include <convert.h>
|
||||
#include <debug.h>
|
||||
|
||||
namespace Memory
|
||||
{
|
||||
Virtual::Virtual(PageTable *Table)
|
||||
{
|
||||
if (Table)
|
||||
this->Table = Table;
|
||||
else
|
||||
this->Table = (PageTable *)CPU::PageTable();
|
||||
}
|
||||
|
||||
Virtual::~Virtual() {}
|
||||
}
|
@ -1,22 +0,0 @@
|
||||
# Core components
|
||||
|
||||
This directory contains the core components of the project. These components are used by the kernel to provide the basic functionality of the operating system.
|
||||
|
||||
---
|
||||
|
||||
## 💾 Memory
|
||||
|
||||
Contains the memory management code.
|
||||
It is responsible for allocating and freeing memory.
|
||||
It also provides the `kmalloc`, `kcalloc`, `krealloc` and `kfree` functions that are used by the rest of the kernel.
|
||||
|
||||
## 📺 Video
|
||||
|
||||
Contains the video management code.
|
||||
It is responsible for printing text to the screen.
|
||||
|
||||
## 🖥 CPU
|
||||
|
||||
Contains the CPU management code.
|
||||
It is responsible for initializing the GDT and IDT.
|
||||
More code related is in the `Architecture` directory.
|
@ -1,35 +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_CRASH_HANDLER_H__
|
||||
#define __FENNIX_KERNEL_CRASH_HANDLER_H__
|
||||
|
||||
#include <types.h>
|
||||
|
||||
#include <ints.hpp>
|
||||
#include <cpu.hpp>
|
||||
|
||||
namespace CrashHandler
|
||||
{
|
||||
extern uintptr_t PageFaultAddress;
|
||||
extern void *EHIntFrames[INT_FRAMES_MAX];
|
||||
|
||||
void EHPrint(const char *Format, ...);
|
||||
void Handle(void *Data);
|
||||
}
|
||||
|
||||
#endif // !__FENNIX_KERNEL_CRASH_HANDLER_H__
|
74
Fex.hpp
74
Fex.hpp
@ -1,33 +1,33 @@
|
||||
/*
|
||||
BSD 3-Clause License
|
||||
BSD 3-Clause License
|
||||
|
||||
Copyright (c) 2023, EnderIce2
|
||||
All rights reserved.
|
||||
Copyright (c) 2023, EnderIce2
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
3. Neither the name of the copyright holder nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef __FENNIX_FILE_FEX_H__
|
||||
@ -50,7 +50,7 @@ enum FexFormatType
|
||||
{
|
||||
FexFormatType_Unknown,
|
||||
FexFormatType_Executable,
|
||||
FexFormatType_Driver
|
||||
FexFormatType_Module
|
||||
/* ... */
|
||||
};
|
||||
|
||||
@ -62,17 +62,17 @@ enum FexOSType
|
||||
/* ... */
|
||||
};
|
||||
|
||||
enum FexDriverType
|
||||
enum FexModuleType
|
||||
{
|
||||
FexDriverType_Unknown,
|
||||
FexDriverType_Generic,
|
||||
FexDriverType_Display,
|
||||
FexDriverType_Network,
|
||||
FexDriverType_Storage,
|
||||
FexDriverType_FileSystem,
|
||||
FexDriverType_Input,
|
||||
FexDriverType_Audio,
|
||||
FexDriverType_ACPI,
|
||||
FexModuleType_Unknown,
|
||||
FexModuleType_Generic,
|
||||
FexModuleType_Display,
|
||||
FexModuleType_Network,
|
||||
FexModuleType_Storage,
|
||||
FexModuleType_FileSystem,
|
||||
FexModuleType_Input,
|
||||
FexModuleType_Audio,
|
||||
FexModuleType_ACPI,
|
||||
/* ... */
|
||||
};
|
||||
|
||||
@ -105,13 +105,13 @@ struct FexExtended
|
||||
struct
|
||||
{
|
||||
char Name[64];
|
||||
enum FexDriverType Type : 4;
|
||||
enum FexModuleType Type : 4;
|
||||
enum FexDriverInputTypes TypeFlags : 4;
|
||||
char OverrideOnConflict;
|
||||
int (*Callback)(union KernelCallback *);
|
||||
int (*InterruptCallback)(union CPURegisters *);
|
||||
|
||||
struct DriverBind
|
||||
struct ModuleBind
|
||||
{
|
||||
int Type;
|
||||
struct
|
||||
@ -139,7 +139,7 @@ struct FexExtended
|
||||
char AttachToKeyboard;
|
||||
} Input;
|
||||
} Bind;
|
||||
} Driver;
|
||||
} Module;
|
||||
} __attribute__((packed));
|
||||
|
||||
/**
|
||||
|
@ -1,158 +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 <filesystem/ustar.hpp>
|
||||
|
||||
#include <memory.hpp>
|
||||
#include <debug.h>
|
||||
|
||||
#include "../../kernel.h"
|
||||
|
||||
namespace VirtualFileSystem
|
||||
{
|
||||
ReadFSFunction(USTAR_Read)
|
||||
{
|
||||
if (Size <= 0)
|
||||
Size = node->Length;
|
||||
|
||||
if (RefOffset > node->Length)
|
||||
return 0;
|
||||
|
||||
if (RefOffset + (off_t)Size > node->Length)
|
||||
Size = node->Length - RefOffset;
|
||||
|
||||
memcpy(Buffer, (uint8_t *)(node->Address + RefOffset), Size);
|
||||
return Size;
|
||||
}
|
||||
|
||||
FileSystemOperations ustar_op = {
|
||||
.Name = "ustar",
|
||||
.Read = USTAR_Read,
|
||||
};
|
||||
|
||||
bool USTAR::TestArchive(uintptr_t Address)
|
||||
{
|
||||
if (!Memory::Virtual().Check((void *)Address))
|
||||
{
|
||||
error("Address %#lx is not mapped!", Address);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (memcmp(((FileHeader *)(uintptr_t)Address)->signature, "ustar", 5) != 0)
|
||||
{
|
||||
error("ustar signature invalid!");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void USTAR::ReadArchive(uintptr_t Address, Virtual *vfs_ctx)
|
||||
{
|
||||
trace("Initializing USTAR with address %#llx", Address);
|
||||
|
||||
if (!this->TestArchive(Address))
|
||||
return; /* Check whether the archive is deflated */
|
||||
|
||||
debug("USTAR signature valid! Name:%s Signature:%s Mode:%c Size:%lu",
|
||||
((FileHeader *)Address)->name,
|
||||
((FileHeader *)Address)->signature,
|
||||
string2int(((FileHeader *)Address)->mode),
|
||||
((FileHeader *)Address)->size);
|
||||
|
||||
vfs_ctx->CreateRoot("/", &ustar_op);
|
||||
|
||||
for (size_t i = 0;; i++)
|
||||
{
|
||||
FileHeader *header = (FileHeader *)Address;
|
||||
if (memcmp(((FileHeader *)Address)->signature, "ustar", 5) != 0)
|
||||
break;
|
||||
memmove(header->name, header->name + 1, strlen(header->name));
|
||||
if (header->name[strlen(header->name) - 1] == '/')
|
||||
header->name[strlen(header->name) - 1] = 0;
|
||||
size_t size = getsize(header->size);
|
||||
Node *node = nullptr;
|
||||
|
||||
// if (!isempty((char *)header->name))
|
||||
// KPrint("Adding file \e88AACC%s\eCCCCCC (\e88AACC%lu \eCCCCCCbytes)", header->name, size);
|
||||
// else
|
||||
// goto NextFileAddress;
|
||||
|
||||
if (isempty((char *)header->name))
|
||||
goto NextFileAddress;
|
||||
|
||||
node = vfs_ctx->Create(header->name, NodeFlags::NODE_FLAG_ERROR);
|
||||
debug("Added node: %s", node->Name);
|
||||
if (node == nullptr)
|
||||
{
|
||||
static int ErrorsAllowed = 20;
|
||||
|
||||
if (ErrorsAllowed > 0)
|
||||
{
|
||||
ErrorsAllowed--;
|
||||
goto NextFileAddress;
|
||||
}
|
||||
else
|
||||
{
|
||||
error("Adding USTAR files failed because too many files were corrupted or invalid.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
debug("%s %d KiB, Type:%c", header->name, TO_KiB(size), header->typeflag[0]);
|
||||
node->Mode = string2int(header->mode);
|
||||
node->Address = (Address + 512);
|
||||
node->Length = size;
|
||||
node->GroupIdentifier = getsize(header->gid);
|
||||
node->UserIdentifier = getsize(header->uid);
|
||||
node->IndexNode = i;
|
||||
|
||||
switch (header->typeflag[0])
|
||||
{
|
||||
case REGULAR_FILE:
|
||||
node->Flags = NodeFlags::FILE;
|
||||
break;
|
||||
case SYMLINK:
|
||||
node->Flags = NodeFlags::SYMLINK;
|
||||
node->Symlink = new char[strlen(header->link) + 1];
|
||||
strncpy((char *)node->Symlink, header->link, strlen(header->link));
|
||||
break;
|
||||
case DIRECTORY:
|
||||
node->Flags = NodeFlags::DIRECTORY;
|
||||
break;
|
||||
case CHARDEV:
|
||||
node->Flags = NodeFlags::CHARDEVICE;
|
||||
break;
|
||||
case BLOCKDEV:
|
||||
node->Flags = NodeFlags::BLOCKDEVICE;
|
||||
break;
|
||||
default:
|
||||
warn("Unknown type: %d", header->typeflag[0]);
|
||||
break;
|
||||
}
|
||||
NextFileAddress:
|
||||
Address += ((size / 512) + 1) * 512;
|
||||
if (size % 512)
|
||||
Address += 512;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
USTAR::USTAR() {}
|
||||
|
||||
USTAR::~USTAR() {}
|
||||
}
|
@ -1,224 +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 <filesystem.hpp>
|
||||
|
||||
#ifdef DEBUG
|
||||
const char *SeekStrings[] =
|
||||
{"SEEK_SET",
|
||||
"SEEK_CUR",
|
||||
"SEEK_END"};
|
||||
#endif
|
||||
|
||||
namespace VirtualFileSystem
|
||||
{
|
||||
ReferenceNode *Node::CreateReference()
|
||||
{
|
||||
SmartLock(NodeLock);
|
||||
ReferenceNode *rn = new ReferenceNode(this);
|
||||
References.push_back(rn);
|
||||
debug("Created reference %p for node %p", rn, this);
|
||||
return rn;
|
||||
}
|
||||
|
||||
void Node::RemoveReference(ReferenceNode *Reference)
|
||||
{
|
||||
SmartLock(NodeLock);
|
||||
debug("Removing reference %p for node %p", Reference, this);
|
||||
References.erase(std::find(References.begin(), References.end(), Reference));
|
||||
}
|
||||
|
||||
/**************************************************************/
|
||||
|
||||
size_t ReferenceNode::Read(uint8_t *Buffer, size_t Size)
|
||||
{
|
||||
if (this->SymlinkTo)
|
||||
return this->SymlinkTo->Read(Buffer, Size);
|
||||
|
||||
if (!this->node->Operator)
|
||||
{
|
||||
errno = EFAULT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
SmartLock(RefNodeLock);
|
||||
|
||||
if (this->node->Operator->Read)
|
||||
{
|
||||
off_t RefOffset = off_t(this->Offset.load());
|
||||
return this->node->Operator->Read(this->node, Size, Buffer, RefOffset);
|
||||
}
|
||||
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
size_t ReferenceNode::Write(uint8_t *Buffer, size_t Size)
|
||||
{
|
||||
if (this->SymlinkTo)
|
||||
return this->SymlinkTo->Write(Buffer, Size);
|
||||
|
||||
if (!this->node->Operator)
|
||||
{
|
||||
errno = EFAULT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
SmartLock(RefNodeLock);
|
||||
|
||||
if (this->node->Operator->Write)
|
||||
{
|
||||
off_t RefOffset = off_t(this->Offset.load());
|
||||
return this->node->Operator->Write(this->node, Size, Buffer, RefOffset);
|
||||
}
|
||||
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
off_t ReferenceNode::Seek(off_t _Offset, int Whence)
|
||||
{
|
||||
if (this->SymlinkTo)
|
||||
return this->SymlinkTo->Seek(_Offset, Whence);
|
||||
|
||||
if (!this->node->Operator)
|
||||
{
|
||||
errno = EFAULT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
SmartLock(RefNodeLock);
|
||||
|
||||
if (this->node->Operator->Seek)
|
||||
{
|
||||
off_t RefOffset = off_t(this->Offset.load());
|
||||
debug("The node has a seek function");
|
||||
return this->node->Operator->Seek(this->node, _Offset, Whence, RefOffset);
|
||||
}
|
||||
|
||||
// debug("Current offset is %d", this->Offset.load());
|
||||
switch (Whence)
|
||||
{
|
||||
case SEEK_SET:
|
||||
{
|
||||
if (_Offset > this->node->Length)
|
||||
{
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (_Offset < 0)
|
||||
{
|
||||
fixme("Negative offset %d is not implemented", _Offset);
|
||||
_Offset = 0;
|
||||
}
|
||||
|
||||
if (_Offset > this->node->Length)
|
||||
{
|
||||
fixme("Offset %d is bigger than file size %d",
|
||||
_Offset, this->node->Length);
|
||||
_Offset = this->node->Length;
|
||||
}
|
||||
|
||||
this->Offset.store(_Offset);
|
||||
break;
|
||||
}
|
||||
case SEEK_CUR:
|
||||
{
|
||||
off_t NewOffset = off_t(this->Offset.load()) + _Offset;
|
||||
if (NewOffset > this->node->Length ||
|
||||
NewOffset < 0)
|
||||
{
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
this->Offset.store(NewOffset);
|
||||
break;
|
||||
}
|
||||
case SEEK_END:
|
||||
{
|
||||
off_t NewOffset = this->node->Length + _Offset;
|
||||
if (NewOffset > this->node->Length ||
|
||||
NewOffset < 0)
|
||||
{
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
this->Offset.store(NewOffset);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
error("Invalid whence!");
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
off_t RetOffset = off_t(this->Offset.load());
|
||||
// debug("( %d %ld %s[%d] ) -> %d",
|
||||
// _Offset, this->Offset.load(),
|
||||
// SeekStrings[Whence], Whence,
|
||||
// RetOffset);
|
||||
return RetOffset;
|
||||
}
|
||||
|
||||
ReferenceNode::ReferenceNode(Node *node)
|
||||
{
|
||||
SmartLock(RefNodeLock);
|
||||
this->node = node;
|
||||
this->FileSize = node->Length;
|
||||
this->AbsolutePath += node->FileSystem->GetPathFromNode(node);
|
||||
if (this->node->Flags == SYMLINK)
|
||||
{
|
||||
if (!this->node->SymlinkTarget)
|
||||
{
|
||||
this->node->SymlinkTarget =
|
||||
node->FileSystem->GetNodeFromPath(this->node->Symlink);
|
||||
|
||||
/* not standard but useful in kernel-space */
|
||||
this->node->Length = this->node->SymlinkTarget->Length;
|
||||
}
|
||||
|
||||
if (!this->node->SymlinkTarget)
|
||||
{
|
||||
error("Symlink target %s not found!",
|
||||
this->node->Symlink);
|
||||
errno = ENOENT;
|
||||
return;
|
||||
}
|
||||
|
||||
this->SymlinkTo = this->node->SymlinkTarget->CreateReference();
|
||||
}
|
||||
|
||||
debug("Created reference node for %s [%#lx]",
|
||||
this->AbsolutePath.c_str(), (uintptr_t)this);
|
||||
}
|
||||
|
||||
ReferenceNode::~ReferenceNode()
|
||||
{
|
||||
SmartLock(RefNodeLock);
|
||||
if (this->SymlinkTo)
|
||||
this->node->SymlinkTarget->RemoveReference(this);
|
||||
this->node->RemoveReference(this);
|
||||
|
||||
debug("Destroyed reference node for %s [%#lx]",
|
||||
this->AbsolutePath.c_str(), (uintptr_t)this);
|
||||
}
|
||||
}
|
@ -1,634 +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 <filesystem.hpp>
|
||||
|
||||
#include <smart_ptr.hpp>
|
||||
#include <convert.h>
|
||||
#include <printf.h>
|
||||
#include <cwalk.h>
|
||||
|
||||
#include "../kernel.h"
|
||||
|
||||
// show debug messages
|
||||
// #define DEBUG_FILESYSTEM 1
|
||||
|
||||
#ifdef DEBUG_FILESYSTEM
|
||||
#define vfsdbg(m, ...) debug(m, ##__VA_ARGS__)
|
||||
#else
|
||||
#define vfsdbg(m, ...)
|
||||
#endif
|
||||
|
||||
namespace VirtualFileSystem
|
||||
{
|
||||
std::string Virtual::GetPathFromNode(Node *File)
|
||||
{
|
||||
vfsdbg("GetPathFromNode( Node: \"%s\" )", File->Name);
|
||||
SmartLock(VirtualLock);
|
||||
|
||||
Node *Parent = File;
|
||||
char **Path = nullptr;
|
||||
size_t PathSize = 0;
|
||||
std::string FinalPath;
|
||||
|
||||
while (Parent != FileSystemRoot && Parent != nullptr)
|
||||
{
|
||||
if (File == FileSystemRoot->Children[0])
|
||||
{
|
||||
FinalPath = "/";
|
||||
break;
|
||||
}
|
||||
|
||||
bool Found = false;
|
||||
foreach (const auto &Children in FileSystemRoot->Children)
|
||||
if (Children == Parent)
|
||||
{
|
||||
Found = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (Found)
|
||||
break;
|
||||
|
||||
if (strlen(Parent->Name) == 0)
|
||||
break;
|
||||
|
||||
char **new_path = new char *[PathSize + 1];
|
||||
if (Path != nullptr)
|
||||
{
|
||||
memcpy(new_path, Path, sizeof(char *) * PathSize);
|
||||
delete[] Path;
|
||||
}
|
||||
|
||||
Path = new_path;
|
||||
Path[PathSize] = (char *)Parent->Name;
|
||||
PathSize++;
|
||||
new_path = new char *[PathSize + 1];
|
||||
memcpy(new_path, Path, sizeof(char *) * PathSize);
|
||||
delete[] Path;
|
||||
Path = new_path;
|
||||
Path[PathSize] = (char *)"/";
|
||||
PathSize++;
|
||||
Parent = Parent->Parent;
|
||||
}
|
||||
|
||||
for (size_t i = PathSize - 1; i < PathSize; i--)
|
||||
{
|
||||
if (Path[i] == nullptr)
|
||||
continue;
|
||||
FinalPath += Path[i];
|
||||
}
|
||||
|
||||
FinalPath += "\0";
|
||||
delete[] Path, Path = nullptr;
|
||||
vfsdbg("GetPathFromNode()->\"%s\"", FinalPath.c_str());
|
||||
return FinalPath;
|
||||
}
|
||||
|
||||
Node *Virtual::GetNodeFromPath_Unsafe(const char *Path, Node *Parent)
|
||||
{
|
||||
vfsdbg("GetNodeFromPath( Path: \"%s\" Parent: \"%s\" )",
|
||||
Path, Parent ? Parent->Name : "(null)");
|
||||
|
||||
if (strcmp(Path, "/") == 0)
|
||||
return FileSystemRoot->Children[0]; // 0 - filesystem root
|
||||
|
||||
if (strcmp(Path, ".") == 0)
|
||||
return Parent;
|
||||
|
||||
if (strcmp(Path, "..") == 0)
|
||||
{
|
||||
if (Parent)
|
||||
{
|
||||
if (Parent->Parent)
|
||||
return Parent->Parent;
|
||||
else
|
||||
return Parent;
|
||||
}
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Node *ReturnNode = Parent;
|
||||
bool IsAbsolutePath = cwk_path_is_absolute(Path);
|
||||
|
||||
if (!ReturnNode)
|
||||
ReturnNode = FileSystemRoot->Children[0]; // 0 - filesystem root
|
||||
|
||||
if (IsAbsolutePath)
|
||||
ReturnNode = FileSystemRoot->Children[0]; // 0 - filesystem root
|
||||
|
||||
cwk_segment segment;
|
||||
if (unlikely(!cwk_path_get_first_segment(Path, &segment)))
|
||||
{
|
||||
error("Path doesn't have any segments.");
|
||||
errno = ENOENT;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
char *SegmentName = new char[segment.end - segment.begin + 1];
|
||||
memcpy(SegmentName, segment.begin, segment.end - segment.begin);
|
||||
vfsdbg("GetNodeFromPath()->SegmentName: \"%s\"", SegmentName);
|
||||
GetNodeFromPathNextParent:
|
||||
foreach (auto Child in ReturnNode->Children)
|
||||
{
|
||||
vfsdbg("comparing \"%s\" with \"%s\"",
|
||||
Child->Name, SegmentName);
|
||||
if (strcmp(Child->Name, SegmentName) == 0)
|
||||
{
|
||||
ReturnNode = Child;
|
||||
goto GetNodeFromPathNextParent;
|
||||
}
|
||||
}
|
||||
delete[] SegmentName;
|
||||
} while (cwk_path_get_next_segment(&segment));
|
||||
|
||||
const char *basename;
|
||||
cwk_path_get_basename(Path, &basename, nullptr);
|
||||
vfsdbg("BaseName: \"%s\" NodeName: \"%s\"",
|
||||
basename, ReturnNode->Name);
|
||||
|
||||
if (strcmp(basename, ReturnNode->Name) == 0)
|
||||
{
|
||||
vfsdbg("GetNodeFromPath()->\"%s\"", ReturnNode->Name);
|
||||
return ReturnNode;
|
||||
}
|
||||
|
||||
vfsdbg("GetNodeFromPath()->\"(null)\"");
|
||||
errno = ENOENT;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Node *Virtual::GetNodeFromPath(const char *Path, Node *Parent)
|
||||
{
|
||||
SmartLock(VirtualLock);
|
||||
return GetNodeFromPath_Unsafe(Path, Parent);
|
||||
}
|
||||
|
||||
bool Virtual::PathIsRelative(const char *Path)
|
||||
{
|
||||
vfsdbg("PathIsRelative( Path: \"%s\" )", Path);
|
||||
bool IsRelative = cwk_path_is_relative(Path);
|
||||
vfsdbg("PathIsRelative()->%s", IsRelative ? "true" : "false");
|
||||
return IsRelative;
|
||||
}
|
||||
|
||||
Node *Virtual::GetParent(const char *Path, Node *Parent)
|
||||
{
|
||||
vfsdbg("GetParent( Path: \"%s\" Parent: \"%s\" )",
|
||||
Path, Parent->Name);
|
||||
|
||||
if (Parent)
|
||||
{
|
||||
vfsdbg("GetParent()->\"%s\"", Parent->Name);
|
||||
return Parent;
|
||||
}
|
||||
|
||||
Node *ParentNode = nullptr;
|
||||
if (FileSystemRoot->Children.size() >= 1)
|
||||
{
|
||||
assert(FileSystemRoot->Children[0] != nullptr);
|
||||
ParentNode = FileSystemRoot->Children[0]; // 0 - filesystem root
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: Check if here is a bug or something...
|
||||
const char *PathCopy;
|
||||
PathCopy = (char *)Path;
|
||||
size_t length;
|
||||
cwk_path_get_root(PathCopy, &length); // not working?
|
||||
if (length > 0)
|
||||
{
|
||||
foreach (auto Child in FileSystemRoot->Children)
|
||||
{
|
||||
if (strcmp(Child->Name, PathCopy) == 0)
|
||||
{
|
||||
ParentNode = Child;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
vfsdbg("GetParent()->\"%s\"", ParentNode->Name);
|
||||
return ParentNode;
|
||||
}
|
||||
|
||||
Node *Virtual::AddNewChild(const char *Name, Node *Parent)
|
||||
{
|
||||
if (!Parent)
|
||||
{
|
||||
error("Parent is null!");
|
||||
return nullptr;
|
||||
}
|
||||
vfsdbg("AddNewChild( Name: \"%s\" Parent: \"%s\" )",
|
||||
Name, Parent->Name);
|
||||
|
||||
Node *newNode = new Node;
|
||||
newNode->Parent = Parent;
|
||||
newNode->Name = new char[strlen(Name) + 1];
|
||||
strncpy((char *)newNode->Name, Name, strlen(Name));
|
||||
|
||||
newNode->Operator = Parent->Operator;
|
||||
newNode->FileSystem = this;
|
||||
Parent->Children.push_back(newNode);
|
||||
|
||||
vfsdbg("AddNewChild()->\"%s\"", newNode->Name);
|
||||
return newNode;
|
||||
}
|
||||
|
||||
Node *Virtual::GetChild(const char *Name, Node *Parent)
|
||||
{
|
||||
vfsdbg("GetChild( Name: \"%s\" Parent: \"%s\" )",
|
||||
Name, Parent->Name);
|
||||
|
||||
if (!Parent)
|
||||
{
|
||||
vfsdbg("GetChild()->nullptr");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
foreach (auto Child in Parent->Children)
|
||||
if (strcmp(Child->Name, Name) == 0)
|
||||
{
|
||||
vfsdbg("GetChild()->\"%s\"", Child->Name);
|
||||
return Child;
|
||||
}
|
||||
vfsdbg("GetChild()->nullptr (not found)");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int Virtual::RemoveChild(const char *Name, Node *Parent)
|
||||
{
|
||||
vfsdbg("RemoveChild( Name: \"%s\" Parent: \"%s\" )",
|
||||
Name, Parent->Name);
|
||||
|
||||
forItr(itr, Parent->Children)
|
||||
{
|
||||
if (strcmp((*itr)->Name, Name) == 0)
|
||||
{
|
||||
delete *itr, *itr = nullptr;
|
||||
Parent->Children.erase(itr);
|
||||
vfsdbg("RemoveChild()->OK");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
vfsdbg("RemoveChild()->NotFound");
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::string Virtual::NormalizePath(const char *Path, Node *Parent)
|
||||
{
|
||||
vfsdbg("NormalizePath( Path: \"%s\" Parent: \"%s\" )",
|
||||
Path, Parent->Name);
|
||||
|
||||
char *NormalizedPath = new char[strlen((char *)Path) + 1];
|
||||
std::string RelativePath;
|
||||
|
||||
cwk_path_normalize(Path, NormalizedPath, strlen((char *)Path) + 1);
|
||||
|
||||
if (cwk_path_is_relative(NormalizedPath))
|
||||
{
|
||||
std::string ParentPath = GetPathFromNode(Parent);
|
||||
size_t PathSize = cwk_path_join(ParentPath.c_str(),
|
||||
NormalizedPath,
|
||||
nullptr, 0);
|
||||
|
||||
RelativePath.resize(PathSize + 1);
|
||||
|
||||
cwk_path_join(ParentPath.c_str(), NormalizedPath,
|
||||
(char *)RelativePath.c_str(),
|
||||
PathSize + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
RelativePath = NormalizedPath;
|
||||
}
|
||||
delete[] NormalizedPath;
|
||||
vfsdbg("NormalizePath()->\"%s\"", RelativePath.get());
|
||||
return RelativePath;
|
||||
}
|
||||
|
||||
bool Virtual::PathExists(const char *Path, Node *Parent)
|
||||
{
|
||||
if (isempty((char *)Path))
|
||||
{
|
||||
vfsdbg("PathExists()->PathIsEmpty");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Parent == nullptr)
|
||||
Parent = FileSystemRoot;
|
||||
|
||||
vfsdbg("PathExists( Path: \"%s\" Parent: \"%s\" )",
|
||||
Path, Parent->Name);
|
||||
|
||||
if (GetNodeFromPath(NormalizePath(Path, Parent).c_str(), Parent))
|
||||
{
|
||||
vfsdbg("PathExists()->OK");
|
||||
return true;
|
||||
}
|
||||
|
||||
vfsdbg("PathExists()->NotFound");
|
||||
return false;
|
||||
}
|
||||
|
||||
Node *Virtual::CreateRoot(const char *RootName,
|
||||
FileSystemOperations *Operator)
|
||||
{
|
||||
if (Operator == nullptr)
|
||||
return nullptr;
|
||||
|
||||
debug("Creating root %s", RootName);
|
||||
|
||||
SmartLock(VirtualLock);
|
||||
Node *newNode = new Node;
|
||||
newNode->Name = RootName;
|
||||
newNode->Flags = NodeFlags::DIRECTORY;
|
||||
newNode->Operator = Operator;
|
||||
newNode->FileSystem = this;
|
||||
FileSystemRoot->Children.push_back(newNode);
|
||||
return newNode;
|
||||
}
|
||||
|
||||
/* TODO: Further testing needed */
|
||||
Node *Virtual::Create(const char *Path, NodeFlags Flag, Node *Parent)
|
||||
{
|
||||
if (isempty((char *)Path))
|
||||
return nullptr;
|
||||
|
||||
SmartLock(VirtualLock);
|
||||
Node *RootNode = FileSystemRoot->Children[0];
|
||||
Node *CurrentParent = this->GetParent(Path, Parent);
|
||||
vfsdbg("Virtual::Create( Path: \"%s\" Parent: \"%s\" )",
|
||||
Path, Parent ? Parent->Name : CurrentParent->Name);
|
||||
|
||||
VirtualLock.Unlock();
|
||||
std::string CleanPath = this->NormalizePath(Path, CurrentParent);
|
||||
VirtualLock.Lock(__FUNCTION__);
|
||||
vfsdbg("CleanPath: \"%s\"", CleanPath.get());
|
||||
|
||||
VirtualLock.Unlock();
|
||||
if (PathExists(CleanPath.c_str(), CurrentParent))
|
||||
{
|
||||
error("Path %s already exists.", CleanPath.c_str());
|
||||
goto CreatePathError;
|
||||
}
|
||||
VirtualLock.Lock(__FUNCTION__);
|
||||
|
||||
cwk_segment segment;
|
||||
if (!cwk_path_get_first_segment(CleanPath.c_str(), &segment))
|
||||
{
|
||||
error("Path doesn't have any segments.");
|
||||
goto CreatePathError;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
char *SegmentName = new char[segment.end - segment.begin + 1];
|
||||
memcpy(SegmentName, segment.begin, segment.end - segment.begin);
|
||||
vfsdbg("SegmentName: \"%s\"", SegmentName);
|
||||
|
||||
if (Parent)
|
||||
{
|
||||
if (GetChild(SegmentName, RootNode) != nullptr)
|
||||
{
|
||||
RootNode = GetChild(SegmentName, RootNode);
|
||||
delete[] SegmentName;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (GetChild(SegmentName, CurrentParent) == nullptr)
|
||||
{
|
||||
CurrentParent = AddNewChild(SegmentName, CurrentParent);
|
||||
CurrentParent->Flags = Flag;
|
||||
}
|
||||
else
|
||||
{
|
||||
CurrentParent = GetChild(SegmentName, CurrentParent);
|
||||
}
|
||||
|
||||
delete[] SegmentName;
|
||||
} while (cwk_path_get_next_segment(&segment));
|
||||
|
||||
vfsdbg("Virtual::Create()->\"%s\"", CurrentParent->Name);
|
||||
#ifdef DEBUG
|
||||
VirtualLock.Unlock();
|
||||
debug("Path created: \"%s\"",
|
||||
GetPathFromNode(CurrentParent).c_str());
|
||||
VirtualLock.Lock(__FUNCTION__);
|
||||
#endif
|
||||
return CurrentParent;
|
||||
|
||||
CreatePathError:
|
||||
vfsdbg("Virtual::Create()->nullptr");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int Virtual::Delete(const char *Path, bool Recursive, Node *Parent)
|
||||
{
|
||||
vfsdbg("Virtual::Delete( Path: \"%s\" Parent: \"%s\" )",
|
||||
Path, Parent ? Parent->Name : "(null)");
|
||||
|
||||
if (isempty((char *)Path))
|
||||
{
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (Parent == nullptr)
|
||||
Parent = FileSystemRoot;
|
||||
|
||||
std::string CleanPath = this->NormalizePath(Path, Parent);
|
||||
vfsdbg("CleanPath: \"%s\"", CleanPath.c_str());
|
||||
|
||||
if (!PathExists(CleanPath.c_str(), Parent))
|
||||
{
|
||||
vfsdbg("Path %s doesn't exist.", CleanPath.c_str());
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
Node *NodeToDelete = GetNodeFromPath(CleanPath.c_str(), Parent);
|
||||
|
||||
if (NodeToDelete->Flags == NodeFlags::DIRECTORY)
|
||||
{
|
||||
SmartLock(VirtualLock);
|
||||
if (Recursive)
|
||||
{
|
||||
foreach (auto Child in NodeToDelete->Children)
|
||||
{
|
||||
VirtualLock.Unlock();
|
||||
int Status = Delete(GetPathFromNode(Child).c_str(), true);
|
||||
VirtualLock.Lock(__FUNCTION__);
|
||||
if (Status != 0)
|
||||
{
|
||||
error("Failed to delete child %s with status %d. (%s)",
|
||||
Child->Name, Status, Path);
|
||||
errno = EIO;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (NodeToDelete->Children.size() > 0)
|
||||
{
|
||||
error("Directory %s is not empty.", CleanPath.c_str());
|
||||
errno = ENOTEMPTY;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
SmartLock(VirtualLock);
|
||||
Node *ParentNode = GetParent(CleanPath.c_str(), Parent);
|
||||
if (RemoveChild(NodeToDelete->Name, ParentNode) != 0)
|
||||
{
|
||||
error("Failed to remove child %s from parent %s. (%s)", NodeToDelete->Name, ParentNode->Name, Path);
|
||||
errno = EIO;
|
||||
return -1;
|
||||
}
|
||||
|
||||
debug("Deleted %s", CleanPath.c_str());
|
||||
vfsdbg("Virtual::Delete()->OK");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Virtual::Delete(Node *Path, bool Recursive, Node *Parent)
|
||||
{
|
||||
std::string PathString = GetPathFromNode(Path);
|
||||
return Delete(PathString.c_str(), Recursive, Parent);
|
||||
}
|
||||
|
||||
/* TODO: REWORK */
|
||||
Node *Virtual::Mount(const char *Path, FileSystemOperations *Operator)
|
||||
{
|
||||
if (unlikely(!Operator))
|
||||
{
|
||||
errno = EFAULT;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (unlikely(isempty((char *)Path)))
|
||||
{
|
||||
errno = EINVAL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
vfsdbg("Mounting %s", Path);
|
||||
const char *PathCopy;
|
||||
cwk_path_get_basename(Path, &PathCopy, 0);
|
||||
Node *MountPoint = Create(Path, NodeFlags::MOUNTPOINT);
|
||||
MountPoint->Operator = Operator;
|
||||
return MountPoint;
|
||||
}
|
||||
|
||||
int Virtual::Unmount(Node *File)
|
||||
{
|
||||
if (unlikely(!File))
|
||||
{
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (unlikely(File->Flags != NodeFlags::MOUNTPOINT))
|
||||
{
|
||||
errno = ENOTDIR;
|
||||
return -1;
|
||||
}
|
||||
|
||||
fixme("Unmounting %s",
|
||||
File->Name);
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
RefNode *Virtual::Open(const char *Path, Node *Parent)
|
||||
{
|
||||
vfsdbg("Opening %s with parent %s", Path, Parent ? Parent->Name : "(null)");
|
||||
|
||||
if (strcmp(Path, "/") == 0)
|
||||
return FileSystemRoot->CreateReference();
|
||||
|
||||
if (!Parent)
|
||||
Parent = FileSystemRoot->Children[0];
|
||||
|
||||
if (strcmp(Path, ".") == 0)
|
||||
return Parent->CreateReference();
|
||||
|
||||
if (strcmp(Path, "..") == 0)
|
||||
{
|
||||
if (Parent->Parent)
|
||||
return Parent->Parent->CreateReference();
|
||||
else
|
||||
return Parent->CreateReference();
|
||||
}
|
||||
|
||||
Node *CurrentParent = this->GetParent(Path, Parent);
|
||||
std::string CleanPath = NormalizePath(Path, CurrentParent);
|
||||
|
||||
/* TODO: Check for other errors */
|
||||
if (!PathExists(CleanPath.c_str(), CurrentParent))
|
||||
{
|
||||
{
|
||||
SmartLock(VirtualLock);
|
||||
foreach (auto Child in FileSystemRoot->Children)
|
||||
{
|
||||
if (strcmp(Child->Name, CleanPath.c_str()) != 0)
|
||||
continue;
|
||||
|
||||
return Child->CreateReference();
|
||||
}
|
||||
}
|
||||
|
||||
Node *node = GetNodeFromPath(CleanPath.c_str(), FileSystemRoot->Children[0]);
|
||||
if (node)
|
||||
return node->CreateReference();
|
||||
}
|
||||
else
|
||||
{
|
||||
Node *node = GetNodeFromPath(CleanPath.c_str(), CurrentParent);
|
||||
if (node)
|
||||
return node->CreateReference();
|
||||
}
|
||||
|
||||
errno = ENOENT;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Virtual::Virtual()
|
||||
{
|
||||
SmartLock(VirtualLock);
|
||||
trace("Initializing virtual file system...");
|
||||
FileSystemRoot = new Node;
|
||||
FileSystemRoot->Flags = NodeFlags::MOUNTPOINT;
|
||||
FileSystemRoot->Operator = nullptr;
|
||||
FileSystemRoot->Parent = nullptr;
|
||||
FileSystemRoot->Name = "root";
|
||||
FileSystemRoot->FileSystem = this;
|
||||
cwk_path_set_style(CWK_STYLE_UNIX);
|
||||
}
|
||||
|
||||
Virtual::~Virtual()
|
||||
{
|
||||
SmartLock(VirtualLock);
|
||||
stub;
|
||||
/* TODO: sync, cache */
|
||||
}
|
||||
}
|
@ -1,49 +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 <filesystem.hpp>
|
||||
#include <errno.h>
|
||||
|
||||
#include "../../kernel.h"
|
||||
|
||||
using namespace VirtualFileSystem;
|
||||
|
||||
ReadFSFunction(Null_Read)
|
||||
{
|
||||
if (Size <= 0)
|
||||
return 0;
|
||||
|
||||
memset(Buffer, 0, Size);
|
||||
return Size;
|
||||
}
|
||||
|
||||
ReadFSFunction(Null_Write)
|
||||
{
|
||||
return Size;
|
||||
}
|
||||
|
||||
FileSystemOperations null_op = {
|
||||
.Name = "Null",
|
||||
.Read = Null_Read,
|
||||
.Write = Null_Write,
|
||||
};
|
||||
|
||||
void Init_Null(Virtual *vfs_ctx)
|
||||
{
|
||||
Node *n = vfs_ctx->Create("null", CHARDEVICE, DevFS);
|
||||
n->Operator = &null_op;
|
||||
}
|
@ -1,52 +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 <filesystem.hpp>
|
||||
#include <rand.hpp>
|
||||
#include <errno.h>
|
||||
|
||||
#include "../../kernel.h"
|
||||
|
||||
using namespace VirtualFileSystem;
|
||||
|
||||
ReadFSFunction(Random_Read)
|
||||
{
|
||||
if (Size <= 0)
|
||||
return 0;
|
||||
|
||||
uint64_t *buf = (uint64_t *)Buffer;
|
||||
for (size_t i = 0; i < Size / sizeof(uint64_t); i++)
|
||||
buf[i] = Random::rand64();
|
||||
return Size;
|
||||
}
|
||||
|
||||
ReadFSFunction(Random_Write)
|
||||
{
|
||||
return Size;
|
||||
}
|
||||
|
||||
FileSystemOperations random_op = {
|
||||
.Name = "Random",
|
||||
.Read = Random_Read,
|
||||
.Write = Random_Write,
|
||||
};
|
||||
|
||||
void Init_Random(Virtual *vfs_ctx)
|
||||
{
|
||||
Node *n = vfs_ctx->Create("random", CHARDEVICE, DevFS);
|
||||
n->Operator = &random_op;
|
||||
}
|
@ -1,43 +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 <filesystem.hpp>
|
||||
#include <errno.h>
|
||||
|
||||
#include "../../kernel.h"
|
||||
|
||||
using namespace VirtualFileSystem;
|
||||
|
||||
ReadFSFunction(tty_Write)
|
||||
{
|
||||
for (size_t i = 0; i < Size; i++)
|
||||
putchar(((char *)Buffer)[i]);
|
||||
|
||||
Display->SetBuffer(0);
|
||||
return Size;
|
||||
}
|
||||
|
||||
FileSystemOperations tty_op = {
|
||||
.Name = "tty",
|
||||
.Write = tty_Write,
|
||||
};
|
||||
|
||||
void Init_Teletype(Virtual *vfs_ctx)
|
||||
{
|
||||
Node *n = vfs_ctx->Create("tty", CHARDEVICE, DevFS);
|
||||
n->Operator = &tty_op;
|
||||
}
|
@ -1,49 +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 <filesystem.hpp>
|
||||
#include <errno.h>
|
||||
|
||||
#include "../../kernel.h"
|
||||
|
||||
using namespace VirtualFileSystem;
|
||||
|
||||
ReadFSFunction(Zero_Read)
|
||||
{
|
||||
if (Size <= 0)
|
||||
return 0;
|
||||
|
||||
memset(Buffer, 0, Size);
|
||||
return Size;
|
||||
}
|
||||
|
||||
ReadFSFunction(Zero_Write)
|
||||
{
|
||||
return Size;
|
||||
}
|
||||
|
||||
FileSystemOperations zero_op = {
|
||||
.Name = "Zero",
|
||||
.Read = Zero_Read,
|
||||
.Write = Zero_Write,
|
||||
};
|
||||
|
||||
void Init_Zero(Virtual *vfs_ctx)
|
||||
{
|
||||
Node *n = vfs_ctx->Create("zero", CHARDEVICE, DevFS);
|
||||
n->Operator = &zero_op;
|
||||
}
|
7
ISSUES.md
Normal file
7
ISSUES.md
Normal file
@ -0,0 +1,7 @@
|
||||
- [x] Kernel stack is smashed when an interrupt occurs. (this bug it occurs when an interrupt like IRQ1 or IRQ12 occurs)
|
||||
- [x] After setting the new stack pointer, the kernel crashes with an invalid opcode.
|
||||
- [ ] Somewhere in the kernel, the memory is wrongly freed or memcpy/memset.
|
||||
- [ ] GlobalDescriptorTable::SetKernelStack() is not working properly.
|
||||
- [ ] Sometimes while the kernel is inside BeforeShutdown(), we end up in a deadlock.
|
||||
- [ ] CPU usage is not working properly.
|
||||
- [x] fork() syscall is not working.
|
740
Kernel.cpp
740
Kernel.cpp
@ -1,740 +0,0 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "kernel.h"
|
||||
|
||||
#include <filesystem/mounts.hpp>
|
||||
#include <filesystem/ustar.hpp>
|
||||
#include <memory.hpp>
|
||||
#include <convert.h>
|
||||
#include <ints.hpp>
|
||||
#include <printf.h>
|
||||
#include <lock.hpp>
|
||||
#include <uart.hpp>
|
||||
#include <debug.h>
|
||||
#include <smp.hpp>
|
||||
#include <cargs.h>
|
||||
#include <io.h>
|
||||
|
||||
#include "Core/smbios.hpp"
|
||||
#include "Tests/t.h"
|
||||
|
||||
bool DebuggerIsAttached = false;
|
||||
|
||||
/**
|
||||
* Fennix Kernel
|
||||
* -------------
|
||||
* This is the main kernel file. It contains the main function and the kernel entry point.
|
||||
*
|
||||
* LOADING PROCEDURE:
|
||||
* [BOOT] -> [Bootloader] -> [Boot Info Parser] -> Entry() -> Main() -> KernelMainThread()
|
||||
* - Bootloader
|
||||
* - Entry() is the first function to be called by the boot info parser function after getting the boot info from the bootloader.
|
||||
* - Main() is the first function to be called by Entry().
|
||||
* - KernelMainThread() is the first function to be called by the task manager.
|
||||
*
|
||||
* TODO:
|
||||
* - [x] Optimize SMP.
|
||||
* - [ ] Support IPv6.
|
||||
* - [ ] Endianess of the network stack (currently: [HOST](LSB)<=>[NETWORK](MSB)). Not sure if this is a standard or not.
|
||||
* - [ ] Support 32-bit applications (ELF, PE, etc).
|
||||
* - [ ] Do not map the entire memory. Map only the needed memory address at allocation time.
|
||||
* - [ ] Implementation of logging (beside serial) with log rotation.
|
||||
* - [ ] Implement a better task manager. (replace struct P/TCB with classes)
|
||||
* - [?] Rewrite virtual file system. (it's very bad, I don't know how I wrote it this bad)
|
||||
* - [ ] Colors in crash screen are not following the kernel color scheme.
|
||||
* - [x] Find a way to add intrinsics.
|
||||
* - [ ] Rework PSF1 font loader.
|
||||
* - [x] The cleanup should be done by a thread (tasking). This is done to avoid a deadlock.
|
||||
* - [ ] Implement a better Display::SetBrightness() function.
|
||||
* - [ ] Fix memcpy, memset and memcmp functions (they are not working properly with SIMD).
|
||||
* - [ ] Fully support i386.
|
||||
* - [ ] Support Aarch64.
|
||||
* - [ ] SMP trampoline shouldn't be hardcoded at 0x2000.
|
||||
* - [ ] Rework the stack guard.
|
||||
* - [x] Mutex implementation.
|
||||
* - [ ] Update SMBIOS functions to support newer versions and actually use it.
|
||||
* - [ ] COW (Copy On Write) for the virtual memory. (https://en.wikipedia.org/wiki/Copy-on-write)
|
||||
* - [ ] Bootstrap should have a separate bss section + PHDR.
|
||||
* - [ ] Reimplement the driver conflict detection.
|
||||
* - [ ] Elf loader shouldn't create a full copy of the elf binary. Copy only the needed sections.
|
||||
* - [ ] Use NX-bit.
|
||||
*
|
||||
* ISSUES:
|
||||
* - [x] Kernel stack is smashed when an interrupt occurs. (this bug it occurs when an interrupt like IRQ1 or IRQ12 occurs)
|
||||
* - [x] After setting the new stack pointer, the kernel crashes with an invalid opcode.
|
||||
* - [?] Somewhere in the kernel, the memory is wrongly freed or memcpy/memset.
|
||||
* - [ ] GlobalDescriptorTable::SetKernelStack() is not working properly.
|
||||
* - [ ] Sometimes while the kernel is inside BeforeShutdown(), we end up in a deadlock.
|
||||
* - [ ] CPU usage is not working properly.
|
||||
* - [x] fork() syscall is not working.
|
||||
*
|
||||
* CREDITS AND REFERENCES:
|
||||
* - General:
|
||||
* https://wiki.osdev.org/Main_Page
|
||||
* https://gcc.gnu.org/onlinedocs/gcc/x86-Built-in-Functions.html#x86-Built-in-Functions
|
||||
* https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#Common-Function-Attributes
|
||||
*
|
||||
* - Font:
|
||||
* http://www.fial.com/~scott/tamsyn-font/
|
||||
*
|
||||
* - CPU XCR0 structure:
|
||||
* https://wiki.osdev.org/CPU_Registers_x86#XCR0
|
||||
*
|
||||
* - CPUID 0x7:
|
||||
* https://en.wikipedia.org/wiki/CPUID
|
||||
*
|
||||
* - Network:
|
||||
* https://web.archive.org/web/20051210132103/http://users.pcnet.ro/dmoroian/beej/Beej.html
|
||||
* https://web.archive.org/web/20060229214053/http://www.cs.rutgers.edu/~pxk/417/notes/sockets/udp.html
|
||||
* https://en.wikipedia.org/wiki/EtherType
|
||||
* https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/6/html/performance_tuning_guide/s-network-packet-reception
|
||||
* https://linux-kernel-labs.github.io/refs/heads/master/labs/networking.html
|
||||
* https://github.com/smoltcp-rs/smoltcp
|
||||
* https://www.ciscopress.com/articles/article.asp?p=3089352&seqNum=5
|
||||
* https://www.cs.unh.edu/cnrg/people/gherrin/linux-net.html
|
||||
* https://en.wikipedia.org/wiki/List_of_IP_protocol_numbers
|
||||
* https://github.com/TheUltimateFoxOS/horizon
|
||||
* https://en.wikipedia.org/wiki/Address_Resolution_Protocol
|
||||
* https://en.cppreference.com/w/cpp/language/operators
|
||||
* https://en.wikipedia.org/wiki/Dynamic_Host_Configuration_Protocol
|
||||
* https://www.cs.usfca.edu/~cruse/cs326f04/RTL8139D_DataSheet.pdf
|
||||
* https://www.javatpoint.com/arp-packet-format
|
||||
* https://www.cs.usfca.edu/~cruse/cs326f04/RTL8139_ProgrammersGuide.pdf
|
||||
* http://realtek.info/pdf/rtl8139cp.pdf
|
||||
* https://en.wikipedia.org/wiki/IPv4
|
||||
* https://www.iana.org/assignments/icmp-parameters/icmp-parameters.xhtml
|
||||
*
|
||||
* - Loading ELF shared libraries and dynamic linking:
|
||||
* https://www.akkadia.org/drepper/dsohowto.pdf
|
||||
* https://wiki.osdev.org/Dynamic_Linker
|
||||
* https://github.com/tyler569/nightingale
|
||||
* https://www.technovelty.org/linux/plt-and-got-the-key-to-code-sharing-and-dynamic-libraries.html
|
||||
* https://www.youtube.com/watch?v=kUk5pw4w0h4
|
||||
* https://docs.oracle.com/cd/E19683-01/817-3677/chapter6-42444/index.html
|
||||
* https://ir0nstone.gitbook.io/notes/types/stack/aslr/plt_and_got
|
||||
*
|
||||
* - IPC:
|
||||
* https://docs.oracle.com/cd/E19048-01/chorus5/806-6897/architecture-103/index.html
|
||||
* https://www.scaler.com/topics/operating-system/inter-process-communication-in-os/
|
||||
* https://en.wikipedia.org/wiki/Inter-process_communication
|
||||
* https://www.geeksforgeeks.org/inter-process-communication-ipc/
|
||||
*
|
||||
* - PCI:
|
||||
* https://wiki.osdev.org/PCI
|
||||
* https://en.wikipedia.org/wiki/PCI_configuration_space
|
||||
*
|
||||
* - Audio:
|
||||
* https://trac.ffmpeg.org/wiki/audio%20types
|
||||
* https://wiki.osdev.org/AC97
|
||||
* https://github.com/LemonOSProject/LemonOS
|
||||
* https://inst.eecs.berkeley.edu//~cs150/Documents/ac97_r23.pdf
|
||||
*
|
||||
* - Intrinsics:
|
||||
* https://learn.microsoft.com/en-us/cpp/intrinsics/x86-intrinsics-list
|
||||
* https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html
|
||||
*
|
||||
* - CPUID lists:
|
||||
* https://www.amd.com/system/files/TechDocs/40332.pdf
|
||||
* https://www.scss.tcd.ie/~jones/CS4021/processor-identification-cpuid-instruction-note.pdf
|
||||
*
|
||||
* - SMBIOS:
|
||||
* https://www.dmtf.org/dsp/DSP0134
|
||||
* https://www.dmtf.org/sites/default/files/standards/documents/DSP0134_3.6.0.pdf
|
||||
* https://wiki.osdev.org/System_Management_BIOS
|
||||
*
|
||||
* - EDBA:
|
||||
* https://wiki.osdev.org/Memory_Map_(x86)
|
||||
*
|
||||
* - UMIP, SMAP and SMEP:
|
||||
* https://en.wikipedia.org/wiki/Control_register
|
||||
* https://web.archive.org/web/20160312223150/http://ncsi.com/nsatc11/presentations/wednesday/emerging_technologies/fischer.pdf
|
||||
* https://en.wikipedia.org/wiki/Supervisor_Mode_Access_Prevention
|
||||
*
|
||||
* - Atomic operations:
|
||||
* https://en.cppreference.com/w/cpp/atomic/atomic
|
||||
*
|
||||
* - ELF:
|
||||
* https://www.sco.com/developers/gabi/latest/ch4.eheader.html
|
||||
* https://refspecs.linuxfoundation.org/elf/elf.pdf
|
||||
* https://docs.oracle.com/cd/E19683-01/817-3677/chapter6-42444/index.html
|
||||
* https://docs.oracle.com/cd/E19683-01/816-1386/chapter6-83432/index.html
|
||||
* https://www.youtube.com/watch?v=nC1U1LJQL8o
|
||||
* https://stevens.netmeister.org/631/elf.html
|
||||
* https://github.com/torvalds/linux/blob/master/include/uapi/linux/elf.h
|
||||
*
|
||||
* - C++ ABI:
|
||||
* https://github.com/gcc-mirror/gcc/tree/master/libstdc%2B%2B-v3
|
||||
* https://itanium-cxx-abi.github.io/cxx-abi/abi.html
|
||||
*
|
||||
* - Keyboard:
|
||||
* https://www.win.tue.nl/~aeb/linux/kbd/scancodes-11.html
|
||||
* https://wiki.osdev.org/PS/2_Keyboard
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef a64
|
||||
#if UINTPTR_MAX != UINT64_MAX
|
||||
#error "uintptr_t is not 64-bit!"
|
||||
#endif // UINTPTR_MAX != UINT64_MAX
|
||||
#endif // a64
|
||||
|
||||
#ifdef a32
|
||||
#if UINTPTR_MAX != UINT32_MAX
|
||||
#error "uintptr_t is not 32-bit!"
|
||||
#endif // UINTPTR_MAX != UINT32_MAX
|
||||
#endif // a32
|
||||
|
||||
#ifdef aa64
|
||||
#if UINTPTR_MAX != UINT64_MAX
|
||||
#error "uintptr_t is not 64-bit!"
|
||||
#endif // UINTPTR_MAX != UINT64_MAX
|
||||
#endif // aa64
|
||||
|
||||
NewLock(KernelLock);
|
||||
|
||||
#include <intrin.hpp>
|
||||
|
||||
using VirtualFileSystem::Node;
|
||||
using VirtualFileSystem::NodeFlags;
|
||||
|
||||
__aligned(16) BootInfo bInfo{};
|
||||
Video::Display *Display = nullptr;
|
||||
SymbolResolver::Symbols *KernelSymbolTable = nullptr;
|
||||
Power::Power *PowerManager = nullptr;
|
||||
PCI::PCI *PCIManager = nullptr;
|
||||
Tasking::Task *TaskManager = nullptr;
|
||||
Time::time *TimeManager = nullptr;
|
||||
VirtualFileSystem::Virtual *vfs = nullptr;
|
||||
|
||||
KernelConfig Config = {
|
||||
.AllocatorType = Memory::MemoryAllocatorType::liballoc11,
|
||||
.SchedulerType = Multi,
|
||||
.DriverDirectory = {'/', 'm', 'o', 'd', 'u', 'l', 'e', 's', '\0'},
|
||||
.InitPath = {'/', 'b', 'i', 'n', '/', 'i', 'n', 'i', 't', '\0'},
|
||||
.UseLinuxSyscalls = false,
|
||||
.InterruptsOnCrash = true,
|
||||
.Cores = 0,
|
||||
.IOAPICInterruptCore = 0,
|
||||
.UnlockDeadLock = false,
|
||||
.SIMD = false,
|
||||
.BootAnimation = false,
|
||||
};
|
||||
|
||||
extern bool EnableProfiler;
|
||||
|
||||
// For the Display class. Printing on first buffer as default.
|
||||
int PutCharBufferIndex = 0;
|
||||
EXTERNC void putchar(char c)
|
||||
{
|
||||
if (Display)
|
||||
Display->Print(c, PutCharBufferIndex);
|
||||
else
|
||||
UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM1).Write(c);
|
||||
}
|
||||
|
||||
EXTERNC void KPrint(const char *Format, ...)
|
||||
{
|
||||
SmartLock(KernelLock);
|
||||
|
||||
if (TimeManager)
|
||||
{
|
||||
uint64_t Nanoseconds = TimeManager->GetNanosecondsSinceClassCreation();
|
||||
if (Nanoseconds != 0)
|
||||
{
|
||||
#if defined(a64)
|
||||
printf("\eCCCCCC[\e00AEFF%lu.%07lu\eCCCCCC] ",
|
||||
Nanoseconds / 10000000, Nanoseconds % 10000000);
|
||||
#elif defined(a32)
|
||||
printf("\eCCCCCC[\e00AEFF%llu.%07llu\eCCCCCC] ",
|
||||
Nanoseconds / 10000000, Nanoseconds % 10000000);
|
||||
#elif defined(aa64)
|
||||
printf("\eCCCCCC[\e00AEFF%lu.%07lu\eCCCCCC] ",
|
||||
Nanoseconds / 10000000, Nanoseconds % 10000000);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
va_list args;
|
||||
va_start(args, Format);
|
||||
vprintf(Format, args);
|
||||
va_end(args);
|
||||
|
||||
printf("\eCCCCCC\n");
|
||||
if (!Config.BootAnimation && Display)
|
||||
Display->SetBuffer(0);
|
||||
}
|
||||
|
||||
EXTERNC NIF void Main()
|
||||
{
|
||||
Display = new Video::Display(bInfo.Framebuffer[0]);
|
||||
|
||||
KPrint("%s - %s [\e058C19%s\eFFFFFF]",
|
||||
KERNEL_NAME, KERNEL_VERSION, GIT_COMMIT_SHORT);
|
||||
KPrint("CPU: \e058C19%s \e8822AA%s \e8888FF%s",
|
||||
CPU::Hypervisor(), CPU::Vendor(), CPU::Name());
|
||||
|
||||
if (Display->GetFramebufferStruct().BitsPerPixel != 32)
|
||||
KPrint("\eFF5500Framebuffer is not 32 bpp. This may cause issues.");
|
||||
|
||||
debug("CPU: %s %s %s",
|
||||
CPU::Hypervisor(), CPU::Vendor(), CPU::Name());
|
||||
|
||||
if (DebuggerIsAttached)
|
||||
KPrint("\eFFA500Kernel debugger detected.");
|
||||
|
||||
#if defined(a86) && defined(DEBUG)
|
||||
uint8_t lpt1 = inb(0x378);
|
||||
uint8_t lpt2 = inb(0x278);
|
||||
uint8_t lpt3 = inb(0x3BC);
|
||||
|
||||
uint8_t com1 = inb(0x3F8);
|
||||
uint8_t com2 = inb(0x2F8);
|
||||
uint8_t com3 = inb(0x3E8);
|
||||
uint8_t com4 = inb(0x2E8);
|
||||
|
||||
if (lpt1 != 0xFF)
|
||||
KPrint("LPT1 is present.");
|
||||
|
||||
if (lpt2 != 0xFF)
|
||||
KPrint("LPT2 is present.");
|
||||
|
||||
if (lpt3 != 0xFF)
|
||||
KPrint("LPT3 is present.");
|
||||
|
||||
if (com1 != 0xFF)
|
||||
KPrint("COM1 is present.");
|
||||
|
||||
if (com2 != 0xFF)
|
||||
KPrint("COM2 is present.");
|
||||
|
||||
if (com3 != 0xFF)
|
||||
KPrint("COM3 is present.");
|
||||
|
||||
if (com4 != 0xFF)
|
||||
KPrint("COM4 is present.");
|
||||
|
||||
KPrint("Display: %dx%d %d bpp \eFF0000R:%d %d \e00FF00G: %d %d \e0000FFB: %d %d",
|
||||
Display->GetFramebufferStruct().Width,
|
||||
Display->GetFramebufferStruct().Height,
|
||||
Display->GetFramebufferStruct().BitsPerPixel,
|
||||
Display->GetFramebufferStruct().RedMaskSize,
|
||||
Display->GetFramebufferStruct().RedMaskShift,
|
||||
Display->GetFramebufferStruct().GreenMaskSize,
|
||||
Display->GetFramebufferStruct().GreenMaskShift,
|
||||
Display->GetFramebufferStruct().BlueMaskSize,
|
||||
Display->GetFramebufferStruct().BlueMaskShift);
|
||||
#endif
|
||||
|
||||
/**************************************************************************************/
|
||||
|
||||
KPrint("Reading Kernel Parameters");
|
||||
ParseConfig((char *)bInfo.Kernel.CommandLine, &Config);
|
||||
|
||||
KPrint("Initializing CPU Features");
|
||||
CPU::InitializeFeatures(0);
|
||||
|
||||
KPrint("Initializing GDT and IDT");
|
||||
Interrupts::Initialize(0);
|
||||
|
||||
KPrint("Loading Kernel Symbols");
|
||||
KernelSymbolTable = new SymbolResolver::Symbols((uintptr_t)bInfo.Kernel.FileBase);
|
||||
|
||||
if (!KernelSymbolTable->SymTableExists)
|
||||
KernelSymbolTable->AddSymbolInfoFromGRUB(bInfo.Kernel.Symbols.Num,
|
||||
bInfo.Kernel.Symbols.EntSize,
|
||||
bInfo.Kernel.Symbols.Shndx,
|
||||
bInfo.Kernel.Symbols.Sections);
|
||||
|
||||
if (Config.BootAnimation)
|
||||
{
|
||||
Display->CreateBuffer(0, 0, 1);
|
||||
|
||||
Display->SetDoNotScroll(true, 1);
|
||||
Video::ScreenBuffer *buf = Display->GetBuffer(1);
|
||||
Video::FontInfo fi = Display->GetCurrentFont()->GetInfo();
|
||||
Display->SetBufferCursor(1, 0, buf->Height - fi.Height);
|
||||
PutCharBufferIndex = 1;
|
||||
printf("Fennix Operating System - %s [\e058C19%s\eFFFFFF]\n",
|
||||
KERNEL_VERSION, GIT_COMMIT_SHORT);
|
||||
Display->SetBuffer(1);
|
||||
PutCharBufferIndex = 0;
|
||||
}
|
||||
|
||||
KPrint("Initializing Power Manager");
|
||||
PowerManager = new Power::Power;
|
||||
|
||||
KPrint("Enabling Interrupts on Bootstrap Processor");
|
||||
Interrupts::Enable(0);
|
||||
|
||||
#if defined(a86)
|
||||
PowerManager->InitDSDT();
|
||||
#elif defined(aa64)
|
||||
#endif
|
||||
|
||||
KPrint("Initializing Timers");
|
||||
TimeManager = new Time::time;
|
||||
TimeManager->FindTimers(PowerManager->GetACPI());
|
||||
|
||||
KPrint("Initializing PCI Manager");
|
||||
PCIManager = new PCI::PCI;
|
||||
|
||||
foreach (auto Device in PCIManager->GetDevices())
|
||||
{
|
||||
KPrint("PCI: \e8888FF%s \eCCCCCC/ \e8888FF%s \eCCCCCC/ \e8888FF%s \eCCCCCC/ \e8888FF%s \eCCCCCC/ \e8888FF%s",
|
||||
PCI::Descriptors::GetVendorName(Device->VendorID),
|
||||
PCI::Descriptors::GetDeviceName(Device->VendorID, Device->DeviceID),
|
||||
PCI::Descriptors::DeviceClasses[Device->Class],
|
||||
PCI::Descriptors::GetSubclassName(Device->Class, Device->Subclass),
|
||||
PCI::Descriptors::GetProgIFName(Device->Class, Device->Subclass, Device->ProgIF));
|
||||
}
|
||||
|
||||
KPrint("Initializing Bootstrap Processor Timer");
|
||||
Interrupts::InitializeTimer(0);
|
||||
|
||||
KPrint("Initializing SMP");
|
||||
SMP::Initialize(PowerManager->GetMADT());
|
||||
|
||||
if (SMBIOS::CheckSMBIOS())
|
||||
{
|
||||
SMBIOS::SMBIOSEntryPoint *smbios = SMBIOS::GetSMBIOSEntryPoint();
|
||||
SMBIOS::SMBIOSBIOSInformation *bios = SMBIOS::GetBIOSInformation();
|
||||
SMBIOS::SMBIOSSystemInformation *system = SMBIOS::GetSystemInformation();
|
||||
SMBIOS::SMBIOSBaseBoardInformation *baseboard = SMBIOS::GetBaseBoardInformation();
|
||||
|
||||
debug("SMBIOS: %p", smbios);
|
||||
debug("BIOS: %p", bios);
|
||||
debug("System: %p", system);
|
||||
debug("Baseboard: %p", baseboard);
|
||||
|
||||
if (smbios)
|
||||
KPrint("SMBIOS: \eCCCCCCString:\e8888FF%.4s \eCCCCCCVersion (Major Minor):\e8888FF%d %d \eCCCCCCTable:\e8888FF%#x \eCCCCCCLength:\e8888FF%d",
|
||||
smbios->EntryPointString, smbios->MajorVersion, smbios->MinorVersion,
|
||||
smbios->TableAddress, smbios->TableLength);
|
||||
else
|
||||
KPrint("SMBIOS: \e8888FFSMBIOS found but not supported?");
|
||||
|
||||
if (bios)
|
||||
{
|
||||
const char *BIOSVendor = bios->GetString(bios->Vendor);
|
||||
const char *BIOSVersion = bios->GetString(bios->Version);
|
||||
const char *BIOSReleaseDate = bios->GetString(bios->ReleaseDate);
|
||||
debug("%d %d %d", bios->Vendor, bios->Version, bios->ReleaseDate);
|
||||
KPrint("BIOS: \e8888FF%s \eCCCCCC/ \e8888FF%s \eCCCCCC/ \e8888FF%s",
|
||||
BIOSVendor, BIOSVersion, BIOSReleaseDate);
|
||||
}
|
||||
|
||||
if (system)
|
||||
{
|
||||
const char *SystemManufacturer = system->GetString(system->Manufacturer);
|
||||
const char *SystemProductName = system->GetString(system->ProductName);
|
||||
const char *SystemVersion = system->GetString(system->Version);
|
||||
const char *SystemSerialNumber = system->GetString(system->SerialNumber);
|
||||
const char *SystemSKU = system->GetString(system->SKU);
|
||||
const char *SystemFamily = system->GetString(system->Family);
|
||||
debug("%d %d %d %d %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c %d %d", system->Manufacturer, system->ProductName, system->Version,
|
||||
system->SerialNumber,
|
||||
system->UUID[0], system->UUID[1], system->UUID[2], system->UUID[3],
|
||||
system->UUID[4], system->UUID[5], system->UUID[6], system->UUID[7],
|
||||
system->UUID[8], system->UUID[9], system->UUID[10], system->UUID[11],
|
||||
system->UUID[12], system->UUID[13], system->UUID[14], system->UUID[15],
|
||||
system->SKU, system->Family);
|
||||
KPrint("System: \e8888FF%s \eCCCCCC/ \e8888FF%s \eCCCCCC/ \e8888FF%s \eCCCCCC/ \e8888FF%s \eCCCCCC/ \e8888FF%s \eCCCCCC/ \e8888FF%s",
|
||||
SystemManufacturer, SystemProductName, SystemVersion, SystemSerialNumber, SystemSKU, SystemFamily);
|
||||
}
|
||||
|
||||
if (baseboard)
|
||||
{
|
||||
const char *Manufacturer = baseboard->GetString(baseboard->Manufacturer);
|
||||
const char *Product = baseboard->GetString(baseboard->Product);
|
||||
const char *Version = baseboard->GetString(baseboard->Version);
|
||||
const char *SerialNumber = baseboard->GetString(baseboard->SerialNumber);
|
||||
debug("%d %d %d %d", baseboard->Manufacturer, baseboard->Product, baseboard->Version, baseboard->SerialNumber);
|
||||
KPrint("Baseboard: \eCCCCCC\e8888FF%s \eCCCCCC/ \e8888FF%s \eCCCCCC/ \e8888FF%s \eCCCCCC/ \e8888FF%s",
|
||||
Manufacturer, Product, Version, SerialNumber);
|
||||
}
|
||||
}
|
||||
else
|
||||
KPrint("SMBIOS: \eFF0000Not Found");
|
||||
|
||||
KPrint("Initializing Filesystem...");
|
||||
vfs = new VirtualFileSystem::Virtual;
|
||||
|
||||
for (size_t i = 0; i < MAX_MODULES; i++)
|
||||
{
|
||||
if (!bInfo.Modules[i].Address)
|
||||
continue;
|
||||
|
||||
if (strcmp(bInfo.Modules[i].CommandLine, "initrd") == 0)
|
||||
{
|
||||
debug("Found initrd at %p", bInfo.Modules[i].Address);
|
||||
static char initrd = 0;
|
||||
if (!initrd++)
|
||||
{
|
||||
uintptr_t initrdAddress = (uintptr_t)bInfo.Modules[i].Address;
|
||||
VirtualFileSystem::USTAR *ustar = new VirtualFileSystem::USTAR;
|
||||
ustar->ReadArchive(initrdAddress, vfs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (vfs->GetRootNode()->Children.size() == 0)
|
||||
{
|
||||
VirtualFileSystem::FileSystemOperations null_op = {
|
||||
.Name = "null",
|
||||
};
|
||||
|
||||
vfs->CreateRoot("/", &null_op);
|
||||
}
|
||||
|
||||
if (!vfs->PathExists("/dev"))
|
||||
DevFS = vfs->Create("/dev", NodeFlags::DIRECTORY);
|
||||
else
|
||||
{
|
||||
RefNode *dev = vfs->Open("/dev");
|
||||
if (dev->GetNode()->Flags != NodeFlags::DIRECTORY)
|
||||
{
|
||||
KPrint("\eE85230/dev is not a directory! Halting...");
|
||||
CPU::Stop();
|
||||
}
|
||||
DevFS = dev->GetNode();
|
||||
delete dev;
|
||||
}
|
||||
|
||||
if (!vfs->PathExists("/mnt"))
|
||||
MntFS = vfs->Create("/mnt", NodeFlags::DIRECTORY);
|
||||
else
|
||||
{
|
||||
RefNode *mnt = vfs->Open("/mnt");
|
||||
if (mnt->GetNode()->Flags != NodeFlags::DIRECTORY)
|
||||
{
|
||||
KPrint("\eE85230/mnt is not a directory! Halting...");
|
||||
CPU::Stop();
|
||||
}
|
||||
MntFS = mnt->GetNode();
|
||||
delete mnt;
|
||||
}
|
||||
|
||||
if (!vfs->PathExists("/proc"))
|
||||
ProcFS = vfs->Create("/proc", NodeFlags::DIRECTORY);
|
||||
else
|
||||
{
|
||||
RefNode *proc = vfs->Open("/proc", nullptr);
|
||||
if (proc->GetNode()->Flags != NodeFlags::DIRECTORY)
|
||||
{
|
||||
KPrint("\eE85230/proc is not a directory! Halting...");
|
||||
CPU::Stop();
|
||||
}
|
||||
ProcFS = proc->GetNode();
|
||||
delete proc;
|
||||
}
|
||||
|
||||
if (!vfs->PathExists("/var"))
|
||||
VarLogFS = vfs->Create("/var", NodeFlags::DIRECTORY);
|
||||
else
|
||||
{
|
||||
RefNode *var = vfs->Open("/var", nullptr);
|
||||
if (var->GetNode()->Flags != NodeFlags::DIRECTORY)
|
||||
{
|
||||
KPrint("\eE85230/var is not a directory! Halting...");
|
||||
CPU::Stop();
|
||||
}
|
||||
VarLogFS = var->GetNode();
|
||||
delete var;
|
||||
|
||||
if (!vfs->PathExists("/var/log"))
|
||||
VarLogFS = vfs->Create("/var/log", NodeFlags::DIRECTORY);
|
||||
else
|
||||
{
|
||||
RefNode *var_log = vfs->Open("/var/log", nullptr);
|
||||
if (var_log->GetNode()->Flags != NodeFlags::DIRECTORY)
|
||||
{
|
||||
KPrint("\eE85230/var/log is not a directory! Halting...");
|
||||
CPU::Stop();
|
||||
}
|
||||
VarLogFS = var_log->GetNode();
|
||||
delete var_log;
|
||||
}
|
||||
}
|
||||
|
||||
Init_Null(vfs);
|
||||
Init_Random(vfs);
|
||||
Init_Teletype(vfs);
|
||||
Init_Zero(vfs);
|
||||
|
||||
KPrint("\e058C19################################");
|
||||
TaskManager = new Tasking::Task(Tasking::IP(KernelMainThread));
|
||||
CPU::Halt(true);
|
||||
}
|
||||
|
||||
typedef void (*CallPtr)(void);
|
||||
extern CallPtr __init_array_start[0], __init_array_end[0];
|
||||
extern CallPtr __fini_array_start[0], __fini_array_end[0];
|
||||
|
||||
EXTERNC __no_stack_protector NIF void Entry(BootInfo *Info)
|
||||
{
|
||||
trace("Hello, World!");
|
||||
|
||||
if (strcmp(CPU::Hypervisor(), x86_CPUID_VENDOR_TCG) == 0)
|
||||
{
|
||||
debug("\n\n----------------------------------------\nDEBUGGER DETECTED\n----------------------------------------\n\n");
|
||||
DebuggerIsAttached = true;
|
||||
}
|
||||
|
||||
memcpy(&bInfo, Info, sizeof(BootInfo));
|
||||
debug("BootInfo structure is at %p", &bInfo);
|
||||
|
||||
// https://wiki.osdev.org/Calling_Global_Constructors
|
||||
trace("There are %d constructors to call", __init_array_end - __init_array_start);
|
||||
for (CallPtr *func = __init_array_start; func != __init_array_end; func++)
|
||||
(*func)();
|
||||
|
||||
#ifdef a86
|
||||
if (!bInfo.SMBIOSPtr)
|
||||
{
|
||||
trace("SMBIOS was not provided by the bootloader. Trying to find it manually.");
|
||||
for (uintptr_t i = 0xF0000; i < 0x100000; i += 16)
|
||||
{
|
||||
if (memcmp((void *)i, "_SM_", 4) == 0 || memcmp((void *)i, "_SM3_", 5) == 0)
|
||||
{
|
||||
bInfo.SMBIOSPtr = (void *)i;
|
||||
trace("Found SMBIOS at %#lx", i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!bInfo.RSDP)
|
||||
{
|
||||
trace("RSDP was not provided by the bootloader. Trying to find it manually.");
|
||||
/* FIXME: Not always shifting by 4 will work. */
|
||||
uintptr_t EBDABase = (uintptr_t)mminw((void *)0x40E) << 4;
|
||||
|
||||
for (uintptr_t ptr = EBDABase;
|
||||
ptr < 0x100000; /* 1MB */
|
||||
ptr += 16)
|
||||
{
|
||||
if (unlikely(ptr == EBDABase + 0x400))
|
||||
{
|
||||
trace("EBDA is full. Trying to find RSDP in the BIOS area.");
|
||||
break;
|
||||
}
|
||||
|
||||
BootInfo::RSDPInfo *rsdp = (BootInfo::RSDPInfo *)ptr;
|
||||
if (memcmp(rsdp->Signature, "RSD PTR ", 8) == 0)
|
||||
{
|
||||
bInfo.RSDP = (BootInfo::RSDPInfo *)rsdp;
|
||||
trace("Found RSDP at %#lx", rsdp);
|
||||
}
|
||||
}
|
||||
|
||||
for (uintptr_t ptr = 0xE0000;
|
||||
ptr < 0x100000; /* 1MB */
|
||||
ptr += 16)
|
||||
{
|
||||
BootInfo::RSDPInfo *rsdp = (BootInfo::RSDPInfo *)ptr;
|
||||
if (memcmp(rsdp->Signature, "RSD PTR ", 8) == 0)
|
||||
{
|
||||
bInfo.RSDP = (BootInfo::RSDPInfo *)rsdp;
|
||||
trace("Found RSDP at %#lx", rsdp);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
InitializeMemoryManagement();
|
||||
|
||||
void *KernelStackAddress = KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE));
|
||||
uintptr_t KernelStack = (uintptr_t)KernelStackAddress + STACK_SIZE - 0x10;
|
||||
debug("Kernel stack: %#lx-%#lx", KernelStackAddress, KernelStack);
|
||||
#if defined(a64)
|
||||
asmv("mov %0, %%rsp"
|
||||
:
|
||||
: "r"(KernelStack)
|
||||
: "memory");
|
||||
asmv("mov $0, %rbp");
|
||||
#elif defined(a32)
|
||||
asmv("mov %0, %%esp"
|
||||
:
|
||||
: "r"(KernelStack)
|
||||
: "memory");
|
||||
asmv("mov $0, %ebp");
|
||||
#elif defined(aa64)
|
||||
#warning "Kernel stack is not set!"
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
/* I had to do this because KernelAllocator
|
||||
* is a global constructor but we need
|
||||
* memory management to be initialized first.
|
||||
*/
|
||||
TestMemoryAllocation();
|
||||
TestString();
|
||||
Test_std();
|
||||
#endif
|
||||
EnableProfiler = true;
|
||||
Main();
|
||||
}
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wdelete-non-virtual-dtor"
|
||||
extern "C" void __cxa_finalize(void *);
|
||||
EXTERNC __no_stack_protector void BeforeShutdown(bool Reboot)
|
||||
{
|
||||
UNUSED(Reboot);
|
||||
/* TODO: Announce shutdown */
|
||||
|
||||
trace("\n\n\n#################### SYSTEM SHUTTING DOWN ####################\n\n");
|
||||
|
||||
if (NIManager)
|
||||
delete NIManager, NIManager = nullptr;
|
||||
|
||||
if (DiskManager)
|
||||
delete DiskManager, DiskManager = nullptr;
|
||||
|
||||
if (DriverManager)
|
||||
delete DriverManager, DriverManager = nullptr;
|
||||
|
||||
if (TaskManager && !TaskManager->IsPanic())
|
||||
{
|
||||
TaskManager->SignalShutdown();
|
||||
delete TaskManager, TaskManager = nullptr;
|
||||
}
|
||||
|
||||
if (vfs)
|
||||
delete vfs, vfs = nullptr;
|
||||
|
||||
if (TimeManager)
|
||||
delete TimeManager, TimeManager = nullptr;
|
||||
|
||||
if (Display)
|
||||
delete Display, Display = nullptr;
|
||||
// PowerManager should not be called
|
||||
|
||||
// https://wiki.osdev.org/Calling_Global_Constructors
|
||||
debug("Calling destructors...");
|
||||
for (CallPtr *func = __fini_array_start; func != __fini_array_end; func++)
|
||||
(*func)();
|
||||
__cxa_finalize(nullptr);
|
||||
debug("Done.");
|
||||
}
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
EXTERNC void TaskingPanic()
|
||||
{
|
||||
if (TaskManager)
|
||||
TaskManager->Panic();
|
||||
}
|
@ -1,55 +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 "../cmds.hpp"
|
||||
|
||||
#include <filesystem.hpp>
|
||||
|
||||
#include "../../kernel.h"
|
||||
|
||||
using namespace VirtualFileSystem;
|
||||
|
||||
void cmd_cat(const char *args)
|
||||
{
|
||||
if (args[0] == '\0')
|
||||
return;
|
||||
|
||||
Node *thisNode = vfs->GetNodeFromPath(args, thisProcess->CurrentWorkingDirectory);
|
||||
if (thisNode == nullptr)
|
||||
{
|
||||
printf("cat: %s: No such file or directory\n", args);
|
||||
return;
|
||||
}
|
||||
|
||||
if (thisNode->Flags != NodeFlags::FILE &&
|
||||
thisNode->Flags != NodeFlags::CHARDEVICE)
|
||||
{
|
||||
printf("cat: %s: Not a file\n", args);
|
||||
return;
|
||||
}
|
||||
std::string path = vfs->GetPathFromNode(thisNode);
|
||||
|
||||
int fd = fopen(path.c_str(), "r");
|
||||
struct stat st;
|
||||
fstat(fd, &st);
|
||||
|
||||
char *buffer = new char[st.st_size + 1];
|
||||
fread(fd, buffer, st.st_size);
|
||||
printf("%s\n", buffer);
|
||||
delete[] buffer;
|
||||
fclose(fd);
|
||||
}
|
@ -1,46 +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 "../cmds.hpp"
|
||||
|
||||
#include <filesystem.hpp>
|
||||
|
||||
#include "../../kernel.h"
|
||||
|
||||
using namespace VirtualFileSystem;
|
||||
|
||||
void cmd_cd(const char *args)
|
||||
{
|
||||
if (args[0] == '\0')
|
||||
return;
|
||||
|
||||
Node *thisNode = vfs->GetNodeFromPath(args, thisProcess->CurrentWorkingDirectory);
|
||||
|
||||
if (thisNode == nullptr)
|
||||
{
|
||||
printf("cd: %s: No such file or directory\n", args);
|
||||
return;
|
||||
}
|
||||
|
||||
if (thisNode->Flags != NodeFlags::DIRECTORY)
|
||||
{
|
||||
printf("cd: %s: Not a directory\n", args);
|
||||
return;
|
||||
}
|
||||
|
||||
thisProcess->CurrentWorkingDirectory = thisNode;
|
||||
}
|
@ -1,25 +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 "../cmds.hpp"
|
||||
|
||||
#include "../../kernel.h"
|
||||
|
||||
void cmd_echo(const char *args)
|
||||
{
|
||||
printf("%s\n", args);
|
||||
}
|
@ -1,33 +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 "../cmds.hpp"
|
||||
|
||||
#include <filesystem.hpp>
|
||||
#include <task.hpp>
|
||||
|
||||
#include "../../kernel.h"
|
||||
|
||||
using namespace VirtualFileSystem;
|
||||
using namespace Tasking;
|
||||
|
||||
void cmd_exit(const char *)
|
||||
{
|
||||
KernelShutdownThread(false);
|
||||
// TaskManager->KillThread(thisThread, KILL_SUCCESS);
|
||||
CPU::Halt(true);
|
||||
}
|
@ -1,39 +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 "../cmds.hpp"
|
||||
|
||||
#include <filesystem.hpp>
|
||||
#include <task.hpp>
|
||||
|
||||
#include "../../kernel.h"
|
||||
|
||||
using namespace VirtualFileSystem;
|
||||
using namespace Tasking;
|
||||
|
||||
void cmd_kill(const char *args)
|
||||
{
|
||||
PID pid = atoi(args);
|
||||
PCB *pcb = TaskManager->GetProcessByID(pid);
|
||||
|
||||
if (pcb == nullptr)
|
||||
{
|
||||
printf("No process with PID %d\n", pid);
|
||||
return;
|
||||
}
|
||||
TaskManager->KillProcess(pcb, KILL_BY_OTHER_PROCESS);
|
||||
}
|
@ -1,37 +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 "../cmds.hpp"
|
||||
|
||||
#include <filesystem.hpp>
|
||||
#include <task.hpp>
|
||||
|
||||
#include "../../kernel.h"
|
||||
|
||||
using namespace VirtualFileSystem;
|
||||
using namespace Tasking;
|
||||
|
||||
void cmd_killall(const char *args)
|
||||
{
|
||||
foreach (auto Proc in TaskManager->GetProcessList())
|
||||
{
|
||||
if (strcmp(Proc->Name, args) == 0)
|
||||
{
|
||||
TaskManager->KillProcess(Proc, KILL_BY_OTHER_PROCESS);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,57 +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 "../cmds.hpp"
|
||||
|
||||
#include <filesystem.hpp>
|
||||
|
||||
#include "../../kernel.h"
|
||||
|
||||
using namespace VirtualFileSystem;
|
||||
|
||||
void cmd_ls(const char *args)
|
||||
{
|
||||
if (args[0] == '\0')
|
||||
{
|
||||
Node *rootNode = thisProcess->CurrentWorkingDirectory;
|
||||
|
||||
if (rootNode == nullptr)
|
||||
rootNode = vfs->GetRootNode()->Children[0];
|
||||
|
||||
foreach (auto var in rootNode->Children)
|
||||
printf("%s\n", var->Name);
|
||||
}
|
||||
else
|
||||
{
|
||||
Node *thisNode = vfs->GetNodeFromPath(args, thisProcess->CurrentWorkingDirectory);
|
||||
|
||||
if (thisNode == nullptr)
|
||||
{
|
||||
printf("ls: %s: No such file or directory\n", args);
|
||||
return;
|
||||
}
|
||||
|
||||
if (thisNode->Flags != NodeFlags::DIRECTORY)
|
||||
{
|
||||
printf("%s\n", thisNode->Name);
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (auto var in thisNode->Children)
|
||||
printf("%s\n", var->Name);
|
||||
}
|
||||
}
|
@ -1,36 +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 "../cmds.hpp"
|
||||
|
||||
#include "../../kernel.h"
|
||||
|
||||
void cmd_lsof(const char *)
|
||||
{
|
||||
printf("PROCESS FD NAME\n");
|
||||
foreach (auto Proc in TaskManager->GetProcessList())
|
||||
{
|
||||
if (!Proc)
|
||||
continue;
|
||||
|
||||
std::vector<VirtualFileSystem::FileDescriptorTable::Fildes> fds_array =
|
||||
Proc->FileDescriptors->GetFileDescriptors();
|
||||
foreach (auto fd in fds_array)
|
||||
printf("%s %d: %s\n", Proc->Name, fd.Descriptor,
|
||||
fd.Handle->AbsolutePath.c_str());
|
||||
}
|
||||
}
|
@ -1,41 +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 "../cmds.hpp"
|
||||
|
||||
#include <filesystem.hpp>
|
||||
|
||||
#include "../../kernel.h"
|
||||
|
||||
using namespace VirtualFileSystem;
|
||||
|
||||
void cmd_lspci(const char *)
|
||||
{
|
||||
foreach (auto Device in PCIManager->GetDevices())
|
||||
{
|
||||
printf("%02x:%02x.%d: %s: %s %s %s\n",
|
||||
// Device->Bus,
|
||||
// Device->Device,
|
||||
// Device->Function,
|
||||
// FIXME
|
||||
0, 0, 0,
|
||||
PCI::Descriptors::BridgeDeviceSubclassName(Device->Subclass),
|
||||
PCI::Descriptors::GetVendorName(Device->VendorID),
|
||||
PCI::Descriptors::GetDeviceName(Device->VendorID, Device->DeviceID),
|
||||
PCI::Descriptors::GetSubclassName(Device->Class, Device->Subclass));
|
||||
}
|
||||
}
|
@ -1,33 +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 "../cmds.hpp"
|
||||
|
||||
#include <filesystem.hpp>
|
||||
#include <task.hpp>
|
||||
|
||||
#include "../../kernel.h"
|
||||
|
||||
using namespace VirtualFileSystem;
|
||||
using namespace Tasking;
|
||||
|
||||
void cmd_ps(const char *)
|
||||
{
|
||||
printf("PID Name\n");
|
||||
foreach (auto p in TaskManager->GetProcessList())
|
||||
printf("%d %s\n", p->ID, p->Name);
|
||||
}
|
@ -1,32 +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 "../cmds.hpp"
|
||||
|
||||
#include <filesystem.hpp>
|
||||
#include <task.hpp>
|
||||
|
||||
#include "../../kernel.h"
|
||||
|
||||
using namespace VirtualFileSystem;
|
||||
using namespace Tasking;
|
||||
|
||||
void cmd_reboot(const char *)
|
||||
{
|
||||
KernelShutdownThread(true);
|
||||
CPU::Halt(true);
|
||||
}
|
@ -1,32 +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 "../cmds.hpp"
|
||||
|
||||
#include <filesystem.hpp>
|
||||
#include <task.hpp>
|
||||
|
||||
#include "../../kernel.h"
|
||||
|
||||
using namespace VirtualFileSystem;
|
||||
using namespace Tasking;
|
||||
|
||||
void cmd_shutdown(const char *)
|
||||
{
|
||||
KernelShutdownThread(false);
|
||||
CPU::Halt(true);
|
||||
}
|
@ -1,60 +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 "../cmds.hpp"
|
||||
|
||||
#include <filesystem.hpp>
|
||||
#include <task.hpp>
|
||||
|
||||
#include "../../kernel.h"
|
||||
|
||||
using namespace VirtualFileSystem;
|
||||
using namespace Tasking;
|
||||
|
||||
void cmd_top(const char *)
|
||||
{
|
||||
printf("\e9400A1PID \e9CA100Name \e00A15BState \eCCCCCCPriority Memory Usage CPU Usage\n");
|
||||
foreach (auto Proc in TaskManager->GetProcessList())
|
||||
{
|
||||
#if defined(a64)
|
||||
printf("\e9400A1%-4d \e9CA100%-20s \e00A15B%s \eCCCCCC%d %ld %ld\n",
|
||||
Proc->ID, Proc->Name, Proc->Status == Running ? "Running" : "Stopped",
|
||||
Proc->Info.Priority, Proc->Memory->GetAllocatedMemorySize(),
|
||||
Proc->Info.UserTime + Proc->Info.KernelTime);
|
||||
#elif defined(a32)
|
||||
printf("\e9400A1%-4d \e9CA100%-20s \e00A15B%s \eCCCCCC%d %lld %lld\n",
|
||||
Proc->ID, Proc->Name, Proc->Status == Running ? "Running" : "Stopped",
|
||||
Proc->Info.Priority, Proc->Memory->GetAllocatedMemorySize(),
|
||||
Proc->Info.UserTime + Proc->Info.KernelTime);
|
||||
#endif
|
||||
|
||||
foreach (auto Thrd in Proc->Threads)
|
||||
{
|
||||
#if defined(a64)
|
||||
printf(" \eA80011%-4d \e9CA100%-20s \e00A15B%s \eCCCCCC%d %ld %ld\n",
|
||||
Thrd->ID, Thrd->Name, Thrd->Status == Running ? "Running" : "Stopped",
|
||||
Thrd->Info.Priority, Thrd->Memory->GetAllocatedMemorySize(),
|
||||
Thrd->Info.UserTime + Thrd->Info.KernelTime);
|
||||
#elif defined(a32)
|
||||
printf(" \eA80011%-4d \e9CA100%-20s \e00A15B%s \eCCCCCC%d %lld %lld\n",
|
||||
Thrd->ID, Thrd->Name, Thrd->Status == Running ? "Running" : "Stopped",
|
||||
Thrd->Info.Priority, Thrd->Memory->GetAllocatedMemorySize(),
|
||||
Thrd->Info.UserTime + Thrd->Info.KernelTime);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
@ -1,29 +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 "../cmds.hpp"
|
||||
|
||||
#include <filesystem.hpp>
|
||||
|
||||
#include "../../kernel.h"
|
||||
|
||||
using namespace VirtualFileSystem;
|
||||
|
||||
void cmd_whoami(const char *)
|
||||
{
|
||||
printf("kernel\n");
|
||||
}
|
691
KernelThread.cpp
691
KernelThread.cpp
@ -1,691 +0,0 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "kernel.h"
|
||||
#ifdef DEBUG
|
||||
#include "Tests/t.h"
|
||||
#endif
|
||||
|
||||
#include <filesystem/ustar.hpp>
|
||||
#include <kshell.hpp>
|
||||
#include <power.hpp>
|
||||
#include <lock.hpp>
|
||||
#include <printf.h>
|
||||
#include <exec.hpp>
|
||||
#include <cwalk.h>
|
||||
#include <vm.hpp>
|
||||
#include <vector>
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#define STBI_NO_STDIO
|
||||
#define STBI_NO_LINEAR
|
||||
#define STBI_NO_THREAD_LOCALS
|
||||
#define STBI_NO_HDR
|
||||
#define STBI_ONLY_TGA
|
||||
#include <stb/image.h>
|
||||
|
||||
#include "DAPI.hpp"
|
||||
#include "Fex.hpp"
|
||||
|
||||
using VirtualFileSystem::Node;
|
||||
using VirtualFileSystem::NodeFlags;
|
||||
|
||||
Driver::Driver *DriverManager = nullptr;
|
||||
Disk::Manager *DiskManager = nullptr;
|
||||
NetworkInterfaceManager::NetworkInterface *NIManager = nullptr;
|
||||
VirtualFileSystem::Node *DevFS = nullptr;
|
||||
VirtualFileSystem::Node *MntFS = nullptr;
|
||||
VirtualFileSystem::Node *ProcFS = nullptr;
|
||||
VirtualFileSystem::Node *VarLogFS = nullptr;
|
||||
|
||||
#ifdef DEBUG
|
||||
void TreeFS(Node *node, int Depth)
|
||||
{
|
||||
return;
|
||||
foreach (auto Chld in node->Children)
|
||||
{
|
||||
printf("%*c %s\eFFFFFF\n", Depth, ' ', Chld->Name);
|
||||
|
||||
if (!Config.BootAnimation)
|
||||
Display->SetBuffer(0);
|
||||
TaskManager->Sleep(100);
|
||||
TreeFS(Chld, Depth + 1);
|
||||
}
|
||||
}
|
||||
|
||||
const char *Statuses[] = {
|
||||
"FF0000", /* Unknown */
|
||||
"AAFF00", /* Ready */
|
||||
"00AA00", /* Running */
|
||||
"FFAA00", /* Sleeping */
|
||||
"FFAA00", /* Blocked */
|
||||
"FF0088", /* Zombie */
|
||||
"FF0000", /* Terminated */
|
||||
};
|
||||
|
||||
const char *StatusesSign[] = {
|
||||
"Unknown",
|
||||
"Ready",
|
||||
"Run",
|
||||
"Sleep",
|
||||
"Wait",
|
||||
"Stop",
|
||||
"Terminated",
|
||||
};
|
||||
|
||||
const char *SuccessSourceStrings[] = {
|
||||
"Unknown",
|
||||
"GetNextAvailableThread",
|
||||
"GetNextAvailableProcess",
|
||||
"SchedulerSearchProcessThread",
|
||||
};
|
||||
|
||||
void TaskMgr_Dummy100Usage()
|
||||
{
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
|
||||
void TaskMgr_Dummy0Usage()
|
||||
{
|
||||
while (1)
|
||||
TaskManager->Sleep(1000000);
|
||||
}
|
||||
|
||||
uint64_t GetUsage(uint64_t OldSystemTime, Tasking::TaskInfo *Info)
|
||||
{
|
||||
/* https://github.com/reactos/reactos/blob/560671a784c1e0e0aa7590df5e0598c1e2f41f5a/base/applications/taskmgr/perfdata.c#L347 */
|
||||
if (Info->OldKernelTime || Info->OldUserTime)
|
||||
{
|
||||
uint64_t SystemTime = TimeManager->GetCounter() - OldSystemTime;
|
||||
uint64_t CurrentTime = Info->KernelTime + Info->UserTime;
|
||||
uint64_t OldTime = Info->OldKernelTime + Info->OldUserTime;
|
||||
uint64_t CpuUsage = (CurrentTime - OldTime) / SystemTime;
|
||||
CpuUsage = CpuUsage * 100;
|
||||
|
||||
// debug("CurrentTime: %ld OldTime: %ld Time Diff: %ld Usage: %ld%%",
|
||||
// CurrentTime, OldTime, SystemTime, CpuUsage);
|
||||
|
||||
Info->OldKernelTime = Info->KernelTime;
|
||||
Info->OldUserTime = Info->UserTime;
|
||||
return CpuUsage;
|
||||
}
|
||||
Info->OldKernelTime = Info->KernelTime;
|
||||
Info->OldUserTime = Info->UserTime;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ShowTaskManager = 0;
|
||||
|
||||
void TaskMgr()
|
||||
{
|
||||
thisThread->Rename("Debug Task Manager");
|
||||
thisThread->SetPriority(Tasking::Idle);
|
||||
|
||||
while (ShowTaskManager == 0)
|
||||
CPU::Pause();
|
||||
|
||||
thisThread->SetPriority(Tasking::Idle);
|
||||
|
||||
TaskManager->CreateThread(thisProcess, Tasking::IP(TaskMgr_Dummy100Usage))->Rename("Dummy 100% Usage");
|
||||
TaskManager->CreateThread(thisProcess, Tasking::IP(TaskMgr_Dummy0Usage))->Rename("Dummy 0% Usage");
|
||||
|
||||
while (true)
|
||||
{
|
||||
while (ShowTaskManager == 0)
|
||||
CPU::Pause();
|
||||
|
||||
static int sanity = 0;
|
||||
Video::ScreenBuffer *sb = Display->GetBuffer(0);
|
||||
for (short i = 0; i < 1000; i++)
|
||||
{
|
||||
for (short j = 0; j < 500; j++)
|
||||
{
|
||||
uint32_t *Pixel = (uint32_t *)((uintptr_t)sb->Buffer + (j * sb->Width + i) * (bInfo.Framebuffer[0].BitsPerPixel / 8));
|
||||
*Pixel = 0x222222;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t tmpX, tmpY;
|
||||
Display->GetBufferCursor(0, &tmpX, &tmpY);
|
||||
Display->SetBufferCursor(0, 0, 0);
|
||||
printf("\eF02C21Task Manager\n");
|
||||
static uint64_t OldSystemTime = 0;
|
||||
foreach (auto Proc in TaskManager->GetProcessList())
|
||||
{
|
||||
if (!Proc)
|
||||
continue;
|
||||
int Status = Proc->Status.load();
|
||||
uint64_t ProcessCpuUsage = GetUsage(OldSystemTime, &Proc->Info);
|
||||
#if defined(a64)
|
||||
printf("\e%s-> \eAABBCC%s \e00AAAA%s %ld%% (KT: %ld UT: %ld)\n",
|
||||
Statuses[Status], Proc->Name, StatusesSign[Status], ProcessCpuUsage, Proc->Info.KernelTime, Proc->Info.UserTime);
|
||||
#elif defined(a32)
|
||||
printf("\e%s-> \eAABBCC%s \e00AAAA%s %lld%% (KT: %lld UT: %lld)\n",
|
||||
Statuses[Status], Proc->Name, StatusesSign[Status], ProcessCpuUsage, Proc->Info.KernelTime, Proc->Info.UserTime);
|
||||
#elif defined(aa64)
|
||||
#endif
|
||||
|
||||
foreach (auto Thd in Proc->Threads)
|
||||
{
|
||||
if (!Thd)
|
||||
continue;
|
||||
Status = Thd->Status.load();
|
||||
uint64_t ThreadCpuUsage = GetUsage(OldSystemTime, &Thd->Info);
|
||||
#if defined(a64)
|
||||
printf(" \e%s-> \eAABBCC%s \e00AAAA%s %ld%% (KT: %ld UT: %ld, IP: \e24FF2B%#lx \eEDFF24%s\e00AAAA)\n\eAABBCC",
|
||||
Statuses[Status], Thd->Name, StatusesSign[Status], ThreadCpuUsage, Thd->Info.KernelTime,
|
||||
Thd->Info.UserTime, Thd->Registers.rip,
|
||||
Thd->Parent->ELFSymbolTable ? Thd->Parent->ELFSymbolTable->GetSymbolFromAddress(Thd->Registers.rip) : "unknown");
|
||||
#elif defined(a32)
|
||||
printf(" \e%s-> \eAABBCC%s \e00AAAA%s %lld%% (KT: %lld UT: %lld, IP: \e24FF2B%#x \eEDFF24%s\e00AAAA)\n\eAABBCC",
|
||||
Statuses[Status], Thd->Name, StatusesSign[Status], ThreadCpuUsage, Thd->Info.KernelTime,
|
||||
Thd->Info.UserTime, Thd->Registers.eip,
|
||||
Thd->Parent->ELFSymbolTable ? Thd->Parent->ELFSymbolTable->GetSymbolFromAddress(Thd->Registers.eip) : "unknown");
|
||||
#elif defined(aa64)
|
||||
#endif
|
||||
}
|
||||
}
|
||||
OldSystemTime = TimeManager->GetCounter();
|
||||
#if defined(a64)
|
||||
register uintptr_t CurrentStackAddress asm("rsp");
|
||||
printf("Sanity: %d, Stack: %#lx", sanity++, CurrentStackAddress);
|
||||
#elif defined(a32)
|
||||
register uintptr_t CurrentStackAddress asm("esp");
|
||||
printf("Sanity: %d, Stack: %#x", sanity++, CurrentStackAddress);
|
||||
#elif defined(aa64)
|
||||
register uintptr_t CurrentStackAddress asm("sp");
|
||||
printf("Sanity: %d, Stack: %#lx", sanity++, CurrentStackAddress);
|
||||
#endif
|
||||
if (sanity > 1000)
|
||||
sanity = 0;
|
||||
Display->SetBufferCursor(0, tmpX, tmpY);
|
||||
if (!Config.BootAnimation)
|
||||
Display->SetBuffer(0);
|
||||
|
||||
TaskManager->Sleep(100);
|
||||
}
|
||||
}
|
||||
|
||||
static int ShowOpenFiles = 0;
|
||||
|
||||
void lsof()
|
||||
{
|
||||
thisThread->Rename("Debug File List");
|
||||
thisThread->SetPriority(Tasking::Idle);
|
||||
|
||||
while (ShowOpenFiles == 0)
|
||||
CPU::Pause();
|
||||
|
||||
thisThread->SetPriority(Tasking::High);
|
||||
|
||||
vfs->Create("/dummy_lsof_file", NodeFlags::FILE);
|
||||
fopen("/dummy_lsof_file", "r");
|
||||
|
||||
while (true)
|
||||
{
|
||||
while (ShowOpenFiles == 0)
|
||||
CPU::Pause();
|
||||
|
||||
Video::ScreenBuffer *sb = Display->GetBuffer(0);
|
||||
for (short i = 0; i < 500; i++)
|
||||
{
|
||||
for (short j = 0; j < 500; j++)
|
||||
{
|
||||
uint32_t *Pixel = (uint32_t *)((uintptr_t)sb->Buffer + (j * sb->Width + i) * (bInfo.Framebuffer[0].BitsPerPixel / 8));
|
||||
*Pixel = 0x222222;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t tmpX, tmpY;
|
||||
Display->GetBufferCursor(0, &tmpX, &tmpY);
|
||||
Display->SetBufferCursor(0, 0, 0);
|
||||
printf("\eF02C21Open Files (%ld):\e00AAAA\n",
|
||||
TaskManager->GetProcessList().size());
|
||||
foreach (auto Proc in TaskManager->GetProcessList())
|
||||
{
|
||||
if (!Proc)
|
||||
continue;
|
||||
|
||||
printf("%s:\n", Proc->Name);
|
||||
|
||||
std::vector<VirtualFileSystem::FileDescriptorTable::Fildes> fds_array =
|
||||
Proc->FileDescriptors->GetFileDescriptors();
|
||||
foreach (auto fd in fds_array)
|
||||
printf(" %d: %s\n", fd.Descriptor, fd.Handle->AbsolutePath.c_str());
|
||||
}
|
||||
Display->SetBufferCursor(0, tmpX, tmpY);
|
||||
if (!Config.BootAnimation)
|
||||
Display->SetBuffer(0);
|
||||
}
|
||||
}
|
||||
|
||||
#include <mutex>
|
||||
std::mutex test_mutex;
|
||||
|
||||
void mutex_test_long()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
test_mutex.lock();
|
||||
debug("Long Thread %d got mutex",
|
||||
thisThread->ID);
|
||||
// TaskManager->Sleep(2000);
|
||||
test_mutex.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
void mutex_test()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
test_mutex.lock();
|
||||
debug("Thread %d got mutex",
|
||||
thisThread->ID);
|
||||
// TaskManager->Sleep(200);
|
||||
test_mutex.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
BootInfo::FramebufferInfo fb_ptr{};
|
||||
void tasking_test_fb_loop(int x, int y, uint32_t color)
|
||||
{
|
||||
assert(fb_ptr.BaseAddress != nullptr);
|
||||
while (true)
|
||||
{
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
uint32_t *Pixel = (uint32_t *)((uintptr_t)fb_ptr.BaseAddress +
|
||||
((y + i) * fb_ptr.Width + x) *
|
||||
(fb_ptr.BitsPerPixel / 8));
|
||||
for (int j = 0; j < 16; j++)
|
||||
{
|
||||
*Pixel = color;
|
||||
Pixel++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TTfbL_red() { tasking_test_fb_loop(0, 0, 0xFFFF0000); }
|
||||
void TTfbL_green() { tasking_test_fb_loop(16, 0, 0xFF00FF00); }
|
||||
void TTfbL_blue() { tasking_test_fb_loop(32, 0, 0xFF0000FF); }
|
||||
void TTfbL_white() { tasking_test_fb_loop(48, 0, 0xFFFFFFFF); }
|
||||
void TTfbL_gray() { tasking_test_fb_loop(64, 0, 0xFF888888); }
|
||||
void TTfbL_red_neg() { tasking_test_fb_loop(0, 0, 0xFF00FFFF); }
|
||||
void TTfbL_green_neg() { tasking_test_fb_loop(16, 0, 0xFFFF00FF); }
|
||||
void TTfbL_blue_neg() { tasking_test_fb_loop(32, 0, 0xFFFFFF00); }
|
||||
void TTfbL_white_neg() { tasking_test_fb_loop(48, 0, 0xFF000000); }
|
||||
void TTfbL_gray_neg() { tasking_test_fb_loop(64, 0, 0xFF777777); }
|
||||
void TTfbL_rainbow_fct(int offset)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
/* AARRGGBB*/
|
||||
static uint32_t color = 0xFF000000;
|
||||
|
||||
for (int i = 0; i < 64; i++)
|
||||
{
|
||||
uint32_t *Pixel = (uint32_t *)((uintptr_t)fb_ptr.BaseAddress +
|
||||
((offset + i) * fb_ptr.Width) *
|
||||
(fb_ptr.BitsPerPixel / 8));
|
||||
for (int j = 0; j < 16; j++)
|
||||
{
|
||||
*Pixel = color;
|
||||
Pixel++;
|
||||
}
|
||||
}
|
||||
if (color >= 0xFFFFFFFF)
|
||||
color = 0xFF000000;
|
||||
color++;
|
||||
}
|
||||
}
|
||||
void TTfbL_rainbow_idle() { TTfbL_rainbow_fct(16); }
|
||||
void TTfbL_rainbow_low() { TTfbL_rainbow_fct(80); }
|
||||
void TTfbL_rainbow_norm() { TTfbL_rainbow_fct(144); }
|
||||
void TTfbL_rainbow_high() { TTfbL_rainbow_fct(208); }
|
||||
void TTfbL_rainbow_crit() { TTfbL_rainbow_fct(272); }
|
||||
void tasking_test_fb()
|
||||
{
|
||||
fb_ptr = Display->GetFramebufferStruct();
|
||||
TaskManager->CreateThread(thisProcess, Tasking::IP(TTfbL_red));
|
||||
TaskManager->CreateThread(thisProcess, Tasking::IP(TTfbL_green));
|
||||
TaskManager->CreateThread(thisProcess, Tasking::IP(TTfbL_blue));
|
||||
TaskManager->CreateThread(thisProcess, Tasking::IP(TTfbL_white));
|
||||
TaskManager->CreateThread(thisProcess, Tasking::IP(TTfbL_gray));
|
||||
TaskManager->CreateThread(thisProcess, Tasking::IP(TTfbL_red_neg));
|
||||
TaskManager->CreateThread(thisProcess, Tasking::IP(TTfbL_green_neg));
|
||||
TaskManager->CreateThread(thisProcess, Tasking::IP(TTfbL_blue_neg));
|
||||
TaskManager->CreateThread(thisProcess, Tasking::IP(TTfbL_white_neg));
|
||||
TaskManager->CreateThread(thisProcess, Tasking::IP(TTfbL_gray_neg));
|
||||
|
||||
{
|
||||
CriticalSection cs; /* Start all threads at the same time */
|
||||
auto tti = TaskManager->CreateThread(thisProcess, Tasking::IP(TTfbL_rainbow_idle));
|
||||
auto ttl = TaskManager->CreateThread(thisProcess, Tasking::IP(TTfbL_rainbow_low));
|
||||
auto ttn = TaskManager->CreateThread(thisProcess, Tasking::IP(TTfbL_rainbow_norm));
|
||||
auto tth = TaskManager->CreateThread(thisProcess, Tasking::IP(TTfbL_rainbow_high));
|
||||
auto ttc = TaskManager->CreateThread(thisProcess, Tasking::IP(TTfbL_rainbow_crit));
|
||||
|
||||
tti->SetPriority(Tasking::TaskPriority::Idle);
|
||||
ttl->SetPriority(Tasking::TaskPriority::Low);
|
||||
ttn->SetPriority(Tasking::TaskPriority::Normal);
|
||||
tth->SetPriority(Tasking::TaskPriority::High);
|
||||
ttc->SetPriority(Tasking::TaskPriority::Critical);
|
||||
}
|
||||
// Exit
|
||||
}
|
||||
#endif
|
||||
|
||||
int SpawnInit()
|
||||
{
|
||||
const char *envp[5] = {
|
||||
"PATH=/bin:/usr/bin",
|
||||
"TERM=tty",
|
||||
"HOME=/root",
|
||||
"USER=root",
|
||||
nullptr};
|
||||
|
||||
const char *argv[4] = {
|
||||
Config.InitPath,
|
||||
"--init",
|
||||
"--critical",
|
||||
nullptr};
|
||||
|
||||
return Execute::Spawn(Config.InitPath, argv, envp,
|
||||
nullptr,
|
||||
Tasking::TaskCompatibility::Native,
|
||||
true);
|
||||
}
|
||||
|
||||
/* Files: 0.tga 1.tga ... 26.tga */
|
||||
uint8_t *Frames[27];
|
||||
uint32_t FrameSizes[27];
|
||||
size_t FrameCount = 1;
|
||||
|
||||
void BootLogoAnimationThread()
|
||||
{
|
||||
char BootAnimPath[16];
|
||||
while (FrameCount < 27)
|
||||
{
|
||||
sprintf(BootAnimPath, "/etc/boot/%ld.tga", FrameCount);
|
||||
RefNode *frame = vfs->Open(BootAnimPath);
|
||||
if (!frame)
|
||||
{
|
||||
debug("Failed to load boot animation frame %s", BootAnimPath);
|
||||
break;
|
||||
}
|
||||
|
||||
FrameSizes[FrameCount] = s_cst(uint32_t, frame->Length);
|
||||
Frames[FrameCount] = new uint8_t[frame->Length];
|
||||
frame->Read(Frames[FrameCount], frame->Length);
|
||||
delete frame;
|
||||
FrameCount++;
|
||||
}
|
||||
|
||||
uint32_t DispX = Display->GetBuffer(1)->Width;
|
||||
uint32_t DispY = Display->GetBuffer(1)->Height;
|
||||
|
||||
for (size_t i = 1; i < FrameCount; i++)
|
||||
{
|
||||
int x, y, channels;
|
||||
|
||||
if (!stbi_info_from_memory((uint8_t *)Frames[i], FrameSizes[i],
|
||||
&x, &y, &channels))
|
||||
continue;
|
||||
|
||||
uint8_t *img = stbi_load_from_memory((uint8_t *)Frames[i],
|
||||
FrameSizes[i], &x, &y,
|
||||
&channels, STBI_rgb_alpha);
|
||||
|
||||
if (img == NULL)
|
||||
continue;
|
||||
|
||||
int offsetX = DispX / 2 - x / 2;
|
||||
int offsetY = DispY / 2 - y / 2;
|
||||
|
||||
for (int i = 0; i < x * y; i++)
|
||||
{
|
||||
uint32_t pixel = ((uint32_t *)img)[i];
|
||||
int r = (pixel >> 16) & 0xFF;
|
||||
int g = (pixel >> 8) & 0xFF;
|
||||
int b = (pixel >> 0) & 0xFF;
|
||||
int a = (pixel >> 24) & 0xFF;
|
||||
|
||||
if (a != 0xFF)
|
||||
{
|
||||
r = (r * a) / 0xFF;
|
||||
g = (g * a) / 0xFF;
|
||||
b = (b * a) / 0xFF;
|
||||
}
|
||||
|
||||
Display->SetPixel((i % x) + offsetX, (i / x) + offsetY,
|
||||
(r << 16) | (g << 8) | (b << 0), 1);
|
||||
}
|
||||
|
||||
free(img);
|
||||
Display->SetBuffer(1);
|
||||
TaskManager->Sleep(50);
|
||||
}
|
||||
|
||||
int brightness = 100;
|
||||
while (brightness >= 0)
|
||||
{
|
||||
brightness -= 10;
|
||||
Display->SetBrightness(brightness, 1);
|
||||
Display->SetBuffer(1);
|
||||
TaskManager->Sleep(5);
|
||||
}
|
||||
}
|
||||
|
||||
void ExitLogoAnimationThread()
|
||||
{
|
||||
Display->SetBrightness(100, 1);
|
||||
Display->SetBuffer(1);
|
||||
|
||||
/* Files: 26.tga 25.tga ... 1.tga */
|
||||
uint32_t DispX = Display->GetBuffer(1)->Width;
|
||||
uint32_t DispY = Display->GetBuffer(1)->Height;
|
||||
|
||||
for (size_t i = FrameCount - 1; i > 0; i--)
|
||||
{
|
||||
int x, y, channels;
|
||||
|
||||
if (!stbi_info_from_memory((uint8_t *)Frames[i], FrameSizes[i],
|
||||
&x, &y, &channels))
|
||||
continue;
|
||||
|
||||
uint8_t *img = stbi_load_from_memory((uint8_t *)Frames[i],
|
||||
FrameSizes[i], &x, &y,
|
||||
&channels, STBI_rgb_alpha);
|
||||
|
||||
if (img == NULL)
|
||||
continue;
|
||||
|
||||
int offsetX = DispX / 2 - x / 2;
|
||||
int offsetY = DispY / 2 - y / 2;
|
||||
|
||||
for (int i = 0; i < x * y; i++)
|
||||
{
|
||||
uint32_t pixel = ((uint32_t *)img)[i];
|
||||
int r = (pixel >> 16) & 0xFF;
|
||||
int g = (pixel >> 8) & 0xFF;
|
||||
int b = (pixel >> 0) & 0xFF;
|
||||
int a = (pixel >> 24) & 0xFF;
|
||||
|
||||
if (a != 0xFF)
|
||||
{
|
||||
r = (r * a) / 0xFF;
|
||||
g = (g * a) / 0xFF;
|
||||
b = (b * a) / 0xFF;
|
||||
}
|
||||
|
||||
Display->SetPixel((i % x) + offsetX, (i / x) + offsetY,
|
||||
(r << 16) | (g << 8) | (b << 0), 1);
|
||||
}
|
||||
|
||||
free(img);
|
||||
Display->SetBuffer(1);
|
||||
TaskManager->Sleep(50);
|
||||
}
|
||||
|
||||
int brightness = 100;
|
||||
while (brightness >= 0)
|
||||
{
|
||||
brightness -= 10;
|
||||
Display->SetBrightness(brightness, 1);
|
||||
Display->SetBuffer(1);
|
||||
TaskManager->Sleep(5);
|
||||
}
|
||||
}
|
||||
|
||||
void CleanupProcessesThreadWrapper()
|
||||
{
|
||||
TaskManager->CleanupProcessesThread();
|
||||
}
|
||||
|
||||
void KernelMainThread()
|
||||
{
|
||||
// TaskManager->CreateThread(thisProcess, Tasking::IP(mutex_test_long));
|
||||
// TaskManager->Yield();
|
||||
// TaskManager->CreateThread(thisProcess, Tasking::IP(mutex_test));
|
||||
// TaskManager->CreateThread(thisProcess, Tasking::IP(mutex_test));
|
||||
// TaskManager->CreateThread(thisProcess, Tasking::IP(mutex_test));
|
||||
// TaskManager->CreateThread(thisProcess, Tasking::IP(mutex_test));
|
||||
// TaskManager->CreateThread(thisProcess, Tasking::IP(mutex_test));
|
||||
// TaskManager->CreateThread(thisProcess, Tasking::IP(mutex_test));
|
||||
// TaskManager->CreateThread(thisProcess, Tasking::IP(mutex_test));
|
||||
// TaskManager->CreateThread(thisProcess, Tasking::IP(mutex_test));
|
||||
// TaskManager->CreateThread(thisProcess, Tasking::IP(mutex_test));
|
||||
// ilp;
|
||||
|
||||
// TaskManager->CreateThread(thisProcess, Tasking::IP(tasking_test_fb));
|
||||
// ilp;
|
||||
|
||||
Tasking::TCB *clnThd =
|
||||
TaskManager->CreateThread(thisProcess,
|
||||
Tasking::IP(CleanupProcessesThreadWrapper));
|
||||
clnThd->SetPriority(Tasking::Idle);
|
||||
TaskManager->SetCleanupThread(clnThd);
|
||||
thisThread->SetPriority(Tasking::Critical);
|
||||
|
||||
Tasking::TCB *blaThread = nullptr;
|
||||
|
||||
if (Config.BootAnimation)
|
||||
{
|
||||
blaThread =
|
||||
TaskManager->CreateThread(thisProcess,
|
||||
Tasking::IP(BootLogoAnimationThread));
|
||||
blaThread->Rename("Logo Animation");
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
TaskManager->CreateThread(thisProcess, Tasking::IP(TaskMgr));
|
||||
TaskManager->CreateThread(thisProcess, Tasking::IP(lsof));
|
||||
TreeFS(vfs->GetRootNode(), 0);
|
||||
#endif
|
||||
|
||||
KPrint("Kernel Compiled at: %s %s with C++ Standard: %d",
|
||||
__DATE__, __TIME__, CPP_LANGUAGE_STANDARD);
|
||||
KPrint("C++ Language Version (__cplusplus): %ld", __cplusplus);
|
||||
|
||||
if (IsVirtualizedEnvironment())
|
||||
KPrint("Running in Virtualized Environment");
|
||||
|
||||
KPrint("Initializing Disk Manager...");
|
||||
DiskManager = new Disk::Manager;
|
||||
|
||||
KPrint("Loading Modules...");
|
||||
DriverManager = new Driver::Driver;
|
||||
DriverManager->LoadDrivers();
|
||||
|
||||
KPrint("Fetching Disks...");
|
||||
if (DriverManager->GetDrivers().size() > 0)
|
||||
{
|
||||
foreach (auto Driver in DriverManager->GetDrivers())
|
||||
if (((FexExtended *)Driver.ExtendedHeaderAddress)->Driver.Type == FexDriverType::FexDriverType_Storage)
|
||||
DiskManager->FetchDisks(Driver.DriverUID);
|
||||
}
|
||||
else
|
||||
KPrint("\eE85230No disk drivers found! Cannot fetch disks!");
|
||||
|
||||
KPrint("Initializing Network Interface Manager...");
|
||||
NIManager = new NetworkInterfaceManager::NetworkInterface;
|
||||
KPrint("Starting Network Interface Manager...");
|
||||
NIManager->StartService();
|
||||
|
||||
KPrint("Setting up userspace");
|
||||
int ExitCode = -1;
|
||||
Tasking::TCB *initThread = nullptr;
|
||||
int tid = SpawnInit();
|
||||
if (tid < 0)
|
||||
{
|
||||
KPrint("\eE85230Failed to start %s! Code: %d", Config.InitPath, tid);
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
KPrint("Waiting for \e22AAFF%s\eCCCCCC to start...", Config.InitPath);
|
||||
thisThread->SetPriority(Tasking::Idle);
|
||||
|
||||
initThread = TaskManager->GetThreadByID(tid);
|
||||
TaskManager->WaitForThread(initThread);
|
||||
ExitCode = initThread->GetExitCode();
|
||||
Exit:
|
||||
if (ExitCode == 0)
|
||||
{
|
||||
KPrint("\eFF7900%s process exited with code %d and it didn't invoked the shutdown function.",
|
||||
Config.InitPath, ExitCode);
|
||||
KPrint("System Halted");
|
||||
CPU::Halt(true);
|
||||
}
|
||||
|
||||
KPrint("\eE85230Userspace process exited with code %d (%#x)",
|
||||
ExitCode, ExitCode < 0 ? -ExitCode : ExitCode);
|
||||
KPrint("Dropping to kernel shell...");
|
||||
TaskManager->Sleep(1000);
|
||||
TaskManager->WaitForThread(blaThread);
|
||||
TaskManager->CreateThread(thisProcess,
|
||||
Tasking::IP(KShellThread))
|
||||
->Rename("Kernel Shell");
|
||||
CPU::Halt(true);
|
||||
}
|
||||
|
||||
NewLock(ShutdownLock);
|
||||
void __no_stack_protector KernelShutdownThread(bool Reboot)
|
||||
{
|
||||
SmartLock(ShutdownLock);
|
||||
debug("KernelShutdownThread(%s)", Reboot ? "true" : "false");
|
||||
if (Config.BootAnimation && TaskManager)
|
||||
{
|
||||
Tasking::TCB *elaThread =
|
||||
TaskManager->CreateThread(thisProcess,
|
||||
Tasking::IP(ExitLogoAnimationThread));
|
||||
elaThread->Rename("Logo Animation");
|
||||
TaskManager->WaitForThread(elaThread);
|
||||
}
|
||||
|
||||
BeforeShutdown(Reboot);
|
||||
|
||||
trace("%s...", Reboot ? "Rebooting" : "Shutting down");
|
||||
if (Reboot)
|
||||
PowerManager->Reboot();
|
||||
else
|
||||
PowerManager->Shutdown();
|
||||
CPU::Stop();
|
||||
}
|
||||
|
||||
void KST_Reboot() { KernelShutdownThread(true); }
|
||||
void KST_Shutdown() { KernelShutdownThread(false); }
|
44
LICENSES.md
Normal file
44
LICENSES.md
Normal file
@ -0,0 +1,44 @@
|
||||
# Licenses in the project
|
||||
|
||||
This project uses code from other projects, each with its own licenses.
|
||||
Below are the licenses associated with these components.
|
||||
Make sure to read and comply with these licenses before using or redistributing this software.
|
||||
|
||||
## printf
|
||||
|
||||
- **License:** The MIT License (MIT)
|
||||
- **Location:** [library/printf.c](library/printf.c) [include/printf.h](include/printf.h)
|
||||
|
||||
## stb_image
|
||||
|
||||
- **License:** The MIT License (MIT) and Public Domain
|
||||
- **Location:** [include/stb/image.h](include/stb/image.h)
|
||||
|
||||
## stb_image_resize
|
||||
|
||||
- **License:** The MIT License (MIT) and Public Domain
|
||||
- **Location:** [include/stb/image_resize.h](include/stb/image_resize.h)
|
||||
|
||||
## cargs
|
||||
|
||||
- **License:** The MIT License (MIT)
|
||||
- **Location:** [library/cargs.c](library/cargs.c) [include/cargs.h](include/cargs.h)
|
||||
|
||||
## cwalk
|
||||
|
||||
- **License:** The MIT License (MIT)
|
||||
- **Location:** [library/cwalk.c](library/cwalk.c) [include/cwalk.h](include/cwalk.h)
|
||||
|
||||
## Tamsyn Font (v1.11)
|
||||
|
||||
- **License:** Unknown
|
||||
- **Location:** [files/tamsyn-font-1.11/LICENSE](files/tamsyn-font-1.11/LICENSE)
|
||||
|
||||
## liballoc
|
||||
|
||||
- **License:** Public Domain
|
||||
- **Location:** [https://raw.githubusercontent.com/blanham/liballoc/master/LICENSE](https://raw.githubusercontent.com/blanham/liballoc/master/LICENSE)
|
||||
|
||||
...
|
||||
|
||||
Please refer to the respective license files for the full text of each license.
|
@ -1,51 +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 <bitmap.hpp>
|
||||
|
||||
bool Bitmap::Get(uint64_t index)
|
||||
{
|
||||
if (index > Size * 8)
|
||||
return false;
|
||||
|
||||
uint64_t byteIndex = index / 8;
|
||||
uint8_t bitIndex = index % 8;
|
||||
uint8_t bitIndexer = 0b10000000 >> bitIndex;
|
||||
|
||||
if ((Buffer[byteIndex] & bitIndexer) > 0)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Bitmap::Set(uint64_t index, bool value)
|
||||
{
|
||||
if (index > Size * 8)
|
||||
return false;
|
||||
|
||||
uint64_t byteIndex = index / 8;
|
||||
uint8_t bitIndex = index % 8;
|
||||
uint8_t bitIndexer = 0b10000000 >> bitIndex;
|
||||
|
||||
Buffer[byteIndex] &= ~bitIndexer;
|
||||
if (value)
|
||||
Buffer[byteIndex] |= bitIndexer;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Bitmap::operator[](uint64_t index) { return this->Get(index); }
|
@ -1,23 +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 <typeinfo>
|
||||
|
||||
namespace __cxxabiv1
|
||||
{
|
||||
__fundamental_type_info::~__fundamental_type_info() {}
|
||||
}
|
@ -1,45 +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 <typeinfo>
|
||||
|
||||
namespace __cxxabiv1
|
||||
{
|
||||
__pointer_type_info::~__pointer_type_info() {}
|
||||
|
||||
bool __pointer_type_info::__is_pointer_p() const { return true; }
|
||||
|
||||
bool __pointer_type_info::__pointer_catch(const __pbase_type_info *ThrownType,
|
||||
void **ThrowObject,
|
||||
unsigned Outer) const
|
||||
{
|
||||
#ifndef __GXX_RTTI
|
||||
UNUSED(ThrownType);
|
||||
UNUSED(ThrowObject);
|
||||
UNUSED(Outer);
|
||||
return false;
|
||||
#else
|
||||
if (Outer < 2 && *this->Pointee == typeid(void))
|
||||
return !ThrownType->Pointee->__is_function_p();
|
||||
|
||||
return __pbase_type_info::__pointer_catch(ThrownType,
|
||||
ThrowObject,
|
||||
Outer);
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
@ -1,41 +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 <unwind.h>
|
||||
#include <cxxabi.h>
|
||||
#include <debug.h>
|
||||
#include <cpu.hpp>
|
||||
#include <smp.hpp>
|
||||
|
||||
#include "../../kernel.h"
|
||||
|
||||
using namespace __cxxabiv1;
|
||||
|
||||
#if (1) /* Stubs if libgcc is not present */
|
||||
extern "C" _Unwind_Reason_Code _Unwind_RaiseException(_Unwind_Exception *Exception)
|
||||
{
|
||||
fixme("_Unwind_RaiseException( %p ) called.", Exception);
|
||||
error("Unhandled exception.");
|
||||
return _URC_FATAL_PHASE1_ERROR;
|
||||
// return _URC_NO_REASON;
|
||||
}
|
||||
|
||||
extern "C" void _Unwind_Resume(struct _Unwind_Exception *Exception)
|
||||
{
|
||||
fixme("_Unwind_Resume( %p ) called.", Exception);
|
||||
}
|
||||
#endif
|
@ -1,33 +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 <errno.h>
|
||||
|
||||
#include <types.h>
|
||||
#include <debug.h>
|
||||
#include <atomic>
|
||||
|
||||
#include "../../kernel.h"
|
||||
|
||||
__aligned(16) static int errno_value = 0;
|
||||
|
||||
int *__errno_location(void)
|
||||
{
|
||||
if (unlikely(!TaskManager || !thisThread))
|
||||
return &errno_value;
|
||||
return &thisThread->ErrorNumber;
|
||||
}
|
@ -1,44 +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 <typeinfo>
|
||||
#include <debug.h>
|
||||
|
||||
namespace std
|
||||
{
|
||||
type_info::~type_info() {}
|
||||
|
||||
bool type_info::__do_catch(const type_info *ThrowType,
|
||||
void **ThrowObject,
|
||||
unsigned Outer) const
|
||||
{
|
||||
stub;
|
||||
UNUSED(ThrowType);
|
||||
UNUSED(ThrowObject);
|
||||
UNUSED(Outer);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool type_info::__do_upcast(const __cxxabiv1::__class_type_info *Target,
|
||||
void **ObjectPointer) const
|
||||
{
|
||||
stub;
|
||||
UNUSED(Target);
|
||||
UNUSED(ObjectPointer);
|
||||
return false;
|
||||
}
|
||||
}
|
36
Makefile
36
Makefile
@ -12,7 +12,7 @@ OBJCOPY = ../$(COMPILER_PATH)/$(COMPILER_ARCH)objcopy
|
||||
OBJDUMP = ../$(COMPILER_PATH)/$(COMPILER_ARCH)objdump
|
||||
GDB = ../$(COMPILER_PATH)/$(COMPILER_ARCH)gdb
|
||||
|
||||
RUST_TARGET_PATH = Architecture/$(OSARCH)/rust-target.json
|
||||
RUST_TARGET_PATH = arch/$(OSARCH)/rust-target.json
|
||||
|
||||
GIT_COMMIT = $(shell git rev-parse HEAD)
|
||||
GIT_COMMIT_SHORT = $(shell git rev-parse --short HEAD)
|
||||
@ -20,20 +20,20 @@ GIT_COMMIT_SHORT = $(shell git rev-parse --short HEAD)
|
||||
BMP_SOURCES = $(shell find ./ -type f -name '*.bmp')
|
||||
PSF_SOURCES = $(shell find ./ -type f -name '*.psf')
|
||||
ifeq ($(OSARCH), amd64)
|
||||
S_SOURCES = $(shell find ./ -type f -name '*.S' -not -path "./Architecture/i386/*" -not -path "./Architecture/aarch64/*")
|
||||
s_SOURCES = $(shell find ./ -type f -name '*.s' -not -path "./Architecture/i386/*" -not -path "./Architecture/aarch64/*")
|
||||
C_SOURCES = $(shell find ./ -type f -name '*.c' -not -path "./Architecture/i386/*" -not -path "./Architecture/aarch64/*")
|
||||
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp' -not -path "./Architecture/i386/*" -not -path "./Architecture/aarch64/*")
|
||||
S_SOURCES = $(shell find ./ -type f -name '*.S' -not -path "./arch/i386/*" -not -path "./arch/aarch64/*")
|
||||
s_SOURCES = $(shell find ./ -type f -name '*.s' -not -path "./arch/i386/*" -not -path "./arch/aarch64/*")
|
||||
C_SOURCES = $(shell find ./ -type f -name '*.c' -not -path "./arch/i386/*" -not -path "./arch/aarch64/*")
|
||||
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp' -not -path "./arch/i386/*" -not -path "./arch/aarch64/*")
|
||||
else ifeq ($(OSARCH), i386)
|
||||
S_SOURCES = $(shell find ./ -type f -name '*.S' -not -path "./Architecture/amd64/*" -not -path "./Architecture/aarch64/*")
|
||||
s_SOURCES = $(shell find ./ -type f -name '*.s' -not -path "./Architecture/amd64/*" -not -path "./Architecture/aarch64/*")
|
||||
C_SOURCES = $(shell find ./ -type f -name '*.c' -not -path "./Architecture/amd64/*" -not -path "./Architecture/aarch64/*")
|
||||
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp' -not -path "./Architecture/amd64/*" -not -path "./Architecture/aarch64/*")
|
||||
S_SOURCES = $(shell find ./ -type f -name '*.S' -not -path "./arch/amd64/*" -not -path "./arch/aarch64/*")
|
||||
s_SOURCES = $(shell find ./ -type f -name '*.s' -not -path "./arch/amd64/*" -not -path "./arch/aarch64/*")
|
||||
C_SOURCES = $(shell find ./ -type f -name '*.c' -not -path "./arch/amd64/*" -not -path "./arch/aarch64/*")
|
||||
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp' -not -path "./arch/amd64/*" -not -path "./arch/aarch64/*")
|
||||
else ifeq ($(OSARCH), aarch64)
|
||||
S_SOURCES = $(shell find ./ -type f -name '*.S' -not -path "./Architecture/amd64/*" -not -path "./Architecture/i386/*")
|
||||
s_SOURCES = $(shell find ./ -type f -name '*.s' -not -path "./Architecture/amd64/*" -not -path "./Architecture/i386/*")
|
||||
C_SOURCES = $(shell find ./ -type f -name '*.c' -not -path "./Architecture/amd64/*" -not -path "./Architecture/i386/*")
|
||||
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp' -not -path "./Architecture/amd64/*" -not -path "./Architecture/i386/*")
|
||||
S_SOURCES = $(shell find ./ -type f -name '*.S' -not -path "./arch/amd64/*" -not -path "./arch/i386/*")
|
||||
s_SOURCES = $(shell find ./ -type f -name '*.s' -not -path "./arch/amd64/*" -not -path "./arch/i386/*")
|
||||
C_SOURCES = $(shell find ./ -type f -name '*.c' -not -path "./arch/amd64/*" -not -path "./arch/i386/*")
|
||||
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp' -not -path "./arch/amd64/*" -not -path "./arch/i386/*")
|
||||
endif
|
||||
HEADERS = $(sort $(dir $(wildcard ./include/*))) $(sort $(dir $(wildcard ./include_std/*)))
|
||||
OBJ = $(C_SOURCES:.c=.o) $(CPP_SOURCES:.cpp=.o) $(ASM_SOURCES:.asm=.o) $(S_SOURCES:.S=.o) $(s_SOURCES:.s=.o) $(PSF_SOURCES:.psf=.o) $(BMP_SOURCES:.bmp=.o)
|
||||
@ -66,7 +66,7 @@ ifeq ($(OSARCH), amd64)
|
||||
CFLAGS += -fno-pic -fno-pie -mno-red-zone -march=core2 \
|
||||
-mcmodel=kernel -fno-builtin -Da64 -Da86 -m64
|
||||
CFLAG_STACK_PROTECTOR := -fstack-protector-all
|
||||
LDFLAGS += -TArchitecture/amd64/linker.ld \
|
||||
LDFLAGS += -Tarch/amd64/linker.ld \
|
||||
-fno-pic -fno-pie \
|
||||
-Wl,-static,--no-dynamic-linker,-ztext \
|
||||
-zmax-page-size=0x1000 \
|
||||
@ -77,7 +77,7 @@ else ifeq ($(OSARCH), i386)
|
||||
CFLAGS += -fno-pic -fno-pie -mno-red-zone -march=pentium \
|
||||
-fno-builtin -Da32 -Da86 -m32
|
||||
CFLAG_STACK_PROTECTOR := -fstack-protector-all
|
||||
LDFLAGS += -TArchitecture/i386/linker.ld \
|
||||
LDFLAGS += -Tarch/i386/linker.ld \
|
||||
-fno-pic -fno-pie \
|
||||
-Wl,-static,--no-dynamic-linker,-ztext \
|
||||
-zmax-page-size=0x1000 \
|
||||
@ -87,9 +87,9 @@ else ifeq ($(OSARCH), aarch64)
|
||||
|
||||
CFLAGS += -fno-builtin -Wstack-protector -Daa64 -fPIC -mno-outline-atomics
|
||||
CFLAG_STACK_PROTECTOR := -fstack-protector-all
|
||||
LDFLAGS += -TArchitecture/aarch64/linker.ld -fPIC -pie \
|
||||
-Wl,-static,--no-dynamic-linker,-ztext \
|
||||
-zmax-page-size=0x1000 \
|
||||
LDFLAGS += -Tarch/aarch64/linker.ld -fPIC -pie \
|
||||
-Wl,-static,--no-dynamic-linker,-ztext \
|
||||
-zmax-page-size=0x1000 \
|
||||
-Wl,-Map kernel.map
|
||||
|
||||
endif
|
||||
|
@ -1,31 +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_ATA_H__
|
||||
#define __FENNIX_KERNEL_ATA_H__
|
||||
|
||||
#include <types.h>
|
||||
#include "../../DAPI.hpp"
|
||||
|
||||
namespace AdvancedTechnologyAttachment
|
||||
{
|
||||
int DriverEntry(void *);
|
||||
int CallbackHandler(KernelCallback *);
|
||||
int InterruptCallback(CPURegisters *);
|
||||
}
|
||||
|
||||
#endif // !__FENNIX_KERNEL_ATA_H__
|
@ -1,38 +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_AMD_PCNET_H__
|
||||
#define __FENNIX_KERNEL_AMD_PCNET_H__
|
||||
|
||||
#include <types.h>
|
||||
#include "../../DAPI.hpp"
|
||||
|
||||
namespace PCNET
|
||||
{
|
||||
struct BARData
|
||||
{
|
||||
uint8_t Type;
|
||||
uint16_t IOBase;
|
||||
uint64_t MemoryBase;
|
||||
};
|
||||
|
||||
int DriverEntry(void *);
|
||||
int CallbackHandler(KernelCallback *);
|
||||
int InterruptCallback(CPURegisters *);
|
||||
}
|
||||
|
||||
#endif // !__FENNIX_KERNEL_AMD_PCNET_H__
|
@ -1,107 +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 "keyboard.hpp"
|
||||
|
||||
#include <limits.h>
|
||||
#include <debug.h>
|
||||
#include <io.h>
|
||||
|
||||
#include "../../DAPI.hpp"
|
||||
#include "../drv.hpp"
|
||||
#include "../../kernel.h"
|
||||
|
||||
namespace PS2Keyboard
|
||||
{
|
||||
KernelAPI KAPI;
|
||||
|
||||
uint8_t ScanCode = 0;
|
||||
bool InputReceived = false;
|
||||
|
||||
int DriverEntry(void *Data)
|
||||
{
|
||||
if (!Data)
|
||||
return INVALID_KERNEL_API;
|
||||
KAPI = *(KernelAPI *)Data;
|
||||
if (KAPI.Version.Major < 0 || KAPI.Version.Minor < 0 || KAPI.Version.Patch < 0)
|
||||
return KERNEL_API_VERSION_NOT_SUPPORTED;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int CallbackHandler(KernelCallback *Data)
|
||||
{
|
||||
switch (Data->Reason)
|
||||
{
|
||||
case AcknowledgeReason:
|
||||
{
|
||||
debug("Kernel acknowledged the driver.");
|
||||
break;
|
||||
}
|
||||
case ConfigurationReason:
|
||||
{
|
||||
while (inb(0x64) & 0x1)
|
||||
inb(0x60);
|
||||
|
||||
outb(0x64, 0xAE);
|
||||
outb(0x64, 0x20);
|
||||
uint8_t ret = (inb(0x60) | 1) & ~0x10;
|
||||
outb(0x64, 0x60);
|
||||
outb(0x60, ret);
|
||||
outb(0x60, 0xF4);
|
||||
|
||||
outb(0x21, 0xFD);
|
||||
outb(0xA1, 0xFF);
|
||||
|
||||
trace("PS/2 keyboard configured.");
|
||||
break;
|
||||
}
|
||||
case QueryReason:
|
||||
{
|
||||
Data->InputCallback.Keyboard.Key = ScanCode;
|
||||
break;
|
||||
}
|
||||
case PollWaitReason:
|
||||
{
|
||||
while (!InputReceived)
|
||||
TaskManager->Yield();
|
||||
InputReceived = false;
|
||||
|
||||
Data->InputCallback.Keyboard.Key = ScanCode;
|
||||
break;
|
||||
}
|
||||
case StopReason:
|
||||
{
|
||||
fixme("Driver stopped.");
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
warn("Unknown reason.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
int InterruptCallback(CPURegisters *)
|
||||
{
|
||||
ScanCode = inb(0x60);
|
||||
InputReceived = true;
|
||||
return OK;
|
||||
}
|
||||
}
|
@ -1,31 +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 <net/net.hpp>
|
||||
|
||||
uint16_t CalculateChecksum(uint16_t *Data, size_t Length)
|
||||
{
|
||||
uint16_t *Data16 = (uint16_t *)Data;
|
||||
uint64_t Checksum = 0;
|
||||
for (uint64_t i = 0; i < Length / 2; i++)
|
||||
Checksum += ((Data16[i] & 0xFF00) >> 8) | ((Data16[i] & 0x00FF) << 8);
|
||||
if (Length % 2)
|
||||
Checksum += ((uint16_t)((char *)Data16)[Length - 1]) << 8;
|
||||
while (Checksum & 0xFFFF0000)
|
||||
Checksum = (Checksum & 0xFFFF) + (Checksum >> 16);
|
||||
return (uint16_t)(((~Checksum & 0xFF00) >> 8) | ((~Checksum & 0x00FF) << 8));
|
||||
}
|
@ -1,35 +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 <net/dns.hpp>
|
||||
#include <debug.h>
|
||||
|
||||
#include "../kernel.h"
|
||||
|
||||
namespace NetworkDNS
|
||||
{
|
||||
DNS::DNS(NetworkUDP::Socket *Socket) : NetworkUDP::UDPEvents()
|
||||
{
|
||||
debug("DNS interface %#lx created.", this);
|
||||
this->UDPSocket = Socket;
|
||||
}
|
||||
|
||||
DNS::~DNS()
|
||||
{
|
||||
debug("DNS interface %#lx destroyed.", this);
|
||||
}
|
||||
}
|
@ -1,25 +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 <net/tcp.hpp>
|
||||
#include <debug.h>
|
||||
|
||||
#include "../kernel.h"
|
||||
|
||||
namespace NetworkTCP
|
||||
{
|
||||
}
|
@ -1,38 +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 <types.h>
|
||||
#include <printf.h>
|
||||
#include <uart.hpp>
|
||||
|
||||
#include "../kernel.h"
|
||||
|
||||
using namespace UniversalAsynchronousReceiverTransmitter;
|
||||
|
||||
static inline SafeFunction NIF void gprof_uart_wrapper(char c, void *unused)
|
||||
{
|
||||
UART(COM2).Write(c);
|
||||
UNUSED(unused);
|
||||
}
|
||||
|
||||
EXTERNC SafeFunction NIF void mcount(unsigned long frompc, unsigned long selfpc)
|
||||
{
|
||||
// TODO: Implement
|
||||
/* https://docs.kernel.org/trace/ftrace-design.html */
|
||||
UNUSED(frompc);
|
||||
UNUSED(selfpc);
|
||||
}
|
@ -1,745 +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 <memory.hpp>
|
||||
#include <lock.hpp>
|
||||
#include <exec.hpp>
|
||||
#include <errno.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include "../syscalls.h"
|
||||
#include "../kernel.h"
|
||||
#include "../ipc.h"
|
||||
|
||||
#if defined(a64) || defined(aa64)
|
||||
static ssize_t ConvertErrno(ssize_t r)
|
||||
{
|
||||
if (r >= 0)
|
||||
return r;
|
||||
return -errno;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int ConvertErrno(int r)
|
||||
{
|
||||
if (r >= 0)
|
||||
return r;
|
||||
return -errno;
|
||||
}
|
||||
|
||||
struct SyscallData
|
||||
{
|
||||
const char *Name;
|
||||
void *Handler;
|
||||
int RequiredID;
|
||||
};
|
||||
|
||||
using InterProcessCommunication::IPC;
|
||||
using InterProcessCommunication::IPCID;
|
||||
using Tasking::PCB;
|
||||
using Tasking::TCB;
|
||||
using Tasking::TaskStatus::Ready;
|
||||
using Tasking::TaskStatus::Terminated;
|
||||
using namespace Memory;
|
||||
|
||||
#define SysFrm SyscallsFrame
|
||||
|
||||
#if defined(a64)
|
||||
typedef long arch_t;
|
||||
#elif defined(a32)
|
||||
typedef int arch_t;
|
||||
#endif
|
||||
|
||||
__noreturn static void sys_exit(SysFrm *, int Code)
|
||||
{
|
||||
trace("Userspace thread %s(%d) exited with code %d (%#x)",
|
||||
thisThread->Name,
|
||||
thisThread->ID, Code,
|
||||
Code < 0 ? -Code : Code);
|
||||
|
||||
thisThread->ExitCode = Code;
|
||||
thisThread->Status = Terminated;
|
||||
TaskManager->Yield();
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
static uintptr_t sys_request_pages(SysFrm *, size_t Count)
|
||||
{
|
||||
MemMgr *MemMgr = thisThread->Memory;
|
||||
return (uintptr_t)MemMgr->RequestPages(Count + 1, true);
|
||||
}
|
||||
|
||||
static int sys_free_pages(SysFrm *, uintptr_t Address,
|
||||
size_t Count)
|
||||
{
|
||||
MemMgr *MemMgr = thisThread->Memory;
|
||||
MemMgr->FreePages((void *)Address, Count + 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sys_detach_address(SysFrm *, uintptr_t Address)
|
||||
{
|
||||
MemMgr *MemMgr = thisThread->Memory;
|
||||
MemMgr->DetachAddress((void *)Address);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sys_memory_map(SysFrm *, uintptr_t VirtualAddress,
|
||||
uintptr_t PhysicalAddress, size_t Size,
|
||||
int Flags)
|
||||
{
|
||||
if (Flags > 7) /* (MAP_PRESENT | MAP_WRITABLE | MAP_USER) */
|
||||
return -EINVAL;
|
||||
|
||||
PageTable *PageTable = thisProcess->PageTable;
|
||||
{
|
||||
Virtual vmm = Virtual(PageTable);
|
||||
vmm.Map((void *)VirtualAddress,
|
||||
(void *)PhysicalAddress,
|
||||
Size, Flags);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sys_memory_unmap(SysFrm *, uintptr_t VirtualAddress,
|
||||
size_t Size)
|
||||
{
|
||||
PageTable *PageTable = thisProcess->PageTable;
|
||||
{
|
||||
Virtual vmm = Virtual(PageTable);
|
||||
vmm.Unmap((void *)VirtualAddress,
|
||||
Size);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static arch_t sys_kernelctl(SysFrm *, KCtl Command,
|
||||
arch_t Arg1, arch_t Arg2,
|
||||
arch_t Arg3, arch_t Arg4)
|
||||
{
|
||||
UNUSED(Arg2);
|
||||
UNUSED(Arg3);
|
||||
UNUSED(Arg4);
|
||||
|
||||
switch (Command)
|
||||
{
|
||||
case KCTL_PRINT:
|
||||
{
|
||||
SmartHeap sh(strlen((const char *)Arg1) + 1);
|
||||
sh = Arg1;
|
||||
KPrint(sh);
|
||||
return 0;
|
||||
}
|
||||
case KCTL_GET_PAGE_SIZE:
|
||||
return PAGE_SIZE;
|
||||
case KCTL_IS_CRITICAL:
|
||||
return thisThread->Security.IsCritical;
|
||||
default:
|
||||
{
|
||||
warn("KernelCTL: Unknown command: %d", Command);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int sys_file_open(SysFrm *, const char *Path,
|
||||
int Flags, mode_t Mode)
|
||||
{
|
||||
function("%s, %d, %d", Path, Flags, Mode);
|
||||
PCB *pcb = thisProcess;
|
||||
VirtualFileSystem::FileDescriptorTable *fdt = pcb->FileDescriptors;
|
||||
return ConvertErrno(fdt->_open(Path, Flags, Mode));
|
||||
}
|
||||
|
||||
static int sys_file_close(SysFrm *, int FileDescriptor)
|
||||
{
|
||||
function("%d", FileDescriptor);
|
||||
PCB *pcb = thisProcess;
|
||||
VirtualFileSystem::FileDescriptorTable *fdt = pcb->FileDescriptors;
|
||||
return ConvertErrno(fdt->_close(FileDescriptor));
|
||||
}
|
||||
|
||||
static uint64_t sys_file_read(SysFrm *, int FileDescriptor,
|
||||
void *Buffer, size_t Count)
|
||||
{
|
||||
function("%d, %p, %d", FileDescriptor, Buffer, Count);
|
||||
PCB *pcb = thisProcess;
|
||||
VirtualFileSystem::FileDescriptorTable *fdt = pcb->FileDescriptors;
|
||||
return ConvertErrno(fdt->_read(FileDescriptor, Buffer, Count));
|
||||
}
|
||||
|
||||
static uint64_t sys_file_write(SysFrm *, int FileDescriptor,
|
||||
const void *Buffer, size_t Count)
|
||||
{
|
||||
function("%d, %p, %d", FileDescriptor, Buffer, Count);
|
||||
PCB *pcb = thisProcess;
|
||||
VirtualFileSystem::FileDescriptorTable *fdt = pcb->FileDescriptors;
|
||||
return ConvertErrno(fdt->_write(FileDescriptor, Buffer, Count));
|
||||
}
|
||||
|
||||
static off_t sys_file_seek(SysFrm *, int FileDescriptor,
|
||||
off_t Offset, int Whence)
|
||||
{
|
||||
function("%d, %d, %d", FileDescriptor, Offset, Whence);
|
||||
PCB *pcb = thisProcess;
|
||||
VirtualFileSystem::FileDescriptorTable *fdt = pcb->FileDescriptors;
|
||||
return ConvertErrno(fdt->_lseek(FileDescriptor, Offset, Whence));
|
||||
}
|
||||
|
||||
static int sys_file_status(SysFrm *, int FileDescriptor,
|
||||
struct stat *StatBuffer)
|
||||
{
|
||||
function("%d", FileDescriptor);
|
||||
PCB *pcb = thisProcess;
|
||||
VirtualFileSystem::FileDescriptorTable *fdt = pcb->FileDescriptors;
|
||||
return ConvertErrno(fdt->_fstat(FileDescriptor, StatBuffer));
|
||||
}
|
||||
|
||||
static int sys_ipc(SysFrm *, enum IPCCommand Command,
|
||||
enum IPCType Type, int ID, int Flags,
|
||||
void *Buffer, size_t Size)
|
||||
{
|
||||
InterProcessCommunication::IPC *ipc = thisProcess->IPC;
|
||||
return ipc->HandleSyscall(Command, Type, ID, Flags, Buffer, Size);
|
||||
}
|
||||
|
||||
static long sys_local_thread_state(SysFrm *, int Code,
|
||||
unsigned long Address)
|
||||
{
|
||||
/* TODO: return EFAULT if Address is not mapped */
|
||||
/* TODO: return EINVAL if Code is invalid */
|
||||
/* TODO: return EPERM if Address is outside of process address space */
|
||||
#if defined(a64) || defined(aa64)
|
||||
switch (Code)
|
||||
{
|
||||
case LTS_SET_GS:
|
||||
{
|
||||
wrmsr(CPU::x64::MSR_GS_BASE, Address);
|
||||
return 0;
|
||||
}
|
||||
case LTS_GET_GS:
|
||||
{
|
||||
return rdmsr(CPU::x64::MSR_GS_BASE);
|
||||
}
|
||||
case LTS_SET_FS:
|
||||
{
|
||||
wrmsr(CPU::x64::MSR_FS_BASE, Address);
|
||||
return 0;
|
||||
}
|
||||
case LTS_GET_FS:
|
||||
{
|
||||
return rdmsr(CPU::x64::MSR_FS_BASE);
|
||||
}
|
||||
case LTS_SET_CPUID:
|
||||
{
|
||||
fixme("TLS_SET_CPUID");
|
||||
return -ENOSYS;
|
||||
}
|
||||
case LTS_GET_CPUID:
|
||||
{
|
||||
fixme("TLS_GET_CPUID");
|
||||
return -ENOSYS;
|
||||
}
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
#endif
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static int sys_sleep(SysFrm *, uint64_t Milliseconds)
|
||||
{
|
||||
TaskManager->Sleep(Milliseconds, true);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sys_fork(SysFrm *Frame)
|
||||
{
|
||||
#ifdef a32
|
||||
return -ENOSYS;
|
||||
#endif
|
||||
PCB *Parent = thisThread->Parent;
|
||||
TCB *Thread = thisThread;
|
||||
|
||||
void *ProcSymTable = nullptr;
|
||||
if (Parent->ELFSymbolTable)
|
||||
ProcSymTable = Parent->ELFSymbolTable->GetImage();
|
||||
|
||||
PCB *NewProcess =
|
||||
TaskManager->CreateProcess(Parent,
|
||||
Parent->Name,
|
||||
Parent->Security.ExecutionMode,
|
||||
ProcSymTable);
|
||||
|
||||
if (!NewProcess)
|
||||
{
|
||||
error("Failed to create process for fork");
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
NewProcess->IPC->Fork(Parent->IPC);
|
||||
|
||||
TCB *NewThread =
|
||||
TaskManager->CreateThread(NewProcess,
|
||||
0,
|
||||
nullptr,
|
||||
nullptr,
|
||||
std::vector<AuxiliaryVector>(),
|
||||
Thread->Info.Architecture,
|
||||
Thread->Info.Compatibility,
|
||||
true);
|
||||
|
||||
NewThread->Rename(Thread->Name);
|
||||
|
||||
if (!NewThread)
|
||||
{
|
||||
error("Failed to create thread for fork");
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
static int RetChild = 0;
|
||||
static uint64_t ReturnAddress = 0;
|
||||
static uint64_t ChildStackPointer = 0;
|
||||
|
||||
TaskManager->UpdateFrame();
|
||||
|
||||
if (RetChild--)
|
||||
{
|
||||
/* We can't just return 0; because the
|
||||
CPUData->SystemCallStack is no
|
||||
longer valid */
|
||||
#if defined(a64) || defined(aa64)
|
||||
asmv("movq %0, %%rcx\n"
|
||||
:
|
||||
: "r"(ReturnAddress));
|
||||
asmv("mov %0, %%rsp\n"
|
||||
:
|
||||
: "r"(ChildStackPointer));
|
||||
asmv("mov %0, %%rbp\n"
|
||||
:
|
||||
: "r"(ChildStackPointer));
|
||||
asmv("movq $0, %rax\n"); /* Return 0 to the child */
|
||||
asmv("swapgs\n"); /* Swap GS back to the user GS */
|
||||
asmv("sti\n"); /* Enable interrupts */
|
||||
asmv("sysretq\n"); /* Return to rcx address in user mode */
|
||||
#elif defined(a32)
|
||||
UNUSED(ReturnAddress);
|
||||
UNUSED(ChildStackPointer);
|
||||
#endif
|
||||
}
|
||||
RetChild = 1;
|
||||
ReturnAddress = Frame->ReturnAddress;
|
||||
ChildStackPointer = Frame->StackPointer;
|
||||
|
||||
memcpy(&NewThread->FPU, &Thread->FPU, sizeof(CPU::x64::FXState));
|
||||
NewThread->Stack->Fork(Thread->Stack);
|
||||
NewThread->Info = Thread->Info;
|
||||
NewThread->Registers = Thread->Registers;
|
||||
|
||||
if (Thread->Security.IsCritical)
|
||||
NewThread->SetCritical(true);
|
||||
|
||||
#ifdef a86
|
||||
NewThread->ShadowGSBase = Thread->ShadowGSBase;
|
||||
NewThread->GSBase = Thread->GSBase;
|
||||
NewThread->FSBase = Thread->FSBase;
|
||||
#endif
|
||||
|
||||
debug("Forked thread \"%s\"(%d) to \"%s\"(%d)",
|
||||
Thread->Name, Thread->ID,
|
||||
NewThread->Name, NewThread->ID);
|
||||
NewThread->Status = Ready;
|
||||
return (int)NewThread->ID;
|
||||
}
|
||||
|
||||
static int sys_wait(SysFrm *)
|
||||
{
|
||||
stub;
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static int sys_kill(SysFrm *)
|
||||
{
|
||||
stub;
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static int sys_spawn(SysFrm *)
|
||||
{
|
||||
stub;
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static int sys_spawn_thread(SysFrm *, uint64_t InstructionPointer)
|
||||
{
|
||||
TCB *thread =
|
||||
TaskManager->CreateThread(thisProcess,
|
||||
Tasking::IP(InstructionPointer));
|
||||
if (thread)
|
||||
return (int)thread->ID;
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
static int sys_get_thread_list_of_process(SysFrm *)
|
||||
{
|
||||
stub;
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static int sys_get_current_process(SysFrm *)
|
||||
{
|
||||
stub;
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static int sys_get_current_thread(SysFrm *)
|
||||
{
|
||||
stub;
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static int sys_get_current_process_id(SysFrm *)
|
||||
{
|
||||
return (int)thisProcess->ID;
|
||||
}
|
||||
|
||||
static int sys_get_current_thread_id(SysFrm *)
|
||||
{
|
||||
return (int)thisThread->ID;
|
||||
}
|
||||
|
||||
static int sys_get_process_by_pid(SysFrm *)
|
||||
{
|
||||
stub;
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static int sys_get_thread_by_tid(SysFrm *)
|
||||
{
|
||||
stub;
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static int sys_kill_process(SysFrm *)
|
||||
{
|
||||
stub;
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static int sys_kill_thread(SysFrm *)
|
||||
{
|
||||
stub;
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static int sys_sys_reserved_create_process(SysFrm *)
|
||||
{
|
||||
stub;
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static int sys_sys_reserved_create_thread(SysFrm *)
|
||||
{
|
||||
stub;
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static SyscallData NativeSyscallsTable[sys_MaxSyscall] = {
|
||||
/**
|
||||
*
|
||||
* Basic syscalls
|
||||
*
|
||||
*/
|
||||
|
||||
[sys_Exit] = {
|
||||
"Exit",
|
||||
(void *)sys_exit,
|
||||
UINT16_MAX,
|
||||
},
|
||||
|
||||
/**
|
||||
*
|
||||
* Memory syscalls
|
||||
*
|
||||
*/
|
||||
|
||||
[sys_RequestPages] = {
|
||||
"RequestPages",
|
||||
(void *)sys_request_pages,
|
||||
UINT16_MAX,
|
||||
},
|
||||
[sys_FreePages] = {
|
||||
"FreePages",
|
||||
(void *)sys_free_pages,
|
||||
UINT16_MAX,
|
||||
},
|
||||
[sys_DetachAddress] = {
|
||||
"DetachAddress",
|
||||
(void *)sys_detach_address,
|
||||
99,
|
||||
},
|
||||
[sys_MemoryMap] = {
|
||||
"MemoryMap",
|
||||
(void *)sys_memory_map,
|
||||
99,
|
||||
},
|
||||
[sys_MemoryUnmap] = {
|
||||
"MemoryUnmap",
|
||||
(void *)sys_memory_unmap,
|
||||
99,
|
||||
},
|
||||
|
||||
/**
|
||||
*
|
||||
* Kernel Control syscalls
|
||||
*
|
||||
*/
|
||||
|
||||
[sys_KernelCTL] = {
|
||||
"KernelCTL",
|
||||
(void *)sys_kernelctl,
|
||||
99,
|
||||
},
|
||||
|
||||
/**
|
||||
*
|
||||
* File syscalls
|
||||
*
|
||||
*/
|
||||
|
||||
[sys_FileOpen] = {
|
||||
"FileOpen",
|
||||
(void *)sys_file_open,
|
||||
UINT16_MAX,
|
||||
},
|
||||
[sys_FileClose] = {
|
||||
"FileClose",
|
||||
(void *)sys_file_close,
|
||||
UINT16_MAX,
|
||||
},
|
||||
[sys_FileRead] = {
|
||||
"FileRead",
|
||||
(void *)sys_file_read,
|
||||
UINT16_MAX,
|
||||
},
|
||||
[sys_FileWrite] = {
|
||||
"FileWrite",
|
||||
(void *)sys_file_write,
|
||||
UINT16_MAX,
|
||||
},
|
||||
[sys_FileSeek] = {
|
||||
"FileSeek",
|
||||
(void *)sys_file_seek,
|
||||
UINT16_MAX,
|
||||
},
|
||||
[sys_FileStatus] = {
|
||||
"FileStatus",
|
||||
(void *)sys_file_status,
|
||||
UINT16_MAX,
|
||||
},
|
||||
|
||||
/**
|
||||
*
|
||||
* Process syscalls
|
||||
*
|
||||
*/
|
||||
|
||||
[sys_IPC] = {
|
||||
"IPC",
|
||||
(void *)sys_ipc,
|
||||
UINT16_MAX,
|
||||
},
|
||||
[sys_LocalThreadState] = {
|
||||
"LocalThreadState",
|
||||
(void *)sys_local_thread_state,
|
||||
UINT16_MAX,
|
||||
},
|
||||
[sys_Sleep] = {
|
||||
"Sleep",
|
||||
(void *)sys_sleep,
|
||||
UINT16_MAX,
|
||||
},
|
||||
[sys_Fork] = {
|
||||
"Fork",
|
||||
(void *)sys_fork,
|
||||
UINT16_MAX,
|
||||
},
|
||||
[sys_Wait] = {
|
||||
"Wait",
|
||||
(void *)sys_wait,
|
||||
0,
|
||||
},
|
||||
[sys_Kill] = {
|
||||
"Kill",
|
||||
(void *)sys_kill,
|
||||
0,
|
||||
},
|
||||
[sys_Spawn] = {
|
||||
"Spawn",
|
||||
(void *)sys_spawn,
|
||||
0,
|
||||
},
|
||||
[sys_SpawnThread] = {
|
||||
"SpawnThread",
|
||||
(void *)sys_spawn_thread,
|
||||
0,
|
||||
},
|
||||
[sys_GetThreadListOfProcess] = {
|
||||
"GetThreadListOfProcess",
|
||||
(void *)sys_get_thread_list_of_process,
|
||||
0,
|
||||
},
|
||||
[sys_GetCurrentProcess] = {
|
||||
"GetCurrentProcess",
|
||||
(void *)sys_get_current_process,
|
||||
0,
|
||||
},
|
||||
[sys_GetCurrentThread] = {
|
||||
"GetCurrentThread",
|
||||
(void *)sys_get_current_thread,
|
||||
0,
|
||||
},
|
||||
[sys_GetCurrentProcessID] = {
|
||||
"GetCurrentProcessID",
|
||||
(void *)sys_get_current_process_id,
|
||||
UINT16_MAX,
|
||||
},
|
||||
[sys_GetCurrentThreadID] = {
|
||||
"GetCurrentThreadID",
|
||||
(void *)sys_get_current_thread_id,
|
||||
UINT16_MAX,
|
||||
},
|
||||
[sys_GetProcessByPID] = {
|
||||
"GetProcessByPID",
|
||||
(void *)sys_get_process_by_pid,
|
||||
0,
|
||||
},
|
||||
[sys_GetThreadByTID] = {
|
||||
"GetThreadByTID",
|
||||
(void *)sys_get_thread_by_tid,
|
||||
0,
|
||||
},
|
||||
[sys_KillProcess] = {
|
||||
"KillProcess",
|
||||
(void *)sys_kill_process,
|
||||
0,
|
||||
},
|
||||
[sys_KillThread] = {
|
||||
"KillThread",
|
||||
(void *)sys_kill_thread,
|
||||
0,
|
||||
},
|
||||
[sys_SysReservedCreateProcess] = {
|
||||
"SysReservedCreateProcess",
|
||||
(void *)sys_sys_reserved_create_process,
|
||||
0,
|
||||
},
|
||||
[sys_SysReservedCreateThread] = {
|
||||
"SysReservedCreateThread",
|
||||
(void *)sys_sys_reserved_create_thread,
|
||||
0,
|
||||
},
|
||||
};
|
||||
|
||||
uintptr_t HandleNativeSyscalls(SysFrm *Frame)
|
||||
{
|
||||
#if defined(a64)
|
||||
if (unlikely(Frame->rax > sys_MaxSyscall))
|
||||
{
|
||||
fixme("Syscall %ld not implemented.", Frame->rax);
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
SyscallData Syscall = NativeSyscallsTable[Frame->rax];
|
||||
|
||||
uintptr_t (*call)(SysFrm *, uintptr_t, ...) =
|
||||
r_cst(uintptr_t(*)(SysFrm *, uintptr_t, ...),
|
||||
Syscall.Handler);
|
||||
|
||||
if (unlikely(!call))
|
||||
{
|
||||
error("Syscall %s(%d) not implemented.",
|
||||
Syscall.Name, Frame->rax);
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
int euid = thisProcess->Security.Effective.UserID;
|
||||
int egid = thisProcess->Security.Effective.GroupID;
|
||||
int reqID = Syscall.RequiredID;
|
||||
if (euid > reqID || egid > reqID)
|
||||
{
|
||||
warn("Process %s(%d) tried to access a system call \"%s\" with insufficient privileges.",
|
||||
thisProcess->Name, thisProcess->ID, Syscall.Name);
|
||||
debug("Required: %d; Effective u:%d, g:%d", reqID, euid, egid);
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
debug("[%d:\"%s\"]->( %#lx %#lx %#lx %#lx %#lx %#lx )",
|
||||
Frame->rax, Syscall.Name,
|
||||
Frame->rdi, Frame->rsi, Frame->rdx,
|
||||
Frame->r10, Frame->r8, Frame->r9);
|
||||
|
||||
return call(Frame,
|
||||
Frame->rdi, Frame->rsi, Frame->rdx,
|
||||
Frame->r10, Frame->r8, Frame->r9);
|
||||
#elif defined(a32)
|
||||
if (unlikely(Frame->eax > sys_MaxSyscall))
|
||||
{
|
||||
fixme("Syscall %ld not implemented.", Frame->eax);
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
SyscallData Syscall = NativeSyscallsTable[Frame->eax];
|
||||
|
||||
uintptr_t (*call)(SysFrm *, uintptr_t, ...) =
|
||||
r_cst(uintptr_t(*)(SysFrm *, uintptr_t, ...),
|
||||
Syscall.Handler);
|
||||
|
||||
if (unlikely(!call))
|
||||
{
|
||||
error("Syscall %s(%d) not implemented.",
|
||||
Syscall.Name, Frame->eax);
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
int euid = thisProcess->Security.Effective.UserID;
|
||||
int egid = thisProcess->Security.Effective.GroupID;
|
||||
int reqID = Syscall.RequiredID;
|
||||
if (euid > reqID || egid > reqID)
|
||||
{
|
||||
warn("Process %s(%d) tried to access a system call \"%s\" with insufficient privileges.",
|
||||
thisProcess->Name, thisProcess->ID, Syscall.Name);
|
||||
debug("Required: %d; Effective u:%d, g:%d", reqID, euid, egid);
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
debug("[%d:\"%s\"]->( %#x %#x %#x %#x %#x %#x )",
|
||||
Frame->eax, Syscall.Name,
|
||||
Frame->ebx, Frame->ecx, Frame->edx,
|
||||
Frame->esi, Frame->edi, Frame->ebp);
|
||||
|
||||
return call(Frame,
|
||||
Frame->ebx, Frame->ecx, Frame->edx,
|
||||
Frame->esi, Frame->edi, Frame->ebp);
|
||||
#elif defined(aa64)
|
||||
return -ENOSYS;
|
||||
#endif
|
||||
}
|
@ -1,96 +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 <debug.h>
|
||||
|
||||
#include "../kernel.h"
|
||||
|
||||
class AutoSwitchPageTable
|
||||
{
|
||||
private:
|
||||
uintptr_t Original;
|
||||
|
||||
public:
|
||||
AutoSwitchPageTable()
|
||||
{
|
||||
#if defined(a86)
|
||||
asmv("mov %%cr3, %0"
|
||||
: "=r"(Original));
|
||||
|
||||
asmv("mov %0, %%cr3"
|
||||
:
|
||||
: "r"(KernelPageTable));
|
||||
#endif
|
||||
}
|
||||
|
||||
~AutoSwitchPageTable()
|
||||
{
|
||||
#if defined(a86)
|
||||
asmv("mov %0, %%cr3"
|
||||
:
|
||||
: "r"(Original));
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
extern "C" uintptr_t SystemCallsHandler(SyscallsFrame *Frame)
|
||||
{
|
||||
/* Automatically switch to kernel page table
|
||||
and switch back when this function returns. */
|
||||
AutoSwitchPageTable PageSwitcher;
|
||||
|
||||
uint64_t TempTimeCalc = TimeManager->GetCounter();
|
||||
Tasking::TaskInfo *Ptinfo = &thisProcess->Info;
|
||||
Tasking::TaskInfo *Ttinfo = &thisThread->Info;
|
||||
|
||||
switch (Ttinfo->Compatibility)
|
||||
{
|
||||
case Tasking::TaskCompatibility::Native:
|
||||
{
|
||||
uintptr_t ret = 0;
|
||||
if (Config.UseLinuxSyscalls)
|
||||
ret = HandleLinuxSyscalls(Frame);
|
||||
else
|
||||
ret = HandleNativeSyscalls(Frame);
|
||||
Ptinfo->KernelTime += TimeManager->GetCounter() - TempTimeCalc;
|
||||
Ttinfo->KernelTime += TimeManager->GetCounter() - TempTimeCalc;
|
||||
return ret;
|
||||
}
|
||||
case Tasking::TaskCompatibility::Linux:
|
||||
{
|
||||
uintptr_t ret = HandleLinuxSyscalls(Frame);
|
||||
Ptinfo->KernelTime += TimeManager->GetCounter() - TempTimeCalc;
|
||||
Ttinfo->KernelTime += TimeManager->GetCounter() - TempTimeCalc;
|
||||
return ret;
|
||||
}
|
||||
case Tasking::TaskCompatibility::Windows:
|
||||
{
|
||||
error("Windows compatibility not implemented yet.");
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
error("Unknown compatibility mode! Killing thread...");
|
||||
TaskManager->KillThread(thisThread, Tasking::KILL_SYSCALL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
assert(false); /* Should never reach here. */
|
||||
return 0;
|
||||
}
|
28
TODO.md
Normal file
28
TODO.md
Normal file
@ -0,0 +1,28 @@
|
||||
- [x] Optimize SMP.
|
||||
- [ ] Support IPv6.
|
||||
- [ ] Endianess of the network stack (currently: [HOST](LSB)<=>[NETWORK](MSB)). Not sure if this is a standard or not.
|
||||
- [ ] Support 32-bit applications (ELF, PE, etc).
|
||||
- [ ] Do not map the entire memory. Map only the needed memory address at allocation time.
|
||||
- [ ] Implementation of logging (beside serial) with log rotation.
|
||||
- [x] Implement a better task manager. (replace struct P/TCB with classes)
|
||||
- [ ] Rewrite virtual file system. (it's very bad, I don't know how I wrote it this bad)
|
||||
- [ ] Colors in crash screen are not following the kernel color scheme.
|
||||
- [x] Find a way to add intrinsics.
|
||||
- [ ] Rework PSF1 font loader.
|
||||
- [x] The cleanup should be done by a thread (tasking). This is done to avoid a deadlock.
|
||||
- [ ] Implement a better Display::SetBrightness() function.
|
||||
- [ ] Fix memcpy, memset and memcmp functions (they are not working properly with SIMD).
|
||||
- [x] Fully support i386.
|
||||
- [ ] Support Aarch64.
|
||||
- [ ] SMP trampoline shouldn't be hardcoded at 0x2000.
|
||||
- [ ] Rework the stack guard.
|
||||
- [x] Mutex implementation.
|
||||
- [ ] Update SMBIOS functions to support newer versions and actually use it.
|
||||
- [ ] COW (Copy On Write) for the virtual memory. (https://en.wikipedia.org/wiki/Copy-on-write)
|
||||
- [ ] Implement lazy allocation. (page faults)
|
||||
- [ ] Bootstrap should have a separate bss section + PHDR.
|
||||
- [ ] Reimplement the driver conflict detection.
|
||||
- [ ] Elf loader shouldn't create a full copy of the elf binary. Copy only the needed sections.
|
||||
- [ ] Use NX-bit.
|
||||
- [ ] Fix std::string
|
||||
- [ ] Rewrite PS/2 drivers.
|
138
Tests/Marco.cpp
138
Tests/Marco.cpp
@ -1,138 +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/>.
|
||||
*/
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
#include <types.h>
|
||||
#include <memory.hpp>
|
||||
#include <assert.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <filesystem.hpp>
|
||||
#include "../syscalls.h"
|
||||
|
||||
void TestSeekMacros() /* static assert, no constructor needed */
|
||||
{
|
||||
static_assert(SYSCALL_SEEK_SET == SEEK_SET);
|
||||
static_assert(SYSCALL_SEEK_CUR == SEEK_CUR);
|
||||
static_assert(SYSCALL_SEEK_END == SEEK_END);
|
||||
}
|
||||
|
||||
__constructor void TestMacros()
|
||||
{
|
||||
{
|
||||
int a = TO_PAGES(4096);
|
||||
int b = FROM_PAGES(1);
|
||||
|
||||
debug("a: 4096 -> %d", a);
|
||||
debug("b: a -> %d", b);
|
||||
|
||||
if (a != 1)
|
||||
{
|
||||
error("t1: TO_PAGES is not equal to 1");
|
||||
inf_loop;
|
||||
}
|
||||
|
||||
if (b != 4096)
|
||||
{
|
||||
error("t1: FROM_PAGES is not equal to 4096");
|
||||
inf_loop;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
int a = TO_PAGES(4097);
|
||||
int b = FROM_PAGES(2);
|
||||
|
||||
debug("a: 4097 -> %d", a);
|
||||
debug("b: a -> %d", b);
|
||||
|
||||
if (a != 2)
|
||||
{
|
||||
error("t2: TO_PAGES is not equal to 2");
|
||||
inf_loop;
|
||||
}
|
||||
|
||||
if (b != 8192)
|
||||
{
|
||||
error("t2: FROM_PAGES is not equal to 8192");
|
||||
inf_loop;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
int a = 10;
|
||||
assert(a == 10);
|
||||
|
||||
const char *str = "Hello";
|
||||
assert(str != nullptr && str[0] == 'H');
|
||||
|
||||
bool flag = false;
|
||||
assert(!flag);
|
||||
}
|
||||
|
||||
debug("-------------------------");
|
||||
|
||||
{
|
||||
uint64_t bytes = PAGE_SIZE;
|
||||
uint64_t pgs = 1;
|
||||
|
||||
for (int i = 0; i < 128; i++)
|
||||
{
|
||||
uint64_t cnv_to_pgs = TO_PAGES(bytes);
|
||||
uint64_t cnv_from_pgs = FROM_PAGES(pgs);
|
||||
|
||||
if (cnv_to_pgs != pgs)
|
||||
{
|
||||
error("TO_PAGES is not equal to %d (pages: %d)", pgs, cnv_to_pgs);
|
||||
inf_loop;
|
||||
}
|
||||
|
||||
if (cnv_from_pgs != bytes)
|
||||
{
|
||||
error("FROM_PAGES is not equal to %d (bytes: %d)", bytes, cnv_from_pgs);
|
||||
inf_loop;
|
||||
}
|
||||
|
||||
bytes += PAGE_SIZE;
|
||||
pgs++;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
debug("Testing ROUND_UP and ROUND_DOWN");
|
||||
int x = 0x101;
|
||||
int y = 0x100;
|
||||
int result;
|
||||
|
||||
result = ROUND_UP(x, y);
|
||||
if (result != 0x200)
|
||||
{
|
||||
error("ERROR: ROUND_UP failed: %d != 0x200", result);
|
||||
inf_loop;
|
||||
}
|
||||
|
||||
result = ROUND_DOWN(x, y);
|
||||
if (result != 0x100)
|
||||
{
|
||||
error("ERROR: ROUND_DOWN failed: %d != 0x100", result);
|
||||
inf_loop;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // DEBUG
|
29
Tests/t.h
29
Tests/t.h
@ -1,29 +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_non_constructor_tests_H__
|
||||
#define __FENNIX_KERNEL_non_constructor_tests_H__
|
||||
#ifdef DEBUG
|
||||
|
||||
#include <types.h>
|
||||
|
||||
void TestString();
|
||||
void Test_std();
|
||||
void TestMemoryAllocation();
|
||||
|
||||
#endif // DEBUG
|
||||
#endif // !__FENNIX_KERNEL_non_constructor_tests_H__
|
59
arch/aarch64/cpu/smp.cpp
Normal file
59
arch/aarch64/cpu/smp.cpp
Normal file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
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 <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];
|
||||
}
|
||||
|
||||
if (CPUs[ret].Checksum != CPU_DATA_CHECKSUM)
|
||||
{
|
||||
error("CPU %d data is corrupted!", ret);
|
||||
return &CPUs[0];
|
||||
}
|
||||
return &CPUs[ret];
|
||||
}
|
||||
|
||||
namespace SMP
|
||||
{
|
||||
int CPUCores = 0;
|
||||
|
||||
void Initialize(void *madt)
|
||||
{
|
||||
fixme("SMP::Initialize() is not implemented!");
|
||||
}
|
||||
}
|
27
arch/aarch64/entry.cpp
Normal file
27
arch/aarch64/entry.cpp
Normal file
@ -0,0 +1,27 @@
|
||||
/*
|
||||
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>
|
||||
#include <cpu.hpp>
|
||||
|
||||
EXTERNC void arm64Entry(uint64_t dtb_ptr32, uint64_t x1, uint64_t x2, uint64_t x3)
|
||||
{
|
||||
trace("Hello, World!");
|
||||
CPU::Halt(true);
|
||||
}
|
90
arch/aarch64/linker.ld
Normal file
90
arch/aarch64/linker.ld
Normal file
@ -0,0 +1,90 @@
|
||||
/*
|
||||
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
|
||||
{
|
||||
_bootstrap_start = .;
|
||||
.text.boot :
|
||||
{
|
||||
*(.text.boot)
|
||||
. += CONSTANT(MAXPAGESIZE);
|
||||
_bss_start = .;
|
||||
*(.text.bss)
|
||||
_bss_end = .;
|
||||
}
|
||||
_bootstrap_end = .;
|
||||
|
||||
_kernel_start = .;
|
||||
_kernel_text_start = .;
|
||||
.text :
|
||||
{
|
||||
KEEP(*(.text.boot))
|
||||
*(.text .text.*)
|
||||
}
|
||||
. = ALIGN(4096);
|
||||
_kernel_text_end = .;
|
||||
|
||||
_kernel_data_start = .;
|
||||
.data :
|
||||
{
|
||||
*(.data .data.*)
|
||||
}
|
||||
. = ALIGN(4096);
|
||||
_kernel_data_end = .;
|
||||
|
||||
_kernel_rodata_start = .;
|
||||
.rodata :
|
||||
{
|
||||
*(.rodata .rodata.*)
|
||||
}
|
||||
. = ALIGN(4096);
|
||||
|
||||
.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 = .);
|
||||
}
|
||||
_kernel_rodata_end = .;
|
||||
|
||||
_kernel_bss_start = .;
|
||||
.bss :
|
||||
{
|
||||
*(.bss .bss.*)
|
||||
}
|
||||
. = ALIGN(4096);
|
||||
_kernel_bss_end = .;
|
||||
_kernel_end = .;
|
||||
_bss_size = _kernel_end - _kernel_rodata_end;
|
||||
|
||||
/DISCARD/ :
|
||||
{
|
||||
*(.comment*)
|
||||
*(.note*)
|
||||
}
|
||||
}
|
40
arch/aarch64/memory/vmm.cpp
Normal file
40
arch/aarch64/memory/vmm.cpp
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <memory.hpp>
|
||||
|
||||
#include <convert.h>
|
||||
#include <debug.h>
|
||||
|
||||
namespace Memory
|
||||
{
|
||||
bool Virtual::Check(void *VirtualAddress, PTFlag Flag, MapType Type)
|
||||
{
|
||||
}
|
||||
|
||||
void *Virtual::GetPhysical(void *VirtualAddress)
|
||||
{
|
||||
}
|
||||
|
||||
void Virtual::Map(void *VirtualAddress, void *PhysicalAddress, uint64_t Flags, MapType Type)
|
||||
{
|
||||
}
|
||||
|
||||
void Virtual::Unmap(void *VirtualAddress, MapType Type)
|
||||
{
|
||||
}
|
||||
}
|
31
arch/aarch64/syscalls.cpp
Normal file
31
arch/aarch64/syscalls.cpp
Normal file
@ -0,0 +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/>.
|
||||
*/
|
||||
|
||||
#include <syscalls.hpp>
|
||||
|
||||
#include <cpu.hpp>
|
||||
|
||||
extern "C" __naked __used __no_stack_protector void SystemCallHandlerStub()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
extern "C" uint64_t SystemCallsHandler(SyscallsFrame *regs);
|
||||
|
||||
void InitializeSystemCalls()
|
||||
{
|
||||
}
|
38
arch/amd64/bootstrap/_start.s
Normal file
38
arch/amd64/bootstrap/_start.s
Normal file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
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/>.
|
||||
*/
|
||||
|
||||
.code32
|
||||
.extern Multiboot_start
|
||||
|
||||
.section .bootstrap.text, "a"
|
||||
|
||||
.global _start
|
||||
_start:
|
||||
/* Check for multiboot */
|
||||
cmp $0x2BADB002, %eax
|
||||
je .Multiboot
|
||||
|
||||
/* Unkown bootloader */
|
||||
.Hang:
|
||||
cli
|
||||
hlt
|
||||
jmp .Hang
|
||||
|
||||
/* Multiboot */
|
||||
.Multiboot:
|
||||
call Multiboot_start
|
||||
jmp .Hang
|
@ -1,18 +1,18 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <boot/binfo.h>
|
@ -1,18 +1,18 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
.intel_syntax noprefix
|
64
arch/amd64/bootstrap/multiboot/Helper/gdt32.s
Normal file
64
arch/amd64/bootstrap/multiboot/Helper/gdt32.s
Normal file
@ -0,0 +1,64 @@
|
||||
/*
|
||||
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/>.
|
||||
*/
|
||||
|
||||
.code32
|
||||
.section .bootstrap.text, "a"
|
||||
|
||||
.align 32
|
||||
.global gdtr
|
||||
gdtr:
|
||||
.word GDT32_END - GDT32 - 1
|
||||
.long GDT32
|
||||
|
||||
.align 32
|
||||
GDT32:
|
||||
.quad 0x0
|
||||
|
||||
.word 0xFFFF
|
||||
.word 0x0000
|
||||
.byte 0x00
|
||||
.word 0xCF9A
|
||||
.byte 0x00
|
||||
|
||||
.word 0xFFFF
|
||||
.word 0x0000
|
||||
.byte 0x00
|
||||
.word 0xCF92
|
||||
.byte 0x00
|
||||
|
||||
.word 0x0100
|
||||
.word 0x1000
|
||||
.byte 0x00
|
||||
.word 0x4092
|
||||
.byte 0x00
|
||||
GDT32_END:
|
||||
nop
|
||||
|
||||
.global LoadGDT32
|
||||
LoadGDT32:
|
||||
lgdt [gdtr]
|
||||
ljmp $0x8, $ActivateGDT
|
||||
|
||||
ActivateGDT:
|
||||
mov $0x10, %cx
|
||||
mov %cx, %ss
|
||||
mov %cx, %ds
|
||||
mov %cx, %es
|
||||
mov %cx, %fs
|
||||
mov $0x18, %cx
|
||||
mov %cx, %gs
|
||||
ret
|
62
arch/amd64/bootstrap/multiboot/Helper/gdt64.s
Normal file
62
arch/amd64/bootstrap/multiboot/Helper/gdt64.s
Normal file
@ -0,0 +1,62 @@
|
||||
/*
|
||||
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/>.
|
||||
*/
|
||||
|
||||
.code64
|
||||
.section .bootstrap.data, "a"
|
||||
|
||||
/* Access bits */
|
||||
A = 0x1
|
||||
RW = 0x2
|
||||
DC = 0x4
|
||||
E = 0x8
|
||||
S = 0x10
|
||||
DPL0 = 0x0 /* 0 << 5 ???? */
|
||||
DPL1 = 0x20
|
||||
P = 0x80
|
||||
|
||||
/* Flags bits */
|
||||
LONG_MODE = 0x20
|
||||
SZ_32 = 0x40
|
||||
GRAN_4K = 0x80
|
||||
|
||||
.global GDT64.Null
|
||||
.global GDT64.Code
|
||||
.global GDT64.Data
|
||||
.global GDT64.Tss
|
||||
.global GDT64.Ptr
|
||||
|
||||
GDT64:
|
||||
GDT64.Null = . - GDT64
|
||||
.quad 0
|
||||
GDT64.Code = . - GDT64
|
||||
.long 0xFFFF
|
||||
.byte 0
|
||||
.byte P | S | E | RW
|
||||
.byte GRAN_4K | LONG_MODE | 0xF
|
||||
.byte 0
|
||||
GDT64.Data = . - GDT64
|
||||
.long 0xFFFF
|
||||
.byte 0
|
||||
.byte P | S | RW
|
||||
.byte GRAN_4K | SZ_32 | 0xF
|
||||
.byte 0
|
||||
GDT64.Tss = . - GDT64
|
||||
.long 0x00000068
|
||||
.long 0x00CF8900
|
||||
GDT64.Ptr:
|
||||
.word . - GDT64 - 1
|
||||
.quad GDT64
|
@ -1,18 +1,18 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <types.h>
|
@ -1,18 +1,18 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
PAGE_TABLE_SIZE = 0x4
|
38
arch/amd64/bootstrap/multiboot/headers/header1.s
Normal file
38
arch/amd64/bootstrap/multiboot/headers/header1.s
Normal file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
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/>.
|
||||
*/
|
||||
|
||||
.code32
|
||||
.extern Multiboot_start
|
||||
|
||||
.section .multiboot, "a"
|
||||
.align 4
|
||||
|
||||
MULTIBOOT_HEADER:
|
||||
.long 0x1BADB002
|
||||
.long 0x1 | 0x2 | 0x4
|
||||
.long -(0x1BADB002 + (0x1 | 0x2 | 0x4))
|
||||
/* KLUDGE */
|
||||
.long 0
|
||||
.long 0
|
||||
.long 0
|
||||
.long 0
|
||||
.long 0
|
||||
/* VIDEO MODE */
|
||||
.long 0
|
||||
.long 0
|
||||
.long 0
|
||||
.long 0
|
@ -1,18 +1,18 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
.code32
|
@ -1,18 +1,18 @@
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <types.h>
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user