Restructured and rewritten entire codebase

This commit is contained in:
Alex 2023-10-09 01:16:24 +03:00
parent 446a571018
commit 889e1522a3
Signed by untrusted user who does not match committer: enderice2
GPG Key ID: EACC3AD603BAB4DD
484 changed files with 15683 additions and 14032 deletions

View File

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

@ -4,4 +4,3 @@
*.map
*.fsys
*.log
.dccache

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

109
CREDITS.md Normal file
View 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!

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

44
LICENSES.md Normal file
View 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.

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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

View 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

View File

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

View File

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

View 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

View 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

View File

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

View File

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

View 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

View File

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

View File

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

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